控制PA8(TIM1CH1)PWM 输出相应 调制后的PWM波
至蜂鸣器引脚BUZ
。
////////////////////////////////////////////////////////////////////////////////
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 正弦查表与计算,具体算法分析参考上一节内容
利用 TIM2 产生定时中断,中断间隔为 100us
////////////////////////////////////////////////////////////////////////////////
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 用来跑流水灯
- 执行音乐处理线程