DAC,即Digital to Analog Convertor,是数字到模拟转换器,也称为D/A转换器。其核心部分由R-2R电阻网络(也称倒T型电阻网络)、模拟开关和运算放大器组成。它可以将二进制码或BCD码表示的数字量转换为与其成正比的模拟量输出。) H. O$ O, d$ x J+ `1 t# H
( \" o2 z) Z: P: R+ J0 F
DAC的工作原理主要包括数字信号采样、量化、编码和模拟信号输出几个步骤。首先,将连续变化的模拟信号在一定的时间间隔内进行离散取样,即数字信号采样。接着,对采样后的数字信号进行量化,将其转换为离散的数值。然后,通过编码将量化后的数值进行转换,以便DAC能够识别和处理。最后,DAC将这些数字信号转换为模拟信号输出。7 t; e! E+ I7 I( B% t t% X
1 I( `2 k# X0 bDAC是数字系统和模拟系统之间的桥梁,具有广泛的应用领域。在音频处理中,DAC被用来将数字音频信号转换为模拟音频信号,以驱动扬声器和耳机,其性能对音频质量有着决定性的影响。在通信系统中,DAC用于将数字信号转换为模拟信号,以实现信号调制和解调。此外,在仪器仪表领域,DAC也被广泛应用于各种测量和控制设备中。, i9 u# }# P5 N$ }3 t
0 O( J, a: K( ?! V5 V
D" D/ Q! k4 u/ b' Q% P+ c0 o3 @' e" ?& }7 T8 r/ y
STM32中的DAC(视芯片而定例如F407ZGT6是2个DAC通道,有些芯片不支持DAC功能)支持12模式的数据输入,可以双通道同时转换。. l$ S" O2 A: V
4 }# G1 T) I7 k本期我们将介绍如何使用STM32F407和CubeMX利用HAL库实现DAC的输出。(本来是想使用C8T6的,结果突然想起来C8T6)没有DAC。
7 Y- A) m: h: h2 f$ e% D7 S
: s2 x3 ?5 J7 M9 n! FCubeMX配置
7 @# F$ g& D* u e! c- l: n3 m, L5 u6 G* b {+ T' c" w
3 `. c4 A2 F% V) I* M4 R2 ~) h
[* Z* O: _3 F- s" Q, W1 I在DAC通道中开启DAC,在F407ZGT6中DAC1对应PA4,DAC2对应PA5。
* s& w; k0 s6 Y, O7 C! C5 K+ J+ g% p, m
* R$ T. C' ^5 C; l/ a' ~7 n
4 K, l5 v7 e- [2 ]$ YOutputBuffer这里设置DAC的输出缓存使能,Trigger是DAC是触发方式,这里我们选择不触发(手动写入)。, o: ?1 A( O1 W( I4 r
8 v* ~ ]1 K2 n8 z如果选择触发的话是从缓存区写入数据。
: e, f/ |" p$ F& ]) O) i5 U e* K" c# S* E
/ y+ Z ~! u7 n% Z( b, x
9 {9 c+ s1 s% p+ a0 I, g |: o这里顺带加一路ADC采样,因为手上没有示波器,所以使用ADC来进行查看。. B. ~( m/ K* L% _- P) Z9 n p7 f
, M& I9 C9 C. I7 \& \2 `这里使用DMA进行采样,具体可以参考公众号之前的关于DMA+ADC采样的内容。
t+ B: l% z( S% ~
8 z4 E+ U# [( {9 `: v. a( J: LSTM32的DMA采样+FFT时域分析(STM32F407)% P* _* @5 D" y; ~8 ?, j+ ?* n
/ `, Y( c5 Q5 V' ]但是相比于之前的,需要更改一些设置,首先是DMA的设置1 v$ A7 n, v, a2 p5 n# a6 N) [
+ L0 ^3 v4 w5 V9 V( m$ ~6 ^* a
6 y9 b: r9 G# q0 o8 I% b
; l) N7 W1 }# X1 s. Q这里设置单词请求,而不是循环模式防止数据跑飞掉。! g8 A. D1 t7 ^1 V3 X! s* B/ |5 Q
0 J2 ^/ V" L: F/ A) f0 _, r6 N& ~/ P3 U" [ b Z8 }. J
- MX_GPIO_Init();/ a8 w! v4 l0 p0 T: W$ Z
- MX_DMA_Init();
' F; S) `9 R+ `4 K0 ^: }5 E, g - MX_ADC1_Init();
: ]0 I9 k8 c2 l4 }( b - MX_DAC_Init();
, ]8 _$ x) p& M - MX_USART1_UART_Init();
& X! p' S, e; w6 j4 J8 t - MX_TIM1_Init();
1 Z, {/ H! j' s! P - MX_TIM2_Init();
, m7 p7 ~, W+ S [! J8 p" |8 n - /* USER CODE BEGIN 2 */( A# ~, O' ?7 J" _
- HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); //用来触发adc采样 8 `: @0 T& x) Y' D1 p' U
- HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AD_Value, ADLenth);//开启ADC
$ r+ U3 G1 Z4 { - HAL_DAC_Start(&hdac,DAC_CHANNEL_1);7 Z5 p. u, A0 T/ F* y: E0 Q- S% o
- /* USER CODE END 2 */1 @. R# i; o0 H
- : }/ R4 h" @3 ^9 [: y I( f
- /* Infinite loop */4 p7 e! l4 j: q- ?
- /* USER CODE BEGIN WHILE */
) n$ `; T: i' @8 S U - while (1)4 X& f0 s; r- w" t4 C
- {0 V6 {1 ]; A/ \8 P- c7 D
- /* USER CODE END WHILE */
' P) a$ {! z$ k& _ |( T* N
; b% e" a- e* w- L* ^6 B6 P- /* USER CODE BEGIN 3 */
2 X; n9 o$ Q) f: a4 W. Z - if(!HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)): _ J* L5 R, J6 o: l. ^
- {
+ b% S- M0 [, E - HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AD_Value, ADLenth);//开启ADC5 l$ ~0 F9 G/ i4 z
- 0 T9 W! p* Q6 S n8 s5 Y" \7 S
- HAL_Delay(20);
5 X( M5 R ]4 p) g! e/ D+ x! o -
+ \. C y+ [% [, t2 w - while(!HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0));, {9 l- j, G ~
- HAL_Delay(1000);( L3 m8 U7 u/ n- B
- for(int i = 0;i<ADLenth;i++)
( Y# ~) s5 Y6 f) k" | - {2 R! p# _! G: Y9 K; V
- printf("A:%d\r\n",AD_Value[i]);
, z# o+ x9 J8 r J# a - }
) e/ l3 Z2 G# m% C% i4 `/ |3 H -
9 e) o. D; S! V7 {" @ -
& U9 n4 H! K. u; P* A - }
; F$ y# Q! X- o! s% }; [6 v - }
' f: E0 N- P+ s' P - /* USER CODE END 3 */
4 a. e7 F: |! O6 o3 r - }
复制代码 4 y6 }% z' m* z# X6 ~6 Z/ ^
! f2 F3 P7 }7 E我们编写一段代码。
# ]7 x2 d: F2 ^; H M5 Z7 j l4 v1 D1 B; h9 p
按下按键的时候设置DAC的值,开启DMA传输,再加上ADC采样,之后输出结果。
W' Y2 h c0 b( G- P( e( t2 z, H
H3 n( G6 A& l! a3 d; z+ R
7 u1 m5 G$ s; V9 m6 T& e; W3 d
可以看到,我们按下按键之后,ADC的值会呈阶梯状上升。
, ]0 q+ D9 B0 F# T3 i
2 F3 p- v; G, x三角波发生器
/ q; s' h0 G4 {6 Z0 C; V) w
$ h3 O- }! X' W- K; o
! ?$ B: \! ~/ O- q2 M. L' u3 b
. b) s* P3 G( {
在DAC配置中打开波形发生器,触发方式选择定时器2触发,三角波最大振幅511。
1 t7 n! {. \- a+ B9 l
, `5 V! f! a; [6 J; \: B5 {
) \- M: Q4 n- M* V+ V T
4 u# S7 n% x- W4 w4 z( `! y# n2 m
之后开启定时器2,由于ADC的采样率是1000HZ,因此根据奈奎斯特采样定律,信号的最大频率不能超过500HZ,因此我们使用100HZ的三角波。
. \& q) M% @' x; p7 Q3 F9 H8 x; V7 W/ z- w
/ I* v6 g) n( K) S/ A0 \) ]" e, B. O* e9 C% d n' w5 [
定时器设置好时间之后,设置触发事件。
, r3 @( C9 q2 d2 ~% R) b4 r" e& m" B5 f) q* v
: e- T$ p* ]; H3 I6 ?7 R
# l, x, {2 H- k0 m4 Z. o% |5 `芯片手册中简单的介绍了一下如何计算三角波的频率。当触发信号发生后,内部计数器的值就会+1,所以频率可以用如下公式计算:
; `9 D$ N7 J1 P& F+ W, t7 @
y& e4 ?2 I5 ?5 O) n定时器频率/分频系数+1/Period/三角波最大值/2
3 [- Y- [7 t* f9 c7 [3 o! j" @+ O. E/ z' Q4 i0 ~* S% ~8 n7 _
- HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); //用来触发adc采样
3 h1 f) L- u4 x - HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); //用来触发DAC输出7 e% k- P0 r/ @ K
- HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AD_Value, ADLenth);//开启ADC; b* v; E* C% ]9 P
- HAL_DAC_Start(&hdac,DAC_CHANNEL_1);
' u- X& a6 s; u; j5 \) x8 i - HAL_DAC_SetValue(&hdac,DAC_CHANNEL_1,DAC_ALIGN_12B_L,0);//设置直流信号
复制代码
; H" R$ S1 {8 R. e( ]" c4 |3 S& z# w+ b
; T% X! U1 w0 a3 t+ T3 ^$ f; |+ ~
# ^! U3 \9 B+ J7 W正弦波发生器 q: M. N; I* N$ W; h1 b' j* X, l6 L: t/ }9 }
9 J8 }7 t2 v4 i- r
- X. ~& g. o7 J7 x3 S
; V0 P" A* {: [. m% F" X
首先是定时器触发(方便控制频率)。但是关闭波形发生器。
+ K9 V) {' c1 P5 Z8 a
# q- g( f. l& g1 i4 J
4 V: n6 F! z% J$ K% N, C/ K( S, a, h! i( s/ M/ D8 l( Y
添加DMA,模式选择循环模式。, T% _6 v9 s6 p/ i# `" ~8 k
0 U! N0 \& k0 h
还有改变一下定时器的频率!1 k. L2 H6 v' f2 O" z# [/ s
7 R& A8 A7 m" Z5 f( o% D其他几乎不做改变。
1 p+ t+ ^; t. ~( T- A& A0 ~
. ^( o5 O8 T5 |- g- p
+ Z7 a- t. [! W Q: |& r# O& f# y5 Z- #define POINTS 256
; O6 V4 }' u8 _ k: | f. t - #define MIN_VALUE 50 / p( ?8 g# k7 x I. u* _
- #define MAX_VALUE 650 - Q3 e) h( [2 X- I+ z* t9 a
- #define SCALE ((MAX_VALUE - MIN_VALUE) / 2.0)
) }$ B2 q2 @/ x - #define OFFSET 50
( z: T3 c' q* X+ e8 v - #define M_PI 3.14159265
4 D+ ]' }5 o# l; m( V. B -
$ a- b/ e- a0 t* \! G% W5 Y4 ~& m7 W - uint16_t SinWaveInt[POINTS];: X/ n* j' _2 i! j; ^
- int SinWave[POINTS];
1 k2 c7 E; u" ~ - void SinInit(void)
7 K5 Z7 t9 j% k" V' d/ r - {
; i# g O/ j# [ - for (int i = 0; i < POINTS; i++)
+ Q G: ?6 q6 _+ Z' e! G, D7 e; h - {
^3 Q$ n( E4 b# G O - double x = ((double)i / (POINTS - 1)) * 2 * M_PI;
2 e. p- O- j4 o7 u$ \+ n - double sin_value = sin(x); // 计算正弦值
" e7 C; h: D! L - SinWave[i] = (int)((sin_value + 1) * SCALE + OFFSET);
6 T- ?6 v9 A, w: v9 W - SinWaveInt[i] = (uint16_t)SinWave[i];
' f; p |4 s l6 y t - }
" k1 a7 e& ~$ y) k) R% M. l - }
复制代码 ! ]( t3 B4 w8 R
计算一个正弦表。0 g7 M3 I8 }/ Q, o- L3 M) J h
6 H5 A9 k! d2 e$ [* J这里的Points决定了分辨率,结合定时器触发频率决定了正弦波的信号。0 s2 _ K. \$ {" s. ~9 B7 [
$ e$ W) ?$ Z5 L
5 ~: I# t3 S- v/ ` v$ n3 h3 w
* Z3 w) H% Z% S* H% @
测试一下正弦表,输出的是正弦信号。
8 J+ D2 y! M# A$ P
, W+ L' I8 a0 B$ j! m) ]我们之后将正弦信号表导入DMA中。9 B7 o" y% a! A" |, S- |
' T2 b8 z% O# k$ V/ v" L. ]- SinInit();" p( I- m) v T5 p' W9 b% a( E7 l
- HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t *)SinWave, POINTS, DAC_ALIGN_12B_R);
复制代码
8 \1 Y* Z1 W$ }正弦表初始化,之后启动DMA传输,导入正弦信号。: f( a; P6 ]: X* P/ P, r( s* w! w
# q! Q8 E9 B$ N- P8 W& a5 i" n! d
3 i9 d( |5 N' \& }) ?+ V( J$ L2 u* x% w; P) C. g& A
测试正弦信号成功。* F9 m+ l* i G# ]9 D' ~ S. g- {
- V( ^. ^6 }' `# X r) FFM调制- #define POINTS 1024
) K$ D' {) K, v: a( ~' T - #define MIN_VALUE 50
0 h9 e6 S7 ~+ D# p - #define MAX_VALUE 650
: q4 T5 P- C3 f: ^1 N- m - #define SCALE ((MAX_VALUE - MIN_VALUE) / 2.0)
3 U% L; ~5 }6 U: O4 P0 W. d7 V - #define OFFSET 50
5 \7 |1 T, W) q - #define M_PI 3.14159265: j2 j# @# ?1 X1 D( v
-
* G4 C* m0 {+ w4 w7 D) S: q - uint16_t SinWaveInt[POINTS];
9 o2 }1 b9 h; M% N' X - int SinWave[POINTS]; 4 e- B, {; S ~
- void SinInit(void) 1 \# A! P0 K$ f5 H+ s8 y) m
- { ( p. \6 ]0 n$ N" A6 u# \
- for (int i = 0; i < POINTS; i++)
Q+ h4 i& M# i$ F1 U - { ' E" m, U2 m o. R: t
- double x = ((double)i / (POINTS/4 - 1)) * 2 * M_PI;
) F t g" W6 K! h! \, w" y - double sin_val = sin(x)*sin(x/4); // 计算正弦值 2 c+ N0 d, J) M
- SinWave[i] = (int)((sin_value + 1) * SCALE + OFFSET);
; {2 `' B: O3 `; I2 x) r - SinWaveInt[i] = (uint16_t)SinWave[i];
4 [+ a5 D. K6 m* Q - }5 y% g5 ?" `% ^- z4 K( ~+ h
- }
复制代码 : B8 f2 }9 o' N& S- j$ O+ d
+ s1 L9 K6 m$ |3 [/ s f. }
拓宽点数,加上载波,即可构成FM调制信号。
' @) N7 i6 p# `. J/ o
+ G% t" p1 ^# K' z) l3 Y
/ b' Q/ \, g* j" I
7 A: T! w b" v$ P6 d
8 J$ F. ?8 s! y. S7 D转载自:电路小白) U6 U0 k+ o! Z8 i5 r
如有侵权请联系删除. o0 F' k% W7 s2 z
" e+ U; b3 m9 u3 I
( a4 ]1 Z: k7 y& `
# i( n5 n f) G7 b! j7 M' M! J |
资料不错,值得参考学习。
dac+dma?