打印
[经验分享]

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

[复制链接]
40|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
使用资源
定时器
高级定时器1(TIM1)
通用定时器2(TIM2)
系统滴答定时器(SYSTICK)
高级定时器1
1.实现功能
控制PA8(TIM1CH1)PWM 输出相应 调制后的PWM波 至蜂鸣器引脚BUZ。



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 用来跑流水灯
执行音乐处理线程
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/chendu103/article/details/106835866

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

20

主题

103

帖子

1

粉丝