最近在做一个项目,需要用到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个脉冲,就是数据每一列都会少放一个脉冲!!!
|
请检查确认下。
评分
查看全部评分
评分
查看全部评分