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

NUCLEO-G071RB-DAC和ADC的简单应用

[复制链接]
电子星辰 发布时间:2019-1-14 04:17
本帖最后由 电子星辰 于 2019-1-14 17:27 编辑
0 N  ^4 j* ]( k8 i; L; q
2 D2 O6 V6 q" N- @) ?' M& n本文在NUCLEO-G071RB核心板平台上,使用CubeMX和HAL库,通过12位ADC,连续DMA采样和不连续转换,单通道(或双通道)采集,DAC连接外部引脚通过DMA输出的一个简易正弦波。最后通过NUCLEO自带的低功耗串口1打印采集到的一个电压。
0 ]% k' t9 n5 _6 w7 N5 W2 Y! {2 A& M6 ]9 X
一、Cube设置
* T* l. d/ V* T8 B' @& K4 ~, N' C首先我是通过选择Board新建的工程,所以会有一个NUCLEO外设初始化的选择,可以省点力气。通过MCU新建也是一样的。# ^" p5 g! S# \; K
新建.JPG 初始化.JPG
( |& f! X3 {: E4 f
, z5 G5 V( ]  M/ g# o其次,RCC、SYS、LPUART都是默认的。
" _; N, d/ }- M4 u, [$ A; L RCC.JPG 7 S& \* g- }" T
用SWD下载的话记得勾选“Serial Wire”,要不下载之后就不能再下载了。不过这个板子有个复位跳线帽应该好整,出了问题可以复位下载试试。8 z- N, f! u+ N& c
SWD.JPG 3 A5 y6 S4 l4 K% x
LPUART1,异步模式自己改下常用参数就行了,“Data Direction”模式选择是我个人只需要发送。. Q) F/ d, e4 G, E# C' G& F- _
LPUART.JPG
, @& c. {$ {7 y# \; n1 r: [! }- o+ W# N) Y' I
然后是DAC和定时器。8 t3 \- U! ]* `/ C* \
DAC输出简单点,选择仅连接外部引脚就行了,另一个连接外设的选项就是连比较器之类的。需要通过定时器做触发事件(基本定时器就够了)。( M3 O" O) P4 s
DAC.JPG $ U# `/ w: W3 E; V) ~2 a% G
DMA通道不用管,方向是内存到外设。选循环模式,到时候打开了就不用管。“Data Width”选1个Byte就够了,方便点,不用取高低位。
5 I  c# D; s; u( M* D5 |. R DAC-DMA.JPG
( s3 ]+ |; g  M8 y" K8 t7 S* T定时器6是基本定时器,我只需要它一个计数触发的功能。/ [4 F9 d0 F$ ]/ f6 i
Prescaler是定时器预分频,定时器实际时钟频率为:主频/(Prescaler+1),7 d) F& X' ]4 v+ F
Counter Period是定时器周期,当定时器开始计数到Counter Period值并且重复计数寄存器(Repetition Counter)为0时更新定时器并生成对应事件和中断,
5 a. Z+ }9 q2 f! Z# L3 p  D, R$ u3 q最终定时器频率计算为: 主频/(Prescaler+1)/(Repetition Counter+1)/(Counter Period+1(也可能不需+1)),比如需要产生20ms周期定时,可以设置为:64MHz/(63+1)/(0+1)/(19999+1)=50Hz,即20ms周期。我现在设置16位定时器的最大数,64分频的话就是65.535ms。
# a" E1 d$ i( B$ u1 m5 `6 D" B time.JPG # F' i0 H* {. i# M. v; n/ G
! `9 k# ?; v" f3 K" f
接着是ADC,我写了2个通道(但是只用了其中1个)。我没有选连续转换和DMA连续请求,所以在程序里还需要循环开启ADC转换。ScanConvMode扫描转换,是根据你的转换通道数自动设置的,转换序列中如果有超过一个通道需要转换的话,那么必须开启扫描模式,否则的话,时钟只转换第一个通道。1 b" f8 f, [  {( ]- C
ADC1.JPG ADC2.JPG
# Q! j8 a, v, b- j1 LDMA通道不用管,方向从外设到内存。选的半字“Half Word”,代码里还需对取的值取低12有效位(因为上面ADC参数我是右对齐)。5 [) \% q: k7 X; c9 n* d. ]
ADC-DMA.JPG - v/ J- h! r4 w
& p7 f# }: L: u5 t* i% C3 @
  W! U$ [/ y) c! d9 ?9 K& L: `) g
HCLK改为64后直接回车,它会自动配置。. c6 \! j, X2 M6 _
时钟.JPG
( v4 s- ~3 m: V. Z) N; m3 l7 r! g% U  }& f+ D# A  p
最后是结果,一共6个值,0.04、0.66、1.33、1.98、2.63、3.27。符合我的预期。我的输出值是0x0,0x33,0x66,0x99,0xCC,0xFF。3 R  L- |" h9 y& R7 g; Z
串口显示.JPG " e, {5 X0 ^8 M: j  v8 t
- Q8 _3 F* C/ L* x3 Y7 k: }
" x2 k* d, p  H) u% M  D. Z

) a8 r; B/ ?6 V, f8 @
  1. /* USER CODE BEGIN PD */3 @! A! ^4 N3 i" o& x$ q
  2. #define ADC_SAMPLE 2//采样数$ E$ e, C$ m. z. W8 l
  3. /* USER CODE END PD */+ D" E' U/ p; K0 g5 u0 ]1 Y
  4. . J" ?$ M' s* X% c( y) Y, M
  5. /* USER CODE BEGIN PV */
    5 p! s- [* e: w$ P
  6. __IO uint16_t ADC_ConvertedData[ADC_SAMPLE]={0};//DMA取得的ADC值( v! Q9 u) }) y! U
  7. const uint8_t aEscalator8bit[6] = {0x0,0x33,0x66,0x99,0xCC,0xFF};//DAC输出量表
    . a- E& O. A' \2 B4 H
  8. /* USER CODE END PV */
    3 B* a% p* v5 i6 z  H0 m: ]

  9. 4 r" D' O- {7 O- I4 n) N4 p7 v4 J
  10. /* Private function prototypes -----------------------------------------------*/
    / U+ h, {! a( j
  11. void SystemClock_Config(void);
    $ a% F! `4 E2 \. k* I0 c
  12. /* USER CODE BEGIN PFP */6 }( K  [  C9 `# g9 X1 S% q( l
  13. int main(void)
    / S1 ]2 V) Z0 k
  14. {9 b: ^% n% H/ Q
  15.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    . f. k: N3 B' {/ O
  16.   HAL_Init();
    " b( E$ X# V- G
  17.   /* Configure the system clock */
    0 g9 B0 N& _; M: u( L
  18.   SystemClock_Config();' I7 [2 n* K2 s
  19.   /* Initialize all configured peripherals */
    0 d) V; y  t( b, I" e2 J
  20.   MX_GPIO_Init();% G# `2 H. `7 [1 V7 d; n
  21.   MX_DMA_Init();
    1 C) A& @; P9 h9 T" E: N/ \- \- M
  22.   MX_DAC1_Init();4 r- {" }" ^" Z, T* b: X. V+ v0 v
  23.   MX_TIM6_Init();
    ! [' ^* L, y6 L/ P
  24.   MX_ADC1_Init();
    % q2 Y+ X9 I" X
  25.   MX_LPUART1_UART_Init();
    . p& y4 z2 S& ]
  26.   /* USER CODE BEGIN 2 */3 }8 T; r& x. H; ^( D2 v. V/ o
  27.         HAL_ADCEx_Calibration_Start(&hadc1);//ADC自校验
    % D% Y* T, w" e  F
  28.         HAL_ADC_Start_DMA(&hadc1,(uint32_t *)ADC_ConvertedData,ADC_SAMPLE);//启动AD转换并使能DMA传输和中断。ADC_ConvertedData的两个元素都是通道0的值
    " y  O; `  q5 K" Z3 Y3 ?
  29.   HAL_TIM_Base_Start(&htim6);//开启定时器6进行触发9 ^9 W9 M) j! _3 j' w8 w$ m5 w
  30.         HAL_DAC_Start_DMA(&hdac1,DAC_CHANNEL_1,(uint32_t *)aEscalator8bit,6,DAC_ALIGN_8B_R);//启动DAC-DMA输出,循环输出6个8bit数        * {) B1 b) E) u! o
  31.   /* USER CODE END 2 */; K. n6 |  i2 [0 e' j3 F. a# Q
  32. " u  j+ I  U* h% j' A0 B
  33.   /* Infinite loop */
    ( e- P8 k1 W3 I
  34.   /* USER CODE BEGIN WHILE */' u8 b0 _5 Q& W1 C9 L+ R
  35.   while (1)8 e& J3 S( t$ m: Z% I5 v! w
  36.   {        
    . t$ z' Y; C( D- u( d# n9 i
  37.                 printf("%.2f ",((ADC_ConvertedData[0] & 0xFFF)*(3.3/4096)));//串口不是重点,这个用法可能有隐患。取有效位和换算一起进行/ ?( T, X5 H$ a) I4 y1 _) x
  38.                 HAL_ADC_Start(&hadc1);//因为是不连续转换,需重复开启
    ( H: H2 X8 {1 a% h/ i" I
  39.     /* USER CODE END WHILE */
      ~8 l$ y1 ?5 B; \3 M) o

  40. ; ~* ?- S- c- l
  41.     /* USER CODE BEGIN 3 */: {. t& i" P; f" \
  42.   }6 V" Y! P$ G3 V. s7 f
  43.   /* USER CODE END 3 */$ r  \1 I9 S- `* O( @$ n1 z
  44. }
复制代码
- \! d1 Q9 ]2 q8 [  C! o# o
. q9 C: \: l$ L
好了,文末放下资料。
! O' Q0 D% U* i! Z! F源代码和Cube工程: NUCLEO-G071_DACandADC.rar (7.98 MB, 下载次数: 1523)
收藏 评论7 发布时间:2019-1-14 04:17

举报

7个回答
STM1024 回答时间:2019-1-14 08:24:30
精度如何啊?
Kevin_G 回答时间:2019-1-14 09:25:55
DAC能输出0V和轨电压吗(带输出缓冲)?
电子星辰 回答时间:2019-1-14 17:28:41
stm1024 发表于 2019-1-14 08:24' }, o: M5 ?, P" B
精度如何啊?
! M& e) X* u4 g" I5 R- ^) T
我家里的万用表很老了,精度我这测不了。不好说不好说
电子星辰 回答时间:2019-1-14 17:29:58
Kevin201707 发表于 2019-1-14 09:25% R9 q. h- X' R* M
DAC能输出0V和轨电压吗(带输出缓冲)?
4 g/ }2 e8 I7 Y- x6 u4 N6 D! y
DAC输出来的是近似0V的值,比如说零点零几V。缓冲的话我是开的内部缓冲。
Kevin_G 回答时间:2019-1-15 09:51:17
STM32其他系列DAC输出可以达到轨电压,但是DAC驱动能力很弱,如果打开内部缓冲器,可以提升驱动能力,但是缓冲器输出无法达到轨电压(0V或VDDA)。
≯断了线的风筝≮ 回答时间:2019-8-13 20:22:48
请问是否遇到ADC不准,AD值会波动的情况,与实际值差了0.几v
阿拉蕾 回答时间:2019-10-17 13:27:45
很不错
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版