详见代码

https://gitee.com/qinyunti/fr3068-e-c-micropython.git


为了实现dac播放音乐,先来实现dac的任意输出测试

原理图

原理图如下使用PB12控制PA,PC7和PC6为DAC的R通道输出

130719h9rlcbcehcy9c3wc

130719ayhefdc3faxgyycf

路径如下,使能mono模式时,始终使用L的FIFO

130719m99c33g23g149oby

PA控制

void app_dac_pa_init(void){

        GPIO_InitTypeDef gpio_config;

        __SYSTEM_GPIOB_CLK_ENABLE();

  gpio_config.Pin = GPIO_PIN_12;

  gpio_config.Mode = GPIO_MODE_OUTPUT_PP;

  gpio_config.Pull = GPIO_PULLUP;

  gpio_config.Alternate = GPIO_FUNCTION_0;

  gpio_init(GPIOB, &gpio_config);

}

void app_dac_pa_ctrl(int en){

                if(en != 0){

                        gpio_write_pin(GPIOB,GPIO_PIN_12,GPIO_PIN_CLEAR);

                }else{

                        gpio_write_pin(GPIOB,GPIO_PIN_12,GPIO_PIN_SET);

                }

}

增加shell命令控制,测试控制

130720mo80hh8h5qoo0nnj

DAC初始化

引脚配置

        __SYSTEM_GPIOC_CLK_ENABLE();

   GPIO_InitTypeDef CodecIO;

   CodecIO.Pin  = GPIO_PIN_6 | GPIO_PIN_7;

   CodecIO.Mode = GPIO_MODE_AF_PP;

   CodecIO.Pull = GPIO_PULLUP;

   CodecIO.Alternate = GPIO_FUNCTION_D;

   gpio_init(GPIOC, &CodecIO);

这里demo功能配置为D,但是数据手册中对应的是C不知道为何??

130720ptdd556tvtux3vud

DAC配置

                __SYSTEM_PSD_DAC_CLK_ENABLE();


        hpsd.Init.DataSrc = PSD_DAC_DATA_SOURCE_DACFIFO;

        hpsd.Init.Right_mix = PSD_DAC_FUNC_DISABLE;

        hpsd.Init.Left_mix = PSD_DAC_FUNC_DISABLE;

        hpsd.Init.MonoEn = PSD_DAC_FUNC_ENABLE;

        hpsd.Init.ClockSource = PSD_DAC_CLOCK_SOURCE_24M_MODE;

        hpsd.Init.Swap = 0;

        hpsd.Init.SampleRate = PSD_DAC_SAMPLE_RATE_16000;

        hpsd.Init.Oversampling_Level = PSD_DAC_OVERSAMPLING_LOW;

        hpsd.Init.DAC_DataFormat = PSD_DAC_FIFO_FORMAT_24BIT;

        hpsd.Init.DAC_FIFOCombine = PSD_DAC_FUNC_DISABLE;

        hpsd.Init.DAC_FIFOThreshold = sizeof(dac_data)/sizeof(dac_data[0]);

        hpsd.DAC_FIFO_LeftEmpty_Callback = dac_leftempty_cb;

        hpsd.DAC_FIFO_RightEmpty_Callback = dac_rightempty_cb;

        hpsd.DAC_FIFO_LeftAlmostEmpty_Callback = dac_leftalmostempty_cb;

        hpsd.DAC_FIFO_RightAlmostEmpty_Callback = dac_rightalmostempty_cb;


  NVIC_SetPriority(PSD_DAC_IRQn, 4);

  NVIC_EnableIRQ(PSD_DAC_IRQn);

        psd_dac_int_clr(PSD_DAC_INT_DACFF_L_AEMPTY);

        psd_dac_int_clr(PSD_DAC_INT_DACFF_R_AEMPTY);               

        psd_dac_int_disable(PSD_DAC_INT_DACFF_L_AEMPTY);

        psd_dac_int_disable(PSD_DAC_INT_DACFF_R_AEMPTY);       

        psd_dac_init(&hpsd);

        psd_dac_mute_contrl(0);

  psd_dac_set_volume(PSD_DAC_CH_LR, 0x1000);       

DAC中断入口配置

默认中断入口是psd_dac_irq

需要在

components\drivers\peripheral\Inc\driver_psd_dac.h中添加驱动的中断函数申明

void psd_dac_IRQHandler(PSD_DAC_HandleTypeDef *hpsd);

examples\evb_demo\lvgl_demo\Src\app_dac.c中

实现中断入口调用驱动的中断函数

void psd_dac_irq(void)

{

    psd_dac_IRQHandler(&hpsd);

}

其实作为SDK来说建议这一部分驱动应该对应好,无需用户再回调一次,

用户只需要init时指定回调即可。

增加清除中断入口

#define __PSD_DAC_INT_STATUS_CLR(__STATUS__)                (PSD_DAC->DACIntRawStatus &= ~(__STATUS__));(PSD_DAC->DACIntStatus &= ~(__STATUS__))

void psd_dac_int_clr(enum_PSD_DAC_INT_Status_t fe_Int_Status)

{

    __PSD_DAC_INT_STATUS_ENABLE(fe_Int_Status);

}

中断测试

FIFO是64个点,对于16k,发送16个点对应1ms,先写32个点,设置阈值16个点,半满中断,继续写下一个16个点,形成ping-pong

static uint32_t dac_data[16];

          psd_dac_write_dac_fifo_left(dac_data, sizeof(dac_data)/sizeof(dac_data[0]));

                psd_dac_write_dac_fifo_left(dac_data, sizeof(dac_data)/sizeof(dac_data[0]));

                psd_dac_int_enable(PSD_DAC_INT_DACFF_L_AEMPTY);

void dac_leftalmostempty_cb(struct __PSD_DAC_HandleTypeDef *hpsd){

        psd_dac_write_dac_fifo_left(dac_data, sizeof(dac_data)/sizeof(dac_data[0]));       

                psd_dac_int_clr(PSD_DAC_INT_DACFF_L_AEMPTY);

        printf("lae\r\n");

}

测试中断产生

130720yg8qfibpm49bl13m

测试输出

产生正弦波测试

线性测试

          for(int i=0; i<sizeof(dac_data)/sizeof(dac_data[0]);i++){

                  int tmp = sin((2*3.141592653*i)/(sizeof(dac_data)/sizeof(dac_data[0])))*32767;

                        //int tmp = -32768 + i*65536/(sizeof(dac_data)/sizeof(dac_data[0]));

                        printf("%d\r\n",tmp);

                        dac_data = ((uint32_t)(tmp&0xFFFF))<<8;

                }

对应如下值

130720ullttlam9zw0sl3b

示波器测量,看到采样率和波形都正确

130720mi9duo8foav4ivfg

130720eb74cbd08betl9ch