51小车的电机驱动思路

本文讲述了在小车电机驱动中,如何通过方波和定时器实现占空比控制,以及如何设计合理的速度变量结构和函数,确保代码的灵活性和性能。重点讨论了如何通过设置目标速度和逐步调整来平滑速度变化,避免因快速切换导致的僵硬感。

方波和定时器

方波的发送是通过占空比来实现的,而想要实现占空比的话,需要借助到使用定时器的计数变量,这个变量一直在循环增加,当这个变量满足一定数值的时候,可以让释放的方波为1,而满足另外一种数值的时候,可以让释放的方波为0。

这是上述两种功能在逻辑上的衔接关系,那接下来想想代码是如何实现的。

由于你发送方波和定时器计数都是需要定时器来操作的,所以两人是平级的,先让计数变量++,等加加完了之后,再来影响方波发射器的发送,代码逻辑很重要。

电机驱动速度

我们在写小车电机驱动的时候,一定需要明确一个逻辑:小车在同一时间只有一个速度,也就是说我们可以定义一个速度变量或者是速度结构体(让和速度有关的变量封装起来),之后关于速度的任何操作值需要影响这个速度变量就可以影响小车的速度了,这叫做将小车的速度具象化,这是个很重要的思路。就像之前学习的LCD显示一样,其中有显示函数,也有装载了字符串的数组,显示模块永远是不用动的,而影响数据如何,只要对这个字符串数组进行操作就可以了,一定要将功能模块化,完成思维的解耦,这对于功能的构建至关重要,否则实现功能的时候将束手无策。

设置速度的改变

我们一开始设置速度的时候,是直接使用一个暴露在外的函数,直接对一个结构体变量里面的数据进行更改。而后面又增加了一个变量,也就是目标速度和目前速度,这样的话之前暴露在外的函数就是直接更改目标速度了,而目标速度和其他速度的之间的关系也是需要更改,而这个更改就要新建一个内部函数来体现了,这个内部函数就起到了衔接的作用

写函数第一件需要注意的事情

写函数第一件需要注意的事情就是考虑边界。

灵活的代码写法

a = (b > 0);

这句话直接将条件判断语句集成了,直接省略了一个if,这个只适用于布尔。

如果一个函数执行的太快怎么办?

如果一个函数

在基于51单片机的步进电机控制系统中,软件设计是实现功能的核心部分。通过AT89C51单片机控制步进电机的启动、停止、方向切换和速度调节等功能,需要编写相应的驱动代码来协调硬件模块的操作。以下是一个完整的基于51单片机的步进电机驱动示例代码,涵盖了按键控制启动/停止、方向切换、三挡速度调节以及使用数码管显示当前速度挡位的功能[^1]。 ```c #include <reg52.h> sbit KEY_START_STOP = P3^0; // 启动/停止按键 sbit KEY_DIR = P3^1; // 方向切换按键 sbit KEY_SPEED_UP = P3^2; // 速度增加按键 sbit SEG_A = P2^0; // 数码管段选A sbit SEG_B = P2^1; sbit SEG_C = P2^2; sbit SEG_D = P2^3; sbit SEG_E = P2^4; sbit SEG_F = P2^5; sbit SEG_G = P2^6; unsigned char speed_level = 1; // 初始速度等级 bit motor_running = 0; // 电机运行状态 bit motor_direction = 0; // 0: 正转, 1: 反转 unsigned int delay_time = 1000; // 初始延迟时间(影响速度) // 数码管显示数字0~2对应的段码 void display_speed(unsigned char level) { switch(level) { case 1: SEG_A = 1; SEG_B = 1; SEG_C = 1; SEG_D = 1; SEG_E = 1; SEG_F = 1; SEG_G = 0; // 显示0 break; case 2: SEG_A = 0; SEG_B = 1; SEG_C = 1; SEG_D = 0; SEG_E = 1; SEG_F = 1; SEG_G = 1; // 显示1 break; case 3: SEG_A = 1; SEG_B = 1; SEG_C = 0; SEG_D = 1; SEG_E = 1; SEG_F = 0; SEG_G = 1; // 显示2 break; } } // 延时函数 void delay(unsigned int time) { unsigned int i, j; for(i = 0; i < time; i++) for(j = 0; j < 120; j++); } // 按键扫描函数 void key_scan() { if(KEY_SPEED_UP == 0) { delay(10); // 消抖 if(KEY_SPEED_UP == 0) { speed_level++; if(speed_level > 3) speed_level = 1; switch(speed_level) { case 1: delay_time = 1000; break; case 2: delay_time = 500; break; case 3: delay_time = 200; break; } while(!KEY_SPEED_UP); // 等待按键释放 } } if(KEY_DIR == 0) { delay(10); if(KEY_DIR == 0) { motor_direction = ~motor_direction; while(!KEY_DIR); } } if(KEY_START_STOP == 0) { delay(10); if(KEY_START_STOP == 0) { motor_running = ~motor_running; while(!KEY_START_STOP); } } } // 步进电机驱动函数(四相五线制) void step_motor() { static unsigned char step = 0; unsigned char code phases[] = {0x08, 0x0C, 0x04, 0x06, 0x02, 0x03, 0x01, 0x09}; // 八拍模式 if(motor_direction == 0) { P1 = phases[step]; // 正转 step++; if(step >= 8) step = 0; } else { P1 = phases[7 - step]; // 反转 step++; if(step >= 8) step = 0; } } void main() { while(1) { key_scan(); // 扫描按键 display_speed(speed_level); // 显示当前速度等级 if(motor_running) { step_motor(); // 驱动步进电机 delay(delay_time); // 控制速度 } else { P1 = 0x00; // 电机停止 } } } ``` ### 说明与扩展 - **硬件连接**:P1口用于控制步进电机的相序输出;P3口连接三个按键分别用于启停、换向和调速;P2口连接七段数码管用于显示当前速度等级。 - **速度控制逻辑**:通过修改`delay_time`变量控制步进电机每一步之间的延时,从而实现不同速度挡位的调节。 - **方向控制逻辑**:正转时按顺序输出相序数组中的值,反转则反向输出数组内容。 - **数码管显示**:根据当前速度等级显示数字0、1、2,分别对应三挡速度。 此外,还可以在此基础上添加LCD屏幕进行更丰富的信息显示或蜂鸣器提示音等附加功能[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值