DAC,即Digital to Analog Convertor,是数字到模拟转换器,也称为D/A转换器。其核心部分由R-2R电阻网络(也称倒T型电阻网络)、模拟开关和运算放大器组成。它可以将二进制码或BCD码表示的数字量转换为与其成正比的模拟量输出。2 t7 i l. O4 y
( S% t+ @1 X" A5 m# {$ @* XDAC的工作原理主要包括数字信号采样、量化、编码和模拟信号输出几个步骤。首先,将连续变化的模拟信号在一定的时间间隔内进行离散取样,即数字信号采样。接着,对采样后的数字信号进行量化,将其转换为离散的数值。然后,通过编码将量化后的数值进行转换,以便DAC能够识别和处理。最后,DAC将这些数字信号转换为模拟信号输出。
) v" O* m. H s x' v7 h& \
- a9 A" e- d4 E+ X) V) `DAC是数字系统和模拟系统之间的桥梁,具有广泛的应用领域。在音频处理中,DAC被用来将数字音频信号转换为模拟音频信号,以驱动扬声器和耳机,其性能对音频质量有着决定性的影响。在通信系统中,DAC用于将数字信号转换为模拟信号,以实现信号调制和解调。此外,在仪器仪表领域,DAC也被广泛应用于各种测量和控制设备中。" m8 v' `- i; u+ y: t- q# f7 H
* _" f( U9 G4 c- `
' M5 U! f+ ~ r$ l4 \0 O
2 T' v: p. v0 S/ z* B
STM32中的DAC(视芯片而定例如F407ZGT6是2个DAC通道,有些芯片不支持DAC功能)支持12模式的数据输入,可以双通道同时转换。
7 [, J2 A# a1 T+ G; p* C; K4 b4 N, a' k" R3 D0 e; `3 K
本期我们将介绍如何使用STM32F407和CubeMX利用HAL库实现DAC的输出。(本来是想使用C8T6的,结果突然想起来C8T6)没有DAC。4 K6 s4 X6 Z [1 g8 x1 a
: Q' U0 @6 o5 W1 n
CubeMX配置2 o) K7 k6 D1 c& Z/ e
% B+ B, |1 V; H/ l* Z% z' K' m8 E6 O
+ l- i, g* Y' I3 G
8 y2 f x$ w7 U$ _* ^- R在DAC通道中开启DAC,在F407ZGT6中DAC1对应PA4,DAC2对应PA5。+ b! A. N! q; x, Z/ X
5 R9 W5 y7 z5 ~: \
- Y+ v; P2 B- H+ D/ M9 i8 R% w$ z
3 G- M; z' K1 Z, j. \; o$ eOutputBuffer这里设置DAC的输出缓存使能,Trigger是DAC是触发方式,这里我们选择不触发(手动写入)。2 h; F4 p9 @) v, h: M; _
' f; _9 J9 ]3 ^1 X6 b# w& m5 S如果选择触发的话是从缓存区写入数据。: ]. R8 z3 v, I, F
$ f; l7 |+ \3 ~
9 Y7 x1 Q0 y; j$ X
3 h7 [ L6 l7 J1 x" r) U1 A
这里顺带加一路ADC采样,因为手上没有示波器,所以使用ADC来进行查看。- B6 A' B& u1 g) a+ T! f0 E* K
8 P- s3 m5 V7 U# I: A9 ^
这里使用DMA进行采样,具体可以参考公众号之前的关于DMA+ADC采样的内容。! F |" C8 C1 i X7 K* b; l& m. m$ @
/ ?, Q6 b9 N& `, ?, tSTM32的DMA采样+FFT时域分析(STM32F407)
" }, o, b$ v: W7 k, K% [2 Z5 E7 O% F5 L+ R! g5 Z3 J7 y
但是相比于之前的,需要更改一些设置,首先是DMA的设置
3 t! J' G' @0 }
) g+ [& s- v, j# {' v
; u5 w) K# N- ?; y
, u' J0 f9 ?( s/ |! M这里设置单词请求,而不是循环模式防止数据跑飞掉。 W, S ~6 H! I) i7 V6 B6 [- _6 J
3 {$ Y/ L8 n% G# R! m/ m" E9 @( J$ V4 u
- MX_GPIO_Init();
- G0 D) n! d9 `8 O - MX_DMA_Init();
' O3 l1 L( ~; W, g$ P. z - MX_ADC1_Init();9 L9 o6 ~. q$ K2 j. U
- MX_DAC_Init();: G. D2 O: k+ \5 [* k. f
- MX_USART1_UART_Init();
- {: ~6 \+ ~2 D/ r% ~) u6 B3 K! c - MX_TIM1_Init();1 }6 z9 \; A1 O+ \* O- T
- MX_TIM2_Init();
7 p$ H' e( E+ ]/ ?+ b& d - /* USER CODE BEGIN 2 */
5 l3 j4 c) k- j - HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); //用来触发adc采样
) T' C' P+ U, P- Z% K7 o% U - HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AD_Value, ADLenth);//开启ADC1 z1 A+ f6 \) Q2 r
- HAL_DAC_Start(&hdac,DAC_CHANNEL_1);. Q; j* X/ m5 r" H2 _
- /* USER CODE END 2 */
9 ^: C/ g2 U J& q$ X! n
7 f) f8 a, u! L5 ^# g) v- /* Infinite loop */
! s' c/ H1 L0 {) j# D4 X# V* ` - /* USER CODE BEGIN WHILE */
2 l! e2 m, A! n# g+ D5 T - while (1)
% a/ w/ L y# R; D8 h - {: y2 g' f* Y0 G6 Z% ^& }! z
- /* USER CODE END WHILE */
4 m% Y! _2 v% f3 f2 R7 V2 j - ' \. H1 m3 U# R. U
- /* USER CODE BEGIN 3 */& R; T5 D B* {# _8 N* H G' A
- if(!HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0))
/ Y0 r# l2 z: h! _: ?9 J - {
& o9 l% ?# `7 b# H+ U - HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AD_Value, ADLenth);//开启ADC: X& w' D. e/ P* t* r, F: U& w
- 8 n- j. K0 O, C) b) ~, O+ I5 T
- HAL_Delay(20);
% v7 [+ g( y; \0 y -
1 t5 T, ]3 f; ]6 p0 S9 _; w4 a; W - while(!HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0));
3 t' e8 n; V8 q/ H& s3 ~" R% T& r - HAL_Delay(1000);
% J0 Y8 ]! f3 K+ [6 j3 w - for(int i = 0;i<ADLenth;i++)
; l) O2 B' b% o$ m: ? - {) r' q' c+ l" V- V( P. Q
- printf("A:%d\r\n",AD_Value[i]);0 t7 ~+ f. R- y& a9 ?( t
- }
- k6 V! `3 u. m6 L6 o4 g -
% r& x, `; R7 L0 D* U -
+ w o b! j1 `# ~0 s, N - }( T- z1 Y" M- x% @8 M) o
- }3 O: J4 p$ c# [7 f+ q( ?- i, _; b
- /* USER CODE END 3 */
; p6 A2 M& a* ]& d: P6 ^3 W! {# I - }
复制代码
/ h; b+ B) Q8 ]8 E, _8 g8 a% U
5 a1 o0 s0 X+ M3 x9 g我们编写一段代码。
) l6 I3 u+ l- @" G1 W8 R+ y- M! ?4 N! o
按下按键的时候设置DAC的值,开启DMA传输,再加上ADC采样,之后输出结果。! v3 P. p. H; f3 J# R
+ G, ]9 b2 o# X R3 p& U8 o
% F$ w/ c; N- ~/ q3 \
L: B; W6 H9 ~. u; N可以看到,我们按下按键之后,ADC的值会呈阶梯状上升。" W8 H9 k j% j. Y3 `8 i0 ?( L
; s, @# T G- U9 u1 @4 s* ~3 t( G
三角波发生器( k9 d$ C" Y* W. Y4 |8 X
, h8 @" U) S1 H' l3 Z( x8 [
$ ]$ m c0 |* T; ?- r7 H
! q- M5 W0 |" y5 k* m在DAC配置中打开波形发生器,触发方式选择定时器2触发,三角波最大振幅511。0 J4 ^% Y B5 D, _; C
X8 |3 Y/ I+ Y6 G* x1 h
2 \1 {8 |- n1 Q1 U
! ?0 ^' _$ G4 m1 k9 `之后开启定时器2,由于ADC的采样率是1000HZ,因此根据奈奎斯特采样定律,信号的最大频率不能超过500HZ,因此我们使用100HZ的三角波。' z* q5 c3 T9 }. z- w6 n5 @
8 Q2 p9 r* D/ h& }8 {
7 S2 z1 g+ F$ A
& u5 @" S+ P9 m% J
定时器设置好时间之后,设置触发事件。1 r: p& `, h) @; w; E7 \5 B4 n
( [/ Q3 m2 n* X' Y
) N$ a8 L* y. n0 K- h
9 w3 w8 Y8 C/ W9 s: N: ~2 y* {芯片手册中简单的介绍了一下如何计算三角波的频率。当触发信号发生后,内部计数器的值就会+1,所以频率可以用如下公式计算:
# L- a6 N' S, A1 y1 D7 V- [
; d2 g& L8 F$ x9 a定时器频率/分频系数+1/Period/三角波最大值/2
# z: D7 p# G: R4 v: h7 L N7 n3 `& v6 F O
- HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); //用来触发adc采样
) V3 |% N: k* x y. r - HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); //用来触发DAC输出, j5 s: j6 p, z, ?# n5 A
- HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AD_Value, ADLenth);//开启ADC: J+ S* Z0 L" I6 ?# n
- HAL_DAC_Start(&hdac,DAC_CHANNEL_1);) b) j4 O* I9 y8 ?4 m% W6 J
- HAL_DAC_SetValue(&hdac,DAC_CHANNEL_1,DAC_ALIGN_12B_L,0);//设置直流信号
复制代码 - g( M3 e! f8 r' R$ i3 M
8 w' k, m. j$ k$ D
0 h% I2 I% o: W7 Q2 {# M5 \
正弦波发生器
# R) v( }& I3 n# @3 @
; I, k+ H$ h9 Z0 \% q/ f4 ?. X
* z7 L; t. t$ I+ e
/ o" ^1 |; R2 ?* @首先是定时器触发(方便控制频率)。但是关闭波形发生器。
/ `7 w9 K3 C$ L
$ e% w7 y$ ]; a M
1 G$ [- s8 X3 M- ` z" y Y3 ]) x j/ [5 \& @, Q
添加DMA,模式选择循环模式。& D q/ n }6 ?! O9 R6 s
7 z! v# m- a. G2 F0 S. |) N/ C还有改变一下定时器的频率!
. O5 \& V/ M8 S# z! M
% V$ X5 q/ a* p$ A( M) e% W5 ~! Y! |其他几乎不做改变。3 _0 W8 G# ^% a4 q2 d
" a" c m$ R* g. N8 [, L5 b
" Z) n3 S( w" u% E4 z) _$ I _- #define POINTS 256
) S! }0 c7 F7 Y; k7 n T - #define MIN_VALUE 50
6 Y7 p, \) T3 u& n9 m - #define MAX_VALUE 650 ' L, `. }* m. k: B3 L
- #define SCALE ((MAX_VALUE - MIN_VALUE) / 2.0)
7 Y# s4 f. c+ W5 f: z) j, c - #define OFFSET 50 & a& P: W; [0 d+ a% V3 A
- #define M_PI 3.141592652 @" b2 v0 d8 ^5 `; c& j- `: @
- * i( k, e/ N) E' @( y7 F$ ~
- uint16_t SinWaveInt[POINTS];1 V* F6 K" D7 E0 F9 ]; |
- int SinWave[POINTS];
# P( `7 b2 p& p9 z! ] - void SinInit(void)
8 c! E2 F9 V* Y7 I9 X/ @- M - { $ @; v8 L/ n, d6 l# |6 Q6 S5 k
- for (int i = 0; i < POINTS; i++) / m8 b$ l a; \
- { 9 \" @$ ? A9 R" w% R/ u2 }" M
- double x = ((double)i / (POINTS - 1)) * 2 * M_PI; 9 h% O O5 w" l+ B# }
- double sin_value = sin(x); // 计算正弦值 ( D9 y0 g( m2 B
- SinWave[i] = (int)((sin_value + 1) * SCALE + OFFSET);
7 c) P3 d% _& P5 q9 T - SinWaveInt[i] = (uint16_t)SinWave[i];
& b* K- S5 \" V8 A - }% i, o+ N( D5 E; K4 ^( x
- }
复制代码
# a* c" P, v B# e" c/ Q9 V计算一个正弦表。
& o* ?# F; T7 X8 i e
" W! s; U* K5 N- B/ c4 r* w这里的Points决定了分辨率,结合定时器触发频率决定了正弦波的信号。. Z$ E1 T5 ? j- J: I7 E" ` W. [
2 s: C% a5 n; b8 `
; T4 [ \' v3 S# h4 |* Z) R
% d2 O2 v) h1 V2 E5 V& E测试一下正弦表,输出的是正弦信号。7 o% T# o& B8 ^$ `! @0 p0 X6 v% v
5 S i5 t- w5 T7 \- \8 l3 D5 \, O我们之后将正弦信号表导入DMA中。
: `0 H6 w9 H& g# }) \( }
' \! C- ?7 D& B: L, [# H- SinInit();
* Q, d% w$ t: v1 ^* l$ l/ J - HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t *)SinWave, POINTS, DAC_ALIGN_12B_R);
复制代码
7 X- C7 C% m2 Y* H* P正弦表初始化,之后启动DMA传输,导入正弦信号。% O) e" U2 m# B' f! n/ G# G
% q$ j( @, W" m
0 u- I/ j/ B9 p3 `' A
+ j" Y/ R' ?" t$ h
测试正弦信号成功。
. |; C& h8 a! v J% K
0 z0 H( t d2 A3 I" ?- FFM调制- #define POINTS 1024
0 }$ G, `9 X7 u9 T* t - #define MIN_VALUE 50
' I4 t4 h; Q N - #define MAX_VALUE 650
4 g- S3 C" O- G( c% K$ | - #define SCALE ((MAX_VALUE - MIN_VALUE) / 2.0) 2 [# T; o% p! j% S7 l( Z8 A
- #define OFFSET 50 & r# v3 t/ i }& ^% H' U0 a
- #define M_PI 3.14159265
; O# d) V$ Y' _& i7 |7 M5 L% [ -
: |7 ~7 _! c* D/ O - uint16_t SinWaveInt[POINTS];# J+ Q7 b y2 ]9 L* e6 V
- int SinWave[POINTS]; - P% z6 J; q B
- void SinInit(void)
9 A1 c# J: v* v2 \; \$ D _6 ? - {
6 o& S& R" Y/ _7 ?1 G4 U/ n, b - for (int i = 0; i < POINTS; i++)
5 j) w# i+ A, C - { ' S+ T( w$ H5 B7 {& h5 w# M
- double x = ((double)i / (POINTS/4 - 1)) * 2 * M_PI; ' t: [/ v( d5 M) x9 H
- double sin_val = sin(x)*sin(x/4); // 计算正弦值 9 H$ E6 Z1 \* B5 B
- SinWave[i] = (int)((sin_value + 1) * SCALE + OFFSET);
; Y; L3 t. i+ \8 o - SinWaveInt[i] = (uint16_t)SinWave[i]; * k! D7 H0 y$ k: C7 i
- }
- w8 Q4 W2 n6 [& [9 m. D. ~ - }
复制代码
% k: `; ?1 s% j$ n( }; `: z+ a& H& |% r% s4 |' z
拓宽点数,加上载波,即可构成FM调制信号。
: C$ v6 s1 X5 B' F+ h8 e
, {6 }0 z) f1 _# n7 z# |9 i; X
" j, W3 a' i4 @ s
; e1 X' k0 r5 `/ }7 s+ d4 t7 C% u6 ]* t2 U& o% X3 j/ L; z
转载自:电路小白
+ {9 r2 j2 D' W- Q. h% L如有侵权请联系删除, C4 ?0 ?' {# R$ }
& L! M' L l" }; s- w' T
0 ^ l K) J* l/ X5 n4 {' g
# Q( u) c/ Y: q |
资料不错,值得参考学习。
dac+dma?