DAC,即Digital to Analog Convertor,是数字到模拟转换器,也称为D/A转换器。其核心部分由R-2R电阻网络(也称倒T型电阻网络)、模拟开关和运算放大器组成。它可以将二进制码或BCD码表示的数字量转换为与其成正比的模拟量输出。
% w/ N; d: a- l- u# m
: u2 U" T" ^4 f. jDAC的工作原理主要包括数字信号采样、量化、编码和模拟信号输出几个步骤。首先,将连续变化的模拟信号在一定的时间间隔内进行离散取样,即数字信号采样。接着,对采样后的数字信号进行量化,将其转换为离散的数值。然后,通过编码将量化后的数值进行转换,以便DAC能够识别和处理。最后,DAC将这些数字信号转换为模拟信号输出。& e. v1 Z' S+ F- h7 V
6 ~, T# m( \& V {& f Y: P0 @DAC是数字系统和模拟系统之间的桥梁,具有广泛的应用领域。在音频处理中,DAC被用来将数字音频信号转换为模拟音频信号,以驱动扬声器和耳机,其性能对音频质量有着决定性的影响。在通信系统中,DAC用于将数字信号转换为模拟信号,以实现信号调制和解调。此外,在仪器仪表领域,DAC也被广泛应用于各种测量和控制设备中。0 G- X( Q7 ^; q
; i! L2 r c, d) a+ e, H D
) H. }7 z4 O+ @, L$ X
% M/ e5 a. ]6 I. x9 f) aSTM32中的DAC(视芯片而定例如F407ZGT6是2个DAC通道,有些芯片不支持DAC功能)支持12模式的数据输入,可以双通道同时转换。, j: \) W8 m. F% [3 y. ], h
* X4 O- F1 s; T& _& w5 e. g本期我们将介绍如何使用STM32F407和CubeMX利用HAL库实现DAC的输出。(本来是想使用C8T6的,结果突然想起来C8T6)没有DAC。' o) a+ a0 f3 O, j) s7 t2 q3 h9 k
5 I% o# H X1 `: Z: J' }4 K# ECubeMX配置0 o, W, V# W8 S n7 a8 R$ d
: H0 r Q8 [ ?2 E8 ?
$ N5 B% G2 j( }: u5 s
1 y0 F: M9 ]( x* z* p0 k在DAC通道中开启DAC,在F407ZGT6中DAC1对应PA4,DAC2对应PA5。
4 B S' u3 R* h1 X! m
- s- u, ]1 c) Y* R) i
, ^7 T0 t( s% b: {4 p
0 G. Z6 W1 q. g7 P8 `* g# E, R% U! f
OutputBuffer这里设置DAC的输出缓存使能,Trigger是DAC是触发方式,这里我们选择不触发(手动写入)。 |+ Q8 ]4 F1 x$ B' N( J
' {) L# D/ t* l$ Y$ I5 I如果选择触发的话是从缓存区写入数据。9 A; _7 z1 } a6 [& a5 y
$ W. o& O0 {+ p0 v% q
' A5 C& h0 a/ L' D4 d; L; w: Y' c% Q* L3 t
这里顺带加一路ADC采样,因为手上没有示波器,所以使用ADC来进行查看。
# O4 ?3 h3 {5 \" [4 E, n2 x8 T) P% ^# j* V
这里使用DMA进行采样,具体可以参考公众号之前的关于DMA+ADC采样的内容。) r# X+ z1 F4 D7 U# @+ k
8 a: |8 V# S% u! ISTM32的DMA采样+FFT时域分析(STM32F407), f. K X; _2 k& n/ A0 b% B( E
: t& q7 g+ Z" I y# v; F但是相比于之前的,需要更改一些设置,首先是DMA的设置* u0 j0 n) S8 i7 o. \0 u
& l2 {1 _. m8 ]# U+ U/ W+ a& q
8 G- N/ g% L2 e% h. ~! |# X7 ^& \& Z
这里设置单词请求,而不是循环模式防止数据跑飞掉。9 r6 D+ M# }% [: t
$ x, V' ?' c/ \5 E
5 Z1 T! Q5 L1 \( j8 ?; l( P- MX_GPIO_Init();
8 ~# l, I0 o5 m ?$ A9 L# L8 q% Y - MX_DMA_Init();3 j3 B# B. g: @ q; w1 T; Q4 Q6 {% Y
- MX_ADC1_Init();
; G8 N# x; b" O9 L+ R( k - MX_DAC_Init();& N! t% u2 U9 b# E/ M- Z
- MX_USART1_UART_Init();2 w+ G2 f2 S8 r6 S$ P$ L
- MX_TIM1_Init();. A' b+ C$ N5 g
- MX_TIM2_Init();4 l4 Z$ y: R+ N' p$ l
- /* USER CODE BEGIN 2 */
& [8 r, `! F" R - HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); //用来触发adc采样
{ L6 P' s+ b. F' O - HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AD_Value, ADLenth);//开启ADC
6 N4 A9 w- `% v4 }3 C, J+ d$ k - HAL_DAC_Start(&hdac,DAC_CHANNEL_1);
5 {7 q* k7 }! a ^" D, V - /* USER CODE END 2 */4 ?5 V+ ~' j% v3 }! d* y& n7 f7 k
- 9 Z- E/ @5 w6 H2 [9 O
- /* Infinite loop */! G& V" r+ G0 x3 ]0 y
- /* USER CODE BEGIN WHILE */
! G E6 m* ^5 D1 {, Q - while (1)# M, f1 Q# V7 G) u, ?' R
- {; h3 ?: { `( S6 P5 z! }
- /* USER CODE END WHILE */
3 x( Y1 a; c" h, l - * s2 Q1 L0 ^9 R- }9 E& T& h
- /* USER CODE BEGIN 3 */
! F( K0 j3 x" S - if(!HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0))7 f* K. G2 u. z5 a/ Z
- {' [* S6 R# |4 R( w% v, Y Y
- HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AD_Value, ADLenth);//开启ADC/ a, T p" _5 L" \+ H7 s
- " V D4 V( b% B2 i0 Q
- HAL_Delay(20);
5 C" M. D& h7 ^ - . `" y! R w5 S9 F; B6 E* s1 U
- while(!HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0));
. z4 Q9 M4 ~. C6 a* \. I) N - HAL_Delay(1000);8 v! H/ ]5 o- d8 o9 m' a1 [
- for(int i = 0;i<ADLenth;i++)) S# @9 }6 p; ?2 }" a
- {% S+ g- |% D3 H3 K" r
- printf("A:%d\r\n",AD_Value[i]);4 r0 D' m0 v. \
- }) M8 s0 A/ f0 U
-
. |5 v- d: M: S) C+ Y2 R* O - 1 p1 S# a! a0 X6 |# W
- }
" s" R$ x* m. Q- p - }6 d2 G, ^& R6 k8 @0 x. ?
- /* USER CODE END 3 */
: \& v8 B* V9 y8 ] - }
复制代码
; v A7 Q* F& h, J6 f4 y u1 `2 |/ n) i8 \
我们编写一段代码。0 X2 e& Y, F8 D' _4 G0 j3 c
1 Y' F4 |4 x( ?* i- k按下按键的时候设置DAC的值,开启DMA传输,再加上ADC采样,之后输出结果。; G& O3 x/ y7 C; ?7 ^
: F" N6 |4 d3 |$ P. E
b/ ^9 m# L' E' l+ V
. L- `2 y& {- \ M
可以看到,我们按下按键之后,ADC的值会呈阶梯状上升。& _9 F$ m( X( p. `; i
8 k2 {4 H- ~+ d$ d# v! ~ O
三角波发生器* t k- h" l! a) @. p# y2 [& A
3 ^* U% {- g" K D V
3 u9 y1 e4 ^4 ~; [2 ^
" Q3 w' D0 N [( |
在DAC配置中打开波形发生器,触发方式选择定时器2触发,三角波最大振幅511。
, ~) J4 [2 \7 r/ A
3 z Y! V% C9 t1 b
0 Y3 e% C, J; D, R+ W0 Q6 i
: B! q' C- n0 k$ Y6 Y. J+ L% {% k之后开启定时器2,由于ADC的采样率是1000HZ,因此根据奈奎斯特采样定律,信号的最大频率不能超过500HZ,因此我们使用100HZ的三角波。
: G; v& }6 v" K$ d
- v4 P4 S4 b: q1 J( J5 v h3 i
$ ~( v& t$ o* K8 W! }1 \. V; o$ z; {" h4 l; b
定时器设置好时间之后,设置触发事件。 m9 K7 J) h7 a4 e3 v7 b
& P' j3 q5 P" w; z" |2 r0 {
, J2 [' ^4 g% f" S
+ {2 Y0 ?- Z- b7 i芯片手册中简单的介绍了一下如何计算三角波的频率。当触发信号发生后,内部计数器的值就会+1,所以频率可以用如下公式计算:
) u$ q- a# S2 g" h3 l% p
8 H( ~6 o, Z( A- V+ X定时器频率/分频系数+1/Period/三角波最大值/2
3 @' Y: R7 ^% `. `& E& X8 V* s* n9 F, J5 j
- HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); //用来触发adc采样, |. w! w) I3 u) S3 e7 Z6 t, n' N" j
- HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); //用来触发DAC输出
! K/ X, v: ?" v5 R; q' l - HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AD_Value, ADLenth);//开启ADC
N4 e, i. G% D - HAL_DAC_Start(&hdac,DAC_CHANNEL_1);
+ `6 g N2 Y+ j( J& G1 Y2 H# m+ n - HAL_DAC_SetValue(&hdac,DAC_CHANNEL_1,DAC_ALIGN_12B_L,0);//设置直流信号
复制代码 ) A9 W! O. y. l0 f- ?, K, ~
' U" J, Y$ R. v" `7 M2 a7 k( S
# X' p$ Z5 J5 q* c( K' `正弦波发生器$ x$ [: Z- R! c0 u$ ^
w1 H4 @% f0 {/ G% [% A+ Z
4 b( {# ]! N) z9 I
T3 a2 `3 y8 \! h首先是定时器触发(方便控制频率)。但是关闭波形发生器。
2 u; A3 x% V2 ?: Q6 h
% b9 M0 m5 u- F" y8 E% I3 o
9 | Q3 X# X/ @* M3 ?# h
1 z& W( P) [1 l6 s* }! W5 F1 \2 ~
添加DMA,模式选择循环模式。
0 m. o. T: f/ F h8 | W0 b4 m8 c
还有改变一下定时器的频率!7 e T7 C8 I2 g
7 S* l2 J: ?$ K5 E! D其他几乎不做改变。0 O+ A- a% I6 f8 i$ l* t
v8 r% U. P' j2 C& s& z
% D1 a+ I8 v$ G% p- [- O9 t
- #define POINTS 256 2 Y' P" k8 d X1 @& V! F9 }
- #define MIN_VALUE 50 % {5 E1 N( y+ g8 A- e" H' b, s4 _
- #define MAX_VALUE 650 1 U+ O" D) j q5 }
- #define SCALE ((MAX_VALUE - MIN_VALUE) / 2.0)
5 p& I F! n" x4 S1 v! W; R% T$ F. R2 ~ - #define OFFSET 50 9 M8 D. H. z D/ m) z, C
- #define M_PI 3.14159265
0 u5 a+ Z) S/ W! t - 0 {3 z5 e( o* T n, y! U' Z5 s, n4 h( U
- uint16_t SinWaveInt[POINTS];
# |4 E; x) x! ?1 |( ~ - int SinWave[POINTS];
! g0 V S, O5 f8 O, ~9 W - void SinInit(void)
" R6 o% M# b6 D# w$ e - {
5 n3 b. \' p. o$ W# d% M - for (int i = 0; i < POINTS; i++) % i9 V: U+ T) H% Q& r" z' {/ E' x
- {
& }& M: y0 {7 [( R1 T) C- K3 A - double x = ((double)i / (POINTS - 1)) * 2 * M_PI;
' p D% i/ ^+ e# W8 I. X - double sin_value = sin(x); // 计算正弦值 ' D6 ] Y, H0 R/ j9 o/ }! ~
- SinWave[i] = (int)((sin_value + 1) * SCALE + OFFSET);
0 v: {- N& `$ F% G - SinWaveInt[i] = (uint16_t)SinWave[i]; : J6 o- v; p) ^( t* Y5 G# p
- }
" A: m1 d- U7 @ - }
复制代码
$ Z Q8 N9 R$ O/ Y. I计算一个正弦表。
* k+ e5 |9 U+ g$ ?# y! B( H# D2 P" ^/ D0 _( h2 l, R) N x1 l
这里的Points决定了分辨率,结合定时器触发频率决定了正弦波的信号。
9 N/ ]" i- A. r; A9 o4 y; \. e# A1 e8 z8 V1 t) z, P
4 |1 r9 i' C+ E# k% v: o
( V G4 v6 b4 G. }0 @4 t
测试一下正弦表,输出的是正弦信号。& B6 r0 Z) O1 N" s# _
" }# n' m, I9 N1 E1 C3 @
我们之后将正弦信号表导入DMA中。! L9 ]6 p# P5 a+ Q: k
" F: |' D6 d* l; ?$ p+ S' D- SinInit();
5 T$ T5 Q, G& x+ z( y - HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t *)SinWave, POINTS, DAC_ALIGN_12B_R);
复制代码
2 c7 ]7 o" b H" T% Y! {1 P3 G+ |正弦表初始化,之后启动DMA传输,导入正弦信号。1 {- d* C# K9 t+ ^1 ~: h
, [- g/ W# P9 H I; s. J8 U' V
' _" I' x3 ]# Q1 G& Q k) w; o: O* u; R0 k' Q7 }
测试正弦信号成功。
4 r) a6 T. Y, ?- p" X) G
9 d+ V2 U9 _: b$ G+ hFM调制- #define POINTS 1024
5 {' t5 o) h9 t; v0 S) S1 r5 m3 e, j - #define MIN_VALUE 50 . q. P( T. q& P7 [" g% ?5 d1 ]
- #define MAX_VALUE 650 5 }6 v- X9 J* O7 O% H; b
- #define SCALE ((MAX_VALUE - MIN_VALUE) / 2.0) 2 x$ A0 r. F) U9 |' U& F
- #define OFFSET 50
+ q# ?5 e" M0 x( H, L& w6 h - #define M_PI 3.14159265$ d9 M5 `4 I. C; {
-
+ {8 }8 S6 ]% J4 O& }; e - uint16_t SinWaveInt[POINTS];
, P. b w9 `, |* @( X9 b+ \+ W - int SinWave[POINTS]; " H) t& ^- ^( S5 T
- void SinInit(void) " J9 w% u4 A* v0 ` f
- {
6 ~* l9 Y( x) F/ [5 X - for (int i = 0; i < POINTS; i++)
. Z9 b( [7 {: t4 c# s - {
# z4 C% |* \" [2 k2 ^' w% N - double x = ((double)i / (POINTS/4 - 1)) * 2 * M_PI;
# f0 ?4 r/ _7 n2 C; q - double sin_val = sin(x)*sin(x/4); // 计算正弦值 5 N2 L/ W" q2 O" O: Y+ Y
- SinWave[i] = (int)((sin_value + 1) * SCALE + OFFSET); 9 B1 p# i* p# f8 r# ~9 `5 w7 a
- SinWaveInt[i] = (uint16_t)SinWave[i]; ! b# l: W# D! K' H
- }& ?9 P) g9 k0 [6 y. K& z3 a
- }
复制代码
0 E% X3 s" m2 A' S; f0 H( u$ `
$ X0 k; }$ s4 c0 a! Q拓宽点数,加上载波,即可构成FM调制信号。. T4 @8 r1 _. q" [) w+ Y
5 n2 k% V9 J0 R) j
& A$ P+ D1 x: T% U0 q
' A3 R+ S6 M5 [! [8 U+ X6 w, T4 p; S/ u9 [1 O% z; Z3 u
转载自:电路小白% |1 x4 D* ~" f- p
如有侵权请联系删除
# q* A3 }% t( A$ `- u+ h: O4 s! M6 A" R ]3 M
1 {" ^* F/ k* b8 u, ?' r
1 D8 t: @8 k" S |
资料不错,值得参考学习。
dac+dma?