DAC,即Digital to Analog Convertor,是数字到模拟转换器,也称为D/A转换器。其核心部分由R-2R电阻网络(也称倒T型电阻网络)、模拟开关和运算放大器组成。它可以将二进制码或BCD码表示的数字量转换为与其成正比的模拟量输出。
$ R$ p) a: Y0 d6 b' n
& R# F+ U @. r8 s: }. H$ HDAC的工作原理主要包括数字信号采样、量化、编码和模拟信号输出几个步骤。首先,将连续变化的模拟信号在一定的时间间隔内进行离散取样,即数字信号采样。接着,对采样后的数字信号进行量化,将其转换为离散的数值。然后,通过编码将量化后的数值进行转换,以便DAC能够识别和处理。最后,DAC将这些数字信号转换为模拟信号输出。
, \- H- M. N1 q# S
! r: o: D: q( [' I7 hDAC是数字系统和模拟系统之间的桥梁,具有广泛的应用领域。在音频处理中,DAC被用来将数字音频信号转换为模拟音频信号,以驱动扬声器和耳机,其性能对音频质量有着决定性的影响。在通信系统中,DAC用于将数字信号转换为模拟信号,以实现信号调制和解调。此外,在仪器仪表领域,DAC也被广泛应用于各种测量和控制设备中。/ p; N' m+ V# ^) J" P7 _
7 g) p- Z# x5 p5 l# [" E3 ^9 T
# H9 w( B6 M. e- ?; g
5 Z( z5 x5 L3 U' v% `& w9 QSTM32中的DAC(视芯片而定例如F407ZGT6是2个DAC通道,有些芯片不支持DAC功能)支持12模式的数据输入,可以双通道同时转换。
, X7 L( A' j# K3 E' T
' @' M+ M" d* R/ F# K5 |; p8 P本期我们将介绍如何使用STM32F407和CubeMX利用HAL库实现DAC的输出。(本来是想使用C8T6的,结果突然想起来C8T6)没有DAC。: o" j1 Z- @# }) T: N j {
) C3 x9 f& m9 e" L
CubeMX配置
; n$ ^1 d+ ^. L8 ?% C1 s0 A0 _3 @( r j& d3 K) q) `/ K
: G8 ^0 w5 r Y& o! I
" C' Y% W! w0 w在DAC通道中开启DAC,在F407ZGT6中DAC1对应PA4,DAC2对应PA5。
8 `5 z, o/ a" B9 [/ H& m* f8 Z7 d; ^
0 S) o) F6 j& R! Y3 T" M2 ~
( }. G4 y: w0 j' M: M
# I4 n. \, w$ @, y" @5 U
OutputBuffer这里设置DAC的输出缓存使能,Trigger是DAC是触发方式,这里我们选择不触发(手动写入)。
$ F1 v& p$ q! j* U5 w5 d
9 ]5 i3 J6 d7 w如果选择触发的话是从缓存区写入数据。
0 l* @: b$ k2 }9 J) v+ q& O% }+ Y$ W3 h* N4 e
% T4 w4 F% s5 p8 F( J3 F
6 h: E% i2 v& T; K/ K3 ~, d i这里顺带加一路ADC采样,因为手上没有示波器,所以使用ADC来进行查看。) r1 h- `" {$ X0 N; G
3 ~# b& M3 B! B6 |这里使用DMA进行采样,具体可以参考公众号之前的关于DMA+ADC采样的内容。
1 J2 O: c0 u& `1 [+ R0 ^, I! M2 g R+ n% B$ o) b' }
STM32的DMA采样+FFT时域分析(STM32F407)
1 C5 q6 y& s) Y* M, a4 M# x
J% T6 p# |7 \2 C8 p4 ^0 `/ i% n# H但是相比于之前的,需要更改一些设置,首先是DMA的设置
' s0 ^0 ^& d! k% e2 s
/ F# a5 F* P0 I4 C) e: l# m/ S
1 a7 w0 x- a0 ]: h
9 a& I! k$ F1 a% v8 g* W这里设置单词请求,而不是循环模式防止数据跑飞掉。
" W/ a k9 g6 I4 g* c- M+ {# F2 k0 a; P- _% o2 p5 |0 U) K9 W2 f
0 j$ E3 q/ r' F, q, D( a- MX_GPIO_Init();
! ?2 a* Q+ m* H; @' ] - MX_DMA_Init();
5 D) A9 D1 d6 z; K7 n& t - MX_ADC1_Init();
7 W5 s8 {0 J" K - MX_DAC_Init();' C* X/ f% j1 o" e4 |' \2 O
- MX_USART1_UART_Init();: b" V& M' v k: e+ T) g
- MX_TIM1_Init();
+ _9 z2 `8 ^6 j# c8 y - MX_TIM2_Init();& j4 q$ ] t! Y) O$ \3 F
- /* USER CODE BEGIN 2 */
/ F, D( _! _8 q& f8 V8 z - HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); //用来触发adc采样 % ^, V4 ?: {4 S# p
- HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AD_Value, ADLenth);//开启ADC
P7 h; F8 s+ Y - HAL_DAC_Start(&hdac,DAC_CHANNEL_1);. D2 L! R! f, M4 M5 y
- /* USER CODE END 2 */
4 ^+ z( Y! h r - 5 G( D, E9 I: g, M' H% _7 w( t. S
- /* Infinite loop */
0 D- d8 L+ p: S/ W& V+ p7 L - /* USER CODE BEGIN WHILE */
& C# m7 ^* G; k- ~( U! M" s - while (1)
d; s2 l' x, \( w* T. k; O - {
" J- C3 D& b2 R9 M& H( q) y' p* I - /* USER CODE END WHILE */" @9 V% j8 Q4 A
3 F+ v' [/ I# ~3 W: u7 t. u- /* USER CODE BEGIN 3 */
( ]5 l1 W# d" y) F2 N - if(!HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0))
, O0 i& \" x. s6 } - {
7 E6 B5 _; O* ` - HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AD_Value, ADLenth);//开启ADC
; ` p0 g# I8 D - - C3 M% z2 g+ t4 @
- HAL_Delay(20);
& ?% A+ d+ K( q3 Y% S& e -
; Y4 U0 `( k: I - while(!HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0));
( {# D& L; f0 N) S1 |: N/ U8 C- a4 J - HAL_Delay(1000);6 \2 E W7 t4 K2 t7 n! O) b
- for(int i = 0;i<ADLenth;i++)
' M/ H7 c/ h7 z6 [3 W5 Z: w - {
9 |; {, ?6 B3 I& _$ E3 } - printf("A:%d\r\n",AD_Value[i]);, H; q! T4 \8 J
- }$ ~! \. z; S3 K3 Y. C, ^5 V
- " j2 D4 S$ I/ R; h5 ]
-
0 X0 c1 z: ~ K6 O( q3 b - }6 w0 Q3 S8 G' P, Z4 n- F
- }
: N9 W* H3 v& p" ? - /* USER CODE END 3 */; W$ E3 t# {. r5 }' ]; l! l+ ^- P
- }
复制代码
( r0 w0 @! b ]* I
" \8 K6 K: x# m6 H0 G7 `5 T" h ]0 [我们编写一段代码。
% p. g; o0 D# I9 w
( w8 l( `7 L+ F+ a# s按下按键的时候设置DAC的值,开启DMA传输,再加上ADC采样,之后输出结果。* e. ^+ y2 @! [8 U. X' F% b
- u8 r1 [) {) t; K" n9 R2 u
3 M# R! @* w/ `% i/ q& s5 o) k* ~% _" ?1 ?8 b7 j% j* {+ O
可以看到,我们按下按键之后,ADC的值会呈阶梯状上升。8 t5 g/ p( ^& r4 m3 E
0 q' K; _8 A w& |" @0 W" x
三角波发生器9 I# y. @0 f0 p+ Z9 P3 G
# o& C2 G# h% B6 `/ ~
; G7 F" m) K* e( _! _- u7 ?
) Y4 f: |' Y. Y, x3 w, E0 E
在DAC配置中打开波形发生器,触发方式选择定时器2触发,三角波最大振幅511。9 `% c' j! m) B
- e; v5 z/ x% B" p
+ {0 R! x& A! a& U' z* ], x* \6 d' `
之后开启定时器2,由于ADC的采样率是1000HZ,因此根据奈奎斯特采样定律,信号的最大频率不能超过500HZ,因此我们使用100HZ的三角波。* h \$ f# y8 k; j7 Z4 U
$ ~) T9 _; U8 i' q
M* l$ t! ^4 F5 q' a, n
9 d' d0 `1 W* y8 z* [定时器设置好时间之后,设置触发事件。
+ ]: f5 e6 ?* \; F4 {
; ~! Z3 _: Y# e) P/ {& `- ^4 h
6 {; ^; j* B: b; o# M2 t: m, h$ @
- J% h; f# q! o% l7 ~芯片手册中简单的介绍了一下如何计算三角波的频率。当触发信号发生后,内部计数器的值就会+1,所以频率可以用如下公式计算:$ `3 ]1 _! X# D7 F5 m$ J* o2 p7 ]
4 t; r0 I# J1 o
定时器频率/分频系数+1/Period/三角波最大值/2
; \( \& D* G: C/ D' T3 v$ L) ?6 I, F" D/ T
- HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); //用来触发adc采样' W8 M) D9 x9 H
- HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); //用来触发DAC输出
9 C8 K. g' T* I& o; Z) B - HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AD_Value, ADLenth);//开启ADC
3 p4 `5 l/ L2 W d1 m5 R - HAL_DAC_Start(&hdac,DAC_CHANNEL_1);
& e7 g: N) _: } - HAL_DAC_SetValue(&hdac,DAC_CHANNEL_1,DAC_ALIGN_12B_L,0);//设置直流信号
复制代码
# d! K$ [2 I0 d/ _, R( }) [2 G
* S& M# c1 [' [
8 z1 I% L2 j7 G/ r+ J- a0 H
正弦波发生器
8 J: q: r5 V1 p) W' ?' @
) _8 E. s) j5 r2 v
. a5 j6 M& h! c/ l2 [1 \
+ U; g# q! M/ C+ b. j8 ]首先是定时器触发(方便控制频率)。但是关闭波形发生器。$ L+ D: w* [, N; U7 D) s
2 w9 |4 [8 {' h. U
( Z% D# m! g- |4 r$ O+ J: i! x0 C3 z) E7 K
添加DMA,模式选择循环模式。
5 _0 I' p; _; f6 a3 W/ E; m; }) P/ r* e4 c
还有改变一下定时器的频率!
- C p6 k; p2 g+ e$ d! b+ W4 T' F9 b7 a- X% P- g# M; H
其他几乎不做改变。; u' X4 e, M1 @% n* f& V2 z! `
6 v7 k8 ]( ]: `; V
; T6 j4 x3 u. Z7 W+ t" v; c1 h# \- #define POINTS 256
, A6 S$ ?. n7 C) O - #define MIN_VALUE 50
6 ^& ?; J% f- _# e# {3 \& X9 C - #define MAX_VALUE 650 ) n8 U; B( k/ h8 @4 Y( p
- #define SCALE ((MAX_VALUE - MIN_VALUE) / 2.0) ; v& ^5 Z6 @' y! ^) b
- #define OFFSET 50
" w W5 A$ `/ X7 @; N& X8 Q( ` - #define M_PI 3.14159265* S; r. p: J5 V% E! J) j0 G. p
- / ?6 ^9 M! a/ s! i [$ J) S- h
- uint16_t SinWaveInt[POINTS];' Q! y( k) r5 Z& `/ [2 V: `
- int SinWave[POINTS]; ' w# U9 x( x. n3 J" g7 T
- void SinInit(void)
) Y2 L9 y* K) y c8 ^5 d- n - { ' K: W: q8 B/ l% @* g
- for (int i = 0; i < POINTS; i++) 0 R3 j0 D% c4 q* b
- {
1 L- p4 N& D- o( z1 [ - double x = ((double)i / (POINTS - 1)) * 2 * M_PI; , n8 A6 l8 q; z7 k4 B
- double sin_value = sin(x); // 计算正弦值 $ o' f; E* d. s5 V
- SinWave[i] = (int)((sin_value + 1) * SCALE + OFFSET); v/ w+ \4 Z1 J2 Q- n$ @# m, `
- SinWaveInt[i] = (uint16_t)SinWave[i]; , L% C4 {4 K2 @/ r
- }4 l( [7 Y4 ^7 A/ @" q
- }
复制代码 $ B$ H; L7 ~% ^& Z
计算一个正弦表。2 M K+ a5 k* `# T1 a: Z+ W
; B4 I# v7 w5 P2 p( W- w/ h; F- f这里的Points决定了分辨率,结合定时器触发频率决定了正弦波的信号。5 i+ H% m, T O6 \) f" j- [. \
& I5 G: ~7 U2 G+ K
% ?7 K2 D) t: M. X' F( |
5 `) d* x% d1 o& m! [测试一下正弦表,输出的是正弦信号。
# N# ~2 N1 m" j: u# X
3 C5 ?. a) o) D( h# [6 M我们之后将正弦信号表导入DMA中。' t- q: z. L! o( U3 S$ q5 a
" w4 x2 v& A( a Y; Y- SinInit();5 G( Y# X% [6 ?! A6 u8 A% Q3 B+ S- I
- HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t *)SinWave, POINTS, DAC_ALIGN_12B_R);
复制代码
4 O4 @) S; P2 s3 V正弦表初始化,之后启动DMA传输,导入正弦信号。
/ r+ N) R9 b7 ?+ B8 g
9 I2 W' E- c9 ~6 U& D
, ?4 G) R4 v3 P, F$ }, T3 ?
" \, Q$ Q( E& i2 X' f. y( M测试正弦信号成功。3 z# G* S' j1 w. Z0 Q M
2 {; J5 x) Y2 _FM调制- #define POINTS 1024 : Y. A; Y" E- u; U; q- `8 u6 e" y
- #define MIN_VALUE 50
8 v4 L# u& w; @4 R. B' }7 @ - #define MAX_VALUE 650
$ Z* B4 m- i, Q- c1 k - #define SCALE ((MAX_VALUE - MIN_VALUE) / 2.0) / x* u! k& v: I8 M& Z5 l' P
- #define OFFSET 50 / `; P* n& g3 _8 \
- #define M_PI 3.14159265
7 T' _) H4 q' S# a# h -
+ l5 ?7 C# P. B3 K - uint16_t SinWaveInt[POINTS];
: u4 p- p9 f# m- x/ v - int SinWave[POINTS]; " l, J0 P& U0 m; `
- void SinInit(void)
) _4 c1 f0 |. `! B! J4 }0 k, Q - { 0 ~! w; y% r0 J& \7 {- ^
- for (int i = 0; i < POINTS; i++) 3 ^0 N3 H1 Y6 B( f. F, Q, L6 @
- {
7 V5 z- C$ d( Z8 m9 s - double x = ((double)i / (POINTS/4 - 1)) * 2 * M_PI; 6 G% O5 h! g; F4 W* p- z4 T
- double sin_val = sin(x)*sin(x/4); // 计算正弦值
! N! q- E) S6 r4 e" @+ K# Q+ c - SinWave[i] = (int)((sin_value + 1) * SCALE + OFFSET); - T# X' R/ l) V
- SinWaveInt[i] = (uint16_t)SinWave[i]; * A, R2 V, V6 ]: k7 ^
- } i/ o6 W/ k, f4 V v
- }
复制代码 2 |3 ]4 C+ d& x+ n9 w" d
7 m6 L' I6 N7 e) B: p4 `
拓宽点数,加上载波,即可构成FM调制信号。
2 F) B2 \3 N3 }" J; ]5 ]6 N5 \7 x
/ T! ]! D5 M) G4 N# q
6 P3 g0 U& |6 ]9 b! T/ [, \4 z1 T, W. U
0 y! `5 |; M* V' D9 H转载自:电路小白
9 F$ P; U+ I* |9 p如有侵权请联系删除
+ S& J% [- h; b) t7 a! |! v3 c! E3 c& |# q0 l% j
6 r! E5 W! s% I3 H z/ h
/ u7 L* e9 O+ x& T8 y" X
|
资料不错,值得参考学习。
dac+dma?