你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32F103单片机ADC功能使用

[复制链接]
STMCU小助手 发布时间:2022-3-20 13:37
  stm32f103系列单片机内部ADC为12位ADC。
12位ADC是一种逐次逼近型模拟数字转换器。它有多达18个通道,可测量16个外部和2个内部
信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右
对齐方式存储在16位数据寄存器中。
模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。
ADC的输入时钟不得超过14MHz,它是由PCLK2经分频产生。

ADC 主要特征

● 12位分辨率

● 转换结束、注入转换结束和发生模拟看门狗事件时产生中断

● 单次和连续转换模式

● 从通道0到通道n的自动扫描模式

● 自校准

● 带内嵌数据一致性的数据对齐

● 采样间隔可以按通道分别编程

● 规则转换和注入转换均有外部触发选项

● 间断模式

● 双重模式(带2个或以上ADC的器件)

下面就用代码演示如何设置ADC单次转换模式

  1. void ADCx_Init(void)
  2. {
  3.     GPIO_InitTypeDef GPIO_InitStructure;
  4.     ADC_InitTypeDef ADC_InitStructure;

  5.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_ADC1, ENABLE);
  6.     RCC_ADCCLKConfig(RCC_PCLK2_Div6);                                        //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M

  7.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1| GPIO_Pin_2| GPIO_Pin_3| GPIO_Pin_4| GPIO_Pin_5;                                //PA1
  8.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;                        //模拟输入
  9.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  10.     GPIO_Init(GPIOA, &GPIO_InitStructure);

  11.     ADC_DeInit(ADC1);

  12.     ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;                //工作在独立模式
  13.     ADC_InitStructure.ADC_ScanConvMode = DISABLE;                        //单通道模式
  14.     ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;                //单次转换模式
  15.     ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //软件触发
  16.     ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;         //右对齐
  17.     ADC_InitStructure.ADC_NbrOfChannel = 1;                                        //规则转换ADC通道数
  18.     ADC_Init(ADC1, &ADC_InitStructure);

  19.     ADC_Cmd(ADC1, ENABLE);                                                //使能ADC1

  20.     ADC_ResetCalibration(ADC1);                                        //复位校准
  21.     while(ADC_GetResetCalibrationStatus(ADC1));        //等待复位校准结束
  22.     ADC_StartCalibration(ADC1);                                        //开启AD校准
  23.     while(ADC_GetCalibrationStatus(ADC1));                //等待校准结束

  24. }
复制代码

  首先初始化IO口,这里的初始化的是ADC抓换通道的0–5,对应的IO口PA0到PA5,将这6个IO口这是为模拟输入模式。接下来在将这几个口设置为ADC口,在设置之前首先将ADC模式复位,然后将ADC设置为单通道单词转换模式,也就是每次只转换一个通道,转换一次后就停止转换,直到接收到下一次转换命令为止。开始转换的命令是由软件来设置的。

  ADC口初始化好之后,还需要一个读取转换结果的函数,用于读取指定通道的转换值。

  1. //获取ADC值
  2. //ch:通道号
  3. u16 Get_Adc( u8 ch )
  4. {
  5.     ADC_RegularChannelConfig( ADC1, ch, 1, ADC_SampleTime_239Cycles5 );        //ADC1,ADC通道,采样时间为239.5周期
  6.     ADC_SoftwareStartConvCmd( ADC1, ENABLE );                                                        //使能ADC1软件启动转换
  7.     while( !ADC_GetFlagStatus( ADC1, ADC_FLAG_EOC ) );                                        //等待转换结束
  8.     return ADC_GetConversionValue( ADC1 );                                                                                                                        //返回最近一次ADC1规则组的转换结果
  9. }

  10. u16 Get_Adc_Average( u8 ch, u8 times )
  11. {
  12.     u32 temp_val = 0;
  13.     u8 t;
  14.     for( t = 0; t < times; t++ )
  15.     {
  16.         temp_val += Get_Adc( ch );
  17.         delay_ms( 5 );
  18.     }
  19.     return temp_val / times;
  20. }
复制代码

Get_Adc()函数用于读取指定通道的ADC转换值,这里的通道必须是初始化函数中初始化过的通道,这个函数每次只读取一次通道值,为了确保转换结果的正确性,需要多次读取通道值取平均值,所以这里Get_Adc_Average()函数就是用来设置多次读取指定通道值,然后取平均值后返回。比如可以设置读取通道1,100次然后取平均值。ADC相关的设置函数就初始化好了,接下来在主函数中调用Get_Adc_Average()函数就可以读取通道值了。

  1. int main(void)
  2. {
  3.     u16 adcx = 0;
  4.     float temp;
  5.     delay_init();                       //延时函数初始化
  6.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  7.     uart_init(115200);
  8.     LED_Init();


  9.     LED0 = 1;
  10.     LED1 = 1;
  11.     delay_ms(500);
  12.     LED0 = 0;
  13.     LED1 = 0;

  14.     ADCx_Init();

  15.     printf("ADC test!!!\r\n");
  16.     while(1)
  17.     {
  18.         adcx = Get_Adc_Average(ADC_Channel_0, 10);
  19.         printf("ch0       num: %d\r\n", adcx);
  20.         temp = (float)adcx * (3.3 / 4096);
  21.         adcx = temp * 1000;
  22.         printf("ch0 adc value: %d\r\n", adcx);

  23.         adcx = Get_Adc_Average(ADC_Channel_1, 10);
  24.         printf("ch1       num: %d\r\n", adcx);
  25.         temp = (float)adcx * (3.3 / 4096);
  26.         adcx = temp * 1000;
  27.         printf("ch1 adc value: %d\r\n", adcx);

  28.         adcx = Get_Adc_Average(ADC_Channel_2, 10);
  29.         printf("ch2       num: %d\r\n", adcx);
  30.         temp = (float)adcx * (3.3 / 4096);
  31.         adcx = temp * 1000;
  32.         printf("ch2 adc value: %d\r\n", adcx);

  33.         adcx = Get_Adc_Average(ADC_Channel_3, 10);
  34.         printf("ch3       num: %d\r\n", adcx);
  35.         temp = (float)adcx * (3.3 / 4096);
  36.         adcx = temp * 1000;
  37.         printf("ch3 adc value: %d\r\n", adcx);

  38.         adcx = Get_Adc_Average(ADC_Channel_4, 10);
  39.         printf("ch4       num: %d\r\n", adcx);
  40.         temp = (float)adcx * (3.3 / 4096);
  41.         adcx = temp * 1000;
  42.         printf("ch4 adc value: %d\r\n", adcx);

  43.         adcx = Get_Adc_Average(ADC_Channel_5, 10);
  44.         printf("ch5       num: %d\r\n", adcx);
  45.         temp = (float)adcx * (3.3 / 4096);
  46.         adcx = temp * 1000;
  47.         printf("ch5 adc value: %d\r\n", adcx);

  48.         LED0 = !LED0;
  49.         delay_ms(500);
  50.     }
  51. }
复制代码

在主函数中依次读取通道0到通道5的值,读取10次取平均值,然后将转换后的值打印出来。由于ADC为12位,所以转换后的最大值为4096,对应的最大电压值为3.3V,为了方便观察,将转换后的值换换位电压值。


收藏 评论0 发布时间:2022-3-20 13:37

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版