对使用STM8S003/903这个片子的ADC中断功能(包括两种情况),记录下自己的理解:
一、单通道使用ADC中断的场合:
如果项目中只需要采集一路模拟量,并且想使用中断方式来获取AD值,那么,设置如下:
void ADC1_Init(void)
{
CLK->PCKENR2 |= CLK_PCKENR2_ADC; //ADC Clock Enable
ADC1->TDRL = 0x02; //禁用对应AD通道的施密特触发器
ADC1->CR2 &= ~ADC1_CR2_ALIGN; //结果左对齐。
/*使能中断的同时一定要同时设定ADC通道号。*/
ADC1->CSR |= ADC1_CSR_EOCIE; //使能ADC中断
ADC1->CSR |= 0x02; //选择通道
ADC1->CR1 |= (0x20 ); //时钟4分频
ADC1->CR1 |= (ADC1_CR1_ADON); //开启ADC1电源
//这里还需要开启全局中断,省略,一般放到main函数的初始化部分开启全局中断。
}
void ADC1_Start(u8 channel)
{
ADC1->CR1 |= ADC1_CR1_ADON; //启动ADC1开始转换
}
@far @interrupt void ADC1_IRQHandler(void)
{
u8 adc_value = 0;
ADC1->CSR &= ~ADC1_CSR_EOC; //结束标志位清零
adc_value = ADC1->DRH;
//在这个中断服务函数中获取数据,你可以取高8位, 也可以把高8位和低8位全部取出来。看你的精度需要。
}
使用思路: 在main函数初始化阶段调用ADC1_Init(),在需要开启ADC采集的时候调用ADC1_Start(),在ADC1_IRQHandler()中断处理函数中,读取AD值。
二、多通道使用的场合:
要在STM8S003/903上使用ADC,特别是多通道又不是连续的通道(因为有时候PCB布线受限制,无法使用连续的ADC通道采集多路模拟量),并且你又需要采用单次转换加中断的方式读取AD值,而不是查询的方式, 那么,这种情况,有点特别的设定,设置如下:
void ADC1_Init(void)
{
CLK->PCKENR2 |= CLK_PCKENR2_ADC; //ADC Clock Enable
ADC1->TDRL = 0x02; //禁用对应AD通道的施密特触发器
ADC1->CR2 &= ~ADC1_CR2_ALIGN; //结果左对齐。
/* 特别的地方:注释掉这两行,不需要在这里设置 */
//ADC1->CSR |= ADC1_CSR_EOCIE; //使能ADC中断
//ADC1->CSR |= 0x02; //选择通道
ADC1->CR1 |= (0x20 ); //时钟4分频
ADC1->CR1 |= (ADC1_CR1_ADON); //开启ADC1电源
//这里还需要开启全局中断,省略,一般放到main函数的初始化部分开启全局中断。
}
void ADC1_Start(u8 channel)
{
/* 特别的地方: 每次启动AD转换的时候设定通道号和开启中断 */
ADC1->CSR = channel; //选择通道
ADC1->CSR |= ADC1_CSR_EOCIE; //使能ADC中断
ADC1->CR1 |= ADC1_CR1_ADON; //启动ADC1开始转换
}
@far @interrupt void ADC1_IRQHandler(void)
{
u8 adc_value = 0;
ADC1->CSR &= ~ADC1_CSR_EOC; //结束标志位清零
adc_value = ADC1->DRH;
//这里获取你的数据,你可以取高8位, 也可以把高8位和低8位全部取出来。看你的精度需要。
if( Enable_ch1_Flag )
{
Enable_ch1_Flag = 0;
//这里读取数据到你的采样数组中。
}
else if( Enable_ch2_Flag )
{
Enable_ch2_Flag = 0;
//这里读取数据到你的采样数组中。
}
else if( Enable_ch3_Flag )
{
Enable_ch3_Flag = 0;
//这里读取数据到你的采样数组中。
}
}
void ADC_Capture(void)
{
static u8 getstep = 0;
switch (getstep )
{
case 0:
ADC1_Start(CH_AD1);
Enable_ch1_Flag = 1;
Enable_ch2_Flag = 0;
Enable_ch3_Flag = 0;
getstep ++;
break;
case 1:
ADC1_Start(CH_AD2);
Enable_ch2_Flag = 1;
Enable_ch1_Flag = 0;
Enable_ch3_Flag = 0;
getstep ++;
break;
case 2:
ADC1_Start(CH_AD3);
Enable_ch3_Flag = 1;
Enable_ch1_Flag = 0;
Enable_ch2_Flag = 0;
getstep ++;
break;
default:
break;
}
}
使用思路: 在main函数初始化阶段调用ADC1_Init(),在一个500us定时器中断中调用ADC_Capture(),在ADC1_IRQHandler()中断处理函数中,读取AD值。