本帖最后由 feiyinglala 于 2016-3-1 20:31 编辑
RCC_APB1PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); //TIM1 RCC用错了函数
我用STM32F051来实现TIM1输出四路PWM波,预想的效果是,在TIM_CNT <CCRx时,输出高电平(TIM1配置见代码段1)
然后CCRx是由TIM3来捕获的遥控器通道1传来的PWM波的宽度,在TIM3的捕获中断中来直接操控寄存器CCRx来更改TIM1输出的PWM高电平宽度(见代码段2)
目前遇到的困难是,在TIM1配置中,无论配置为PWM1还是PWM2,极性配置为高还是低,输出的PWM波形都是与我预想的情况相反的(TIM_CNT <CCRx时输出低电平)
请各位高手大侠指点,我问题出在哪里? TIM3的捕获脉冲宽度功能是正常的,我在示波器上验证过
说明:芯片是STM32F051R8 系统:win7 64位 开发环境:uVersion V5.11
下载器:ST-LINK 山寨版(USB口连到电脑,然后通过SWD连接电路板)
void TIM1_INT_Config(void)
{
<font color="red">RCC_APB1PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); //TIM1 RCC 使能</font>
// RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); //GPIOA的RCC已在点亮LED灯时使能
TIM_DeInit(TIM1);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_1;
GPIO_Init(GPIOA,&GPIO_InitStructure);
//GPIO_ResetBits(GPIOA,GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource8,GPIO_AF_2); //配置端口复用
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_2); //GPIO¹Ü½Å¸´ÓÃÉèÖÃ
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_2); //GPIO¹Ü½Å¸´ÓÃÉèÖÃ
GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_2); //GPIO¹Ü½Å¸´ÓÃÉèÖÃ
//配置TIM1每20ms溢出一次,以控制无刷电调
TIM_TimeBaseStructure.TIM_Period = 63999; //
TIM_TimeBaseStructure.TIM_Prescaler = 14; //
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
}
void TIM1_OUT_Config(void)
{
CCR1_Val = 0;
CCR2_Val = 0;
CCR3_Val = 0;
CCR4_Val = 0;
//输出PWM模式
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //TIM1输出PWM1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //TIM1ʹÄÜÊä³ö±È½Ï¹¦ÄÜ״̬
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; //TIM1输出比较极性高
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set; //TIM1£ºµ±MOE=1 ÉèÖÃTIM1Êä³ö±È½Ï¿ÕÏÐ״̬
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
TIM_OC1Init(TIM1, &TIM_OCInitStructure); //ʹÄÜƵµÀ1ÅäÖÃ
TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
TIM_OC2Init(TIM1, &TIM_OCInitStructure); //ʹÄÜƵµÀ1ÅäÖÃ
TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
TIM_OC3Init(TIM1, &TIM_OCInitStructure); //ʹÄÜƵµÀ1ÅäÖÃ
TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
TIM_OC4Init(TIM1, &TIM_OCInitStructure); //ʹÄÜƵµÀ1ÅäÖÃ
TIM_OC4PreloadConfig(TIM1,TIM_OCPreload_Enable);
TIM_Cmd(TIM1, ENABLE); //Timer3ʹÄÜ
TIM_CtrlPWMOutputs(TIM1, ENABLE); //TIM1Ö÷Êä³öʹÄÜ
}
<p>void TIM3_IRQHandler(void)
{//主要功能是捕获一个周期为20ms的PWM的脉冲时间,测得时间后把相应数值赋予TIM1->CCRx
static uint16_t this_time_CH1 = 0; //当前进入时刻计数器值
static uint16_t last_time_CH1 = 0; //上次中断进入时刻计数器值
static uint8_t capture_number_CH1 = 0; //捕获过程中,方向的标志位
uint16_t tmp16_CH1; //测得的脉冲宽度对应的计数器值
static uint16_t this_time_CH2 = 0; //µ±Ç°ÖжϽøÈëʱ¿Ì¶¨Ê±Æ÷µÄ¼ÆÊýÖµ
static uint16_t last_time_CH2 = 0; //ÉÏ´ÎÖжϽøÈëʱ¿ÌµÄ¶¨Ê±Æ÷¼ÆÊýÖµ
static uint8_t capture_number_CH2 = 0; //²¶»ñ¹ý³Ì±ê־λ
uint16_t tmp16_CH2; //ʱ¼ä²îÖµ
if(TIM_GetITStatus(TIM3, TIM_IT_CC1) == SET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_CC1); //清除中断标志位
if(capture_number_CH1 == 0)
{
capture_number_CH1 = 1;
last_time_CH1 = TIM_GetCapture1(TIM3); //保存计数值
TIM3->CCER |= (1 << 1); //更改为捕获下降沿
LED_Open(0);
}
else if(capture_number_CH1 == 1)
{
capture_number_CH1 = 0;
this_time_CH1 = TIM_GetCapture1(TIM3); //»ñÈ¡¼ÆÊýÆ÷µÄÖµ
if(this_time_CH1 > last_time_CH1) //若未溢出,则直接计算计数器差值
{
tmp16_CH1 = (this_time_CH1 - last_time_CH1);//¼ÆËãʱ¼ä¼ä¸ô
}
else
{
tmp16_CH1 = ((0xFFFF - last_time_CH1) + this_time_CH1);
}
TIM3->CCER &= ~(1 << 1); //更改为捕获上升沿
//±¸ÓôúÂë
tmp16_CH1 = (tmp16_CH1 * 3) / 2; //TIM3配置后为30ms溢出一次,因为TIM3的通道输入的信号为20ms的PWM,故用30ms的TIM来捕获,而TIM1为20ms溢出
TIM1->CCR1 = tmp16_CH1;
TIM1->CCR2 = tmp16_CH1;
TIM1->CCR3 = tmp16_CH1;
TIM1->CCR4 = tmp16_CH1;
LED_Close(0);
}
}//if(TIM_GetITStatus(TIM4, TIM_IT_CC1) == SET)
}</p>
//主函数
int main(void)
{
SystemInit();
LED_Init();
Systick_Init();
LED_Open(1);
Delay_ms(1000);
LED_Close(1);
Delay_ms(1000);
TIM3_INT_Config();
TIM1_INT_Config();
TIM3_IN_Config();
TIM1_OUT_Config();
while(1)
{
LED_Open(0);
Delay_ms(1000);
LED_Close(0);
Delay_ms(1000);/**/
}
}
|