|
发表于 2020-6-8 10:27:33
|
显示全部楼层
用STM32F030C8T6的TIM16【PB8管脚】播放PCM音频流,11K/s,8bit;仅供参考:
- #define AUDIO_MUTE_LEN (118) /* 118个样本大约播放10毫秒 */
- static uint8_t const audio_mute[AUDIO_MUTE_LEN] = {
- 128,128,128,128,128,128,128,128,
- 128,128,128,128,128,128,128,128,
- 128,128,128,128,128,128,128,128,
- 128,128,128,128,128,128,128,128,
- 128,128,128,128,128,128,128,128,
- 128,128,128,128,128,128,128,128,
- 128,128,128,128,128,128,128,128,
- 128,128,128,128,128,128,128,128,
- 128,128,128,128,128,128,128,128,
- 128,128,128,128,128,128,128,128,
- 128,128,128,128,128,128,128,128,
- 128,128,128,128,128,128,128,128,
- 128,128,128,128,128,128,128,128,
- 128,128,128,128,128,128,128,128,
- 128,128,128,128,128,128
- };
- static volatile struct {
- const uint8_t *buf_addr1;
- uint32_t buf_len1;
-
- const uint8_t *buf_addr2;
- uint32_t buf_len2;
-
- uint8_t trig_req;
- } audio_dev = { .buf_len1 = 0, .buf_len2 = 0, .trig_req = 0 };
- void Drv_AudioOpen(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- /**************************************************************************/
- /* Timer16用作音频输出,管脚为PB8(AF2=TIM16_CH1),PB6(AF2=TIM16_CH1N) */
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_8;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
- GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
- GPIO_Init(GPIOB, &GPIO_InitStructure);
- GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_2);
- GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_2);
-
- /* 开启Timer16的系统时钟,并初始化Timer16 */
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM16, ENABLE);
- /* 关闭Timer计数器 */
- TIM16->CR1 = TIM_CR1_ARPE|TIM_CR1_URS;
- TIM16->CR2 = 0;
- /* 关闭Timer中断 */
- TIM16->DIER = 0;
- TIM16->SR = 0;
- /* 预分频使CK_CNT=12MHZ,同时配置RCR=3且ARR=254,
- 就可以得到11718.75HZ脉冲,
- 与标准音频采样频率11025HZ近似 */
- TIM16->PSC = (4-1);
- /* 每个音频脉冲输出4次 */
- TIM16->RCR = (4-1);
- /* 配置PWM脉宽 */
- TIM16->ARR = (uint16_t)(255-1);
-
- /* 配置比较器工作在PWM方式,并配置其电平逻辑 */
- TIM16->CCMR1 = ((6<<4)|TIM_CCMR1_OC1PE|TIM_CCMR1_OC1FE|(0<<0));
- TIM16->CCER = ((0<<3)|TIM_CCER_CC1NE|(0<<1)|TIM_CCER_CC1E);
- TIM16->BDTR = (TIM_BDTR_MOE|TIM_BDTR_AOE|(0<<12));
- /* 配置PWM的有效电平脉宽 */
- TIM16->CCR1 = (uint16_t)128;
- TIM16->EGR = TIM_EGR_UG; /* 手动更新设定值 */
- /* 配置Timer模块的DMA功能 */
- TIM16->DCR = TIM_DMABurstLength_1Transfer|TIM_DMABase_CCR1;
- TIM16->DIER = TIM_DIER_CC1DE; /* 使能CC1的DMA请求 */
- TIM16->CR2 |= TIM_CR2_CCDS; /* Update时产生CCx的DMA请求 */
- TIM16->CR1 |= TIM_CR1_CEN;
-
- /* 配置DMA1_Channel4模块,用于Timer */
- RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
- /* 注意:要使SYSCFG_CFGR1寄存器起作用,必须开启SYSCFG模块时钟! */
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
- SYSCFG_DMAChannelRemapConfig(SYSCFG_DMARemap_TIM16, ENABLE);
-
- /* 使用DMA1通道4响应TIM16_UP的传输请求 */
- DMA1->IFCR = DMA_IFCR_CGIF4;
- /* 源端口8位宽,目的端口16位宽,NDT是指源端口读取次数 */
- DMA1_Channel4->CCR = ((0<<12)|(1<<8)|DMA_CCR_MINC|DMA_CCR_DIR);
- DMA1_Channel4->CCR |= (DMA_CCR_TEIE|DMA_CCR_TCIE);
- DMA1_Channel4->CPAR = (uint32_t)&TIM16->DMAR;
- DMA1_Channel4->CMAR = (uint32_t)audio_mute;
- DMA1_Channel4->CNDTR = (uint16_t)AUDIO_MUTE_LEN;
- /* DMA1_Channel4->CCR |= DMA_CCR_EN; */
- NVIC_EnableIRQ(DMA1_Channel4_5_IRQn);
- audio_dev.trig_req = 1;
- }
- int Drv_AudioPlay(uint8_t const stream[], int num)
- {
- if(audio_dev.buf_len1 == 0){
- audio_dev.buf_addr1 = stream;
- audio_dev.buf_len1 = num;
- return num;
- }else if(!audio_dev.buf_len2){
- audio_dev.buf_addr2 = stream;
- audio_dev.buf_len2 = num;
- return num;
- }
- return 0;
- }
- void Drv_AudioClose(void)
- {
- audio_dev.trig_req = 0;
- TIM16->CR1 &= ~TIM_CR1_CEN;
- NVIC_DisableIRQ(DMA1_Channel4_5_IRQn);
- DMA1_Channel4->CCR &= ~DMA_CCR_EN;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM16, DISABLE);
- }
- void Drv_AudioAppHook(void)
- {
- if(audio_dev.trig_req){
- if(audio_dev.buf_len1){
- audio_dev.trig_req = 0;
- DMA1_Channel4->CCR &= ~DMA_CCR_EN;
- DMA1_Channel4->CMAR = (uint32_t)audio_dev.buf_addr1;
- DMA1_Channel4->CNDTR = (uint16_t)audio_dev.buf_len1;
- DMA1_Channel4->CCR |= DMA_CCR_EN;
- audio_dev.buf_len1 = 0;
- }else if(audio_dev.buf_len2){
- audio_dev.trig_req = 0;
- DMA1_Channel4->CCR &= ~DMA_CCR_EN;
- DMA1_Channel4->CMAR = (uint32_t)audio_dev.buf_addr2;
- DMA1_Channel4->CNDTR = (uint16_t)audio_dev.buf_len2;
- DMA1_Channel4->CCR |= DMA_CCR_EN;
- audio_dev.buf_len2 = 0;
- }
- }
- }
- /* PWM音频引擎控制中断 */
- void TIM16_IRQHandler(void)
- {
- TIM16->SR = 0;
- }
- /* PWM音频引擎输出中断 */
- void DMA1_Channel4_5_IRQHandler(void)
- {
- uint32_t isr = DMA1->ISR;
-
- if(isr & DMA_ISR_GIF4){
-
- DMA1->IFCR = DMA_IFCR_CGIF4;
-
- if(isr & DMA_ISR_TEIF4){
- /* A transfer error (TE) occurred */
- audio_dev.trig_req = 0;
- DMA1_Channel4->CCR &= ~DMA_CCR_EN;
- DMA1_Channel4->CMAR = (uint32_t)audio_mute;
- DMA1_Channel4->CNDTR = (uint16_t)AUDIO_MUTE_LEN;
- DMA1_Channel4->CCR |= DMA_CCR_EN;
- }
-
- if(isr & DMA_ISR_TCIF4){
- /* A transfer complete (TC) event occurred */
- DMA1_Channel4->CCR &= ~DMA_CCR_EN;
- if(audio_dev.buf_len1){
- audio_dev.trig_req = 0;
- DMA1_Channel4->CMAR = (uint32_t)audio_dev.buf_addr1;
- DMA1_Channel4->CNDTR = (uint16_t)audio_dev.buf_len1;
- DMA1_Channel4->CCR |= DMA_CCR_EN;
- audio_dev.buf_len1 = 0;
- }else if(audio_dev.buf_len2){
- audio_dev.trig_req = 0;
- DMA1_Channel4->CMAR = (uint32_t)audio_dev.buf_addr2;
- DMA1_Channel4->CNDTR = (uint16_t)audio_dev.buf_len2;
- DMA1_Channel4->CCR |= DMA_CCR_EN;
- audio_dev.buf_len2 = 0;
- }else{
- audio_dev.trig_req = 1;
- }
- }
- }
- }
复制代码 |
|