DAC,即Digital to Analog Convertor,是数字到模拟转换器,也称为D/A转换器。其核心部分由R-2R电阻网络(也称倒T型电阻网络)、模拟开关和运算放大器组成。它可以将二进制码或BCD码表示的数字量转换为与其成正比的模拟量输出。: r- w9 ]' D, `8 t
, P# k# V* N6 q; R+ \7 d- VDAC的工作原理主要包括数字信号采样、量化、编码和模拟信号输出几个步骤。首先,将连续变化的模拟信号在一定的时间间隔内进行离散取样,即数字信号采样。接着,对采样后的数字信号进行量化,将其转换为离散的数值。然后,通过编码将量化后的数值进行转换,以便DAC能够识别和处理。最后,DAC将这些数字信号转换为模拟信号输出。
1 y; K5 t2 o. Z2 ]
9 }7 S {( Z& N O( `; v6 Z% z$ T4 c8 yDAC是数字系统和模拟系统之间的桥梁,具有广泛的应用领域。在音频处理中,DAC被用来将数字音频信号转换为模拟音频信号,以驱动扬声器和耳机,其性能对音频质量有着决定性的影响。在通信系统中,DAC用于将数字信号转换为模拟信号,以实现信号调制和解调。此外,在仪器仪表领域,DAC也被广泛应用于各种测量和控制设备中。4 O$ n* K3 [& b* P' U8 [( I2 h4 h
& C& u. Z8 G8 F4 |. y/ K4 {
- h( T# {+ ]9 |' G( D/ p. f4 w1 W. D
STM32中的DAC(视芯片而定例如F407ZGT6是2个DAC通道,有些芯片不支持DAC功能)支持12模式的数据输入,可以双通道同时转换。
* k( V: E1 b$ g# N
+ A$ Q( ^% q! |5 J本期我们将介绍如何使用STM32F407和CubeMX利用HAL库实现DAC的输出。(本来是想使用C8T6的,结果突然想起来C8T6)没有DAC。
& ~. z1 y& ]# P3 k/ a
% m- u5 Y- r% H# T" vCubeMX配置$ L, A2 E+ R7 H5 \1 u }1 N& N! }% p
- n' H: _5 C+ z1 e# Z! F* J
( y' ], H! ]- K, O7 u7 L
( b3 @. W7 k6 f' ~1 `. p
在DAC通道中开启DAC,在F407ZGT6中DAC1对应PA4,DAC2对应PA5。
9 h0 z4 P- A; o7 x0 m$ Z7 O
4 B3 A: {; w/ n- P2 j% E
# l1 V! r! w' S: O3 R
5 |% `* m- J; B; F& x7 _OutputBuffer这里设置DAC的输出缓存使能,Trigger是DAC是触发方式,这里我们选择不触发(手动写入)。
9 h( Z0 J' Q2 H' E# S2 n! q8 x) J7 f/ X; J8 x% y. z% W8 b$ a
如果选择触发的话是从缓存区写入数据。
! [' R9 j6 r4 O' C. q" y5 O
; Y0 l" i( V/ G4 m7 o9 N
: ?' h' Q2 R* {" W, {6 f( s
9 k- F2 Y1 I/ i2 E: u y# c这里顺带加一路ADC采样,因为手上没有示波器,所以使用ADC来进行查看。7 k9 {4 V) E8 n+ u9 S0 U: N9 M
4 A, Z8 ] F2 y6 D8 l
这里使用DMA进行采样,具体可以参考公众号之前的关于DMA+ADC采样的内容。
]0 c5 U/ q( s. [; P0 T( G
/ T& ]0 R9 t$ a0 LSTM32的DMA采样+FFT时域分析(STM32F407)
+ ]9 y N+ S8 x
8 T1 `0 O" G g1 W( x1 E) g6 [4 E但是相比于之前的,需要更改一些设置,首先是DMA的设置
! P6 h/ k9 B2 w' S9 [% V+ B6 n0 ~8 {8 o
3 ^ ?. Y& v2 Z f
) [5 g3 G' E) t# {
这里设置单词请求,而不是循环模式防止数据跑飞掉。8 n6 B6 u! w4 q- n* f& L
8 l9 T7 C3 b; E
$ e( G- Q* A0 V# [3 S; V2 h6 \- MX_GPIO_Init();
4 V2 o3 |8 v, ]3 R5 _ - MX_DMA_Init();8 H4 ^2 Y/ l' ~- S0 C
- MX_ADC1_Init();
; E) p$ r+ E4 M' j/ e - MX_DAC_Init();& Z! F9 L) P3 L, D- ?
- MX_USART1_UART_Init();
& O6 U- B! i1 X4 T9 m, g O$ ^; n4 F! O9 g - MX_TIM1_Init();) I" k# u1 z; s7 B
- MX_TIM2_Init();
! Z6 g$ c; N. ]5 Q/ | - /* USER CODE BEGIN 2 */
+ X2 z) y# S! b6 } - HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); //用来触发adc采样 ) E( d7 M0 e9 y, ~ W& C; P
- HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AD_Value, ADLenth);//开启ADC& d- S+ s* R, h, l- E! D1 {$ v
- HAL_DAC_Start(&hdac,DAC_CHANNEL_1);5 A9 }/ a1 t0 y2 F. w' g, H
- /* USER CODE END 2 */
7 L+ G2 Y' F' |5 n, D5 @) Z- U" S - . r) w9 F* x7 y5 q1 ]8 o
- /* Infinite loop */2 e5 t' r2 R$ i2 M! @9 C' Z- s9 s
- /* USER CODE BEGIN WHILE */9 H3 }3 A+ B$ `! Z$ h% J3 q6 a
- while (1)
( L- [- m9 G8 {& @# b( k - {
- J# C( _% L+ k5 q8 |' H& r - /* USER CODE END WHILE */9 V9 {/ X# F! D. A+ q2 _
- 1 J* g6 T) e$ u! P- v8 t- g
- /* USER CODE BEGIN 3 */3 h# a7 E9 L# T1 B" ]- N' t9 V
- if(!HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)), ]$ H. E- a) f) S( r6 n y/ ^
- {
: I1 e; q o8 ~" u% h' i( @ - HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AD_Value, ADLenth);//开启ADC- J4 q3 o/ I3 s2 }5 _ M
' v6 m2 s% c1 m- R& Z! o" H0 \% t- HAL_Delay(20);0 C3 y( p6 |& _! O9 n. N
-
- ^; d/ D4 Z M$ T( |; }+ q - while(!HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0));6 x- a, j( k2 C- b
- HAL_Delay(1000);
" [# @( `- m1 X- T: A! N - for(int i = 0;i<ADLenth;i++); W/ c2 K. `& _. ~/ e( u
- {
8 ?% O5 X. P! } l4 ^4 `* Y - printf("A:%d\r\n",AD_Value[i]);
% R% U( o& e3 R7 @5 I% o* N - }# `" P' o* Z* J( Q4 O7 E/ x
- 9 Y0 ?5 b# o$ t2 j
-
7 E! f: a! t$ ^* c - }
( K2 ?! s( p7 B1 Y5 T) L# z$ q - }
h" \: j6 b7 c5 j6 h+ j- F8 w - /* USER CODE END 3 */$ |6 F( |4 U8 W( ?' l. \
- }
复制代码 : L ` F) J- s3 z5 p
* s" K& `5 Q4 L/ v I我们编写一段代码。4 O- I4 W# N$ A$ z% v: w% u
6 D, E# F5 d5 c! z( `" _4 ~按下按键的时候设置DAC的值,开启DMA传输,再加上ADC采样,之后输出结果。
* c) c& y1 x0 h& L! I Z* J) ^# |
7 Y. {, B+ N S% w* Z, ^; B2 y# E
/ J, ?$ D. V4 G( d6 S1 G# R
9 N; a7 e) ~$ F; e可以看到,我们按下按键之后,ADC的值会呈阶梯状上升。
- N% m# ?9 |; u- P, N* E; Y) T. c$ r' {
三角波发生器
8 F9 E9 C @5 n: C3 N5 i
5 ]5 {' o6 V0 z% ~
+ w3 K7 p7 N$ S d# C3 y6 i5 ?5 Q% y# V" ]' G! X3 Z
在DAC配置中打开波形发生器,触发方式选择定时器2触发,三角波最大振幅511。$ Z: V) I; w7 H' I3 D
* r3 i& ?; s2 R9 }9 Z
% a9 b6 J4 l; k$ O! `) L" p( f
$ s/ v: ]+ Q1 [+ F$ h, [之后开启定时器2,由于ADC的采样率是1000HZ,因此根据奈奎斯特采样定律,信号的最大频率不能超过500HZ,因此我们使用100HZ的三角波。 H0 v7 a. q$ l# a+ C! |+ p' d
8 e8 S+ ~6 L6 U$ j
+ o& q: a8 _6 L" X
s9 s" E- ]* x- a定时器设置好时间之后,设置触发事件。! J& h8 a# l% g
) }1 s7 [6 v: z* d$ w* Z. F4 g }
) ?* @! w7 a9 O$ K
: x3 l: e6 g' J# l& ^( j8 Y3 @芯片手册中简单的介绍了一下如何计算三角波的频率。当触发信号发生后,内部计数器的值就会+1,所以频率可以用如下公式计算:* T/ @3 ~( X( c8 @; j# y
- Z R) p. ?5 z2 U1 q
定时器频率/分频系数+1/Period/三角波最大值/2
5 |; W/ h9 m0 P4 E u# w. T3 C$ f# o* g; V& W' O& s
- HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); //用来触发adc采样
7 Z F6 r8 y2 f* v$ {* K% _ - HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); //用来触发DAC输出+ A ?% X8 @+ g( I- M( ~
- HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AD_Value, ADLenth);//开启ADC
# a7 {$ U8 F* |* A$ [* o6 m+ D) m. H6 k7 U - HAL_DAC_Start(&hdac,DAC_CHANNEL_1);
L8 d( D2 L, z - HAL_DAC_SetValue(&hdac,DAC_CHANNEL_1,DAC_ALIGN_12B_L,0);//设置直流信号
复制代码
' N7 r8 g7 H. X% s! U6 l
+ n5 |+ i. r& b! n8 n/ P- H. w9 f2 z( w
正弦波发生器
, P4 H1 d5 g( Y3 T& N$ m3 K; M# [4 \; w, q$ C0 g: {
5 g) J! Q/ V/ w4 G1 D0 I
+ K& N; u8 s0 k- A4 K首先是定时器触发(方便控制频率)。但是关闭波形发生器。9 D9 }1 B4 y- j5 c0 \
K8 \$ Q- J6 U! y5 P
! ~4 a& e( S& N2 a3 ?' Z- p
, L$ [! M' ^( r* e+ Q1 f
添加DMA,模式选择循环模式。
- a& Y4 h9 N8 [
( K2 ]9 O' h; q0 S还有改变一下定时器的频率!
. G8 T& P+ V" c$ y4 a8 G
' H' z' S$ i( b" y其他几乎不做改变。/ k6 f$ a. u- B, X- u# w
0 a/ F8 O r8 C2 \! D
; D5 }( T; U( ?) B" z) R w- #define POINTS 256 " I4 t; d( H6 T$ X! J% _$ x9 |# f
- #define MIN_VALUE 50 8 ]) [6 W" _! ~3 u
- #define MAX_VALUE 650 8 O) D& k( [ c. m& e& {
- #define SCALE ((MAX_VALUE - MIN_VALUE) / 2.0)
6 p3 p4 }! G" w! f" } - #define OFFSET 50 & y. V- B7 J; p$ m, v# l6 D
- #define M_PI 3.14159265
) L) A' P& z9 e0 B& \ - % v6 e! P- Y2 q6 w7 R* X* ~
- uint16_t SinWaveInt[POINTS];+ F! C; L+ @6 |1 X5 q
- int SinWave[POINTS]; W8 n- K4 ^5 J" d7 e: i" S' ~6 l& v
- void SinInit(void)
' ^* D, A! k0 Q- d. J* R - { ' m# Q v! d; L* _# z
- for (int i = 0; i < POINTS; i++) 7 Y0 q2 Z# J: N
- {
7 A& D: ~( w! F9 {" u! V, y b$ O - double x = ((double)i / (POINTS - 1)) * 2 * M_PI;
) Q! |8 N! x9 I4 P - double sin_value = sin(x); // 计算正弦值
! Z5 \, C c6 h0 n& @9 n7 `1 K/ k - SinWave[i] = (int)((sin_value + 1) * SCALE + OFFSET);
1 H* C5 o8 t5 a9 c+ L$ C - SinWaveInt[i] = (uint16_t)SinWave[i];
' Y& I/ l! r1 m5 W - }
1 `+ w& j5 a% j7 F$ f- S3 ~! C - }
复制代码
/ k e9 j4 x( w g计算一个正弦表。7 R& Y3 R f5 B6 |/ n: \
7 v5 d' i, f" {7 f5 N. Y这里的Points决定了分辨率,结合定时器触发频率决定了正弦波的信号。) q; B7 V: l8 B0 _- x
: F* M; W+ ~5 S- ~1 ^
. |( l3 [" t0 |6 e
) |- n! q& `; b _' Y7 h测试一下正弦表,输出的是正弦信号。
, v n, z) [$ t* k
7 S! l/ I7 m% g! l1 ~我们之后将正弦信号表导入DMA中。
/ ~/ o# M4 W6 ]$ K5 e4 Y5 r0 {6 P2 `' @$ e
- SinInit();6 e/ B% t6 j* f8 ?2 b* d$ H
- HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t *)SinWave, POINTS, DAC_ALIGN_12B_R);
复制代码
5 [6 S) j6 j, R5 I正弦表初始化,之后启动DMA传输,导入正弦信号。
9 z% {( L% N% m& H! ~, B1 t+ E. I
/ l& i$ C- |" b" T6 X; R$ @
. R S3 g! s( p. z0 W7 u$ N
: n% x5 s& G4 g8 u测试正弦信号成功。
1 e. m" u7 g, l* ^
; N8 |& H" G \FM调制- #define POINTS 1024 - t' d% ^/ E, N% E! \( J
- #define MIN_VALUE 50 % h N4 U4 M& A) v6 ~" }
- #define MAX_VALUE 650
0 g- `0 I Q- m! q' ]; ~1 D - #define SCALE ((MAX_VALUE - MIN_VALUE) / 2.0) ' l% V! V; ^* T) E- e
- #define OFFSET 50 3 G d# N) |& Q) P& K5 q7 @
- #define M_PI 3.141592653 l9 i1 E8 E( k6 o5 }0 J
- : i, V0 m9 L, R6 T6 u* G2 i
- uint16_t SinWaveInt[POINTS];& p/ q# R- u. a4 _
- int SinWave[POINTS];
% {# ~& j8 F0 C9 I. ~: Y4 K - void SinInit(void) & Y6 y" f- f5 _
- {
4 X! `) a( R- `) D2 U& O - for (int i = 0; i < POINTS; i++)
% w/ g1 b7 ?- \, `. G) ^ - {
- c. A ?# K2 J# `3 } - double x = ((double)i / (POINTS/4 - 1)) * 2 * M_PI;
0 n+ Z0 @; T2 h8 H - double sin_val = sin(x)*sin(x/4); // 计算正弦值 6 ^$ X( c* M- a8 B+ h7 F; L5 j
- SinWave[i] = (int)((sin_value + 1) * SCALE + OFFSET);
4 k' T( Z0 p# S6 A& } - SinWaveInt[i] = (uint16_t)SinWave[i]; / ?$ i% R+ [' J M5 K8 m
- }
! w4 W5 u- R$ P, B - }
复制代码 6 }* X. f# K: z* B
7 @6 g2 } N0 z% u1 d1 V" F
拓宽点数,加上载波,即可构成FM调制信号。
1 C4 T6 ], j3 E( u/ W$ A5 _( C, {( }- d# l5 n, R) u
& d- _6 V+ Y2 c% [5 l' y2 \! ]
0 c; I2 y& k# i5 _6 w! o# C' b; r6 `# [( a/ p
转载自:电路小白+ e! U8 i) } }, y6 F5 Q
如有侵权请联系删除
! A K! r. z! }7 W; y0 K- v0 h% M$ z
8 V4 F6 g v' f, N
: f) S6 |2 R& Y/ c
|
资料不错,值得参考学习。
dac+dma?