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

1.介绍
gd32l233c采用的是一款m23的内核。这个芯片据说功耗非常的低,低到什么程度呢?等后面我们再进行测试,今天我们主要来测试gd32l233c-start的dac,既然要测试dac,示波器是不可少的,这个实验在家做,然而lz家里并没有示波器,不过最近看到一款好东西,loto虚拟示波器,看过这款示波器的参数,还不错。所以入手了一款,测量芯片输出的dac应该没什么问题,接下来开始测试吧。
2.设计
首先需要输出让芯片输出dac,而且还需要输出波形,这个稍微费点功夫,之前在gd32l233c-start移植了rtthread,现在在这个代码的基础上添加dac的输出程序,这个程序移植了其他网友的,代码我也贴出来,经过测试,代码没有啥问题:
比较麻烦的是正弦波的代码:
const float sinus_i_quarter[91] =
{
    0.0000, 0.0175, 0.0349, 0.0523, 0.0698, 0.0872, 0.1045, 0.1219, 0.1392, 0.1564, // 00 .. 09
    0.1736, 0.1908, 0.2079, 0.2250, 0.2419, 0.2588, 0.2756, 0.2924, 0.3090, 0.3256, // 10 .. 19
    0.3420, 0.3584, 0.3746, 0.3907, 0.4067, 0.4226, 0.4384, 0.4540, 0.4695, 0.4848, // 20 .. 29
    0.5000, 0.5150, 0.5299, 0.5446, 0.5592, 0.5736, 0.5878, 0.6018, 0.6157, 0.6293, // 30 .. 39
    0.6428, 0.6561, 0.6691, 0.6820, 0.6947, 0.7071, 0.7193, 0.7314, 0.7431, 0.7547, // 40 .. 49
    0.7660, 0.7771, 0.7880, 0.7986, 0.8090, 0.8192, 0.8290, 0.8387, 0.8480, 0.8572, // 50 .. 59
    0.8660, 0.8746, 0.8829, 0.8910, 0.8988, 0.9063, 0.9135, 0.9205, 0.9272, 0.9336, // 60 .. 69
    0.9397, 0.9455, 0.9511, 0.9563, 0.9613, 0.9659, 0.9703, 0.9744, 0.9781, 0.9816, // 70 .. 79
    0.9848, 0.9877, 0.9903, 0.9925, 0.9945, 0.9962, 0.9976, 0.9986, 0.9994, 0.9998, // 80 .. 89
    1.0000                                                                          // 90
};
#define circle_quarter_1        1
#define circle_quarter_2        2
#define circle_quarter_3        3
#define circle_quarter_4        4
float sinus_lookup (unsigned int angle)
{
    float sin_value;
    unsigned int circle_quarter;
    // correct angles outside the accepted angle range into 0 .. 359
    if (angle > 359u)
        angle = angle % 360u;
    circle_quarter = 1 + (angle / 90u);
    switch (circle_quarter)
    {
        case circle_quarter_1: // 00 .. 89
            sin_value = sinus_i_quarter[angle];
            break;
        case circle_quarter_2: // 90 .. 179
            sin_value = sinus_i_quarter[180 - angle];
            break;
        case circle_quarter_3: // 180 .. 269
            sin_value = -sinus_i_quarter[angle - 180];
            break;
        case circle_quarter_4: // 270 .. 359
            sin_value = -sinus_i_quarter[360 - angle];
            break;
    }
    return sin_value;
}
void plot_sin(uint32_t f, uint32_t delta_f)
{
    /* 定时周期为t=1/delta_f, f=1/(pmax*t) */
    static uint32_t point = 0;
    uint32_t pmax = delta_f/f;
    uint32_t value = 0;
    if (point++ > pmax) point = 0;    
    value = (uint32_t)((sinus_lookup(360*point/pmax)+1)*10000)*2047/10000;
    dac_software_trigger_enable();
    dac_data_set(dac_align_12b_r, value);
}
接下来是锯齿波和方波的代码,这两个代码比较简单:
void plot_triangle(uint32_t f, uint32_t delta_f)
{
    /* 定时周期为t=1/delta_f, f=1/(pmax*t) */
    static uint32_t point = 0;
    uint32_t pmax = delta_f/f;
    uint32_t pmax2 = pmax/2;
    uint32_t value = 0;
    if (++point > pmax) point = 0;
    if (point pmax) point = 0;
    if (point < pmax2)
    {
        value = 0;
    }
    else
    {
        value = 0xfff;
    }
    dac_software_trigger_enable();
    dac_data_set(dac_align_12b_r, value);
}
最后需要开启一个定时器,还有dac的初始化:
void timerx_init(uint32_t timer_periph, uint16_t period, uint16_t prescaler)
{
    /* timer1 configuration: input capture mode -------------------
    the external signal is connected to timer1 ch0 pin (pa0)
    the rising edge is used as active edge
    the timer1 ch0cv is used to compute the frequency value
    ------------------------------------------------------------ */
    timer_parameter_struct timer_initpara;
    timer_ic_parameter_struct timer_icinitpara;
/* enable the peripherals clock */
    rcu_periph_clock_enable(rcu_timer2);
/* deinit a timer */
    timer_deinit(timer_periph);
    /* initialize timer init parameter struct */
    timer_struct_para_init(&timer_initpara);
    /* timer1 configuration */
    timer_initpara.prescaler        = prescaler;
    timer_initpara.alignedmode      = timer_counter_edge;
    timer_initpara.counterdirection = timer_counter_up;
    timer_initpara.period           = period;
    timer_initpara.clockdivision    = timer_ckdiv_div1;
    timer_init(timer_periph, &timer_initpara);
/* timer1 ch0 input capture configuration */
    timer_icinitpara.icpolarity  = timer_ic_polarity_rising;
    timer_icinitpara.icselection = timer_ic_selection_directti;
    timer_icinitpara.icprescaler = timer_ic_psc_div1;
    timer_icinitpara.icfilter = 0x00;
    timer_input_capture_config(timer_periph, timer_ch_0, &timer_icinitpara);
/* auto-reload preload enable */
    timer_auto_reload_shadow_enable(timer_periph);
    /* clear channel 0 interrupt bit */
    timer_interrupt_flag_clear(timer_periph, timer_int_ch0);
    /* channel 0 interrupt enable */
    timer_interrupt_enable(timer_periph, timer_int_ch0);
/* enable a timer */
    timer_enable(timer_periph);
}
#define dac_wave_test
void timer2_init(void)
{
    timer_deinit(timer2);
    rcu_periph_clock_enable(rcu_timer2);
#ifdef dac_wave_test
    timerx_init(timer2, 639, 9);  // 100khz 0.1ms
#endif
    timer_interrupt_enable(timer2, timer_int_up);
    nvic_irq_enable(timer2_irqn, 3);
}
void timer2_irqhandler(void)
{
#ifdef dac_wave_test
    plot_sin(100, 10000);       //正弦波
    //plot_triangle(1, 10000);  //锯齿波
    //plot_square(1, 10000);    //方波
#endif
    timer_interrupt_flag_clear(timer2, timer_int_flag_up);
}
void dac1_init(void)
{
    rcu_periph_clock_enable(rcu_gpioa);
    rcu_periph_clock_enable(rcu_dac);
    gpio_mode_set(gpioa, gpio_mode_analog, gpio_pupd_none, gpio_pin_4);
    dac_deinit();
    /* software trigger */
    dac_trigger_enable();
    dac_trigger_source_config(dac_trigger_software);
    /* no noise wave */
    dac_wave_mode_config(dac_wave_disable);
    /* noise wave - triangle */
    //dac_wave_mode_config(dac_wave_mode_triangle);
    //dac_triangle_noise_config(dac_triangle_amplitude_4095);
    /* noise wave - lfsr */
    //dac_wave_mode_config(dac_wave_mode_lfsr);
    //dac_lfsr_noise_config(dac_lfsr_bits11_0);
    dac_output_buffer_enable();
    /* enable dac and set data */
    dac_enable();
    dac_software_trigger_enable();
    dac_data_set(dac_align_12b_r, 0);
}
这样就可以输出正弦波、锯齿波和方波了。
3.波形测量
接下来我们来看一下输出的波形是否符合要求,首先需要将【gd32l233c-start】开发板连接loto示波器,分别连接gnd和pa4管教,连接效果图如下图1所示。
图1
然后让dac输出正弦波,看一下波形如何。
图2
从上图2中可以看到,一个周期大约在10ms,所以正弦波的周期为100hz,输出还是听精准的。
然后输出锯齿波看看波形如何。
图3
从上图3可以得出,锯齿波的波形频率为1hz。
最后我们来看看方波的波形图如何。
图4
从上图4可以看到,方波的波形频率为1hz。
从上面波形可以得出,【gd32l233c-start】的定时器比较精准,dac的输出值也比较稳定,性能还是不错的!
4.总结
刚入手的loto示波器还不错,测量的精度挺高的,不过还有好多设置没弄明白,等后续多琢磨琢磨。做电子的示波器是必不可少的,我先替你们测试测试这个示波器如何。
gd32l233c是新出来的芯片,整体功能还需要多进行测试,它最突出的低功耗后续要好好测量一下,这次就先到这里了。

Kang Watch智能血压手表高调亮相
马达驱动厂商:深圳市联德合微电子有限公司简介
微软的Xbox Series X及索尼的PS5主机即将正式上市
汽车芯片封装工艺:深入探究芯片封装的详细工艺流程
助焊膏有什么作用?什么成份?
【GD32L233C-START】DAC输出(正弦波、锯齿波、方波)
2022 CNCC DPU技术论坛亮点提前看
英伟达Shield TV Pro的售价再次爆出,运行速度将提高25%
泰凌微深耕IoT蓝牙技术 低功耗蓝牙终端产品认证数量突破
[组图]门控开关
利用LabVIEW对飞机推进装置进行飞行压力测试
众多低速电动车品牌面临困境 雷丁却斥资14.6亿收购野马
国外服务器如何租用,需要注意些什么
英特尔公司推出 酷睿 博锐 处理器家族
汽车钥匙解码器的工作原理与结构解析
2023:汽车行业哪些技术趋势值得关注?
盘点一些最近动作频繁的AR Cloud公司
盘点无线传感器网络三大应用领域
能耗监测系统在学校中的应用说明
DSP是什么?详解DSP又称数字信号处理器