#include "ADC_Convert.h"

#define ADC_START ADCSRA |= 0x40

//轉換腳位對應

#define PINPC0 0

#define PINPC1 1

#define PINPC2 2

#define PINPC3 3

#define PINADC6 6

#define PINADC7 7

//轉換後放置陣列位置

#define NUM_PC0 0

#define NUM_PC1 1

#define NUM_PC2 2

#define NUM_PC3 3

#define NUM_ADC6 4

#define NUM_ADC7 5

#define CONV_MAX 6

#define AVG_MAX 4

typedef unsigned char  U8;

typedef char               S8;

typedef unsigned int   U16;

typedef int                 S16;

typedef unsigned long U32;

typedef long               S32;

typedef struct

{

U16 Resullt[CONV_MAX];   // ADC轉換後之Buffer

U16 AVG[CONV_MAX];     // 運算後平均值(程式可使用之值)

U16 Tmp[CONV_MAX];    // 運算中的暫存Buffer

U8 Count;                            // 轉換腳位

U8 AVG_Count;                 // 平均值累加次數

U8 ADC_OK;                      // 轉換並取完平均

}TADC_Struct;

TADC_Struct ADCs;

U8 convert_number[CONV_MAX] = { PINPC0, PINPC1, PINPC2, PINPC3, PINADC6, PINADC7};

//初始化ADC SFR(Special Function Register)

void Init_ADC()

{

ACSR = 0x80;            // Disable Analog Comparator

ADMUX = 0x40;       // Vref with external AREF pin

ADCSRA = 0x88;     // Enable ADC & interrupt

ADCSRB = 0x00;     // Free Running mode

DIDR0 = 0x0F;        // PC0 ~ PC3 set Analog pin

}

//累加平均值

void Tmp_Calc()

{

U8 i;

for(i = 0; i < CONV_MAX; i++)

{

        ADCs.Tmp[i] += ADCs.Resullt[i];

}

}

//平均值計算

void AVG_Calc()

{

U8 i;

for(i = 0; i < CONV_MAX; i++)

{

        ADCs.AVG[i] = ADCs.Tmp[i] >> 2;

        ADCs.Tmp[i] = 0;

}

}

// ADC平均處理程序(判斷要累加還是取平均)

void ADC_Process()

{

if(ADCs.AVG_Count < AVG_MAX)

{

        Tmp_Calc();

        ADCs.AVG_Count++;

        ADC_START;

}

else

{

        AVG_Calc();

        ADCs.AVG_Count = 0;

        ADCs.ADC_OK = 1;

}

}

// 清除ADC結構內之相關參數

void ADC_InitParameter()

{

U8 i;

ADCs.ADC_OK = 0;

ADCs.AVG_Count = 0;

ADCs.Count = 0;

for(i = 0; i < CONV_MAX; i++)

{

        ADCs.AVG[i] = 0;

        ADCs.Tmp[i] = 0;

        ADCs.Resullt[i] = 0;

}

ADMUX = 0x40;

ADC_START;

}

// ADC interrupt

ISR(ADC_vect)

{

U8 i;

sei();

if(ADCs.Count < (CONV_MAX – 1))

{

        ADCs.Resullt[ADCs.Count] = ADC;

        ADCs.Count++;

        ADMUX = 0x40 + convert_number[ADCs.Count];

      for(i = 0; i < 10; i++);         //注意做完多工器切換必須等待一下

        ADC_START;

}

else

{

        ADCs.Resullt[ADCs.Count] = ADC;

        ADMUX = 0x40;

        ADCs.Count = 0;

        ADC_Process();

}

}

// 初始ADC轉換(建議先做幾次,除一開始電壓不準做矯正以外亦可取得第一次之相關數值)

void check_ADC()

{

ADMUX = 0x40;

ADC_START;

ADCs.Count = 0;

ADCs.AVG_Count = 0;

while(!ADCs.ADC_OK);

ADCs.ADC_OK = 0;

}

int main()

{

Init_ADC();

ADC_InitParameter();

sei(); // 開啟全域中斷

check_ADC(); // 建議判斷三次後進入穩定

check_ADC();

check_ADC();

ADMUX = 0x40;

ADC_START;

while(1)

{

        if(ADCs.ADC_OK)

          {

                 //process

                           //ex:

                 if(ADCs.AVG[NUM_PC0] > 512)

                      {

                             // 相關程序

                       }

                       ADCs.ADC_OK = 0;

                       ADC_START;             //再繼續轉換可放在時間中斷內

           }

}

return 0;

}