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

【经验分享】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开发指南库函数版本)$ ^: A( X& u! D0 {( j/ S
1596066-20190220221637971-485884485.png 1 x$ @. v* I# q+ C. J# k& e
- B7 |3 K% I0 L& d$ `2 B( ]6 Q. Y

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

ADC相关的寄存器
. h9 Y! k* v- |0 Q0 J( g- f" cADC_CR1
3 ?/ P9 ?# q+ Q! b& N各个位描述如下图:! d+ y: f0 N) m  g$ |/ c& n( X* C

1 a$ ]# j  p6 v, T+ P# M% x8 L, m* I, n 1596066-20190220125934517-1018400293.png 8 H" N; J! M' _
  • scan位:% z* n1 w: v0 D4 ?
    设置扫描模式,1为使用扫描模式,0则关闭.扫描模式下,有ADC_SQRx或ADC_JSQRx寄存器选中的通道被转换,此时如果设置了EOCIE或JEOCIE,则只有在最后一个通道转换完毕后才会产生EOC或JEOC中断
  • DUALMOD位:6 _. n/ Q# a1 \3 Q
    设置ADC的操作模式,详细的看下面的来自<<stm32中文参考手册>>截图
    + ^7 ~: q! h# ?" I7 V: y$ f* @
1596066-20190220125006848-1345393600.png
% w9 U2 w3 f# T" t, A: l7 v6 e' d: A9 m; y: R: Q$ o: v1 g
ADC_CR2
! J0 \; Z) Q9 r6 |& u8 u% s
各个位描述如下图:
' t: I( H* H  W; E 1596066-20190220125225219-294969131.png
  • ADON位:用于开关AD转换器
  • CONT位:用于设置是否进行连续转换,使用单次转换CONT位必须设置为0.
  • EXTSEL[2:0]:用于选择启动规则转换组转换的外部事件* k6 M3 X. z5 `8 o7 e
    1596066-20190220125542983-2020545141.png
    - c9 W8 R5 C: ?8 r如果需要使用软件触发,就将这三个位设置为 111: }2 _6 ?: @" z# h2 l( ?. q( ?
ADC采样事件寄存器(ADC_SMPR1和ADC_SMPR2)
0 \4 g' \. k; Y$ U0 G/ _1 g6 ~各个位描述如下图:+ |8 e8 a5 a5 R4 b1 b% H- e3 O4 s
这两个寄存器用来设置通道0~17的采样时间,每个通道要占3位.

: w" k' Q, C4 y! B4 {& k 1596066-20190220130118600-68854333.png
( O( [2 |/ k" H# G
对于每个要转换的通道,采样时间尽量长一点,以获得较高的准确度,但是会降低ADC的转换速率.ADC的转换时间可以由以下公式计算:
Tconv = 采样时间 + 12.5周期
ADC规则序列寄存器(ADC_SQR1~3)
这几个寄存器功能都差不多,不一一详细说明了.
1596066-20190220130800779-2131325589.png
+ s. |; c9 R+ l0 i2 W/ B
  • L[3:0]:用于存储规则序列的长度) U0 }' }/ N+ {; M0 r4 M
ADC数据寄存器(ADC_DR)
这个没什么好说的,用来存放AD转换后的结果
要注意可以通过ADC_CR2的ALIGN位设置这个寄存器是左对齐还是右对齐
ADC状态寄存器(ADC_SR)
没啥好说的,保存了各种状态,看图吧.
1596066-20190220131727247-1744214194.png
* e  `; R" Q; b) S8 |( U4 p
  _. m  ~3 A1 ?

通过库函数配置ADC1通道1进行AD转换
查看手册可以知道ADC1通道1对应着PA1,如下图
, \4 ^& J) K8 D- i& R9 `0 j+ G/ r$ V& Q$ Q
1596066-20190220185340169-812432818.png
7 S" z! O' I8 D" B8 @
4 w& e" K5 b' O5 j1.外设使能
  • STM32F103ZET6的ADC通道1在PA1上所以我们先要使能 PORTA的时钟 和 ADC1时钟,然后设置 PA1为模拟输入.
    0 z* c" C* F( \" r3 F
& L$ s( O9 p0 C. }
2.复位ADC1,同时设置ADC1的分频因子
  • 开启了ADC1的时钟后,要复位ADC1,将ADC1的全部寄存器重设位缺省值,然后通过RCC_CFGR设置ADC1的分频因子,并且分频因子要确保ADC1的时钟不超过14MHz!3 U1 ~8 U, L8 Z* ]8 y0 k
    //ADC复位 ADC_DeInit();
    - n5 B. y& Q: i/ k  J3 rRCC_ADCCLKConfig(RCC_PCLK2_DIV6); //设置分配因子的库函数
    6 Q' y' _; @3 b& {( x+ G' `

8 H2 B' d. c, b0 j# S
3.初始化ADC1参数,设置ADC1的工作模式以及规则序列的相关信息.9 ^, \0 C: x+ T
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);// ADC初始化

6 H9 W7 ?/ o( c) k% I
4.使能ADC并校准
6 b1 G( Z: R$ Y0 A: H7 kvoid ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState); //使能指定的ADC
. _) n- X# l3 C: x% cvoid ADC_ResetCalibration(ADC_TypeDef* ADCx);//复位校准/ P4 K  L5 L" L7 [8 p
while(ADC_GetResetCalibrationStatus(ADCx));//等待复位校准结束0 A. b  d% `0 x" i. ?* A+ p$ e
void ADC_StartCalibration(ADC_TypeDef* ADCx);//执行ADC校准) G4 d( d+ q  b8 F
while(ADC_GetCalibrationStatus(ADCx));//等待AD校准结束
. @9 n6 D+ c8 F/ s9 e2 p" [1 |
5.设置规则序列1里面的通道,读取ADC的值
# p* a/ v6 z1 d+ i6 x, T9 Kvoid ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); //设置规则序列通道以及采样周期
" d1 @6 o4 D, V+ h5 X  \void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);//允许软件开启ADC转换4 c6 p% M2 D/ w. w& e0 Q+ A
while(!ADC_GetFlagStatus(ADCx,ADC_FLAG_EOC));//等待转换结束; h' e+ }' c' ]- o7 t9 |
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);//获取转 换结果数据
5 {) [( d$ B! n) Z, X% k
MDK5中实现代码
  • 配置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()函数;

    7 G; J  s+ }# V! y8 k, {7 [
总结库函数配置ADC的步骤
1.使能需要用到的GPIO 和 ADC的时钟;2 X& ?8 t" z; T) u6 ]8 R
2.配置ADC的时钟分频:
: F2 `8 w7 j# p% e5 i( V: gvoid RCC_ADCCLKConfig(uint32_t RCC_PCLK2);! H6 Q9 `9 Y6 m6 |$ T
2.配置IO口,输入模式为 GPIO_Mode_AIN,模拟输入模式;
! o5 r# g6 r+ f( H3 v* Y4 i3.调用 ADC_DeInit(); 对ADC进行复位;
, A3 N- Z- D; G" J! v9 ~4.调用 ADC_Init();初始化ADC! p. @, s1 K  {* ?1 U' F5 n2 z$ t
5.调用 ADC_Cmd(ADCx,ENABLE);,使能ADC
4 E5 i! @* A$ {& }& ]' o6.校准ADC:; H" w! l0 ]& Q8 e8 d
ADC_ResetCalibration(ADC1); //复位校准 while(ADC_GetResetCalibrationStatus(ADC1));//等待复位校准完成 ADC_StartCalibration(ADC1); //ACD校准 while(ADC_GetCalibrationStatus(ADC1)); //等待ADC校准完成3 S$ E8 z% G" |7 B5 U" d- ~
7.获取AD转换的结果

. F" A! F! D' H5 x; }! Z  j
: ~# F( a- j8 K) F
1596066-20190220124325888-1041525534.png
收藏 评论0 发布时间:2022-1-28 18:36

举报

0个回答

所属标签

相似分享

官网相关资源

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