DAC-DMA-TIMER总结(实现5阶正弦波)

一、实现原理:

先将一个可以生成正弦波的数据表(table)保存在一片固定地址的内存中,然后在DAC以及这块内存中间使用DMA建立一个专属通道,使用定时器的TRGO触发模式触发DAC,DAC模块就可以定时地通过DAM通道拿取这片内存中的正弦波的数据,然后经过DAC数模转换,输出到引脚就可以得到一定频率、幅值的正弦波(波形)了。

二、实现方法(基于GD32):

1、定义正弦波数组

const unsigned short int sine_data[200] =

{    2048,2308,2555,2773,2952,3083,3158,3179,3150,3075,2965,2830,2683,2535,2401,2286,2199,2144,2120,2128,    2157,2205,2264,2323,2378,2419,2440,2442,2424,2388,2337,2278,2214,2154,2104,2066,2046,2042,2055,2081,    2115,2153,2190,2218,2238,2242,2228,2199,2158,2105,2048,1990,1937,1896,1867,1853,1858,1877,1905,1942,    1980,2014,2040,2053,2049,2029,1991,1942,1881,1817,1758,1707,1671,1653,1655,1676,1717,1772,1831,1890,    1938,1968,1975,1951,1896,1809,1694,1560,1412,1265,1130,1020,945,916,937,1012,1143,1322,1540,1788,    2048,2308,2555,2773,2952,3083,3158,3179,3150,3075,2965,2830,2683,2535,2401,2286,2199,2144,2120,2128,    2157,2205,2264,2323,2378,2419,2440,2442,2424,2388,2337,2278,2214,2154,2104,2066,2046,2042,2055,2081,    2115,2153,2190,2218,2238,2242,2228,2199,2158,2105,2048,1990,1937,1896,1867,1853,1858,1877,1905,1942,    1980,2014,2040,2053,2049,2029,1991,1942,1881,1817,1758,1707,1671,1653,1655,1676,1717,1772,1831,1890,    1938,1968,1975,1951,1896,1809,1694,1560,1412,1265,1130,1020,945,916,937,1012,1143,1322,1540,1788

};

注意:全局变量已赋初值,单片机一上电后,会将此数据从ROM中拷贝到RAM中。

 

2、初始化各路时钟(GPIOA+DMA1+DAC+TIEMR5)

void rcu_config(void)
{
    /* enable the clock of peripherals */
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_DMA1);
    rcu_periph_clock_enable(RCU_DAC);
    rcu_periph_clock_enable(RCU_TIMER5);
}

3、GPIO初始化(模拟输入)

void gpio_config(void)
{
    /* once enabled the DAC, the corresponding GPIO pin is connected to the DAC converter automatically */
    gpio_init(GPIOA, GPIO_MODE_AIN, GPIO_OSPEED_50MHZ, GPIO_PIN_5);
}

4、 DMA配置
(使用DMA1的CH3通道)

#define   DAC_DHR12R2_Address     (0x40007414)  // 如果使用DAC0(PA4)的话,地址为(0x40007408
)
void dma_config(void)
{
    dma_parameter_struct dma_struct;
    /* clear all the interrupt flags */
    dma_flag_clear(DMA1, DMA_CH3, DMA_INTF_GIF);
    dma_flag_clear(DMA1, DMA_CH3, DMA_INTF_FTFIF);
    dma_flag_clear(DMA1, DMA_CH3, DMA_INTF_HTFIF);
    dma_flag_clear(DMA1, DMA_CH3, DMA_INTF_ERRIF);
    
    /* configure the DMA1 channel 2 */
    dma_struct.periph_addr  = DAC_DHR12R2_Address;
    dma_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
    dma_struct.memory_addr  = (uint32_t)(sine_data);
    dma_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;
    dma_struct.number       = 200;
    dma_struct.priority     = DMA_PRIORITY_ULTRA_HIGH;
    dma_struct.periph_inc   = DMA_PERIPH_INCREASE_DISABLE;
    dma_struct.memory_inc   = DMA_MEMORY_INCREASE_ENABLE;
    dma_struct.direction    = DMA_MEMORY_TO_PERIPHERAL;
    dma_init(DMA1, DMA_CH3, &dma_struct);

    dma_circulation_disable(DMA1, DMA_CH3); // 只触发一个数据组(200个),如果想持续触发,则enable即可
    dma_channel_enable(DMA1, DMA_CH3);
}

5、DAC配置
(使用的是DAC1(对应PA5引脚))

void dac_config(void)
{
    dac_deinit();
    /* configure the DAC1 */
    dac_trigger_source_config(DAC1, DAC_TRIGGER_T5_TRGO); // 使用定时器5的TRGO触发DAC
    dac_trigger_enable(DAC1);
    dac_wave_mode_config(DAC1, DAC_WAVE_DISABLE);
    //dac_output_buffer_disable(DAC1);
    dac_output_buffer_enable(DAC1);
    
    /* enable DAC1 and DMA for DAC1 */
    dac_enable(DAC1);
    dac_dma_enable(DAC1);
}

6、定时器配置
(此处系统时钟为108MHz,设置定时器触发频率收到为50kHz,对应正弦波频率为50/200=0.25kHz)

/*!
    \brief      configure the TIMER5
    \param[in]  none
    \param[out] none
    \retval     none
    \ 20us ==> 50kHz ==> 108000000/2160 ==> (0xF+1)*(0x86+1)=2160
*/
void timer5_config(void)
{
    /* configure the TIMER5 */
    timer_prescaler_config(TIMER5, 0xF, TIMER_PSC_RELOAD_UPDATE);
    timer_autoreload_value_config(TIMER5, 0x86);
    timer_master_output_trigger_source_select(TIMER5, TIMER_TRI_OUT_SRC_UPDATE);
    
timer_enable(TIMER5);
}

总体实现流程:

 

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值