找回密码
 注册
关于网站域名变更的通知
查看: 273|回复: 1
打印 上一主题 下一主题

【GD32L233C-START】DAC输出(正弦波、锯齿波、方波)

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2022-3-30 16:02 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
  f5 Q; q& Q/ h( ]: b$ t: Y
1.介绍2 m0 |* x7 Y( j- U3 k+ j
GD32L233C采用的是一款M23的内核。这个芯片据说功耗非常的低,低到什么程度呢?等后面我们再进行测试,今天我们主要来测试GD32L233C-START的DAC,既然要测试DAC,示波器是不可少的,这个实验在家做,然而LZ家里并没有示波器,不过最近看到一款好东西,LOTO虚拟示波器,看过这款示波器的参数,还不错。所以入手了一款,测量芯片输出的DAC应该没什么问题,接下来开始测试吧。5 d. S& N& N6 D, j/ x; e# L
2.设计
, |- g) D+ d" O2 T$ U6 Z, g
首先需要输出让芯片输出DAC,而且还需要输出波形,这个稍微费点功夫,之前在GD32L233C-START移植了RTThread,现在在这个代码的基础上添加DAC的输出程序,这个程序移植了其他网友的,代码我也贴出来,经过测试,代码没有啥问题:
+ Y: Q% `7 C6 d' P
比较麻烦的是正弦波的代码:
const float sinus_I_quarter[91] =
5 S/ M4 U7 V& f{
2 z# ~, j0 D- o- b3 j    0.0000, 0.0175, 0.0349, 0.0523, 0.0698, 0.0872, 0.1045, 0.1219, 0.1392, 0.1564, // 00 .. 09) j! i6 l4 [) t( c* `" b$ ~
    0.1736, 0.1908, 0.2079, 0.2250, 0.2419, 0.2588, 0.2756, 0.2924, 0.3090, 0.3256, // 10 .. 19, p& H0 S9 b) \8 y6 _
    0.3420, 0.3584, 0.3746, 0.3907, 0.4067, 0.4226, 0.4384, 0.4540, 0.4695, 0.4848, // 20 .. 29$ l6 i- v# `- q+ F& y+ }
    0.5000, 0.5150, 0.5299, 0.5446, 0.5592, 0.5736, 0.5878, 0.6018, 0.6157, 0.6293, // 30 .. 391 J, @( `( p5 x( C
    0.6428, 0.6561, 0.6691, 0.6820, 0.6947, 0.7071, 0.7193, 0.7314, 0.7431, 0.7547, // 40 .. 49# o5 A% s# M$ ]% |# s
    0.7660, 0.7771, 0.7880, 0.7986, 0.8090, 0.8192, 0.8290, 0.8387, 0.8480, 0.8572, // 50 .. 597 l0 U3 q1 i8 g) L. ^# J6 `; V/ }
    0.8660, 0.8746, 0.8829, 0.8910, 0.8988, 0.9063, 0.9135, 0.9205, 0.9272, 0.9336, // 60 .. 69
4 R7 i4 d3 h! }+ o" a    0.9397, 0.9455, 0.9511, 0.9563, 0.9613, 0.9659, 0.9703, 0.9744, 0.9781, 0.9816, // 70 .. 79& @4 M9 ?  t  W" F2 Y
    0.9848, 0.9877, 0.9903, 0.9925, 0.9945, 0.9962, 0.9976, 0.9986, 0.9994, 0.9998, // 80 .. 89
2 M3 T( f  ~- x6 ?  A8 S" O- ^    1.0000                                                                          // 90( Y( `* F4 k7 ?7 T
};9 {6 C0 c% h; p7 ~* f; i" y+ f
( h+ [4 t% s" R7 N9 w
#define CIRCLE_QUARTER_1        13 j! m0 S9 S/ d' I
#define CIRCLE_QUARTER_2        2' C6 }) I% F0 ?3 Y) V/ c  i
#define CIRCLE_QUARTER_3        30 v: L: y8 h( b0 v" e
#define CIRCLE_QUARTER_4        4
: |3 v( `8 O* A* `/ x5 }% \float sinus_lookup (unsigned int angle)3 z9 L! m# o  J5 n: T
{3 y+ d  C# q' a; w0 {6 E
    float sin_value;
- V& T2 O$ q2 V" T" ?* l    unsigned int circle_quarter;. y) r7 S3 H$ t0 z9 M3 S
    // correct angles outside the accepted angle range into 0 .. 359
6 R2 b, W2 q9 y. X& k4 x    if (angle > 359u)
2 E: u- Z* T3 f; E        angle = angle % 360u;
7 u% j( I  `# Y1 A' I    circle_quarter = 1 + (angle / 90u);, B6 e: U' Z. [8 A+ }' b
    switch (circle_quarter)+ \2 M, b4 V( ^/ [
    {
5 b2 t7 M* N3 u: c$ t( `5 N        case CIRCLE_QUARTER_1: // 00 .. 89# S7 ^$ M/ G9 z" U3 D
            sin_value = sinus_I_quarter[angle];
; g+ X# a! e0 {9 B' V            break;/ E5 }+ q* n) G' w
        case CIRCLE_QUARTER_2: // 90 .. 179
5 K" F+ l' G! ]+ `            sin_value = sinus_I_quarter[180 - angle];
/ l! Z( {! E2 o+ @: p0 T( {! g, j7 s            break;
) H! U2 ?& s2 H8 I7 r1 L1 ^        case CIRCLE_QUARTER_3: // 180 .. 269
2 e' Y* i& K$ a& v4 R+ q            sin_value = -sinus_I_quarter[angle - 180];% {. l: H  y, p2 h1 G1 D) M
            break;
& {/ ~; \% O2 x3 m& [% a( F% H& |! j        case CIRCLE_QUARTER_4: // 270 .. 359
1 \+ Z- B5 `/ U5 S- x0 C2 }  {            sin_value = -sinus_I_quarter[360 - angle];
& M1 |; X* A3 r8 @1 c( Z$ C' s6 ^            break;
8 j/ u; n$ b6 u2 U  k' l, b5 T    }, F, f- k# |4 ~' W! ]
    return sin_value;  q7 W3 v; p* N
}  k2 ?) D( A/ e8 ^; u6 B3 ^+ d
0 I/ u; D; F+ s
void plot_sin(uint32_t f, uint32_t delta_f)
; N3 \$ n( i8 D{
3 L8 \: X* N% j: k) y  N    /* 定时周期为T=1/delta_f, f=1/(pMax*T) */
5 S- U6 I$ K, l5 P6 j" Q& u3 n) _    static uint32_t point = 0;3 n- X+ B# A4 q" {# t
    uint32_t pMAX = delta_f/f;$ U* c1 n# E4 A
    uint32_t value = 0;+ N2 p) J8 Y! V+ G
    if (point++ > pMAX) point = 0;    2 R1 r3 J( s0 v+ j  A( k- n% k
    value = (uint32_t)((sinus_lookup(360*point/pMAX)+1)*10000)*2047/10000;
" A* b" [+ K) C  U. _    dac_software_trigger_enable();1 E$ _  L$ H3 L0 M. S# x
    dac_data_set(DAC_ALIGN_12B_R, value);7 a4 L# |6 Q. J
}
接下来是锯齿波和方波的代码,这两个代码比较简单:
void plot_triangle(uint32_t f, uint32_t delta_f)( ]! |% @7 M7 @# f3 t/ I7 E( g
{
; p& Y2 X, r# E# c7 u; S    /* 定时周期为T=1/delta_f, f=1/(pMax*T) */( Y9 K5 b' w+ k$ N7 y2 Q, b. J6 U
    static uint32_t point = 0;6 w2 n& @4 @* }- [9 l* u: Y* o
    uint32_t pMAX = delta_f/f;
, g5 a# @3 R8 X3 b" b, I    uint32_t pMAX2 = pMAX/2;
$ c/ G3 T- B4 `' v( j# w( z    uint32_t value = 0;. s+ x' l1 g- J& [( z4 H2 _1 |
    if (++point > pMAX) point = 0;
+ g, ]2 S- O+ T1 T    if (point < pMAX2)
& C, V3 o0 j: f8 w+ r2 ]    {
7 z1 C  R1 d" N        value = point * 4095 / pMAX2;
3 H$ \" f/ \$ i5 l    }
+ d8 f4 l( r2 ?7 w9 f7 M, ]. Q    else  b, S* S. w9 [0 M' M. w! v
    {
$ A/ _8 _, C2 |5 T( j' M1 i+ \        value = (pMAX - point) * 4095 / pMAX2;
9 N3 D9 H9 v, i) C4 E2 |3 X4 g    }
+ @7 ?4 ?" }1 K- i; v8 A    dac_software_trigger_enable();
4 t3 ~1 s+ i. ]3 S    dac_data_set(DAC_ALIGN_12B_R, value);
  S% O9 ?, x! o0 H9 c}
7 u9 T- z- X. x/ wvoid plot_square(uint32_t f, uint32_t delta_f)
. N8 @" @# m. n/ o{
! `/ k5 y8 H: C% e, y% d( M8 a9 h    /* 定时周期为T=1/delta_f, f=1/(pMax*T) */) v% E8 g, \' c  L. K
    static uint32_t point = 0;
5 d; U  b7 ?- Y/ Z% r& u    uint32_t pMAX = delta_f/f;9 `* D5 H5 Z8 Y, l8 A
    uint32_t pMAX2 = pMAX/2;! `% \* ?% i$ O$ {5 w, r
    uint32_t value = 0;
9 t0 G! w. a; R( [1 e, G$ F7 K. I1 D    if (++point > pMAX) point = 0;3 n( V! e: J7 ~. ~2 `2 Q
    if (point < pMAX2); p& F; l/ B, u, f! x
    {
. P7 T/ R2 }( _# W# U- q: n        value = 0;/ x& r" z$ j! J  e
    }
+ `/ X4 _( C$ b3 p8 M* O    else1 T1 b# s, }7 ]" ?1 b
    {
, X* t. ~& v$ i+ j        value = 0xFFF;& y3 a$ Y) U$ _3 s" L# ~
    }: N. |9 T9 V# ]8 }
    dac_software_trigger_enable();
5 ]8 @1 [, t. i    dac_data_set(DAC_ALIGN_12B_R, value);. `! h9 A6 M: i7 V& g+ P- p
}
最后需要开启一个定时器,还有DAC的初始化:
void timerx_init(uint32_t timer_periph, uint16_t period, uint16_t prescaler)
+ W$ r; r6 I( D5 h7 X* g% {8 K{6 p- M# C" v) F6 T8 r
    /* TIMER1 configuration: input capture mode -------------------: N: E8 @/ J! x' D$ g8 n- V# u
    the external signal is connected to TIMER1 CH0 pin (PA0)1 K7 J8 u6 N& z
    the rising edge is used as active edge
; A- R3 E1 L* c7 [. r1 q) L% r" f    the TIMER1 CH0CV is used to compute the frequency value
( R$ c/ p: w$ i' b7 P2 O+ }0 A    ------------------------------------------------------------ */
6 c, g% e  w: h    timer_parameter_struct timer_initpara;
2 Q' e9 p7 Q1 {& Q    timer_ic_parameter_struct timer_icinitpara;
% R4 H$ p0 C% i  U! j- D& o% q$ \* H( m  e* F# R
    /* enable the peripherals clock */9 i* N: e9 o& u
    rcu_periph_clock_enable(RCU_TIMER2);
- ~- \0 u  I# Z) S2 s& z7 j' O) G
- ~1 o4 S+ `- H/ s    /* deinit a TIMER */0 {; Y& A' ?- h" y3 d. _
    timer_deinit(timer_periph);( l& P& Y2 n) @% x6 u
    /* initialize TIMER init parameter struct */# Z5 x* w& A, k2 s$ l
    timer_struct_para_init(&timer_initpara);  a; m1 N9 v& {; B* D
    /* TIMER1 configuration */
) S0 w, }$ V" M  e    timer_initpara.prescaler        = prescaler;' W2 C& i4 [. X. `1 E
    timer_initpara.alignedmode      = TIMER_COUNTER_EDGE;6 e1 u: c9 ]2 u8 d% s$ b
    timer_initpara.counterdirection = TIMER_COUNTER_UP;* i/ W  K; }( ]* P9 n
    timer_initpara.period           = period;
# C: x$ Q- e- U' N% }    timer_initpara.clockdivision    = TIMER_CKDIV_DIV1;' B% d1 ^0 _% s0 j
    timer_init(timer_periph, &timer_initpara);4 m1 ^1 y" X: S2 p$ f8 u
/ o( ]6 o/ ^1 `. I; \1 Y
    /* TIMER1 CH0 input capture configuration */
6 p0 r6 L) Y6 H1 V9 J    timer_icinitpara.icpolarity  = TIMER_IC_POLARITY_RISING;. V) r- @% h; q( h& i7 Z2 V2 L* f
    timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI;$ L  m5 v9 f& E1 N6 O3 [
    timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;0 L9 o, B% a4 `3 E+ B3 j/ W7 K8 ~
    timer_icinitpara.icfilter = 0x00;
, G) X3 o0 N" h4 b# @$ v. X: @    timer_input_capture_config(timer_periph, TIMER_CH_0, &timer_icinitpara);
* S7 b1 S4 _, T# P/ F3 p+ s/ v) N" U
    /* auto-reload preload enable */
% b- k* H& Q8 F' i: O    timer_auto_reload_shadow_enable(timer_periph);7 L4 A3 s, ]. E) G- \
    /* clear channel 0 interrupt bit */3 h# H  @; @/ _
    timer_interrupt_flag_clear(timer_periph, TIMER_INT_CH0);3 X' i1 y* P+ \( ~0 F( [5 d
    /* channel 0 interrupt enable */
9 ~" w: {: ]: j, `0 S; W' E3 n2 q# c/ g    timer_interrupt_enable(timer_periph, TIMER_INT_CH0);* o# t/ _+ a, F" A% w2 H( |4 Y

5 O6 g2 Q& I; C8 @* w" W% l    /* enable a TIMER */  w" _& \: v# Q# n
    timer_enable(timer_periph);
" W' z7 s7 ]* y0 q}
' @0 y) k+ z4 i1 R+ x" d) F
' X8 K0 w- n9 W$ W& u6 p4 S+ M#define DAC_WAVE_TEST
* l5 z; d& f& o0 F9 P9 N& o) V& _# x( h' m# E* \2 R. E
void timer2_init(void): F" X2 V  [$ v4 U: s, _5 G+ `, k/ T
{
) X. ]. O7 L/ ?, {) e" i, x    timer_deinit(TIMER2);
0 x5 z8 T! X! e" S7 S/ [; B    rcu_periph_clock_enable(RCU_TIMER2);
( A4 [/ J& r& N1 _" Q#ifdef DAC_WAVE_TEST
2 I/ h" u6 W& W    timerx_init(TIMER2, 639, 9);  // 100KHz 0.1ms5 H5 U! [; Z  a7 Z' D
#endif
8 e# K% H2 F+ f3 L$ m    timer_interrupt_enable(TIMER2, TIMER_INT_UP);1 a  [5 Q8 E; _4 E/ p. z3 q- }/ |& Y
    nvic_irq_enable(TIMER2_IRQn, 3);& f+ a  B+ p9 E6 S2 {
}  D. m2 j; m& D% j1 C

- O8 v; t# H+ B( F6 Nvoid TIMER2_IRQHandler(void), n' G4 P4 U/ M5 G2 E
{
- ~* ~. A* F6 |#ifdef DAC_WAVE_TEST0 X! Y4 m) I- \9 m
    plot_sin(100, 10000);       //正弦波
% w+ N3 y8 o, K' y! H- O' ?/ l    //plot_triangle(1, 10000);  //锯齿波3 i4 k! R4 p) q. [
    //plot_square(1, 10000);    //方波* `% [7 K: K* W6 U
#endif
( h! T: r' ?' f4 F3 o. u7 U    timer_interrupt_flag_clear(TIMER2, TIMER_INT_FLAG_UP);' A( h( ]: o8 U! k
}3 h8 V4 ^& ]$ w& k& C/ ]- J
; F; R1 f- H; z7 F& S( m; V4 V
void dac1_init(void)* J" q8 H# T; o6 H
{, Y; n9 A- q/ S& \/ i( B
    rcu_periph_clock_enable(RCU_GPIOA);
$ r7 J" G1 J# i3 @$ {+ E    rcu_periph_clock_enable(RCU_DAC);
! I* \9 r; [+ N$ n5 h3 [( H% b    gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_4);2 ~( V9 t; Q+ C1 H' x- e, T
    dac_deinit();
7 T% d2 Q% _/ K3 _5 y    /* software trigger */
+ |; K1 J; L# b+ R" \4 j    dac_trigger_enable();2 s. w# [, w* t# }; V
    dac_trigger_source_config(DAC_TRIGGER_SOFTWARE);
$ q, i7 b* T1 f1 V( e    /* no noise wave */! _1 O$ ?( e4 c! @# O9 M( S# l
    dac_wave_mode_config(DAC_WAVE_DISABLE);/ f$ Z5 M; d: P% R: c" k
    /* noise wave - triangle */
; ~" y7 w  W, ^5 i5 {    //dac_wave_mode_config(DAC_WAVE_MODE_TRIANGLE);$ |" i% a5 S/ ?* y3 X$ R& q, `; g
    //dac_triangle_noise_config(DAC_TRIANGLE_AMPLITUDE_4095);9 ^" q( e3 k, U0 p
    /* noise wave - lfsr */$ t  k, f  Q0 Z
    //dac_wave_mode_config(DAC_WAVE_MODE_LFSR);
) J  d: P5 g, f5 E! h: ]2 L    //dac_lfsr_noise_config(DAC_LFSR_BITS11_0);
* ^) ?$ d$ t) T+ G+ h    dac_output_buffer_enable();
5 V! _, |% h4 e2 v/ ]    /* enable DAC and set data */' E6 W, A1 W$ Y2 f9 o& u: [! o
    dac_enable();
+ r: l; S, ^* M+ R2 p$ [, z( b    dac_software_trigger_enable();
9 C! G4 D$ Z5 r" f+ R1 y    dac_data_set(DAC_ALIGN_12B_R, 0);9 S* ^: b: q% Z- h+ D
}
这样就可以输出正弦波、锯齿波和方波了。
2 ~& {! }* u7 q" Q, ~* D8 F' B
3.波形测量
. L: O8 p: X0 s: ]/ B. l7 e
接下来我们来看一下输出的波形是否符合要求,首先需要将【GD32L233C-START】开发板连接LOTO示波器,分别连接GND和PA4管教,连接效果图如下图1所示。
图1

) c% e; C: W' S7 m! s) r- {
然后让DAC输出正弦波,看一下波形如何。
图2
" [0 y+ R; k5 j2 v; r; x
从上图2中可以看到,一个周期大约在10ms,所以正弦波的周期为100Hz,输出还是听精准的。/ I+ P+ P4 k7 z2 Q+ A% v- ^
然后输出锯齿波看看波形如何。
图3
3 z3 Z3 D* [# R. [: K8 T
从上图3可以得出,锯齿波的波形频率为1Hz。
/ F- `  M2 Q2 Q# r
最后我们来看看方波的波形图如何。
图4

2 O: I% V/ V# A2 M; ?: i
从上图4可以看到,方波的波形频率为1Hz。
% Z& f* f9 P! I3 f
从上面波形可以得出,【GD32L233C-START】的定时器比较精准,DAC的输出值也比较稳定,性能还是不错的!
2 u* A# m7 \7 o6 k3 I/ h
4.总结
) P1 p# @' L/ `
刚入手的LOTO示波器还不错,测量的精度挺高的,不过还有好多设置没弄明白,等后续多琢磨琢磨。做电子的示波器是必不可少的,我先替你们测试测试这个示波器如何。) }# `4 ?6 ^% [* \+ ^+ [2 V
GD32L233C是新出来的芯片,整体功能还需要多进行测试,它最突出的低功耗后续要好好测量一下,这次就先到这里了。
  • TA的每日心情
    开心
    2022-12-26 15:46
  • 签到天数: 1 天

    [LV.1]初来乍到

    2#
    发表于 2022-3-30 17:47 | 只看该作者
    低功耗芯片
    您需要登录后才可以回帖 登录 | 注册

    本版积分规则

    关闭

    推荐内容上一条 /1 下一条

    EDA365公众号

    关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

    GMT+8, 2025-8-24 12:07 , Processed in 0.140625 second(s), 26 queries , Gzip On.

    深圳市墨知创新科技有限公司

    地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

    快速回复 返回顶部 返回列表