PID学习笔记03(硬件驱动基础代码测试)
- 2026-11-12 08:39:19
PID学习笔记03(硬件驱动基础代码测试)停更了好几天,设备到位了,继续学习研究。 买了一套江协科技的练习模型。 
这个模型主要用来练习PWM电机闭环控制,最终可以实现单垂臂倒立摆。 开始测试 1. OLED测试 main.c主程序如下 测试程序中的参数可以任意修改,用到的程序模块如下 OLED.c为自定义函数库,可以在main.c主程序中直接调用 
测试效果如下。 
2.led测试 利用STM32开发板自带的led工作指示灯进行功能测试 测试程序点亮和熄灭,交替0.5s main.c主程序如下 用到的模块如下 
使用的是C13端口 
测试效果如下 3. 按键测试 采用非阻塞式写法编写测试程序 main.c主程序如下 用到的程序模块 key.c 自定义开关程序,Timer.c为定时器,用于调用定时中断程序 
使用TIM1进行定时中断 
这里修改自增分频值,1ms自增1 
四个按键分别定义的是PA11、PA12、PB10、PB11 
四个按键每次按下,分别+1,-1,+10,-10 
测试效果如下 4. 旋钮电位器测试 main.c主程序如下 用到的程序模块 
开启PA2、PA3、PA4、PA5,用于四个电位器旋钮。 用ADC2。 
测试 5. 直流电机PWM测试 main.c主程序如下 用到下面四个模块 PWM.c中,使用TIM2时钟定时中断 电机PWM信号使用PA0引脚 
方向控制引脚,使用PB12和PB13输出信号 
main.c中,编写测试程序 使用按键控制电机增速和减速测试 测试 使用的是外接板子上的12V外供电,USB接口的3.3V电源摘了再进行测试 6. 编码器测试 main.c主程序如下 用于测量电机的实际转速和位置 使用下面模块 引脚设置的是PA6和PA7 使用TIM3定时器 
测试如下 用手拨动电机驱动盘,会随着手指的旋动,电机的位置和速度会发生变化,编码器检测到这个变化,读取位置和速度值,然后进行百分数计算后,显示到OLED中 7. 串口测试 测试流程,先读取旋钮电位器的数值,然后通过串口进行发送, 使用TTL usb串口工具接上电脑,读取四个电位器的实时数值 
分别旋动四个旋钮电位器 观察串口助手的数值变化与OLED显示一致。 

旋动旋钮1,RP1位置数值随即发生变化,串口助手也读取到相同的数值。

/*OLED测试*//*下载此段程序后,OLED屏幕上会显示一些测试内容*/int main(void){/*模块初始化*/OLED_Init(); //OLED初始化/*显示测试字符串*/OLED_ShowString(0, 0, "Hello,世界。", OLED_8X16);/*显示测试浮点数*/OLED_ShowFloatNum(0, 16, 12345.76, 5,2, OLED_8X16);/*OLED_Printf格式化打印测试*/OLED_Printf(0, 32, OLED_8X16, "Num=%d", 666888);/*调用OLED功能函数后,必须调用OLED_Update,否则OLED将不会收到任何数据*/OLED_Update();while (1){}}
OLED_Data.c 为字库,自定义的图片和汉字可以用字模软件生成字模,复制到这里,然后就可以在main.c主程序中写程序进行显示。


/*LED测试*//*下载此段程序后,STM32板载的LED会以1s为周期闪烁*/int main(void){/*模块初始化*/LED_Init(); //LED初始化,此LED为STM32板载连接在PC13端口的LEDwhile (1){LED_ON(); //LED点亮Delay_ms(500); //延时500msLED_OFF(); //LED熄灭Delay_ms(500); //延时500msLED_Turn(); //LED亮灭状态取反Delay_ms(500); //延时500msLED_Turn(); //LED亮灭状态取反Delay_ms(500); //延时500ms}}


关注
重播 分享 赞
/*定时中断和非阻塞式按键测试*//*下载此段程序后,OLED显示变量i会1ms自增一次*//*按下K1按键,OLED显示变量j加1,按下K2,j减1,按下K3,j加10,按下K4,j减10*/uint16_t i;uint16_t j;uint8_t KeyNum;intmain(void){/*模块初始化*/OLED_Init(); //OLED初始化Key_Init(); //非阻塞式按键初始化Timer_Init(); //定时器初始化,1ms定时中断一次while (1){KeyNum = Key_GetNum(); //获取键码if (KeyNum == 1) //如果K1按下{j ++; //变量j加1}if (KeyNum == 2) //如果K2按下{j --; //变量j减1}if (KeyNum == 3) //如果K3按下{j += 10; //变量j加10}if (KeyNum == 4) //如果K4按下{j -= 10; //变量j减10}/*OLED显示*/OLED_Printf(0, 0, OLED_8X16, "i:%05d", i); //显示变量iOLED_Printf(0, 16, OLED_8X16, "j:%05d", j); //显示变量j/*OLED更新*/OLED_Update();}}voidTIM1_UP_IRQHandler(void){if (TIM_GetITStatus(TIM1, TIM_IT_Update) == SET){/*定时中断函数1ms自动执行一次*/i ++; //测试变量i自增Key_Tick(); //调用按键模块的Tick函数,用于驱动按键模块工作TIM_ClearITPendingBit(TIM1, TIM_IT_Update);}}





关注
重播 分享 赞
/*旋钮电位器测试*//*下载此段程序后,分别旋转4个电位器旋钮,OLED显示的4个AD值会对应变化*/int main(void){/*模块初始化*/OLED_Init(); //OLED初始化RP_Init(); //电位器旋钮初始化while (1){/*OLED显示*/OLED_Printf(0, 0, OLED_8X16, "RP1:%04d", RP_GetValue(1)); //显示电位器旋钮RP1的AD值OLED_Printf(0, 16, OLED_8X16, "RP2:%04d", RP_GetValue(2)); //显示电位器旋钮RP2的AD值OLED_Printf(0, 32, OLED_8X16, "RP3:%04d", RP_GetValue(3)); //显示电位器旋钮RP3的AD值OLED_Printf(0, 48, OLED_8X16, "RP4:%04d", RP_GetValue(4)); //显示电位器旋钮RP4的AD值/*OLED更新*/OLED_Update();}}


关注
重播 分享 赞
/*电机测试*//*下载此段程序后,按下K1,电机速度增加,按下K2,电机速度减小,按下K3,电机停止*/uint8_t KeyNum;int16_t PWM;intmain(void){/*模块初始化*/OLED_Init(); //OLED初始化Key_Init(); //非阻塞式按键初始化Motor_Init(); //电机初始化Timer_Init(); //定时器初始化,1ms定时中断一次while (1){KeyNum = Key_GetNum(); //获取键码if (KeyNum == 1) //如果K1按下{PWM += 10; //PWM变量加10if (PWM > 100) {PWM = 100;} //加到100后不再增加}if (KeyNum == 2) //如果K2按下{PWM -= 10; //PWM变量减10if (PWM < -100) {PWM = -100;} //减到-100后不再减小}if (KeyNum == 3) //如果K3按下{PWM = 0; //PWM变量归0}Motor_SetPWM(PWM); //电机设定PWM,将PWM变量的值给电机OLED_Printf(0, 0, OLED_8X16, "PWM:%+04d", PWM); //OLED显示PWM变量值OLED_Update(); //OLED更新}}voidTIM1_UP_IRQHandler(void){if (TIM_GetITStatus(TIM1, TIM_IT_Update) == SET){/*定时中断函数1ms自动执行一次*/Key_Tick(); //调用按键模块的Tick函数,用于驱动按键模块工作TIM_ClearITPendingBit(TIM1, TIM_IT_Update);}}

MOTOR.c中

关注
重播 分享 赞
/*编码器测试*//*下载此段程序后,手动旋转电机编码器,OLED上会显示旋转速度和位置*/int16_t Speed;int16_t Location;intmain(void){/*模块初始化*/OLED_Init(); //OLED初始化Encoder_Init(); //编码器初始化Timer_Init(); //定时器初始化,1ms定时中断一次while (1){OLED_Printf(0, 0, OLED_8X16, "Speed:%+05d", Speed); //OLED显示速度OLED_Printf(0, 16, OLED_8X16, "Location:%+05d", Location); //OLED显示位置OLED_Update(); //OLED更新}}voidTIM1_UP_IRQHandler(void){staticuint16_t Count; //定义静态变量,默认初始化为0,函数结束后,仍保留值和存储空间if (TIM_GetITStatus(TIM1, TIM_IT_Update) == SET){/*定时中断函数1ms自动执行一次*/Count ++; //使用Count变量计次进行分频if (Count >= 40) //计次到达40后,进入一次if,即40ms进一次if{Count = 0; //Count清零,以便下一个周期的计数/*获取编码器的计次值增量,即为速度*//*此Encoder_Get函数,可以获取两次读取编码器的计次值增量*//*此Speed值正比于速度,所以可以表示速度,但它的单位并不是速度的标准单位*//*此处每隔40ms获取一次计次值增量,电机旋转一周的计次值增量约为408*//*因此如果想转换为标准单位,比如转/秒*//*则可将此句代码改成Speed = Encoder_Get() / 408.0 / 0.04;*//*注意Speed变量的类型改为float*/Speed = Encoder_Get();/*速度累加,即为位置*/Location += Speed;}TIM_ClearITPendingBit(TIM1, TIM_IT_Update);}}

关注
重播 分享 赞
/*串口测试*//*下载此段程序后,分别旋转4个电位器旋钮,OLED显示的4个AD值会对应变化*//*同时这些值也会通过串口以文本格式发送出去*/uint16_t RP1, RP2, RP3, RP4;intmain(void){/*模块初始化*/OLED_Init(); //OLED初始化RP_Init(); //电位器旋钮初始化Serial_Init(); //串口初始化,波特率9600while (1){/*获取4个电位器旋钮的AD值*/RP1 = RP_GetValue(1);RP2 = RP_GetValue(2);RP3 = RP_GetValue(3);RP4 = RP_GetValue(4);/*OLED显示4个电位器旋钮的AD值*/OLED_Printf(0, 0, OLED_8X16, "RP1:%04d", RP1);OLED_Printf(0, 16, OLED_8X16, "RP2:%04d", RP2);OLED_Printf(0, 32, OLED_8X16, "RP3:%04d", RP3);OLED_Printf(0, 48, OLED_8X16, "RP4:%04d", RP4);/*OLED更新*/OLED_Update();/*使用串口格式化打印函数,将4个AD值通过串口发送出去*/Serial_Printf("%d,%d,%d,%d\r\n", RP1, RP2, RP3, RP4);// /*延时10ms,避免发送过快*/// Delay_ms(10);}}



驱动程序代码如下
通过网盘分享的文件:PID学习笔记03(硬件驱动基础代码测试).zip
链接: https://pan.baidu.com/s/1D6BueDSkE353K65lWVcBTA?pwd=jdyk 提取码: jdyk
通过网盘分享的文件:串口助手.zip
链接: https://pan.baidu.com/s/1ZNNeRH96-S_gSb-_RiWkWA?pwd=b8x6 提取码: b8x6
本文来自网友投稿或网络内容,如有侵犯您的权益请联系我们删除,联系邮箱:wyl860211@qq.com 。