请教各位大牛一个问题,卡住我几天了。我使用如下定时器配置PWM,如下示:
PA6 -> PWM0
tim1_cha(4)
PA7 -> PWM1 tim2_cha(5)
PB0 -> PWM2 tim3_ch1b(2)
在应行如下初始化代码后,直接卡死了,请问是什么原因呢
void pwm_init()
{
Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); //端口外设时钟使能
TimerPortCfg(PWM0);
TimerPortCfg(PWM1);
TimerPortCfg(PWM2);
Timer1Cfg(100, PWM_DUTY);
Bt_M23_EnPWM_Output(TIM1, TRUE, FALSE); //端口输出使能
Timer2Cfg(100, PWM_DUTY);
Bt_M23_EnPWM_Output(TIM2, TRUE, FALSE); //端口输出使能
Timer3Cfg(100, PWM_DUTY);
Tim3_M23_EnPWM_Output(TRUE, FALSE); //端口输出使能
Bt_M23_Run(TIM2); //运行。
Bt_M23_Run(TIM1); //运行。
Tim3_M23_Run(); //运行。
}
完整模块代码发下:
#include "pwm.h"
#include "timer3.h"
#include "bt.h"
#include "gpio.h"
#include "motor.h"
volatile char pwm_duty = 95;
// PA6 -> PWM0 tim1_cha(4)
// PA7 -> PWM1 tim2_cha(5) 或 tim3_ch0b(4)
// PB0 -> PWM2 tim3_ch1b(2)
typedef enum
{
PWM0 = 0u,
PWM1,
PWM2,
}pwm_index_t;
/*******************************************************************************
* 中断服务函数
******************************************************************************/
void Tim1_IRQHandler(void)
{
//Timer1 模式23 更新中断
if(TRUE == Bt_GetIntFlag(TIM1,BtUevIrq)){
Bt_M23_CCR_Set(TIM1, BtCCR0A, 100-pwm_duty); //设置通道A比较值
Bt_ClearIntFlag(TIM1,BtUevIrq); //清中断标志
}
}
void Tim2_IRQHandler(void)
{
//Timer2 模式23 更新中断
if(TRUE == Bt_GetIntFlag(TIM2,BtUevIrq))
{
Bt_M23_CCR_Set(TIM2, BtCCR0A, 100-pwm_duty); //设置通道A比较值
Bt_ClearIntFlag(TIM2,BtUevIrq); //清中断标志
}
}
void Tim3_IRQHandler(void)
{
//Timer3 模式23 更新中断
if(TRUE == Tim3_GetIntFlag(Tim3UevIrq)){
Tim3_M23_CCR_Set(Tim3CCR1B, 100-pwm_duty); //设置CH1 通道B比较值
Tim3_ClearIntFlag(Tim3UevIrq); //清中断标志
}
}
//Timer1 配置
void Timer1Cfg(uint16_t u16Period, uint16_t u16CHxACompare)
{
uint16_t u16CntValue;
uint8_t u8ValidPeriod;
stc_bt_mode23_cfg_t stcTim1BaseCfg;
stc_bt_m23_compare_cfg_t stcTim1PortCmpCfg;
//结构体初始化清零
DDL_ZERO_STRUCT(stcTim1BaseCfg);
DDL_ZERO_STRUCT(stcTim1PortCmpCfg);
Sysctrl_SetPeripheralGate(SysctrlPeripheralBTim, TRUE); //Timer1外设时钟使能
stcTim1BaseCfg.enWorkMode = BtWorkMode2; //锯齿波模式
stcTim1BaseCfg.enCT = BtTimer; //定时器功能,计数时钟为内部PCLK
stcTim1BaseCfg.enPRS = BtPCLKDiv1; //PCLK
stcTim1BaseCfg.enCntDir = BtCntUp; //向上计数,在三角波模式时只读
stcTim1BaseCfg.enPWMTypeSel = BtIndependentPWM; //独立输出PWM
stcTim1BaseCfg.enPWM2sSel = BtSinglePointCmp; //单点比较功能
stcTim1BaseCfg.bOneShot = FALSE; //循环计数
stcTim1BaseCfg.bURSSel = FALSE; //上下溢更新
Bt_Mode23_Init(TIM1, &stcTim1BaseCfg); //TIM3 的模式23功能初始化
Bt_M23_ARRSet(TIM1, u16Period, TRUE); //设置重载值,并使能缓存
Bt_M23_CCR_Set(TIM1, BtCCR0A, u16CHxACompare); //设置CH0比较值A
stcTim1PortCmpCfg.enCH0ACmpCtrl = BtPWMMode2; //OCREFA输出控制OCMA:PWM模式2
stcTim1PortCmpCfg.enCH0APolarity = BtPortPositive; //正常输出
stcTim1PortCmpCfg.bCh0ACmpBufEn = TRUE; //A通道缓存控制
stcTim1PortCmpCfg.enCh0ACmpIntSel = BtCmpIntNone; //A通道比较中断控制:无
Bt_M23_PortOutput_Cfg(TIM1, &stcTim1PortCmpCfg); //比较输出端口配置
u8ValidPeriod = 0; //事件更新周期设置,0表示锯齿波每个周期更新一次,每+1代表延迟1个周期
Bt_M23_SetValidPeriod(TIM1, u8ValidPeriod); //间隔周期设置
u16CntValue = 0;
Bt_M23_Cnt16Set(TIM1, u16CntValue); //设置计数初值
Bt_ClearAllIntFlag(TIM1); //清中断标志
Bt_Mode23_EnableIrq(TIM1,BtUevIrq); //使能TIM1 UEV更新中断
EnableNvic(TIM1_IRQn, IrqLevel0, TRUE); //TIM1中断使能
}
//Timer2 配置
void Timer2Cfg(uint16_t u16Period, uint16_t u16CHxACompare)
{
uint16_t u16CntValue;
uint8_t u8ValidPeriod;
stc_bt_mode23_cfg_t stcTim2BaseCfg;
stc_bt_m23_compare_cfg_t stcTim2PortCmpCfg;
//结构体初始化清零
DDL_ZERO_STRUCT(stcTim2BaseCfg);
DDL_ZERO_STRUCT(stcTim2PortCmpCfg);
Sysctrl_SetPeripheralGate(SysctrlPeripheralBTim, TRUE); //Timer1外设时钟使能
stcTim2BaseCfg.enWorkMode = BtWorkMode2; //锯齿波模式
stcTim2BaseCfg.enCT = BtTimer; //定时器功能,计数时钟为内部PCLK
stcTim2BaseCfg.enPRS = BtPCLKDiv1; //PCLK
stcTim2BaseCfg.enCntDir = BtCntUp; //向上计数,在三角波模式时只读
stcTim2BaseCfg.enPWMTypeSel = BtIndependentPWM; //独立输出PWM
stcTim2BaseCfg.enPWM2sSel = BtSinglePointCmp; //单点比较功能
stcTim2BaseCfg.bOneShot = FALSE; //循环计数
stcTim2BaseCfg.bURSSel = FALSE; //上下溢更新
Bt_Mode23_Init(TIM2, &stcTim2BaseCfg); //TIM3 的模式23功能初始化
Bt_M23_ARRSet(TIM2, u16Period, TRUE); //设置重载值,并使能缓存
Bt_M23_CCR_Set(TIM2, BtCCR0A, u16CHxACompare); //设置CH0比较值B
stcTim2PortCmpCfg.enCH0ACmpCtrl = BtPWMMode2; //OCREFA输出控制OCMA:PWM模式2
stcTim2PortCmpCfg.enCH0APolarity = BtPortPositive; //正常输出
stcTim2PortCmpCfg.bCh0ACmpBufEn = TRUE; //A通道缓存控制
stcTim2PortCmpCfg.enCh0ACmpIntSel = BtCmpIntNone; //A通道比较中断控制:无
Bt_M23_PortOutput_Cfg(TIM2, &stcTim2PortCmpCfg); //比较输出端口配置
u8ValidPeriod = 0; //事件更新周期设置,0表示锯齿波每个周期更新一次,每+1代表延迟1个周期
Bt_M23_SetValidPeriod(TIM2, u8ValidPeriod); //间隔周期设置
u16CntValue = 0;
Bt_M23_Cnt16Set(TIM2, u16CntValue); //设置计数初值
Bt_ClearAllIntFlag(TIM2); //清中断标志
Bt_Mode23_EnableIrq(TIM2,BtUevIrq); //使能TIM3 UEV更新中断
EnableNvic(TIM2_IRQn, IrqLevel0, TRUE); //TIM3中断使能
}
//Timer3 配置
void Timer3Cfg(uint16_t u16Period, uint16_t u16CHxBCompare)
{
uint16_t u16CntValue;
uint8_t u8ValidPeriod;
stc_tim3_mode23_cfg_t stcTim3BaseCfg;
stc_tim3_m23_compare_cfg_t stcTim3PortCmpCfg;
//结构体初始化清零
DDL_ZERO_STRUCT(stcTim3BaseCfg);
DDL_ZERO_STRUCT(stcTim3PortCmpCfg);
Sysctrl_SetPeripheralGate(SysctrlPeripheralTim3, TRUE); //Timer3外设时钟使能
stcTim3BaseCfg.enWorkMode = Tim3WorkMode2; //锯齿波模式
stcTim3BaseCfg.enCT = Tim3Timer; //定时器功能,计数时钟为内部PCLK
stcTim3BaseCfg.enPRS = Tim3PCLKDiv1; //PCLK
stcTim3BaseCfg.enCntDir = Tim3CntUp; //向上计数,在三角波模式时只读
stcTim3BaseCfg.enPWMTypeSel = Tim3IndependentPWM; //独立输出PWM
stcTim3BaseCfg.enPWM2sSel = Tim3SinglePointCmp; //单点比较功能
stcTim3BaseCfg.bOneShot = FALSE; //循环计数
stcTim3BaseCfg.bURSSel = FALSE; //上下溢更新
Tim3_Mode23_Init(&stcTim3BaseCfg); //TIM3 的模式23功能初始化
Tim3_M23_ARRSet(u16Period, TRUE); //设置重载值,并使能缓存
Tim3_M23_CCR_Set(Tim3CCR1B, u16CHxBCompare); //设置CH1比较值B
stcTim3PortCmpCfg.enCHxBCmpCtrl = Tim3PWMMode2; //OCREFB输出控制OCMB:PWM模式2(PWM互补模式下也要设置,避免强制输出)
stcTim3PortCmpCfg.enCHxBPolarity = Tim3PortPositive; //正常输出
stcTim3PortCmpCfg.bCHxBCmpBufEn = TRUE; //B通道缓存控制使能
stcTim3PortCmpCfg.enCHxBCmpIntSel = Tim3CmpIntNone; //B通道比较中断控制:无
// Tim3_M23_PortOutput_Cfg(Tim3CH0, &stcTim3PortCmpCfg); //比较输出端口配置
Tim3_M23_PortOutput_Cfg(Tim3CH1, &stcTim3PortCmpCfg); //比较输出端口配置
u8ValidPeriod = 0; //事件更新周期设置,0表示锯齿波每个周期更新一次,每+1代表延迟1个周期
Tim3_M23_SetValidPeriod(u8ValidPeriod); //间隔周期设置
u16CntValue = 0;
Tim3_M23_Cnt16Set(u16CntValue); //设置计数初值
Tim3_ClearAllIntFlag(); //清中断标志
Tim3_Mode23_EnableIrq(Tim3UevIrq); //使能TIM3 UEV更新中断
EnableNvic(TIM3_IRQn, IrqLevel0, TRUE); //TIM3中断使能
}
void TimerPortCfg(pwm_index_t pwm_index)
{
stc_gpio_cfg_t stcTIMPort;
DDL_ZERO_STRUCT(stcTIMPort);
stcTIMPort.enDir = GpioDirOut;
switch (pwm_index){
case PWM0:
Gpio_Init(GpioPortA, GpioPin6, &stcTIMPort);
Gpio_SetAfMode(GpioPortA,GpioPin6,GpioAf4); //PA6 -> PWM0 tim1_cha(4)
break;
case PWM1:
Gpio_Init(GpioPortA, GpioPin7, &stcTIMPort);
Gpio_SetAfMode(GpioPortA,GpioPin7,GpioAf5); //PA7 -> PWM1 tim2_cha(5)
break;
case PWM2:
Gpio_Init(GpioPortB, GpioPin0, &stcTIMPort);
Gpio_SetAfMode(GpioPortB,GpioPin0,GpioAf2); //PB0 -> PWM2 tim3_ch1b(2)
break;
default:
break;
}
}
void TimerPortDeiniCfg(pwm_index_t pwm_index)
{
stc_gpio_cfg_t stcTIMPort;
DDL_ZERO_STRUCT(stcTIMPort);
stcTIMPort.enDir = GpioDirOut;
switch (pwm_index){
case PWM0:
Gpio_Init(GpioPortA, GpioPin6, &stcTIMPort);
Gpio_SetAfMode(GpioPortA,GpioPin6,GpioAf0);
Gpio_ClrIO(GpioPortA, GpioPin6);
break;
case PWM1:
Gpio_Init(GpioPortA, GpioPin7, &stcTIMPort);
Gpio_SetAfMode(GpioPortA,GpioPin7,GpioAf0); //PA7 -> PWM1 tim2_cha(5)
Gpio_ClrIO(GpioPortA, GpioPin7);
break;
case PWM2:
Gpio_Init(GpioPortB, GpioPin0, &stcTIMPort);
Gpio_SetAfMode(GpioPortB,GpioPin0,GpioAf0); //PB0 -> PWM2 tim3_ch1b(2)
Gpio_ClrIO(GpioPortB, GpioPin0);
break;
default:
break;
}
}
// -----------pwm enable
void pwm0_enable(uint8_t duty)
{
TimerPortCfg(PWM0);
if (duty > 100){
duty = 100;
}
pwm_duty = duty;
Bt_M23_Run(TIM1);
}
void pwm1_enable(uint8_t duty)
{
TimerPortCfg(PWM1);
if (duty > 100){
duty = 100;
}
pwm_duty = duty;
Bt_M23_Run(TIM2);
}
void pwm2_enable(uint8_t duty)
{
TimerPortCfg(PWM2);
if (duty > 100){
duty = 100;
}
pwm_duty = duty;
Tim3_M23_Run();
}
// -----------pwm disable
void pwm0_disable(void)
{
Bt_M23_Stop(TIM1);
TimerPortDeiniCfg(PWM0);
}
void pwm1_disable(void)
{
Bt_M23_Stop(TIM2);
TimerPortDeiniCfg(PWM1);
}
void pwm2_disable(void)
{
Tim3_M23_Stop();
TimerPortDeiniCfg(PWM2);
}