DAC,即Digital to Analog Convertor,是数字到模拟转换器,也称为D/A转换器。其核心部分由R-2R电阻网络(也称倒T型电阻网络)、模拟开关和运算放大器组成。它可以将二进制码或BCD码表示的数字量转换为与其成正比的模拟量输出。
% p7 \5 t% k+ ~( X
. A3 y! d2 D& A! F/ YDAC的工作原理主要包括数字信号采样、量化、编码和模拟信号输出几个步骤。首先,将连续变化的模拟信号在一定的时间间隔内进行离散取样,即数字信号采样。接着,对采样后的数字信号进行量化,将其转换为离散的数值。然后,通过编码将量化后的数值进行转换,以便DAC能够识别和处理。最后,DAC将这些数字信号转换为模拟信号输出。
( _8 L2 x3 E9 d3 m# p: R9 ]' X: ^( c3 ~6 L) a) s' b3 R
DAC是数字系统和模拟系统之间的桥梁,具有广泛的应用领域。在音频处理中,DAC被用来将数字音频信号转换为模拟音频信号,以驱动扬声器和耳机,其性能对音频质量有着决定性的影响。在通信系统中,DAC用于将数字信号转换为模拟信号,以实现信号调制和解调。此外,在仪器仪表领域,DAC也被广泛应用于各种测量和控制设备中。2 ? D" W+ ?$ P% v% i
3 v( I+ o4 B1 p" s& V0 U7 X
7 @8 K" x: c8 a* B2 U4 F; k q
i2 {9 _3 P. |) z* \3 kSTM32中的DAC(视芯片而定例如F407ZGT6是2个DAC通道,有些芯片不支持DAC功能)支持12模式的数据输入,可以双通道同时转换。
+ g: j- `# H7 J l
6 Y5 f8 j1 E, S% u$ X4 C本期我们将介绍如何使用STM32F407和CubeMX利用HAL库实现DAC的输出。(本来是想使用C8T6的,结果突然想起来C8T6)没有DAC。7 Z9 O+ \# }& o/ }& X. @& p) [& Q
* z* M$ B& m4 O, s1 h! ~% ^$ m
CubeMX配置
2 d8 W( ?: E9 L M8 K
! M8 h" F3 Q/ S# _& |9 E
0 ~2 n! h6 @! p0 t. y! y X1 N, o7 ?( i+ x
在DAC通道中开启DAC,在F407ZGT6中DAC1对应PA4,DAC2对应PA5。& C( Z* J& A6 H) S4 s8 J( {% Z
4 `' Z T* ]- N
9 ~4 H$ e- W8 v. r9 R r0 Z8 R4 r+ P& {9 X6 e
OutputBuffer这里设置DAC的输出缓存使能,Trigger是DAC是触发方式,这里我们选择不触发(手动写入)。+ Z. [# x, [! F \( s
+ t; F. s* q5 O9 X( G- F% }2 v' ?" J如果选择触发的话是从缓存区写入数据。
+ [9 q* X4 E9 o v( e3 a. y$ _5 h, y( z' d
7 I) L9 E' H' ~* t6 Z0 a
+ V r+ W- P5 D/ n3 ?8 G# }
这里顺带加一路ADC采样,因为手上没有示波器,所以使用ADC来进行查看。9 q) _+ D2 L% M# e7 T
: c! y3 i/ x8 ?; \+ ~这里使用DMA进行采样,具体可以参考公众号之前的关于DMA+ADC采样的内容。8 C& v# @4 v V0 G& n! Q
% R! d, K3 D( Q0 G- Y$ w, K
STM32的DMA采样+FFT时域分析(STM32F407)
! z" D* y; X* U; E1 r# X6 o4 R
( C. C- q D! W( w# S但是相比于之前的,需要更改一些设置,首先是DMA的设置+ l, y+ a2 _& _3 f0 @4 M$ W
9 q6 h* Z( U- M& n
+ Z: W6 T: ]9 ]% b, ~/ m) U8 V9 G0 R- k8 z* Z
这里设置单词请求,而不是循环模式防止数据跑飞掉。
. _( Y: _( h9 u- ^6 `9 }. \
3 F) Y8 \# h' }
% u1 x. ?' g: |, d9 k/ n9 q- MX_GPIO_Init();6 o/ M' S8 S. ?+ x/ ?
- MX_DMA_Init();
! [; q* g: M# c* Z8 u" `7 D - MX_ADC1_Init();
* @0 M" }& R" {2 M% Z+ ~2 ^+ N - MX_DAC_Init();
t m$ H: l6 |6 J$ b - MX_USART1_UART_Init();% w9 ^' S5 Q: Y/ a+ K) U; C1 @; w
- MX_TIM1_Init();
4 ]7 i8 n9 p3 q8 t - MX_TIM2_Init();- N2 v" Q; e; T+ m) }" P K1 K' O
- /* USER CODE BEGIN 2 */
# F: |* v/ y( k9 o - HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); //用来触发adc采样
+ |& ?6 _( u8 \3 b! d% i1 M% _' n - HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AD_Value, ADLenth);//开启ADC3 L3 b, b* o. w! o5 `
- HAL_DAC_Start(&hdac,DAC_CHANNEL_1);( A' Q' C4 d5 r4 c. u `/ y
- /* USER CODE END 2 */
* o- u' P( G N& D
* S: C: s, [6 I3 J- /* Infinite loop */1 v, ^! l6 ^0 B/ R2 s) h
- /* USER CODE BEGIN WHILE */; C6 \( u# H3 @8 h2 _
- while (1)
; `5 L% k/ v) m8 E. p - {9 z+ b/ M% R9 a7 p
- /* USER CODE END WHILE */7 n3 @) y( e6 W7 J8 P7 w
2 D( p1 X& r2 `% |1 C- /* USER CODE BEGIN 3 */- q5 C% V+ k9 i
- if(!HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0))
( I' j1 q+ c* f - {% g% n( y2 |* T( o. z$ p
- HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AD_Value, ADLenth);//开启ADC
0 ~$ [* a/ E# o6 M
$ H9 I7 p6 J( b- HAL_Delay(20);3 z$ u8 T' i0 s& [
- 6 l1 F2 X1 c J7 V' e" d0 O
- while(!HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0));
4 y" i, J9 n0 f& w9 R9 J - HAL_Delay(1000);1 o$ j0 j$ E1 t& d+ J; L8 ?
- for(int i = 0;i<ADLenth;i++)6 J7 |: P$ t8 F4 T C7 Q6 W- ^
- {' N& L0 i7 U+ [: Q+ e" b
- printf("A:%d\r\n",AD_Value[i]);
* b% Y5 Z; Q( C7 {0 P3 \' W8 }% T' A - }
* J9 ?4 x& j& @2 q3 N -
5 d$ Z0 D; U! g3 w! k& p -
3 Q; V+ j, z% W8 p2 ?. [/ L - }
4 \- `# O$ x5 H - }
' C" N! V- k3 S" I" W4 m - /* USER CODE END 3 */" b. s3 K% E; z
- }
复制代码
6 ~; c- n( r8 j
5 D3 Q# S: L6 p% o! O0 z2 o; A" z我们编写一段代码。
! c% X9 Q/ ~" w5 I/ ?
1 _7 D6 T0 a" D% D按下按键的时候设置DAC的值,开启DMA传输,再加上ADC采样,之后输出结果。% @" x. D) M' |- k$ a0 F
% ?" G4 t+ W" A/ f! H
. p( w: T/ W' E4 y A
# i- e* i! k1 V; n# M6 l可以看到,我们按下按键之后,ADC的值会呈阶梯状上升。' ]: b8 i+ s& f
# n6 L9 T; ]7 J! V- J1 ^三角波发生器; K3 E3 i4 n2 y! C$ B" c8 z
+ r7 D4 K$ j9 k( m2 F: p: j) v
9 h! m5 }3 t7 Y2 l5 e; W( i: V9 V, T+ @/ t: T. z' |( m4 ^
在DAC配置中打开波形发生器,触发方式选择定时器2触发,三角波最大振幅511。. {% S" [& w! y" h( J( o
2 M3 S `7 c6 J" Q# N
- H* E3 N$ z+ g6 o; `2 m
; [" m: q4 E& s- t3 c
之后开启定时器2,由于ADC的采样率是1000HZ,因此根据奈奎斯特采样定律,信号的最大频率不能超过500HZ,因此我们使用100HZ的三角波。
4 r) P# @) B- Z- D) m
) J( A1 d8 G( q& ^' n
3 ~3 t* R) _4 u' p7 o
3 @ r. n% F& e- ?
定时器设置好时间之后,设置触发事件。
5 n. M( z7 [7 G' N E, `* N2 R3 z/ n; }" |
3 ]! m/ p! U: l, W; c
. s/ z9 E; K* c% [+ ?+ X/ X) H( e3 G芯片手册中简单的介绍了一下如何计算三角波的频率。当触发信号发生后,内部计数器的值就会+1,所以频率可以用如下公式计算:' B k' d# f9 g* }0 {( H
0 f4 u: \- E% }& q定时器频率/分频系数+1/Period/三角波最大值/2
3 D! \: f' u% _) S( ?% L1 C
" g; w+ |9 f% r9 B6 s; W- HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1); //用来触发adc采样
8 b1 s7 Q) }! d2 T' R6 r( m% i9 K - HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); //用来触发DAC输出3 s7 ~5 ]4 k6 S) R
- HAL_ADC_Start_DMA(&hadc1, (uint32_t *)AD_Value, ADLenth);//开启ADC
" O0 _! j) X9 j) i1 P9 B$ ]8 Y - HAL_DAC_Start(&hdac,DAC_CHANNEL_1);
. \6 J3 C/ K& j - HAL_DAC_SetValue(&hdac,DAC_CHANNEL_1,DAC_ALIGN_12B_L,0);//设置直流信号
复制代码 ' t5 l; V9 ~# R) @( {& s, s. q
9 y" ^+ }. B) J- g( D! b: u
4 p+ z3 |" E6 O* m! o2 R* Z$ y
正弦波发生器
% n$ g% I" Q; W3 o
# ]5 T/ L) h# D. }" `8 @) E7 M8 T
# V2 Q' @( b( N/ b1 F
3 Z% @5 A$ S' m! K7 y0 \% p首先是定时器触发(方便控制频率)。但是关闭波形发生器。% K v! [$ L ]
2 e! Y3 E; g; W# }
; I/ \: H' o7 E: k' { T
( u8 x! D* z% ~8 d
添加DMA,模式选择循环模式。
/ \' J3 v+ @7 Z; D9 I
! R, i! Z& o @. i# Y( S还有改变一下定时器的频率!
1 s1 q4 f K- R3 `+ o5 ]$ I: D0 b# i4 T
其他几乎不做改变。# N6 Z6 N6 W; W3 d
, O- U$ V; ?3 w/ m5 O! l, p/ V
5 W m& C& Q7 K' @2 J9 [- #define POINTS 256 $ u5 M8 C& K L/ g' c, }7 d3 s
- #define MIN_VALUE 50 2 M. F7 M$ W, w* E& }3 l2 ~1 W- E; r9 W
- #define MAX_VALUE 650
9 t2 Q3 u) |* [/ a) K - #define SCALE ((MAX_VALUE - MIN_VALUE) / 2.0) " E& i) s- `; }+ ]$ O* B$ `
- #define OFFSET 50 " ]+ \3 v9 U9 O' d
- #define M_PI 3.14159265
; M' }% ~: s5 r -
* P2 M/ O/ H9 W& c7 E - uint16_t SinWaveInt[POINTS];# D5 z0 j3 Q0 J" V; t6 o
- int SinWave[POINTS]; 3 Y/ t' H8 ^2 ~$ m+ l" ^5 @* @6 {
- void SinInit(void) C- ?' o: ~" s6 a. U8 ^8 ^
- {
1 B# j6 j& L. W+ C5 {( L0 w - for (int i = 0; i < POINTS; i++) " M: p5 Y% m" w& Q8 B
- { + F0 X2 t9 `4 X( H6 h
- double x = ((double)i / (POINTS - 1)) * 2 * M_PI; ; M8 |4 `: D( M; b
- double sin_value = sin(x); // 计算正弦值 ' y* \" \) L4 E6 a8 I0 A; q
- SinWave[i] = (int)((sin_value + 1) * SCALE + OFFSET);
, A% x. t4 ^: P& G4 F5 b: R: e5 g - SinWaveInt[i] = (uint16_t)SinWave[i];
7 t) r7 O! J8 v3 Z - }
9 o& A8 @4 Z! d - }
复制代码
; t5 w5 i+ P1 p2 t计算一个正弦表。
! A/ N! F3 s7 z! s, a! I
2 v9 Z u9 t7 P9 l" I; h这里的Points决定了分辨率,结合定时器触发频率决定了正弦波的信号。
V7 Z9 p6 g& b/ N* B0 U+ C4 B3 X3 m+ H1 N- V& K
( m. _+ X: d4 @5 H Q* Q. f
3 z1 G% L B B2 }+ c测试一下正弦表,输出的是正弦信号。1 `" O8 {, W' y
1 x* q' \: D. z4 X1 I7 e7 f9 j( x
我们之后将正弦信号表导入DMA中。0 D6 ]" R6 k( l3 K
( N9 U* }& ~" X7 S: r5 J) _5 \- SinInit();7 w; ]# l( x6 }( N( K
- HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t *)SinWave, POINTS, DAC_ALIGN_12B_R);
复制代码
8 j( A6 @( m" |" ~正弦表初始化,之后启动DMA传输,导入正弦信号。
' B I6 s7 |6 S$ p% T7 X4 Z; w5 U& r
: p! g( N: H6 ^4 Z& U
8 O- V! j# ]& M1 T( s
1 W: K" x* G7 p+ |$ w$ }( t测试正弦信号成功。
) H. x/ j; A- m, e! q+ q8 j' o3 l2 l- {3 X
FM调制- #define POINTS 1024 0 b8 p' X& e; ~1 k4 s: p8 [& [
- #define MIN_VALUE 50
; d; I- `3 e% G: _3 v! i - #define MAX_VALUE 650 8 X# q; ~ v& B1 F$ ?: z+ v- ?# S5 j. d
- #define SCALE ((MAX_VALUE - MIN_VALUE) / 2.0)
6 B4 {9 Q# P' Q3 c. t: i$ c - #define OFFSET 50 + h C" I( P$ Y3 d4 @
- #define M_PI 3.14159265
/ V! L* R; c+ j. t2 l- Q -
7 Y6 Z* E u" \ v! G; }* m - uint16_t SinWaveInt[POINTS];
# I! a# V0 y$ H5 v3 \/ u( Z$ h - int SinWave[POINTS]; 8 ^: t: m' Z4 b" D" z9 I" n& g
- void SinInit(void)
; N3 k3 |! g0 e3 z) r+ J - {
% q2 @+ N) \* F4 `0 X - for (int i = 0; i < POINTS; i++) 6 O1 D, k! P* m! R' I1 S0 s/ F9 ^
- { 2 [# U( e0 ? ~" z4 L; l
- double x = ((double)i / (POINTS/4 - 1)) * 2 * M_PI;
1 l. e7 Z, X* a( d% B# _% z! P& l - double sin_val = sin(x)*sin(x/4); // 计算正弦值
; v* N; y7 ?! e* L* q$ r, O* ? - SinWave[i] = (int)((sin_value + 1) * SCALE + OFFSET);
+ [( e5 G) k5 D8 T" V' z - SinWaveInt[i] = (uint16_t)SinWave[i]; 9 R* D% J6 n T( y7 E$ C
- }
0 K/ l5 X$ b- M0 }& J: M - }
复制代码 ) u( l0 Z: f( D1 c% g
. |9 H0 i) l' ]2 U2 t拓宽点数,加上载波,即可构成FM调制信号。
$ j- a6 M1 `7 X4 `8 U% L# T: o' @/ o, {5 r8 H$ Z# m9 R8 L
7 O9 @% m y, }8 T$ k" {( n
9 L, N3 H! _) j9 k9 B
. ^8 I* ^4 W- u' ?" }7 Y转载自:电路小白
+ [* @1 i" n7 P4 q1 A+ Z' x如有侵权请联系删除: y j& p0 m& ~9 N# S4 v
4 p. Z7 p5 Z1 J9 W. @# }" g2 f/ s8 u
$ A. E; U0 N) U- n
) W0 k; S& {2 J |
资料不错,值得参考学习。
dac+dma?