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

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

[复制链接]
电子星辰 发布时间:2019-1-14 04:17
本帖最后由 电子星辰 于 2019-1-14 17:27 编辑 3 N9 c- B# f/ \& |

8 l1 |0 g- S0 S" A; g! }* O本文在NUCLEO-G071RB核心板平台上,使用CubeMX和HAL库,通过12位ADC,连续DMA采样和不连续转换,单通道(或双通道)采集,DAC连接外部引脚通过DMA输出的一个简易正弦波。最后通过NUCLEO自带的低功耗串口1打印采集到的一个电压。5 G9 B; S/ B; q, M# B$ Z

4 N; F) ^* B# H, Q6 U6 o( Q5 }' o一、Cube设置
' x" _8 j& o# T首先我是通过选择Board新建的工程,所以会有一个NUCLEO外设初始化的选择,可以省点力气。通过MCU新建也是一样的。0 ], ~2 [3 |- M! u! y! Q* S
新建.JPG 初始化.JPG $ M/ t# [* M% J% N
2 S0 {* E4 S1 y  m, d  e: K* ?
其次,RCC、SYS、LPUART都是默认的。
. ^+ x; b, E6 y9 v RCC.JPG
8 c  D* u0 q0 _3 ]  E/ o用SWD下载的话记得勾选“Serial Wire”,要不下载之后就不能再下载了。不过这个板子有个复位跳线帽应该好整,出了问题可以复位下载试试。6 n4 }; j. `# L( y# N3 H- Q
SWD.JPG . z% H! K$ [4 l/ I* h( E) z! e
LPUART1,异步模式自己改下常用参数就行了,“Data Direction”模式选择是我个人只需要发送。+ [. k. ]5 J7 y/ z7 W% A/ f- C
LPUART.JPG
+ d" A  y6 V! Z3 v! C/ M8 S+ B$ ^% w
然后是DAC和定时器。4 {, {8 u* q% b" Z2 e
DAC输出简单点,选择仅连接外部引脚就行了,另一个连接外设的选项就是连比较器之类的。需要通过定时器做触发事件(基本定时器就够了)。
, E: ]. u" N' p5 U, q4 _ DAC.JPG
' e( Z0 M# i$ y- A( @6 ~, NDMA通道不用管,方向是内存到外设。选循环模式,到时候打开了就不用管。“Data Width”选1个Byte就够了,方便点,不用取高低位。3 u0 m: G, Y4 ]6 m! d; q
DAC-DMA.JPG
9 l6 @; ?' g9 Q5 U7 f( h# x  m6 N" }定时器6是基本定时器,我只需要它一个计数触发的功能。
4 L; `6 x* {, T; Y' ePrescaler是定时器预分频,定时器实际时钟频率为:主频/(Prescaler+1),
7 k6 A4 Z- M( d0 C8 l* [5 f  RCounter Period是定时器周期,当定时器开始计数到Counter Period值并且重复计数寄存器(Repetition Counter)为0时更新定时器并生成对应事件和中断,
4 n8 V7 W3 o: A2 \. u最终定时器频率计算为: 主频/(Prescaler+1)/(Repetition Counter+1)/(Counter Period+1(也可能不需+1)),比如需要产生20ms周期定时,可以设置为:64MHz/(63+1)/(0+1)/(19999+1)=50Hz,即20ms周期。我现在设置16位定时器的最大数,64分频的话就是65.535ms。0 I! q( v; d" w+ t4 D( c
time.JPG
; I) r# {8 N& ]& N+ W- k9 g0 U+ s( `
9 g; i6 E9 x- S% L) c- Y接着是ADC,我写了2个通道(但是只用了其中1个)。我没有选连续转换和DMA连续请求,所以在程序里还需要循环开启ADC转换。ScanConvMode扫描转换,是根据你的转换通道数自动设置的,转换序列中如果有超过一个通道需要转换的话,那么必须开启扫描模式,否则的话,时钟只转换第一个通道。
, [, ?( j! h( ]$ A4 N ADC1.JPG ADC2.JPG - m( z" C. @# J3 F/ p  c: l
DMA通道不用管,方向从外设到内存。选的半字“Half Word”,代码里还需对取的值取低12有效位(因为上面ADC参数我是右对齐)。
- }$ {5 @, m6 ]- S3 v3 g ADC-DMA.JPG
+ d* A* @1 n6 ~4 W
7 P; v1 V' r7 f0 |" Y- d/ _! E1 B9 ~; X: o& Q. D0 u
HCLK改为64后直接回车,它会自动配置。
. d" d+ i: K+ o8 w9 `' q% e 时钟.JPG
* V" q+ y5 @4 L$ O, y
$ V+ ^9 d* i; H2 h: W6 ]最后是结果,一共6个值,0.04、0.66、1.33、1.98、2.63、3.27。符合我的预期。我的输出值是0x0,0x33,0x66,0x99,0xCC,0xFF。
0 Z( @1 X+ k  _- K 串口显示.JPG 0 y2 v$ G7 g5 ?

0 j. P8 F4 h- c  x% c7 L" u9 a- y3 f
8 N% [+ U6 f4 w9 U7 Q
  1. /* USER CODE BEGIN PD */$ g7 Y& x% g9 A* I9 `# q
  2. #define ADC_SAMPLE 2//采样数2 D: y8 y6 t& h8 o* D
  3. /* USER CODE END PD */& _( r( H3 r* X" `: S
  4. / Y5 Y9 q5 ~1 I2 \4 C
  5. /* USER CODE BEGIN PV */
    4 q' x8 v; k' i# K8 G0 y
  6. __IO uint16_t ADC_ConvertedData[ADC_SAMPLE]={0};//DMA取得的ADC值; _! h; l* z, i# F/ Z) v) w
  7. const uint8_t aEscalator8bit[6] = {0x0,0x33,0x66,0x99,0xCC,0xFF};//DAC输出量表0 F; a4 m1 ?2 }% {  K
  8. /* USER CODE END PV */0 Y( R9 f& k* K; u* S# k
  9.   t% F  H7 r4 I- V8 {! P- d
  10. /* Private function prototypes -----------------------------------------------*/
    6 v* r# S! a4 N3 U' r3 _) s0 ~
  11. void SystemClock_Config(void);
    ; I$ A& [# s2 v- _# h$ Y
  12. /* USER CODE BEGIN PFP */. |, n' }3 K8 S8 k. i' E" F! V
  13. int main(void)
      w; v1 a# t) O7 V
  14. {' C' i* t* g6 a" V/ C; u3 g5 ~1 E1 g2 V
  15.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */5 Y5 \9 [, G9 i6 s' J3 P
  16.   HAL_Init();; s+ h2 u& v3 c" y+ X4 K+ T# t# e0 X
  17.   /* Configure the system clock */% S1 a( g2 Q/ \: C5 W
  18.   SystemClock_Config();
    " L5 n4 M* k/ c: @/ I7 _5 O
  19.   /* Initialize all configured peripherals */
    * Z& e/ H/ L' T" b8 a- v6 a
  20.   MX_GPIO_Init();
    * D+ K+ o: |/ b8 X# r
  21.   MX_DMA_Init();
    & Q4 |, ?" W5 _
  22.   MX_DAC1_Init();
    ! b2 D6 X/ E) n( Q9 a
  23.   MX_TIM6_Init();! v/ j2 ?8 ?! f0 H) _' p
  24.   MX_ADC1_Init();* ^- w! |% q5 {, P
  25.   MX_LPUART1_UART_Init();" K8 o; L& M  p
  26.   /* USER CODE BEGIN 2 */# v7 \2 ~! r2 _: ^( ]3 `
  27.         HAL_ADCEx_Calibration_Start(&hadc1);//ADC自校验
    2 E" d- T. @+ v# e. u0 y
  28.         HAL_ADC_Start_DMA(&hadc1,(uint32_t *)ADC_ConvertedData,ADC_SAMPLE);//启动AD转换并使能DMA传输和中断。ADC_ConvertedData的两个元素都是通道0的值
    4 a8 f: u7 D, A# t
  29.   HAL_TIM_Base_Start(&htim6);//开启定时器6进行触发. t5 G" V( _5 f6 t* }0 _9 ^
  30.         HAL_DAC_Start_DMA(&hdac1,DAC_CHANNEL_1,(uint32_t *)aEscalator8bit,6,DAC_ALIGN_8B_R);//启动DAC-DMA输出,循环输出6个8bit数        - ]* ?" j% p# i
  31.   /* USER CODE END 2 */+ K. z6 X6 c: Y' Z5 k% t) j( R3 E. ?

  32. 2 |( |% o4 w1 s1 ]1 e1 D3 Q4 B
  33.   /* Infinite loop */9 K4 S, Z: |( @5 U3 \
  34.   /* USER CODE BEGIN WHILE */6 ^/ F7 s, b9 m3 [3 v7 {
  35.   while (1)& \$ S% I. V  H" T* I- R
  36.   {        
    + c$ b, m  C0 I# |6 r
  37.                 printf("%.2f ",((ADC_ConvertedData[0] & 0xFFF)*(3.3/4096)));//串口不是重点,这个用法可能有隐患。取有效位和换算一起进行
    . C3 |2 I, ~' p- I1 r
  38.                 HAL_ADC_Start(&hadc1);//因为是不连续转换,需重复开启+ l( n0 h: w# X$ `
  39.     /* USER CODE END WHILE */
    - [0 P" `+ Y  {( W' G! Y
  40. $ K0 S% Y* C# Z* _
  41.     /* USER CODE BEGIN 3 */
    % M! p# @* `1 e  m5 Y
  42.   }
    % F; d5 [$ E1 l2 b% d  D
  43.   /* USER CODE END 3 */6 R* N  Q; F) |3 ]+ d2 g& Y, T$ P
  44. }
复制代码

5 z& s& a, \% X1 f" G. Q. f. {, F* Q( F& q/ w* n
好了,文末放下资料。
0 d0 M7 x" y" B, e* a# r( Q" A源代码和Cube工程: NUCLEO-G071_DACandADC.rar (7.98 MB, 下载次数: 1524)
收藏 评论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% q4 Z9 ], n! H9 V
精度如何啊?
  \+ c9 S# N; `8 w$ N$ S+ `
我家里的万用表很老了,精度我这测不了。不好说不好说
电子星辰 回答时间:2019-1-14 17:29:58
Kevin201707 发表于 2019-1-14 09:25: ?2 L, m; a" t2 X0 R
DAC能输出0V和轨电压吗(带输出缓冲)?
2 C" C# ^% j; H* x# [$ F
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 手机版