历史上的今天
返回首页

历史上的今天

今天是:2025年02月12日(星期三)

正在发生

2020年02月12日 | STM8的ADC的五种工作模式

2020-02-12 来源:elecfans

STM8的ADC的五种工作模式


STM8的ADC是10位的逐次比较型模拟数字转换器,多达16个多功能的输入通道。拥有5种转换模式,转换结束可产生中断。


STM8 ADC的初始化顺序如下:


1、AD输入通道对应的IO设置为上拉输入;


2、配置AD参数,如:预分频系数、是否使用外部触发转换、是否使用施密特触发器、是否使用缓存以及是否使用扫描模式等;


3、开启ADC;


4、开启转换;


注意!开启ADC和开启转换实际上都是置位ADON。


然后就可以通过ADC_DR寄存器读取转换后的值。



l 单次模式:


在单次转换模式中,ADC仅在由ADC_CSR寄存器的CH[3:0]选定的通道上完成一次转换。该模式是在当CONT位为0时通过置位ADC_CR1寄存器的ADON位来启动的。


一旦转换完成,转换后的数据存储在ADC_DR寄存器中,EOC(转换结束)标志被置EOCIE 被置位将产生一个中断。


注意!初始化的时候只能选择一个通道。转换多个通道只能通过反复重新初始化或扫描模式!


示例程序:


void  adc_init(void)


{  


GPIO_Init(GPIOD,GPIO_PIN_3,GPIO_MODE_IN_PU_NO_IT);//AIN4 IO设置为上拉输入


  ADC1_PrescalerConfig(ADC1_PRESSEL_FCPU_D2);//预分频2


  ADC1_ExternalTriggerConfig(ADC1_EXTTRIG_TIM,DISABLE);//不使用外部触发


  ADC1_SchmittTriggerConfig(ADC1_SCHMITTTRIG_CHANNEL4,DISABLE);


  //禁止AIN2 AIN4的施密特触发器,降低IO静态功耗


  //PD5,PD6上的通道如果施密特方式禁用会导致串口无法收发数据!


  


ADC1_ConversionConfig(ADC1_CONVERSIONMODE_SINGLE,//单次转换


                        ADC1_CHANNEL_4,//只能选择一个通道!


                        ADC1_ALIGN_RIGHT);//右对齐


 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值


}


}


l 连续模式与带缓存的连续模式:


在连换模式中,ADC在完成一次转换后就立刻开始下一次的转换。当CONT位被置位时即将ADC设为连续模式,该模式是通过置位 ADC_CR1寄存器的 ADON 位来启动的。


如果缓冲功能没有被使能(ADC_CR3寄存器的DBUF位=0),那么转换结果数据保存在ADC_DR寄存器中同时 EOC 标志被置位。如果EOCIE 位已被置位时将产生一次中断。然后开始下一次转换。


如果缓存功能被使能(DBUF=1),那么某个选定通道上的8个或者10个连续的转换结果会填满数据缓存(此时填满的是同一个通道的数据!!扫描模式时才是不同通道的数据!),当缓存被填满时,EOC(转换结束)标志被置位,如果EOCIE位已被置位,则会产生一个中断,然后一个新的转换自动开始。如果某个数据缓存寄存器在被读走之前被覆盖,OVR标志将置1。


如果要停止连续转换,可以复位清零CONT位来停止转换或者复位清零ADON位来关闭ADC的电源。


示例程序(不带缓存):


void  adc_init(void)


{  


GPIO_Init(GPIOD,GPIO_PIN_3,GPIO_MODE_IN_PU_NO_IT);//AIN4 IO设置为上拉输入


  ADC1_PrescalerConfig(ADC1_PRESSEL_FCPU_D2);//预分频2


  ADC1_ExternalTriggerConfig(ADC1_EXTTRIG_TIM,DISABLE);//不使用外部触发


  ADC1_SchmittTriggerConfig(ADC1_SCHMITTTRIG_CHANNEL4,DISABLE);


  //禁止AIN2 AIN4的施密特触发器,降低IO静态功耗


  //PD5,PD6上的通道如果施密特方式禁用会导致串口无法收发数据!


 


 ADC1_ConversionConfig(ADC1_CONVERSIONMODE_CONTINUOUS, //连续转换


                        ADC1_CHANNEL_4,//只能选择一个通道!


                        ADC1_ALIGN_RIGHT);//右对齐


 ADC1_Cmd(ENABLE);//开启ADC


 ADC1_StartConversion();//开启连续转换


}


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值


}


}


示例程序(带缓存):


void  adc_init(void)


{  


GPIO_Init(GPIOD,GPIO_PIN_3,GPIO_MODE_IN_PU_NO_IT);//AIN4 IO设置为上拉输入


  


ADC1_PrescalerConfig(ADC1_PRESSEL_FCPU_D2);//预分频2


  ADC1_ExternalTriggerConfig(ADC1_EXTTRIG_TIM,DISABLE);//不使用外部触发


  ADC1_SchmittTriggerConfig(ADC1_SCHMITTTRIG_CHANNEL4,DISABLE);


  //禁止AIN2 AIN4的施密特触发器,降低IO静态功耗


  //PD5,PD6上的通道如果施密特方式禁用会导致串口无法收发数据!


 


 ADC1_ConversionConfig(ADC1_CONVERSIONMODE_CONTINUOUS, //连续转换


                        ADC1_CHANNEL_4,//只能选择一个通道!


                        ADC1_ALIGN_RIGHT);//右对齐


 ADC1_Cmd(ENABLE);//开启ADC


 ADC1_StartConversion();//开启连续转换


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的平均值


}


}


注意,只有在连续转换模式下ADC_DB寄存器才能称之为缓存,此时存储的是同一个通道多次转换的值。在单次扫描和连续扫描模式下该寄存器被用来存放不同通道的转换值。


 


l 单次扫描模式:


该模式是用来转换从AIN0到AINn之间的一连串模拟通道,‘n’是在 ADC_CSR寄存器的CH[3:0]位中指定的通道编号(即CH[3:0]里配置第n个通道,就从通道0顺序递增逐个通道进行转换,直到第n个通道结束。例如,CH[3:0]里配置为AIN4,则对AIN0、AIN1、AIN2、AIN3、AIN4进行转换,其他通道不转换)。在扫描转换的过程中,序号 CH[3:0]位的值是被硬件自动更新的,它总保存当前正在被转换的通道编号。


单次转换模式可以在在SCAN 位被置位且CONT 位以被清零时通过置位 ADON 位来启动。


注意:当使用扫描模式时,不可以将AIN0到AINn之间通道对应的I/O口设为输出状态,因为ADC的多路选择器已经将这些I/O口的输出模块禁用了。


对于单次扫描模式,转换是从AIN0通道开始的,而且结果数据被存储在数据缓冲寄存器ADC_DBxR 中(例如,CH[3:0]里配置为AIN4,则ADC_DB0R存放AIN0的转换结果,ADC_DB1R存放AIN1的转换结果,以此类推。 ),当最后一个通道(通道‘n’)被转换完成后,EOC(转换结束)标志被置位,当EOCIE 位已被置位时将产生一个中断。


可以从缓冲寄存器中读取各个通道的转换结果值。如果某个数据缓存寄存器在被读走之前被覆盖,OVR标志将置1。


在转换序列正在进行过程中不要清零SCAN位;单次扫描模式可通过清零ADON位来立即停止。为了开启一次新SCAN扫描转换,可以通过对ADC_CR1寄存器的EOC位清零和ADON位置位来实现。


示例程序:


void  adc_init(void)


{  


GPIO_Init(GPIOC,GPIO_PIN_4,GPIO_MODE_IN_PU_NO_IT);//AIN2 IO设置为上拉输入


  GPIO_Init(GPIOD,GPIO_PIN_3,GPIO_MODE_IN_PU_NO_IT);//AIN4 IO设置为上拉输入


 


ADC1_PrescalerConfig(ADC1_PRESSEL_FCPU_D2);//预分频2


  ADC1_ExternalTriggerConfig(ADC1_EXTTRIG_TIM,DISABLE);//不使用外部触发


  ADC1_SchmittTriggerConfig(ADC1_SCHMITTTRIG_CHANNEL4,DISABLE);


  //禁止AIN2 AIN4的施密特触发器,降低IO静态功耗


  //PD5,PD6上的通道如果施密特方式禁用会导致串口无法收发数据!


  


ADC1_ConversionConfig(ADC1_CONVERSIONMODE_SINGLE,//单次转换


                        ADC1_CHANNEL_4,//配置通道号最大的那个


                        ADC1_ALIGN_RIGHT);//右对齐


  ADC1_Cmd(ENABLE);//开启ADC


ADC1_ScanModeCmd(ENABLE);//开启扫描模式


}


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的值


}


}


 


l 连续扫描模式:


该模式和单次扫描模式相近,只是每一次在最后通道转换完成时,一次新的从通道0到通道n扫


描转换会自动开始。如果某个数据缓存寄存器在被读走之前被覆盖,OVR标志将置1。连续扫描模式是在当SCAN位和CONT位已被置时,通过置位ADON位来启动的。在转换序列正在进行过程中不要清零SCAN位。


连续扫描模式可以通过清零ADON位来立即停止。另外一种选择就是当转换过程中清除CONT位那么转换会在下一次的最后一个通道转换完成时停止。


注意:在扫描模式(连续扫描模式)中,不要使用位操作指令(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表示扫描到那个通道结束。


示例程序:


void  adc_init(void)


{  


GPIO_Init(GPIOC,GPIO_PIN_4,GPIO_MODE_IN_PU_NO_IT);//AIN2 IO设置为上拉输入


  GPIO_Init(GPIOD,GPIO_PIN_3,GPIO_MODE_IN_PU_NO_IT);//AIN4 IO设置为上拉输入


 


  ADC1_PrescalerConfig(ADC1_PRESSEL_FCPU_D2);//预分频2


  ADC1_ExternalTriggerConfig(ADC1_EXTTRIG_TIM,DISABLE);//不使用外部触发


  ADC1_SchmittTriggerConfig(ADC1_SCHMITTTRIG_CHANNEL4,DISABLE);


  //禁止AIN2 AIN4的施密特触发器,降低IO静态功耗


  //PD5,PD6上的通道如果施密特方式禁用会导致串口无法收发数据!


 


  ADC1_ConversionConfig(ADC1_CONVERSIONMODE_CONTINUOUS, //连续转换


                        ADC1_CHANNEL_4,//配置通道号最大的那个


                        ADC1_ALIGN_RIGHT);//右对齐


 ADC1_Cmd(ENABLE);//开启ADC


ADC1_ScanModeCmd(ENABLE);//开启扫描模式


 ADC1_StartConversion();//开启转换


}


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的值


}


}


至此,STM8的ADC的5种工作模式全部介绍完毕。总结一下学习经验就是仔细对照芯片手册编写程序,然后进行仿真调试,观察寄存器中的值的变化,从中领悟手册中的意思。


推荐阅读

史海拾趣

Diodes公司的发展小趣事

Diodes公司积极实施全球化战略,不断拓展海外市场。公司在以色列、加利福尼亚、得克萨斯和日本等地设立了制造工厂,形成了覆盖全球的生产和销售网络。这些工厂不仅为Diodes提供了充足的产能支持,也为公司赢得了更多国际客户的青睐。同时,Diodes还积极参加国际展会和交流活动,加强与国际同行的合作与交流,不断提升公司的国际化水平。

Asian Best Components Co Ltd公司的发展小趣事

品质是Asian Best Components Co Ltd的生命线。公司自成立之初就高度重视品质管理,建立了严格的质量控制体系。从原材料的采购到生产过程的每一个环节,再到产品的最终检验,公司都严格把关,确保每一件产品都符合高标准的质量要求。这种对品质的执着追求,使得Asian Best的产品在市场上赢得了广泛的认可和信赖,也铸就了公司的良好品牌形象。

ENTRELECUK公司的发展小趣事

在电子行业中,绿色环保和可持续发展已成为重要的议题。ENTRELEC UK积极响应这一趋势,致力于研发和生产环保型产品。公司采用环保材料和节能技术,降低产品对环境的影响。同时,公司还积极参与环保公益活动,推动行业的可持续发展。

Colibrys SA公司的发展小趣事

Colibrys SA公司的故事始于2001年,它作为瑞士科技孵化器的衍生公司诞生。瑞士以其精密制造和微机械技术闻名于世,这为Colibrys的起步提供了得天独厚的条件。初期,公司专注于MEMS(微机电系统)技术的研发,凭借对专业知识的深入理解和不懈探索,逐步在行业内崭露头角。

福斯特(FIRST)公司的发展小趣事
ESP系统通常采用CAN总线协议进行数据传输。CAN总线是一种广泛应用于汽车领域的串行通信协议,具有高速、可靠、抗干扰能力强等特点。
Custom Electronics Inc公司的发展小趣事

随着科技的快速发展和市场需求的变化,CEI不断调整自身的发展战略和业务结构。公司加大了对新技术、新产品的研发投入,推动产业结构的升级和转型。同时,CEI还积极探索新的商业模式和市场机会,为公司的可持续发展提供了有力保障。

问答坊 | AI 解惑

Quartus2会取代maxplus2吗?

现在大多数人都在用Quartus2,有没有这种可能。…

查看全部问答>

LPCXpresso 平台工程创建

如下是本人编写的《LPCXpresso 平台工程创建》,可以带不熟悉LPCXpresso 平台的网友快速入门。当然本人也是初学,再加上E文不好,错误难免,望高手们多多指教。…

查看全部问答>

跪求2007年B题无线识别装置

跪求2007年B题无线识别装置,有没有由西安电子科技大学,作者是闵彪 谢胜祥 周涛,赛前辅导老师:谢楷 的相关资料,跪求了!!!!!!!!!!,感激不尽啊…

查看全部问答>

GPS同步时钟怎么做

我现在一点思路都没有。是不是某个元件能从GPS获取时间,用CPU读出这个时间值就可以啊?这某个元件是什么啊? 或者还是有什么别的东西…

查看全部问答>

STM32I2C中断传输方式服务程序,欢迎抛砖。

#define _I2C_DEBUG_#ifdef _I2C_DEBUG_  u32 gAu32Tmp[100];#endif// I2C1中断服务程序.void I2C1_EV_IRQHandler(void){  u32 lu32Event;  static u8 lu8BusyCount&n ...…

查看全部问答>

蜂鸣器使用问题

请问单片机与蜂鸣器、直流电机的接口电路为什么要放大器驱动????…

查看全部问答>

数字接收机码元同步探讨,也称位同步,已经实现仿真探讨结果

正在设计一个数字接收机如下流程,射频(模拟)-->中频-->基带(4FSK调制)-->码元同步-->帧同步。目前实现到码元同步,采用内插滤波器+gardner误差检错算法。模拟25db AWGN 信道,偏离最佳抽判点+-5%--+-15% 经过插值校正后抽判结果 4个电平信号 ...…

查看全部问答>

坚决不用STM,转学Xmega A3U

坚决不用STM,转学Xmega A3U,8 bit就是好…

查看全部问答>

电源测试:稳定性测量

作者:Bob Hanrahan 德州仪器 此前,我已经发表了有关如何测试电源设计的三篇文章中的前两篇,即效率测量(第 1 篇)和噪声测量(第 2 篇)。文章主要涵盖各种噪声源以及如何使用示波器正确测量噪声。此外,我还讨论了由线路及负载瞬态产生的输出 ...…

查看全部问答>

电源设计中几个有关功率因数的误区,校正一下!

一,什么是功率因数校正(PFC)? 功率因数指的是有效功率与总耗电量(视在功率)之间的关系,也就是有效功率除以总耗电量(视在功率)的比值。 基本上功率因数可以衡量电力被有效利用的程度, 当功率因数值越大,代表其电力利用率越高。开关电源供应器 ...…

查看全部问答>