int16_t Get_MotorB_Speed(void) { int16_t TEST; //Read_EncoderB(); // 获取编码器产生的脉冲数 转速n = 总脉冲数/四倍频/单圈脉冲数/减速比/时间 ( EncoderB / 2 / 13 / 30 /10 * 1000) TEST =1; return TEST; } void TIM2_IRQHandler(void) //TM2的中断函数 { if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET) { GetMotorB_Speed =Read_EncoderB(); TIM_ClearITPendingBit(TIM2, TIM_IT_Update); } }
时间: 2024-04-09 12:29:51 浏览: 107
这段代码是一个C语言函数和中断处理函数的例代码。函数`Get_MotorB_Speed`返回一个`int16_t`类型的变量,它的值在这个示例中被设置为1。中断处理函数`TIM2_IRQHandler`用于处理TIM2定时器的中断事件。在这个示例中,当TIM2的更新中断被触发时,会调用`Read_EncoderB`函数获取编码器的脉冲数,并将其赋值给变量`GetMotorB_Speed`。然后,通过调用`TIM_ClearITPendingBit`函数清除中断标志位。请注意,这只是一个代码片段,缺少了一些关键信息,如函数`Read_EncoderB`的具体实现和相关的初始化代码。
相关问题
#include "stm32f10x.h" // Device header #include "Delay.h" #include "OLED.h" #include "Encoder.h" #include "Motor.h" #include "Timer.h" #include "Serial.h" int8_t L=0; int8_t l_stop=0; int16_t Larr[]={1000,2000,3000,4000,5000}; int16_t countL=0; int16_t Llocation=0; float Lkp=0.5,Lki=0.14,Lkd=0; int16_t Lspeed_goal=50,Lspeed_current; int16_t Lspeederror_current,Lspeederror_add=0; int16_t Lspeederror_before=0; float Loutput=0; int8_t R=0; int8_t r_stop=0; int16_t Rarr[]={5000,5000,5000,5000,5000}; int16_t countR; int16_t Rlocation=0; float Rkp=0.4,Rki=0.15,Rkd=0; int16_t Rspeed_goal=50,Rspeed_current; int16_t Rspeederror_current,Rspeederror_add=0; int16_t Rspeederror_before=0; float Routput=0; int main(void) { OLED_Init(); Motor_Init(); Encoder_Init(); Timer_Init(); Serial_Init(); while (1) { Serial_Printf("%d,%d\r\n",Rlocation,Llocation); OLED_ShowChar(0,0,'L',OLED_8X16); OLED_ShowSignedNum(8,0,Lspeed_current,3,OLED_8X16); OLED_ShowSignedNum(0,16,Llocation,5,OLED_8X16); OLED_ShowChar(0,32,'R',OLED_8X16); OLED_ShowSignedNum(8,32,Rspeed_current,3,OLED_8X16); OLED_ShowSignedNum(0,48,Rlocation,5,OLED_8X16); OLED_Update(); } } void TIM3_IRQHandler(void)//1毫秒进一次中断 { if(TIM_GetITStatus(TIM3, TIM_IT_Update) == SET) { countL++; if(countL==40)//每四十毫秒进入一次 { //*************************************************************************************************************** //这是左轮子 Lspeed_current=Encoder_GetA(); Lspeederror_current=Lspeed_goal-Lspeed_current; Lspeederror_add+=Lspeederror_current; //积分限幅 if(Lspeederror_add>350) { Lspeederror_add=350; } else if(Lspeederror_add<-350) { Lspeederror_add=-350; } //计算输出 Loutput=Lkp*Lspeederror_current+Lki*Lspeederror_add+Lkd*(Lspeederror_current-Lspeederror_before); //输出限幅 if(Loutput>100) { Loutput=100; } else if(Loutput<-100) { Loutput=-100; } Llocation+=Lspeed_current; if(Llocation>=Larr[L]-50&&Larr[L]-50<=Llocation) { L++; Llocation=0; l_stop=1; } else { l_stop=0; } if(l_stop==0|| (l_stop&&r_stop) ) { Motor_SetSpeedA(Loutput);//输出 l_stop=0; } else { Motor_SetSpeedA(0);//等一下另一个轮子 } Lspeederror_before=Lspeederror_current; countL=0; } countR++; if(countR==40) { //******************************************************************************************************************** //这是右轮 Rspeed_current=Encoder_GetB(); Rspeederror_current=Rspeed_goal-Rspeed_current; Rspeederror_add+=Rspeederror_current; //积分限幅 if(Rspeederror_add>300) { Rspeederror_add=300; } else if(Rspeederror_add<-300) { Rspeederror_add=-300; } //计算输出 Routput=Rkp*Rspeederror_current+Rki*Rspeederror_add+Rkd*(Rspeederror_current-Rspeederror_before); //输出限幅 if(Routput>100) { Routput=100; } else if(Routput<-100) { Routput=-100; } Rlocation+=Rspeed_current; if(Rlocation>=Rarr[R]-50&&Rarr[R]-50<=Rlocation) { R++; Rlocation=0; r_stop=1; } else { r_stop=0; } if(r_stop==0|| (l_stop&&r_stop) ) { Motor_SetSpeedB(Routput);//输出 r_stop=0; } else { Motor_SetSpeedB(0);//等一下另一个轮子 } Rspeederror_before=Rspeederror_current; countR=0; } TIM_ClearITPendingBit(TIM3, TIM_IT_Update); } } 我希望小车轮子能停下来等另一个小车轮子,为什么停不下来,是哪里写错了吗
### 小车轮子同步问题分析
在双轮小车的 PID 控制中,实现两个轮子的速度同步是一个常见的挑战。通过分析提供的代码片段以及 STM32F10x 的特性,可以发现一些可能导致轮子不同步的原因。
#### 1. **停止条件中的绝对值判断**
代码中使用了 `if (abs(encountA) <= 5 && pidMotor1Speed.target_val == 0)` 来决定是否停止电机 A 和 B。这种逻辑存在潜在问题:
- 如果编码器计数值 (`encountA` 或 `encountB`) 波动较大,则可能频繁触发该条件,导致电机反复启停。
- 编码器分辨率较低时,`abs(encountA) <= 5` 这一阈值可能不够精确,无法有效检测到真正的静止状态[^1]。
#### 2. **增量式 PID 输出的影响**
增量式 PID 控制器计算的是每次调节所需的 PWM 值变化量,而非直接的目标 PWM 值。因此,在目标速度为零的情况下,如果当前误差较小,PWM 调整可能会非常缓慢甚至停滞不前。这可能导致一侧轮子先达到完全停止的状态,而另一侧仍然有微弱转动,从而破坏同步性。
以下是改进后的伪代码示例:
```c
// 定义全局变量用于记录上次输出值
static int last_motorA_output = 0;
static int last_motorB_output = 0;
void Timer_ISR(void) {
if (pidMotor1Speed.target_val == 0) {
if (abs(encountA) <= THRESHOLD_STOP) { // 更严格的停止判定
PWMA = 0;
} else {
motorA = Incremental_PID(&pidMotor1Speed, encountA);
last_motorA_output += motorA; // 累加增量输出
ControlLeftMotor(last_motorA_output);
}
}
if (pidMotor2Speed.target_val == 0) {
if (abs(encountB) <= THRESHOLD_STOP) { // 更严格的停止判定
PWMB = 0;
} else {
motorB = Incremental_PID(&pidMotor2Speed, encountB);
last_motorB_output += motorB; // 累加增量输出
ControlRightMotor(last_motorB_output);
}
}
}
```
#### 3. **左右轮独立控制带来的偏差**
即使两路 PID 参数相同,由于硬件差异(如电机性能、齿轮磨损)、环境干扰等因素,实际运行过程中仍可能出现速度不对称的情况。为了改善这一现象,可以在软件层面引入额外补偿机制,例如动态调整两侧目标转速以维持一致距离差。
一种简单的方法是在主循环中加入如下校正算法:
```c
int error_distance = encoder_left_count - encoder_right_count;
float correction_factor = Kp * error_distance / MAX_ENCODER_COUNTS_PER_REVOLUTION;
pidMotor1Speed.target_val -= correction_factor; // 减少左轮目标值
pidMotor2Speed.target_val += correction_factor; // 增大右轮目标值
```
其中 `Kp` 是比例增益系数,需根据实验调优;`MAX_ENCODER_COUNTS_PER_REVOLUTION` 表示每圈脉冲数。
---
### 总结
通过对现有代码逻辑的剖析可知,主要存在问题包括但不限于:过宽泛的停止判据设定容易引起误操作;单纯依赖增量型PID难以快速响应至零速指令等问题均会影响最终效果达成度。针对这些问题提出了相应的优化措施并给出了具体实施办法以便于后续开发人员参考应用实践当中去解决此类难题[^1]。
int GetMotorB_Speed=1; void TIM2_IRQHandler(void) //TM2的中断函数 { if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET) { GetMotorB_Speed = Read_EncoderB(); TIM_ClearITPendingBit(TIM2, TIM_IT_Update); } } 这段代码错误的原因
根据你提供的代码,我无法确定是否存在错误。代码中的函数`TIM2_IRQHandler`是用来处理TIM2的中断的。在该函数中,首先通过调用`TIM_GetITStatus`函数来检查TIM2的更新中断是否被触发。如果中断被触发,那么会调用`Read_EncoderB`函数来获取`MotorB`的速度,并将其赋值给`GetMotorB_Speed`变量。最后,通过调用`TIM_ClearITPendingBit`函数来清除中断标志位。
如果你遇到了错误,可能是由于以下原因之一:
1. `Read_EncoderB`函数未定义或未声明:请确保你在代码的其他地方定义或声明了这个函数。
2. `TIM2`未正确配置:在使用TIM2之前,你需要进行正确的配置,包括时钟使能、定时器模式、中断使能等。
3. TIM2中断优先级设置不正确:请确保中断优先级设置正确,并且中断向量表正确地指向了`TIM2_IRQHandler`函数。
4. 其他代码逻辑问题:请仔细检查代码逻辑,确保没有其他错误导致该段代码无法正常运行。
如果你能提供更多的上下文信息或错误提示,我可以更具体地帮助你找到错误所在。
阅读全文
相关推荐















