最近在做一个项目,需要用到STM32F407的定时器产生一个频率可调的PWM驱动电机,思路是这样的??
需要放出的PWM放在两个数组里面,cycles表示需要放脉冲的时间(按照定时器单位周期为单位),steps表示在指定的cycles时间内需要放出的脉冲的数量。表示如下:
int16_t steps[10] = {5,-5,6,-7,8,-9,0,3};
uint32_t cycles[10] = {354672,145256,33423,45612,180356,20444,5647343};
最后用STM32F407的PF9(TIM14)作为PWM输出引脚,PC2作为方向引脚,
思路大概是:我首先开启定时器(定时10ms),在第一次中断中记录该次pwm脉冲的宽度,并把值转化为PSC和ARR的值,采用自动重装模式,也就是在本次中断里面计算出下一个脉冲的宽度,最后选择在中断时自动PSC和ARR的值,进行放脉冲(第一个10ms中断目的就是重装第一个pwm脉冲的宽度,在 10ms之后放出)。
最后发现实际放出的脉冲数组的每段少放一个脉冲,比如数组的第一列,在354672个周期内放出5个脉冲,实际只放出了4个脉冲,少了一个,数组的每列都少放了一个脉冲,不知道什么情况,我猜测是不是寄存器重装(PSC和ARR的值)装载出了问题?这一块由于不是很熟悉,调试了一个上午,现象依旧,大家帮忙看一下代码?非常感谢!
初始化函数:
void Motor_Init_T1(void)
{
//定义IO口初始化变量
GPIO_InitTypeDef GPIO_InitStructure;
//定义定时器初始化变量
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
//定时器时钟初始化
RCC_APB1PeriphClockCmd(MOTOR1_TIMER_CLOCK, ENABLE);
//IO口时钟初始化
RCC_AHB1PeriphClockCmd(MOTOR1_PU_CLOCK | MOTOR1_DR_CLOCK, ENABLE);
//MOTOR_DR1 IO口初始化
GPIO_InitStructure.GPIO_Pin = MOTOR1_DR_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(MOTOR1_DR_BASE, &GPIO_InitStructure);
//初始化方向引脚电平
MOTOR_DR_OUTBIT = 1;
//初始化MOTOR_PU IO口
GPIO_InitStructure.GPIO_Pin = MOTOR1_PU_PIN ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(MOTOR1_PU_BASE, &GPIO_InitStructure);
//设置定时器PWM输出到MOTOR_PU1引脚上
GPIO_PinAFConfig(MOTOR1_PU_BASE, MOTOR1_PU_PINSOURCE, GPIO_AF_TIM14);
//定时器中断初始化
NVIC_InitStructure.NVIC_IRQChannel = TIM8_TRG_COM_TIM14_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
//定时器初始化
TIM_DeInit(TIM14);
TIM_TimeBaseStructure.TIM_Period = 999;
TIM_TimeBaseStructure.TIM_Prescaler = 839;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM14, &TIM_TimeBaseStructure);
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0xffff;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM14, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);
TIM_ClearFlag(TIM14, TIM_FLAG_Update);
TIM_ITConfig(TIM14, TIM_IT_Update, ENABLE);
TIM_ARRPreloadConfig(TIM14, ENABLE);
TIM_Cmd(TIM14, DISABLE);
}
定时器溢出中断处理函数:
uint16_t serial = 0;
uint16_t serialOld = 0;
int16_t dir = 1;
uint16_t count = 0;
uint16_t period = 1000, prescaler = 840;
uint16_t pulse = 0xffff;
uint16_t error = 0; //误差累计值,计算脉冲的时间产生的误差,叠加到下一个脉冲中去)
uint32_t times = 0;
uint16_t serialNums = 1;//要放出脉冲的数组的个数(小于数据的长度即可)
uint16_t stepNums = 0;
void Motor_ISR_T1( const int16_t * pSteps, const uint32_t * pCycles)
{
uint32_t timerPwm = 0;
if(serial <= serialNums)
{
TIM_SetCompare1(TIM14,pulse);
}
if(count == 0)
{
if(serial < serialNums)
{
if(pSteps[serial] > 0)
{
MOTOR_DR_OUTBIT = 1; //正方向
count = pSteps[serial];
}
else if(pSteps[serial] < 0)
{
MOTOR_DR_OUTBIT = 0; //反方向
count = -pSteps[serial];
}
else if (pSteps[serial] == 0)
{
count = 5;
}
times = pCycles[serial] + error;
serial++;
serialOld = serial - 1;
}
else if(serial == serialNums)
{
serial++;
}
else if(serial > serialNums) //脉冲已经全部放完
{
Motor_Stop_T1();
}
}
if(count > 0) //有脉冲需要放
{
timerPwm = times/count;
prescaler = (timerPwm >> 16) + 1;
period = timerPwm/prescaler;
error = timerPwm - period * prescaler;
times = times - timerPwm + error;
TIM_PrescalerConfig(TIM14, prescaler - 1, TIM_PSCReloadMode_Update);
TIM_SetAutoreload(TIM14, period - 1);
if(pSteps[serialOld] == 0)
{
pulse = 0xffff;
}
else
{
pulse = period - (4000/prescaler + 1);
}
count--;
}
}
这里serialNums 为1表示只放出数组的第一列的数据,5个脉冲,实际只放出了4个,如果取2,表示只放出2列总计10个脉冲,前面5个正转,后面5个反转,但是实际只放出了4+4 = 8个脉冲,就是数据每一列都会少放一个脉冲!!!
|