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

【经验分享】Stm32 ADC学习

[复制链接]
STMCU小助手 发布时间:2022-1-28 18:36
stm32 ADC 简介
stm32的ADC是 12位逐次逼近型 模拟数字转换器;它包括18个通道,可以用来测量16个外部通道和2个内部通道.ADC转换的结果存放在16位数据寄存器(ADC规则数据寄存器,ADC_DR 和 ADC注入数据寄存器,ADC_JDCx)中,这个数据寄存器可以设置对齐方式为左对齐或右对齐.
ADC通道与GPIO对应表(图片来自整点原子STM32F1开发指南库函数版本)
( j" E9 k1 [) K 1596066-20190220221637971-485884485.png 2 D7 A) w6 v* c1 a# m
9 p: C9 w" P8 K  [5 S

规则通道组和注入通道组
注入通道可打断规则通道的转换
所谓规则通道组和注入通道组其实应该就是通道的分组吧,按照OOP的思想来理解,通道组是一个基类,注入通道组和规则通道组派生自通道组这个基类,通道组这个基类中包含了一个保存各个通道的数组.
为什么要对通道进行分组呢,这个有待深究,以后再说.

ADC相关的寄存器
2 Y& V% K, O  C+ b0 aADC_CR1/ Q9 u1 L; r6 b
各个位描述如下图:- p, K+ \* q, v# R0 B1 v; s& B
4 C: a: |) q; _7 _: Y% i" \1 R7 _
1596066-20190220125934517-1018400293.png 0 [" a/ a1 z0 b8 c
  • scan位:
    % e4 S- ~8 e6 ~4 P" a设置扫描模式,1为使用扫描模式,0则关闭.扫描模式下,有ADC_SQRx或ADC_JSQRx寄存器选中的通道被转换,此时如果设置了EOCIE或JEOCIE,则只有在最后一个通道转换完毕后才会产生EOC或JEOC中断
  • DUALMOD位:# B$ A) T; Y' H- A% N5 {
    设置ADC的操作模式,详细的看下面的来自<<stm32中文参考手册>>截图/ R7 w; }3 n4 ?2 x1 H6 y
1596066-20190220125006848-1345393600.png . U: B6 U; a( w% x% `

8 G& y( Y3 p! ?& G+ RADC_CR2
/ Z8 H6 {0 |& O7 J
各个位描述如下图:: u; s6 _! O0 m  ?7 d
1596066-20190220125225219-294969131.png
  • ADON位:用于开关AD转换器
  • CONT位:用于设置是否进行连续转换,使用单次转换CONT位必须设置为0.
  • EXTSEL[2:0]:用于选择启动规则转换组转换的外部事件
    3 P2 }6 H8 G" l$ {8 W 1596066-20190220125542983-2020545141.png   I) x; m# A( i/ L. A( D
    如果需要使用软件触发,就将这三个位设置为 1116 ?3 e1 ?. F# ^8 G1 b7 s! R
ADC采样事件寄存器(ADC_SMPR1和ADC_SMPR2)0 Z4 }& y/ s) }
各个位描述如下图:, S/ f, @& }$ ]( O) X- k
这两个寄存器用来设置通道0~17的采样时间,每个通道要占3位.

8 r5 Q: |) _1 |& h6 h 1596066-20190220130118600-68854333.png
1 O6 m: i6 P$ j0 @
对于每个要转换的通道,采样时间尽量长一点,以获得较高的准确度,但是会降低ADC的转换速率.ADC的转换时间可以由以下公式计算:
Tconv = 采样时间 + 12.5周期
ADC规则序列寄存器(ADC_SQR1~3)
这几个寄存器功能都差不多,不一一详细说明了.
1596066-20190220130800779-2131325589.png
& ^* X, w3 y. J2 J1 `! y+ w
  • L[3:0]:用于存储规则序列的长度
    ! T6 z- q1 `! _1 w6 R
ADC数据寄存器(ADC_DR)
这个没什么好说的,用来存放AD转换后的结果
要注意可以通过ADC_CR2的ALIGN位设置这个寄存器是左对齐还是右对齐
ADC状态寄存器(ADC_SR)
没啥好说的,保存了各种状态,看图吧.
1596066-20190220131727247-1744214194.png
. J! {: X& c9 q$ O; S0 @' G, F! J
1 x8 }4 N8 K( W5 |: K

通过库函数配置ADC1通道1进行AD转换
查看手册可以知道ADC1通道1对应着PA1,如下图7 o& Z  I4 z4 ~4 B0 |) J

1 [# i( X; S% s- u/ F
1596066-20190220185340169-812432818.png 4 C- v1 K; f9 y$ w  P; G( Y

6 Y6 z9 ~) ?7 Z( A! s1.外设使能
  • STM32F103ZET6的ADC通道1在PA1上所以我们先要使能 PORTA的时钟 和 ADC1时钟,然后设置 PA1为模拟输入.' R* ~3 ]' N" L) }. ^
4 [4 C. L7 ~/ F7 N/ D
2.复位ADC1,同时设置ADC1的分频因子
  • 开启了ADC1的时钟后,要复位ADC1,将ADC1的全部寄存器重设位缺省值,然后通过RCC_CFGR设置ADC1的分频因子,并且分频因子要确保ADC1的时钟不超过14MHz!
    . l  {6 C8 K7 a( A/ @' S& }* M* a//ADC复位 ADC_DeInit();5 {5 Y  }, C. l2 V- b# x2 U
    RCC_ADCCLKConfig(RCC_PCLK2_DIV6); //设置分配因子的库函数
    # c4 E( g- V. r$ c! g

1 ~0 [3 Z. |5 |# a
3.初始化ADC1参数,设置ADC1的工作模式以及规则序列的相关信息.. H, d* W$ a; n1 z, N& ^; c$ v$ U
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);// ADC初始化

5 Y) C8 }* a6 k3 c
4.使能ADC并校准
: N1 E0 f7 W0 K, g9 z, Y3 O1 l& u! evoid ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState); //使能指定的ADC# \0 r8 ?% D7 ?' w1 l
void ADC_ResetCalibration(ADC_TypeDef* ADCx);//复位校准
1 t( _0 [! V$ K6 `while(ADC_GetResetCalibrationStatus(ADCx));//等待复位校准结束5 D8 q- j' z( i" W# T
void ADC_StartCalibration(ADC_TypeDef* ADCx);//执行ADC校准
0 u' C# P+ b5 [7 awhile(ADC_GetCalibrationStatus(ADCx));//等待AD校准结束
3 T" }; x* |$ q" m8 T% g" @. i( o
5.设置规则序列1里面的通道,读取ADC的值
+ H: m9 _% Q. ]8 x+ K  a9 ^! b9 fvoid ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); //设置规则序列通道以及采样周期6 t6 i  \! i6 Y& Z
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);//允许软件开启ADC转换
  i# m3 B" P" Vwhile(!ADC_GetFlagStatus(ADCx,ADC_FLAG_EOC));//等待转换结束
' U: E' Z! a4 d& B2 E5 \uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);//获取转 换结果数据

# S1 m1 t% f+ ]: g8 x, yMDK5中实现代码
  • 配置stm32f103库函数编程环境,我用的是正点原子的那一套,不多记录了;
  • ADC1_Init() 函数
    void ADC1_Init(void)
  • ADC_GetConvValue()
    u16 ADC_GetConvValue(u8 channel)
  • ADC_GetAverageConvValue()
    u16 ADC_GetAverageConvValue(u8 channel,u8 times)
  • ADC_SampleValue2ReadableValue()
    double ADC_SampleValue2ReadableValue(u16 sampleValue)
  • main.c文件代码
    main.c
  • 在main.c中使用的 USART_WriteLine(const char*str,...)函数 是我自己封装的串口函数,也可以使用正点原子 System文件夹 下提供的printf()函数;
    * C+ P0 Z1 u* @" ?% `4 R$ W; P* n
总结库函数配置ADC的步骤
1.使能需要用到的GPIO 和 ADC的时钟;) Y' s/ S: x3 K) V, W
2.配置ADC的时钟分频:
' w0 `$ b( W& `( Q) A. A) ^void RCC_ADCCLKConfig(uint32_t RCC_PCLK2);& G0 g; T4 |+ Q/ ?) M  C( R
2.配置IO口,输入模式为 GPIO_Mode_AIN,模拟输入模式;
/ D' g( I/ z% ]% ?' b/ Z+ x3.调用 ADC_DeInit(); 对ADC进行复位;
' w& O: b# k0 w! f. N4.调用 ADC_Init();初始化ADC7 W- E2 x8 \+ }) }) @) P5 r
5.调用 ADC_Cmd(ADCx,ENABLE);,使能ADC, ^/ F/ }  x& f) ~
6.校准ADC:+ O6 p6 P# ], @/ J
ADC_ResetCalibration(ADC1); //复位校准 while(ADC_GetResetCalibrationStatus(ADC1));//等待复位校准完成 ADC_StartCalibration(ADC1); //ACD校准 while(ADC_GetCalibrationStatus(ADC1)); //等待ADC校准完成: s# k6 E$ ~: M5 n
7.获取AD转换的结果

, k* C/ h  I# h0 y" p  ?1 Q) b4 e* Q8 z. S# }- b
1596066-20190220124325888-1041525534.png
赞 收藏 评论0 发布时间:2022-1-28 18:36

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版