历史上的今天
今天是:2024年09月24日(星期二)
2021年09月24日 | STM8的ADC多种采集模式详解及应用
2021-09-24 来源:eefocus
一,STM8S 的 ADC 支持 5 种转换模式:单次模式、连续模式、带缓冲的连续模式、单次扫描模式、连续扫描模式。

1单次模式
单次模式,STM8S 的 ADC 只在选定的通道上进行一次 ADC 转换,转换的结果存储在 ADC_DR 寄存器中。
void ADC_Init(void)
{
ADC1_DeInit();//ADC 相关寄存器恢复默认值
//初始化 ADC:单次转换/通道 8/时钟分频/关闭事件/数据右对齐/使能施密特触发器
ADC1_Init(ADC1_CONVERSIONMODE_SINGLE, ADC1_CHANNEL_8, ADC1_PRESSEL_FCPU_D2,
ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_ALL,
DISABLE);
ADC1_Cmd(ENABLE);//使能 ADC
}
void main( void )
{
u16value=0;
adc_init();
while(1)
{
ADC1_StartConversion();//开启一次转换一次
while(!ADC1_GetFlagStatus(ADC1_FLAG_EOC));//等待转换完成
ADC1_ClearFlag(ADC1_FLAG_EOC);//软件清除
value=(u16)ADC1_GetConversionValue();//从ADC_DR中读取ADC值
}
}
}
**2连续模式
连续模式,ADC 在结束一次转换之后立刻自动进行下一次转换。连续模式时,转换结果存储在 ADC_DR 寄存器**
void ADC_Init(void)
{
ADC1_DeInit();//ADC 相关寄存器恢复默认值
//初始化 ADC:连续转换/通道 8/时钟分频/关闭事件/数据右对齐/使能施密特触发器
ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC1_CHANNEL_8, ADC1_PRESSEL_FCPU_D2,
ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_ALL,
DISABLE);
ADC1_Cmd(ENABLE);//使能 ADC
}
void main( void )
{
u16value=0;
adc_init();
while(1)
{
while(!ADC1_GetFlagStatus(ADC1_FLAG_EOC));//等待转换完成
ADC1_ClearFlag(ADC1_FLAG_EOC);//软件清除
value=(u16)ADC1_GetConversionValue();//从ADC_DR中读取ADC值
}
}
**3带缓冲的连续模式
ADC 在结束一次转换之后立刻自动进行下一次转换,连续 8 个或 10 个转换结果被存储在数据缓冲区。**
void ADC_Init(void)
{
ADC1_DeInit();//ADC 相关寄存器恢复默认值
//初始化 ADC:连续转换/通道 8/时钟分频/关闭事件/数据右对齐/使能施密特触发器
ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS,ADC1_CHANNEL_8, ADC1_PRESSEL_FCPU_D2,
ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_ALL,
DISABLE);
ADC1_Cmd(ENABLE);//使能 ADC
ADC1_DataBufferCmd(ENABLE);//开启缓存
}
void main( void )
{
u16value=0;
adc_init();
while(1)
{
while(!ADC1_GetFlagStatus(ADC1_FLAG_EOC));//等待转换完成
ADC1_ClearFlag(ADC1_FLAG_EOC);//软件清除
value=0;
for(u8 i=0;i<10;i++)//
{
value+=ADC1_GetBufferValue(i);//将10个缓存中的值求和
}
value=value/10;//求出ADC的平均值
}
}
**4单次扫描模式
ADC 对通道 AIN0~AINn 逐个进行单次转换,并接结果存储在数据缓冲区**
void ADC_Init(void)
{
ADC1_DeInit();//ADC 相关寄存器恢复默认值
//初始化 ADC:连续转换/通道 8/时钟分频/关闭事件/数据右对齐/使能施密特触发器
ADC1_Init(ADC1_CONVERSIONMODE_SINGLE, ADC1_CHANNEL_8, ADC1_PRESSEL_FCPU_D2,
ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_ALL,
ENABLE);//该处在串口发送及接收时需配置为ENABLE,否则会出现无法发送的现象。
ADC1_ScanModeCmd(ENABLE);
ADC1_Cmd(ENABLE);//使能 ADC
}
void main( void )
{
u16value1=0;
u16value2=0;
adc_init();
while(1)
{
ADC1_StartConversion();//开启一次转换
while(!ADC1_GetFlagStatus(ADC1_FLAG_EOC));//等待转换完成
ADC1_ClearFlag(ADC1_FLAG_EOC);//软件清除
value1=(u16)ADC1_GetBufferValue(ADC1_SCHMITTTRIG_CHANNEL2)//读取AIN2的值
value2=(u16)ADC1_GetBufferValue(ADC1_SCHMITTTRIG_CHANNEL4)//读取AIN4的值
}
}
**5连续扫描模式
此模式下 ADC 重复单次扫描模式**
void ADC_Init(void)
{
ADC1_DeInit();//ADC 相关寄存器恢复默认值
//初始化 ADC:连续转换/通道 8/时钟分频/关闭事件/数据右对齐/使能施密特触发器
ADC1_Init(ADC1_CONVERSIONMODE_CONTINUOUS, ADC1_CHANNEL_8, ADC1_PRESSEL_FCPU_D2,
ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_RIGHT, ADC1_SCHMITTTRIG_ALL,
DISABLE);
ADC1_Cmd(ENABLE);//使能 ADC
}
void main( void )
{
u16value1=0;
u16value2=0;
adc_init();
while(1)
{
while(!ADC1_GetFlagStatus(ADC1_FLAG_EOC));//等待转换完成
ADC1->CSR = (uint8_t)(ADC1->CSR &(~ADC1_FLAG_EOC)|ADC1_CHANNEL_4);//软件清除
value1=(u16)ADC1_GetBufferValue(ADC1_SCHMITTTRIG_CHANNEL2)//读取AIN2的值
value2=(u16)ADC1_GetBufferValue(ADC1_SCHMITTTRIG_CHANNEL4)//读取AIN4的值
}
}
二,在单次扫描模式工作时,必须使用ADC1_ClearFlag函数清除ADC读取标志位。而在连续扫描模式中,则不能清除该标志位,否则会导致ADC通道工作不正常。代码如下:
void main(void)
{
ADC1_StartConversion();//启动转换
while(1)
{
u16_adc1_value=ADC1_GetBufferValue(2);//读取通道2
VoltageValue=u16_adc1_value;//转换为电压值
u16_adc1_value=ADC1_GetBufferValue(3);//读取通道3
CurrentValue=u16_adc1_value;//转换为电流值
//ADC1_ClearFlag(ADC1_FLAG_EOC); //该处代码在ADC连续扫描模式时禁用
}
}
三,在ADC1_PRESSEL_FCPU_D2函数中D2代表预分频器选择fcpu/2
该函数还有
typedef enum
{
ADC1_PRESSEL_FCPU_D2 = (uint8_t)0x00, /**< Prescaler selection fADC1 = fcpu/2 */
ADC1_PRESSEL_FCPU_D3 = (uint8_t)0x10, /**< Prescaler selection fADC1 = fcpu/3 */
ADC1_PRESSEL_FCPU_D4 = (uint8_t)0x20, /**< Prescaler selection fADC1 = fcpu/4 */
ADC1_PRESSEL_FCPU_D6 = (uint8_t)0x30, /**< Prescaler selection fADC1 = fcpu/6 */
ADC1_PRESSEL_FCPU_D8 = (uint8_t)0x40, /**< Prescaler selection fADC1 = fcpu/8 */
ADC1_PRESSEL_FCPU_D10 = (uint8_t)0x50, /**< Prescaler selection fADC1 = fcpu/10 */
ADC1_PRESSEL_FCPU_D12 = (uint8_t)0x60, /**< Prescaler selection fADC1 = fcpu/12 */
ADC1_PRESSEL_FCPU_D18 = (uint8_t)0x70 /**< Prescaler selection fADC1 = fcpu/18 */
} ADC1_PresSel_TypeDef;
共八种选项,D2→D18,该值越大,则ADC转换速度越慢,数值越稳定。误差也会越小。
四,注意:在扫描模式(连续扫描模式)中,不要使用位操作指令(BRES)去清除EOC标志位,这是因为该指令是对整个ADC_CSR寄存器的一个读-修改-写操作。从CH[3:0]寄存器中读取当前的通道编号和写回该寄存器,将会改变扫描系列的最后通道编号。在连续扫描模式中正确的清除EOC标志位的方法是 个RAM变量中载入一个字节到ADC_CSR寄存器,这样来清除EOC标志位同时还重新载入扫描系列新的最后通道编号。
通过实验可以发现,位操作指令只在连续扫描模式中会清除CH[3:0]寄存器中的值,但并不影响其他值。因此将ADC_CSR中的值读出,再将CH[3:0]中原来通道号加入进去,最后重新写入ADC_CSR中即可。写法如下:
ADC1->CSR = (uint8_t)(ADC1->CSR &(~ADC1_FLAG_EOC)|ADC1_CHANNEL_n);
注:ADC1_CHANNEL_n表示扫描到那个通道结束。
史海拾趣
|
1 引言 所谓中断是指当CPU正在处理某件事情的时候,外部发生的某一事件(如一个电平的变化,一个脉冲沿的发生或定时器计数溢出等)请求CPU迅速去处理,于是CPU暂时中止当前的工作,转去处理所发生的事件。中断服务处理完该事件以后,再 ...… 查看全部问答> |
|
近日,汽车大亨本田宣称与其它公司合作开发出了一种新的脑波识别系统(BMI),这种系统允许控制者单纯通过脑波即可控制机器人运动。该系统是本田和日本政府资助的国际高等电信研究院(ATR)以及一家精密仪器制造商Shimadzu共同开发,系统以三年前发 ...… 查看全部问答> |
|
已经非常成熟的电池技术无法像是依循着摩尔定律(Moore\'s law)的IC那样,继续在能量密度上有所进展;但无可讳言,虽然我们希望电池能储存更多的电能,那也有可能带来其他的安全性风险。各种可携式电子设备都需要电池来供电,诉求环保的电动车若是少 ...… 查看全部问答> |
|
我现在是当发完inquiry命令后,出现bus reset现象,在BUS HOUND出现如下命令后 DO 55 53 42 43 10 84 53 89 08 00 00 00 80 00 0a 25 00 00 00 00 00 00 00 00 00 00 00 00 00 ssts 0e bus reset 就出现bus reset~~~,而且不知为什 ...… 查看全部问答> |
|
我公司一直有大量的(Linux/UNIX) 以及ORACLE中的人才,如有需要,请加 MSN:xuchuang3344@hotmail.com 邮箱:xuchuang@uplooking.com ...… 查看全部问答> |




