【MM32】PWM 正弦波调制音频 - 定时器之 FDS 配置

文章目录

  • 使用资源
    • 定时器
      • 高级定时器1
        • 1.实现功能
        • 2.初始化配置
      • 通用定时器2
        • 1.实现功能
        • 2.初始化配置
      • 系统滴答定时器

使用资源

定时器

  • 高级定时器1(TIM1)
  • 通用定时器2(TIM2)
  • 系统滴答定时器(SYSTICK)

高级定时器1

1.实现功能

控制PA8(TIM1CH1)PWM 输出相应 调制后的PWM波 至蜂鸣器引脚BUZ
【MM32】PWM 正弦波调制音频 - 定时器之 FDS 配置_第1张图片

2.初始化配置

////////////////////////////////////////////////////////////////////////////////
void initTimer1()
{
    hTIM = CreateFile(emIP_TIM);
	if (hTIM == NULL)		while(1);
	tAPP_TIM_DCB dcb1 = {
		.hSub 		= emFILE_TIM1,
        .mode		= emTIM_PWM,
        .cntFreq    = BASEFREQ,
        .period     = BASEARR,
        .pulse      = 0,
		.ch         = emTIM_CH1,
        .cbUp       = (u32)(&UpdateCallback1),
		.cbCc       = NULL,
		.type		= emTYPE_IT,
		.sync		= emTYPE_Sync,
        .remapEn	= false,
		.remapIdx	= 0
	};
	if (!OpenFile(hTIM, (void*)&dcb1))		while(1);
}
  • 该初始化配置调用了 MM32-FDS 固件库 ,具体参数配置参考MM32-FDS内部注释。本文不做详解,
  • 说明一点:
    1.Timer1 之 update 更新中断回调函数为 void UpdateCallback1(void* fPtr)
////////////////////////////////////////////////////////////////////////////////
void UpdateCallback1(void* fPtr)
{
    if(toneStr.start){
        if(toneStr.idx++ < toneStr.len){
            X = singStr.idx * 10 / toneStr.len;
            deltaX = singStr.idx - X * (toneStr.len / 10);
            deltaStr = sineTable[X + 1] - sineTable[X];
            deltaY = deltaX * deltaStr * 10 / toneStr.len ;
            pwmValue = volume * (singStr.max * (u16)fabs(sineTable[X] + deltaY) / 100) / 100;  //??ChenDo: Add fabs() to protect
            if(pwmValue > BASEARR)
                pwmValue = 0;
            WriteFile(hTIM, emFILE_TIM1, (u8*)(&pwmValue), 1);
            singStr.idx++;
        }
        else{
            singStr.idx = 0; 
            toneStr.idx = 0;
            toneStr.end = true;
        }
    }
}

说明:

  • 高级定时器的更新频率为 20KHz,在中断处理中进行 PWM 正弦查表与计算,具体算法分析参考上一节内容

通用定时器2

1.实现功能

利用 TIM2 产生定时中断,中断间隔为 100us

2.初始化配置

////////////////////////////////////////////////////////////////////////////////
void initTimer2()
{
    hTIM = CreateFile(emIP_TIM);
	if (hTIM == NULL)		while(1);
	tAPP_TIM_DCB dcb2 = {
		.hSub 		= emFILE_TIM2,
        .mode		= emTIM_PWM,
        .cntFreq    = 10000,
        .period     = 9,
        .pulse      = 0,
		.ch         = emTIM_CH1,
        .cbUp       = (u32)(&UpdateCallback2),
		.cbCc       = NULL,
		.type		= emTYPE_IT,
		.sync		= emTYPE_Sync,
        .remapEn	= false,
		.remapIdx	= 0
	};
	if (!OpenFile(hTIM, (void*)&dcb2))		while(1);
}

中断回调函数:

////////////////////////////////////////////////////////////////////////////////
void UpdateCallback2(void* fPtr)
{
    if(beatStr.start){
        if(beatStr.cnt < (delayTime)){
            toneStr.start = true;
        }
        else if(beatStr.cnt < beatStr.toneTim){
            toneStr.start = false;
        }
        else{
            beatStr.cnt = 0;
            beatStr.start = false;
            beatStr.end = true;
            tuneFinish = true;
        }

        beatStr.cnt ++;
    }
}

说明:

  • 本函数主要控制节拍长度、各种状态标记(简单不做分析)

系统滴答定时器

系统调度,我先给出配置代码:

void main()
{
    MCUID = SetSystemClock(emSYSTICK_On, (u32*)&AppTaskTick);
	
	//.............
	while(1){}
}

中断回调函数:

////////////////////////////////////////////////////////////////////////////////
void AppTaskTick(void)
{
    if (tickCnt++ >= 250) {
        tickCnt  = 0;
        tickFlag = true;
        SysDisplay((u8*)&vdLED);
        if (vdLED == 0) vdLED = 1;
        else vdLED <<= 1;
        if (vdLED >= 0x10) vdLED = 0x0001;
    }
#if TESTTONE 
    
#else
    musicTick(music1);
#endif
}

说明

  • 250ms 用来跑流水灯
  • 执行音乐处理线程

你可能感兴趣的:(MM32)