原创 ATmega168 A/D 转换 使用连续转换和中断方式的例子

2008-11-3 17:28 5647 9 9 分类: MCU/ 嵌入式

ATmega168的A/D转换可以实现单次转换和连续转换。下面的例子实现连续转换。


     说明:采用中断方式,4路AD单端输入,分别接入AD4~AD7。程序应用层认为AD通道是1~4,因此下面程序中选择通道做了特殊处理,ADMUX |= ( AI_CHANNEL1_PORT+ucChl-1 );  


     用户应用程序调用时,先调用vStartADConvert(),来完成一个通道的AD转换,然后调用fGetAIData(),得到具体的电压值。


     推荐的程序结构是:周期性地调用vStartADConvert(),将AD结果保存在本文件的数据结构xAIDatastruct_t xAIData[MAX_AI_CHANNEL]中;当用户需要数据时,再在需要的地方调用fGetAIData(),获取真实数值。


/* ----------------------- Defines ------------------------------------------*/
#define AREF 1.1


#define AI_CHANNEL1_PORT  4
#define AI_CHANNEL2_PORT  5
#define AI_CHANNEL3_PORT  6
#define AI_CHANNEL4_PORT  7


#define TRANSFER_TIMES    5   //多次转换求平均值时的转换次数


/* ----------------------- Static variables ---------------------------------*/
typedef struct
{
    volatile UBYTE  ucCurrentConvertTimes;
    volatile USHORT usValidData;
    volatile USHORT usTempData;
} xAIDatastruct_t;


STATIC xAIDatastruct_t xAIData[MAX_AI_CHANNEL];
STATIC volatile unsigned char ucADCurrentChannel;


/* ----------------------- Static functions ---------------------------------*/
void vADInit(void);



/* ----------------------- Start implementation -----------------------------*/



/******************************************
* 名称    :  vADInit
* 功能描述:  AD初始化,初始化4个AD输入通道,设置转换速率、内部参考电压源
* 输入参量:  无
* 输出参量:  无
* 调用子程: 
* 使用方法: 
--------------------------*/
void
vADInit(void)
{
  PRR &= ~_BV( PRADC );//
  ADMUX = _BV( REFS1) | _BV( REFS0 );


  ADCSRA = _BV( ADEN ) | _BV( ADPS2 )| _BV( ADPS1 )| _BV( ADATE ) ;
  ADCSRB="0x00";
}


void
vStartADConvert( UCHAR ucChl)

 vADInit();
 ADMUX |= ( AI_CHANNEL1_PORT+ucChl-1 );    //从第ucChl个通道开始进行转换,由于从外部AD通道从1开始,对应第4通道
 ADCSRA |= _BV( ADSC ) ;                   //开始AD转换,并且使能ad中断
 ADCSRA |= _BV( ADIE ) ;
 ucADCurrentChannel = ucChl-1;
}


ISR( ADC_vect, ISR_BLOCK )
{  
 ADCSRA &= ~_BV( ADIF );
 if(xAIData[ucADCurrentChannel].ucCurrentConvertTimes != 0)
     xAIData[ucADCurrentChannel].usTempData += ( int ) ADC;
 xAIData[ucADCurrentChannel].ucCurrentConvertTimes++;


 if( xAIData[ucADCurrentChannel].ucCurrentConvertTimes > TRANSFER_TIMES)
 {
  ADCSRA &= ~_BV( ADSC );                      //停止AD转换
  ADCSRA &= ~_BV( ADIE );                      //禁止中断


  xAIData[ucADCurrentChannel].usValidData = xAIData[ucADCurrentChannel].usTempData/TRANSFER_TIMES;
  xAIData[ucADCurrentChannel].usTempData = 0;
  xAIData[ucADCurrentChannel].ucCurrentConvertTimes = 0;
 }
}


float
fGetAIData( UCHAR ucChl)
{
 return ( xAIData[ucChl-1].usValidData*AREF/1024);
}


应用要点:切换通道后的第一次转换结果需要舍弃。上面的例子中,AD中断发生了6次,但是我们只利用其中的后5次。我测试发现,切换通道后的第一次AD转换的数值是上个通道的AD值。



 

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
9
关闭 站长推荐上一条 /3 下一条