本文介绍STM8L051F3的ADC相关知识。内容分为以下几部分:
1、STM8L的ADC基础知识ADC(Analog-to-Digital Converter):模拟-数字转换,就是把模拟信号转换为数字信号。STM8L051F3的ADC可以执行在单次或连续模式,主要特点如下:
- 可配置的转换精度(最高12位)
- 众多模拟通道
- 两个内部通道连接到温度传感器和内部参考电压
- 可配置单次或连续转换
- 可预分频ADC时钟
- 模拟看门狗
- 在转换结束、看门狗或溢出时间可独立产生中断
- 多通道转换(扫描模式)
- 数据完整性
- DMA功能
- 施密特触发器禁止功能
- 转换时间在系统时钟=16MHz时可达1us
- 电压范围在8V~3.6V:
- 最大的转换率在4V~3.6V中获得
- 8V~2.4V时,ADC处于低速模式
- 低于8V时ADC功能无法保障
ADC开-关控制。ADC可以设置ADC_CR1寄存器的ADON位上电,当ADON位被设置,ADC会从掉电模式下唤醒。ADC转换应该发生在在上电唤醒后最大空闲时间前。当ADON位被复位,ADC将停止转换并进入掉电模式。
单次转换模式。在这个模式下,在ADC_SQRx寄存器中只能选择一个输入通道(如果有多个通道被选择,最高的通道有效),然后ADC_SQR1寄存器的DMAOFF位必须设置(禁止DMA),输入通道转换后就会停止,转换后的值保存在ADC_DR数据寄存器,在转换完成之后可以产生一个(EOC)中断。两次转换的时间必须小于ADC最大空闲延迟(tIDLE)
连续转换模式。在这个模式下,ADC转换完成后不会停止,而是继续进入下一个所选的通道序列,转换持续到CONT位和ADON位被设置和转换结果经过DMA发送到RAM或EEPROM。只有每次所选的通道序列转换完成后EOC中断才会产生,每个通道转换的结果不能从ADC_DR寄存器中读取。为了保存每个通道的转换结果在存储器(RAM或EEPROM)中,DMA必须使用在外设到内存模式,如果在转换过程中CONT位被复位,那么当前选择的通道序列在最后一个选择通道转换完后结束转换,然后ADC停止。
通道选择(扫描模式)。该模式在连续模式下自动工作,也可以通过复位ADC_SQR1寄存器DMAOFF位来工作在单次转换模式。在该模式下,将选择的通道序列(如单次模式)转换完成后经过DMA把数据发送到内存中。在so秒模式下选择通道或者通道的顺序相关的寄存器有三个:ADC_SQR1、ADC_SQR2和ADC_SQR3。
ADC还有时钟配置、模拟看门狗、中断、数据完整性、DMA传送、分辨率配置、数据对齐、可编程的采样时间,施密特触发器、内部的温度传感器、内部的参考电压、低功耗模式、中断等内容,用户可以参考官方手册RM0031的第14章。ADC模块的框图如下所示:
2、ADC单通道软件触发采样2.1 ADC配置本小节介绍如何配置ADC1的通道22(PD0)为单次转换模式模式,软件触发,并把在ADC1上采集的数据在OLED上显示出来。使用的例程:STM8L051F3_11_ADC。在单次模式下ADC1的配置步骤为(非中断模式):
1)打开ADC1外设时钟
2)初始化ADC1通道22的IO口(配置为浮空输入模式)
3)初始化ADC1:单次转换模式,分辨率12位,ADC时钟2分频
4)配置ADC1采样时间
5)打开ADC1通道22
6)使能ADC1
ADC1采样控制步骤如下:
1)启动ADC1转换
2)等待转换结束
3)读取ADC1采样值
2.2 例程介绍ADC1的配置与采样函数都在adc.c文件实现:
ADC1配置函数:
void ADC1_Config(void)
{
//打开ADC1外设的时钟 CLK_PeripheralClockConfig(CLK_Peripheral_ADC1, ENABLE); //配置ADC1的GPIO为浮空输入模式 GPIO_Init(ADC_IN22_GPIO_PORT, ADC_IN22_GPIO_PINS, GPIO_Mode_In_FL_No_IT); //初始化ADC1,单次转换模式,12位分辨率,ADC时钟2分频 ADC_Init(ADC1, ADC_ConversionMode_Single, ADC_Resolution_12Bit, ADC_Prescaler_2); //配置ADC采样时间,384个时钟周期 ADC_SamplingTimeConfig(ADC1, ADC_Group_SlowChannels, ADC_SamplingTime_384Cycles); //打开ADC1的22通道 ADC_ChannelCmd(ADC1, ADC_Channel_22, ENABLE); //使能ADC1 ADC_Cmd(ADC1, ENABLE); }
ADC1采样函数:
uint16_t Read_ADC_Value(void)
{
uint16_t temp; //启动一次ADC转换 ADC_SoftwareStartConv(ADC1); //等待转换结束 while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)== RESET); //读取ADC值 temp = ADC_GetConversionValue(ADC1); //返回ADC值 return temp; }
在主函数中,每300ms采样移植,把采样的ADC值与计算后的值在OLED上显示出来,主函数如下:
void main(void)
{
uint32_t ADC_Value; uint32_t Vol_Value; LED_Init(); //初始化LED IIC_Init(); //IIC初始化 ADC1_Config(); //初始化ADC OLED_Init(); //OLED初始化 OLED_Clear(); //OLED清屏 OLED_ShowString(16, 0, "D-VALUE:"); OLED_ShowString(16, 2, "V-VALUE:"); while(1) { ADC_Value = Read_ADC_Value(); //读取ADC值 Vol_Value =(ADC_Value * 3300 / 4096); //转换为电压值,单位mV OLED_ShowNum(80, 0,ADC_Value, 4, 16); //OELD显示ADC值 OLED_ShowNum(80, 2,(uint16_t)Vol_Value, 4, 16); //OLED显示电压值 GPIO_ToggleBits(LED1_GPIO_PORT, LED1_GPIO_PINS); //改变LED1状态 delay_ms(300); //延迟 } }
使用ST-LINK把程序下载到开发板,LED1闪烁,把PD0口用杜邦线接到VCC可以看到OLED上显示D-VALUE::4096(可能会有一点误差),V-VALUE:3300(可能会有一点误差)。把PD0口用杜邦线接到GND可以看到OLED上显示D-VALUE::0(可能会有一点误差),V-VALUE:0(可能会有一点误差)。注:OLED采用的是技新0.96寸OLED(4PIN),可参考第九章内容。
|