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值。
文章评论(0条评论)
登录后参与讨论