毕设的东西,目前在测量电机转速,用的驱动模块是L298N,电机的测速传感器用的光电码盘,开发板为战舰,想实现的功能是:输出PWM波控制电机转速,光电编码器会输出方波脉冲,用中断对脉冲计数,遇到高电平就进入外部中断,中断函数计数加一,主函数中计算转速,通过串口输出,显示到电脑上。代码如下。现在的问题是进入中断出现问题,只有在PWM波输出线插拔的一瞬间才能进入中断,而且转速输出一直是0,求助[mw_shl_code=cpp,true]#include "stm32f10x.h"
#include "delay.h"
#include "sys.h"
#include "led.h"
#include "timer.h"
#include "usart.h"
#include "exti.h"
float rot;
int count=0;
void GPIO_Configuration(void);
void TIM3_Configuration(void);
void EXTI_Configuration(void);
void USART_Configuration(void);
GPIO_Configuration();
EXTI_Configuration();
TIM3_Configuration();
USART_Configuration();
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
uart_init(115200);
delay_init();
while(1)
{
EXTI_ClearITPendingBit(EXTI_Line6);
delay_ms(500);
printf("
转速为%d
",count);
// rot=(float)count*60/0.5/448;
count=0;
// printf("
转速为(r/min):%f
",rot);
}
while(1)
{
EXTI_ClearITPendingBit(EXTI_Line6);
delay_ms(500);
printf("
计数为%d
",count);
// rot=(float)count*60/0.5/448;
count=0;
// printf("
转速为(r/min):%f
",rot);
}
void EXTI4_IRQnHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line4)!=RESET)
{
count++;
printf("
01010101010101
");
}
EXTI_ClearITPendingBit(EXTI_Line4);
}
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;//½óêÕ
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//·¢Ëí
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
}
void EXTI_Configuration(void)
{
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//ê1ÄüAFIOê±Öó
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource6);//ÖD¶ÏÏßÅäÖÃ
EXTI_InitStructure.EXTI_Line=EXTI_Line6;
EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd=ENABLE;
EXTI_Init(&EXTI_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel=EXTI9_5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0X02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0X02;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void TIM3_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
u16 CCR1_Val=700;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStructure);
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period=999;
TIM_TimeBaseInitStructure.TIM_Prescaler=3599;
TIM_TimeBaseInitStructure.TIM_ClockDivision=0;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OCNPolarity=TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse=CCR1_Val;
TIM_OC1Init(TIM3,&TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
TIM_Cmd(TIM3,ENABLE);
}
void USART_Configuration(void)
{
USART_InitTypeDef USART_InitStruction;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
USART_InitStruction.USART_BaudRate=115200;
USART_InitStruction.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
USART_InitStruction.USART_Mode=USART_Mode_Rx | USART_Mode_Tx;
USART_InitStruction.USART_Parity=USART_Parity_No;
USART_InitStruction.USART_StopBits=USART_StopBits_1;
USART_InitStruction.USART_WordLength=USART_WordLength_8b;
USART_Init(USART1,&USART_InitStruction);
USART_Cmd(USART1,ENABLE);
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
我这个是库函数版的,不过用的是原子哥的mini板,代码如下
[mw_shl_code=c,true]
#define U8_MAX ((u8)255)
#define S8_MAX ((s8)127)
#define S8_MIN ((s8)-128)
#define U16_MAX ((u16)65535u)
#define S16_MAX ((s16)32767)
#define S16_MIN ((s16)-32768)
#define U32_MAX ((u32)4294967295uL)
#define S32_MAX ((s32)2147483647)
#define S32_MIN ((s32)2147483648uL)
#define ENCODER_TIMER TIM4 // Encoder unit connected to TIM3
#define ENCODER_PPR (u16)(448) // number of pulses per revolution
#define SPEED_BUFFER_SIZE 8
#define COUNTER_RESET ((u16)0)
#define ICx_FILTER (u8) 6 // 6<-> 670nsec
#define SPEED_SAMPLING_TIME 9 // (9+1)*500usec = 5msec
#define SPEED_SAMPLING_FREQ (u16)(2000/(SPEED_SAMPLING_TIME+1))
/* Private variables ---------------------------------------------------------*/
typedef enum
{
FALSE = 0, TRUE = !FALSE
} bool;
static s16 hPrevious_angle, hSpeed_Buffer[SPEED_BUFFER_SIZE]={0}, hRot_Speed;
static u8 bSpeed_Buffer_Index = 0;
static volatile u16 hEncoder_Timer_Overflow;
static bool bIs_First_Measurement = TRUE;
//正交编码器初始化
void Encoder_Init(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
//编码器接口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_TimeBaseInitStructure.TIM_Period = (4*ENCODER_PPR)-1;
TIM_TimeBaseInitStructure.TIM_Prescaler = 0;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(ENCODER_TIMER,&TIM_TimeBaseInitStructure);
TIM_EncoderInterfaceConfig(ENCODER_TIMER, TIM_EncoderMode_TI12,
TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
//输入滤波器的设置
TIM_ICStructInit(&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_ICFilter = ICx_FILTER;
TIM_ICInit(ENCODER_TIMER, &TIM_ICInitStructure);
TIM_ClearFlag(ENCODER_TIMER, TIM_FLAG_Update);
TIM_ITConfig(ENCODER_TIMER, TIM_IT_Update, ENABLE);
TIM_Cmd(ENCODER_TIMER, ENABLE);//开启计数器
}
/*******************************************************************************
* Function Name : ENC_Calc_Rot_Speed
* Description : Compute return latest speed measurement
* Input : None
* Output : s16
* Return : Return the speed in 0.1 Hz resolution.
*******************************************************************************/
s16 ENC_Calc_Rot_Speed(void)
{
s8 i = 0;
s32 wDelta_angle;
u16 hEnc_Timer_Overflow_sample_one, hEnc_Timer_Overflow_sample_two;
u16 hCurrent_angle_sample_one, hCurrent_angle_sample_two;
signed long long temp;
s16 haux;
if (!bIs_First_Measurement)
{
// 1st reading of overflow counter
hEnc_Timer_Overflow_sample_one = hEncoder_Timer_Overflow;
// 1st reading of encoder timer counter
hCurrent_angle_sample_one = ENCODER_TIMER->CNT;
// 2nd reading of overflow counter
hEnc_Timer_Overflow_sample_two = hEncoder_Timer_Overflow;
// 2nd reading of encoder timer counter
hCurrent_angle_sample_two = ENCODER_TIMER->CNT;
// Reset hEncoder_Timer_Overflow and read the counter value for the next
// measurement
hEncoder_Timer_Overflow = 0;
haux = ENCODER_TIMER->CNT;
if (hEncoder_Timer_Overflow != 0)
{
haux = ENCODER_TIMER->CNT;
hEncoder_Timer_Overflow = 0;
}
if (hEnc_Timer_Overflow_sample_one != hEnc_Timer_Overflow_sample_two)
{ //Compare sample 1 & 2 and check if an overflow has been generated right
//after the reading of encoder timer. If yes, copy sample 2 result in
//sample 1 for next process
hCurrent_angle_sample_one = hCurrent_angle_sample_two;
hEnc_Timer_Overflow_sample_one = hEnc_Timer_Overflow_sample_two;
}
if ( (ENCODER_TIMER->CR1 & TIM_CounterMode_Down) == TIM_CounterMode_Down)
{// encoder timer down-counting
wDelta_angle = (s32)(hCurrent_angle_sample_one - hPrevious_angle -
(hEnc_Timer_Overflow_sample_one) * (4*ENCODER_PPR));
}
else
{//encoder timer up-counting
wDelta_angle = (s32)(hCurrent_angle_sample_one - hPrevious_angle +
(hEnc_Timer_Overflow_sample_one) * (4*ENCODER_PPR));
}
// speed computation as delta angle * 1/(speed sempling time)
temp = (signed long long)(wDelta_angle * SPEED_SAMPLING_FREQ);
temp *= 10; // 0.1 Hz resolution
temp /= (4*ENCODER_PPR);
} //is first measurement, discard it
else
{
bIs_First_Measurement = FALSE;
temp = 0;
hEncoder_Timer_Overflow = 0;
haux = ENCODER_TIMER->CNT;
// Check if Encoder_Timer_Overflow is still zero. In case an overflow IT
// occured it resets overflow counter and wPWM_Counter_Angular_Velocity
if (hEncoder_Timer_Overflow != 0)
{
haux = ENCODER_TIMER->CNT;
hEncoder_Timer_Overflow = 0;
}
}
hPrevious_angle = haux;
return((s16) temp);
}
/*******************************************************************************
* Function Name : ENC_Calc_Average_Speed
* Description : Compute smoothed motor speed based on last SPEED_BUFFER_SIZE
informations and store it variable
* Input : None
* Output : s16
* Return : Return rotor speed in 0.1 Hz resolution. This routine
will return the average mechanical speed of the motor.
*******************************************************************************/
void ENC_Calc_Average_Speed(void)//滑动平均滤波
{
s32 wtemp;
u32 i;
wtemp = ENC_Calc_Rot_Speed();
/* Compute the average of the read speeds */
hSpeed_Buffer[bSpeed_Buffer_Index] = (s16)wtemp;
bSpeed_Buffer_Index++;
if (bSpeed_Buffer_Index == SPEED_BUFFER_SIZE)
{
bSpeed_Buffer_Index = 0;
}
wtemp=0;
for (i=0;i<SPEED_BUFFER_SIZE;i++)
{
wtemp += hSpeed_Buffer;
}
wtemp /= SPEED_BUFFER_SIZE;
hRot_Speed = ((s16)(wtemp));
}
void TIM4_IRQHandler(void)
{
OSIntEnter();
if (TIM_GetITStatus(ENCODER_TIMER, TIM_IT_Update) == SET)
{
if (hEncoder_Timer_Overflow != U16_MAX)
hEncoder_Timer_Overflow++;
TIM_ClearITPendingBit(ENCODER_TIMER,TIM_IT_Update);
}
OSIntExit();
}
void Encode_test(void)
{
Debug("ENCODER_TIMER->CNT 的值是:%d, 电机的速度为%d ",ENCODER_TIMER->CNT, hRot_Speed);
}
[/mw_shl_code]
这个代码也是参照网上的代码,自己调试通的,[size=13.3333px]ENC_Calc_Average_Speed这个函数需要在另一个定时器里面500us调用一次,其他数值也行,就是需要自己修改下面两个数值[size=13.3333px]#define[size=13.3333px] SPEED_SAMPLING_TIME [size=13.3333px]9[size=13.3333px] [size=13.3333px]// (9+1)*500usec = 5msec#define SPEED_SAMPLING_FREQ (u16)(2000/(SPEED_SAMPLING_TIME+1))
还有在调试编码器的时候,TI跟T2的相应引脚千万不要有上拉电阻,要不然,计数值的数值在临近的两个数值来回跳变,其他问题我这边没有遇到过,希望对你有帮助,不过现在这个时间你的毕业设计已经完了吧,希望对其他人有帮助吧。
一周热门 更多>