小车PWM调速-模式选择

写好程序后,接上蓝牙模块,打开手机蓝牙助手,小车运行效果:首先进行模式选择,有快速模式、中速模式、慢速模式,按下模式选择,小车接收到串口信号后(串口接收指示灯会闪一下),便可进行不同模式下的前进和后退,在前进和后退期间也可以进行左转和右转的操作,想停止就按停止按钮;切换模式时都要先按下模式选择按钮,再按其他按键

1.程序文件如下

main.c:主函数,调用定时器0、定时器1和串口初始化函数

Motor.c:控制电机旋转,控制小车前进、后退、左转、右转、停止

Delay.c:延时函数

Timer0.c:定时器0初始化,前进的PWM调速

Timer2.c:定时器2初始化,后退的PWM调速

Uart.c:串口初始化,中断处理函数,接收串口指令,根据指令控制小车不同运行模式

2.定时器2的使用

为什么会用到定时器2,因为定时器1被用作了串口波特率发生器,定时器0用作前进PWM调速,所以后退的PWM调速就要用到平时不怎么用过的定时器2,手上STC89C52RC型号有定时器2

定时器2配置

数据手册有详细介绍,这里截出关键的地方

定时器2中断号

中断示意图

定时器2的中断请求标志位TF2EXF2。当定时器寄存器TH2/TL2溢出时,溢出标志位TF2会被置位,定时器中断发生。当单片机转去执行该定时器中断时,定时器的溢出标志位TF2会被硬件清除。当EXEN2=1且T2EX的负跳变产生捕获或重装时,EXF2置位。定时器2中断使能时,EXF2=1也将使CPU从中断向量处执行定时器2中断子程序。

中断允许寄存器IE:

ET2:定时/计数器T2的溢出中断允许位。ET2=1,允许T2中断;ET2=0,禁止T2中断。

定时器/计数器2控制寄存器T2CON

TF2:定时器2溢出标志。定时器2溢出时置位,必须由软件清除。当RCLK或TCLK=1时,TF2将不会置位

TR2:定时器2启动/停止控制位。置1时启动定时器

可使用STC-ISP工具生成定时器2配置函数,这里注意,初始化函数中先不着急开启计时,要在接收到串口信号再开启

/*** @brief 定时器2初始化函数* @param 无* @retval无*/
void Timer2Init(void)       //500微秒@11.0592MHz
{T2MOD = 0;        //初始化模式寄存器T2CON = 0;       //初始化控制寄存器TL2 = 0x33;      //设置定时初值TH2 = 0xFE;        //设置定时初值RCAP2L = 0x33;     //设置定时重载值RCAP2H = 0xFE;        //设置定时重载值TR2 = 0;      //定时器2不开始计时,接收到串口信号时开启ET2 = 1;      //开启定时器2中断EA = 1;          //开启总中断
}

然后中断处理函数跟定时器0的内容几乎一样,只是中断号是5,然后定时器0是让小车前进

//Timer1中断处理函数,每隔0.5毫秒进入一次中断
void Timer2_Rountine() interrupt 5
{count1++;TF2 = 0;       //定时器2溢出标志,软件清零if(count1 < BackSpeed){//定时器0里是调用GoForward()函数让小车前进//后退GoBack();}else{//停止Stop();}//每次count+1是0.5ms,加了40次,是20msif(count1 == 40 ){count1 = 0;}
}

3.串口中断处理函数

本次的中断处理函数有所更改

1.在判断第一个字母时,加入Q,M,S,分别是快速模式,中速模式和慢速模式

2.定义一个速度选择标志位,当判断串口收到的指令是"Quick",“Middle”,"Slow"中的一种时,相应的让标志位值位

3.然后下一个指令如果是前进或者后退,就判断速度选择标志位,给ForwardSpeed或BackSpeed赋不同的值,达到不同的速度

4.收到停止信号时,前进和后退的speed都要清0,speed一直有数据的话,小车就会一直走,串口这边让停PWM那边又让走,小车会出故障

5.收到指令后开启定时器的原因:

前提:如果定时器0和定时器2的初始化函数中让定时器开始计时,在main函数调用初始化函数,那么单片机一上电后两个定时器便会开始计时,而此时ForwardSpeed(前进速度)和BackSpeed(后退速度)都是0,所以在两者的中断处理函数中,count自增,都不满足count < ForwardSpeed/BackSpeed条件,此时小车会停止;

出现问题:如果此时收到串口前进信号,那么ForwardSpeed会被赋值,必定有段时间满足count < ForwardSpeed条件,所以小车会开始前进,但此时后退的PWM中断处理函数中BackSpeed的值仍然是0,会一直调用Stop()停止函数,定时器0想让小车前进,定时器2想让小车停止,所以两者出现了冲突,出现的现象是小车不动并且会发出吱吱的电流声

解决:解决上诉问题的做法便是两个定时器的初始化函数中不着急着开启计时,而是将TR0 = 1;(开启定时器0计时)放在串口接收到前进指令时开启,此时ForwardSpeed被赋值了,前进PWM调速开始,小车会前进,而定时器2因没有开始计时,所以不会溢出进入中断处理函数,不会进行后退PWM调速,没有调用Stop函数就不会对前进进行干扰;同理,在收到串口后退指令时再开启定时器2;为了避免已经开启的定时器0干扰,先关闭了定时器0计时,再开启定时器2,同理,如果一开始已经开启了定时器2进行后退,再前进的话就要先关闭了定时器2计时,再开启定时器0前进

优化后的现象:手机蓝牙先发送模式,然后按下前进按钮,小车就根据速度模式前进,按下后退按钮,小车也能后退,左转和右转也不受影响

总结:定时器0和定时器2只能有一个在计时,不能同时进行;在收到停止信号后,要将ForwardSpeed和BackSpeed都清零

6.串口最后 if 判断当接收数组为空时让小车停止,加上这句判断的原因是:根据之前的长按控制小车代码进行的优化;

出现问题:之前的长按控制代码中是在main函数的while循环里一直调用Stop函数,这种情况下,左转和右转可以实现长按控制,但前进和后退就不行了,按下前进或者后退按钮小车不动并会发出吱吱电流声,原因跟上面定时器的冲突一样,在PWM调速时,主函数却一直让小车停止;

解决:把main函数中的Stop()函数删掉,在串口最后加上一句 if 判断,当接收的数组为空时,再调用Stop()函数让小车停止,因为每接收到一个有效指令后,都会清空接收数组等待下一次接收,所以串口那边就要一直有信号接收,不然小车就会停止

优化后现象:

所以加上后实现的效果就是:一直按着左转或右转,小车正常转动,松手就停止,模式选择后,点击前进或后退也能正常启动

不足之处:因为前进和后退受PWM控制,是一个前进/后退与停止的不断进行的过程,若外界让小车停止时破坏到了PWM时序,则小车就不会启动并有电流声,而这次加上最后一条 if 语句判断后,虽然左转右转能长按控制,但前进和后退都不能长按控制,按一下按钮便前进或后退,按停止便停止,尝试过在最后的 if 判断中加入清除ForwardSpeed和BackSpeed的语句,但这样前进和后退就会抽搐,原因也简单,ForwardSpeed和BackSpeed在被赋值后很快便又被清0,PWM还没开启让小车启动就又要停止,所以出现轮子抽搐现象

暂且先这样吧,待以后想到好的解决办法再进行优化……

#define SIZE 10
unsigned char rec[SIZE];extern unsigned char ForwardSpeed;  //前进速度
extern unsigned char BackSpeed; //后退速度//速度选择标志位
unsigned char Speed_Flag = 0;
/*** @brief 串口中断处理函数,先接收模式选择,再前进和后退* @param 无* @retval无*/
void Uart_Rountine() interrupt 4
{static unsigned int i = 0;unsigned char temp;if(RI){RI = 0;temp = SBUF;if(temp == 'F' || temp == 'B' || temp == 'L' || temp == 'R' || temp == 'S'||temp == 'Q'||temp == 'S'||temp == 'M'){i = 0;}rec[i++] = temp;//模式选择//快速if(rec[0] == 'Q' && rec[1] == 'u'){Speed_Flag = 3;i = 0;memset(rec,'\0',SIZE);}//中速if(rec[0] == 'M' && rec[1] == 'i'){Speed_Flag = 2;i = 0;memset(rec,'\0',SIZE);}//慢速if(rec[0] == 'S' && rec[1] == 'l'){Speed_Flag = 1;i = 0;memset(rec,'\0',SIZE);}//前进if(rec[0] == 'F' && rec[1] == 'o'){TR2 = 0;    //关闭定时器2计时TR0 = 1; //开启定时器0计时if(Speed_Flag == 3){ForwardSpeed = 35;}else if(Speed_Flag == 2){ForwardSpeed = 25;}else if(Speed_Flag == 1){ForwardSpeed = 15;}      i = 0;memset(rec,'\0',SIZE);}//后退if(rec[0] == 'B' && rec[1] == 'a'){TR0 = 0;        //关闭定时器0计时TR2 = 1;     //打开定时器2计时if(Speed_Flag == 3){BackSpeed = 35;}else if(Speed_Flag == 2){BackSpeed = 25;}else if(Speed_Flag == 1){BackSpeed = 15;}i = 0;memset(rec,'\0',SIZE);}//左转if(rec[0] == 'L' && rec[1] == 'e'){GoLeft();/*左转的延时少一点,可通过点动方式一点一点地调方向,如果延时大的话,按一下就转动很大,不便调方向*/Delay1ms(200);      i = 0;memset(rec,'\0',SIZE);}//右转if(rec[0] == 'R' && rec[1] == 'i'){GoRight();Delay1ms(200);     //右转的延时跟左转同理i = 0;memset(rec,'\0',SIZE);}//收到停止信号,speed记得要清零if(rec[0] == 'S' && rec[1] == 't'){ForwardSpeed = 0;BackSpeed = 0;          Stop();i = 0;memset(rec,'\0',SIZE);}//如果串口不发送信息,则停止if(rec[0] == '\0' && rec[1] == '\0'){Stop();}if(i == SIZE){i = 0;}}
}

小车PWM调速-模式选择相关推荐

  1. 小车PWM调速-左右轮差速转弯

    小车PWM调速-左右轮差速转弯 之前写的左转和右转函数都是一个轮子停止,另一个轮子转动,才实现了转弯效果,那差速就是,两个轮子都转动,只不过一个轮子快,一个轮子慢,这样就实现了较平滑的转弯 左转:右轮 ...

  2. 小车PWM调速-串口控制

    小车PWM调速-串口控制 串口控制调速,即通过串口修改speed的值, 1.将上节PWM调速用到的定时器0源文件和头文件引入进来,工程文件如下 mian.c:主函数 Motor.c:小车前进.后退.左 ...

  3. 智能小车PWM调速原理

    电机驱动电路 智能小车电机的驱动芯片采用L293D.L293D是一款单片集成的高电压.高电流.4通道电机驱动,设计用于连接标准DTL或TTL逻辑电平,驱动电感负载(诸如继电线圈.DC和步进电机)和开关 ...

  4. 51智能小车pwm调速

    首先pwm调速主要运用的是定时器和中断的知识,此段代码运用的是定时器0,8位自动重装模块 下面了解pwm是如何控制速度的 调速的本质就是通过定时器控制小车的左右两轮使能:对小车的轮子转的时间和停的时间 ...

  5. pwm调速流程图小车_求智能小车 PWM调速?

    1. PWM原理 2.调制器设计思想 3.具体实现设计 一. PWM(脉冲宽度调制Pulse Width Modulation)原理: 脉冲宽度调制波通常由一列占空比不同的矩形脉冲构成,其占空比与信号 ...

  6. 51 PWM调速蓝牙小车

    文章目录 前言 一.硬件配置 二.相关接线 1.L298N驱动模块 2.HC-05蓝牙模块 3.接线图解 三.PWM调速 四.完整代码 总结 前言 当你看到无人机升天.平衡车的落地以及超声波避障等技术 ...

  7. STM32蓝牙小车以及PWM调速

    STM32蓝牙遥控小车 基于STM32F103系列的蓝牙控制小车以及PWM调速 代码下载 HC-06蓝牙模块 使用蓝牙模块前,需要先对其进行一些设置: 使用USB转TTL模块将蓝牙模块连接到电脑,蓝牙 ...

  8. 51单片机-PWM调速(直流电机,智能小车的电机调速)

    文章目录 前言 一.PWM 二.产生PWM的方法 使用定时器产生一个恒定的周期 中断服务子程序里设置比较值 三.实验 使用PWM对直流电机调速 使用PWM对智能小车的电机调速 总结 前言 这次来对PW ...

  9. STM32 学习笔记1-智能小车-基于PWM 调速 的电机设置

    目录 本文章主要介绍 STM32 电机相关软件的配置,PWM的相关介绍,csdn上面有很多资料 硬件: PWM(Pulse Width Modulation) 介绍: 基本定时器(TIM6/7) 通用 ...

最新文章

  1. 安装完之后设置动态ip地址
  2. Spring3:AOP
  3. 边缘计算 — 与硬件厂商
  4. Cassandra 数据模型设计,根据你的查询来制定设计——反范式设计本质:空间换时间...
  5. 微信小程序input批量赋值(setData)
  6. C# 的EF框架怎么连接Oracle数据库
  7. 记录我对Padding Oracle攻击的分析和思考之抄写
  8. C# 的未来:主构造函数
  9. mysql表空间不足_MySQL Innodb表空间不足的处理方法 风好大
  10. linux 网络定时断链,客户端连接linux经常间隔性断开链接
  11. vega56刷64_Vega56刷64的BIOS教程
  12. 实习转正述职报告PPT模板
  13. 任性与自制力差--拖延症(行为训练)
  14. python-求两个数的最小公倍数
  15. MATLAB 绘制颜色图的 几个函数 colormap caxis colorbar shading+pcolor用法记录
  16. 环信php修改头像,环信客服 如何正确设置用户的头像和昵称?
  17. qq小程序开发者工具无法编写代码
  18. 匈牙利算法——你一定可以看懂的图论算法
  19. 基于查找表的正弦波生成的研究
  20. 销售人员面对陌生客户时的谈话技巧

热门文章

  1. 仿选单网图片合成小工具
  2. day19-爬虫和前端
  3. iOS开发之自定义键盘(数字,字母类型等随意切换)
  4. 天地图实现标注用户当前坐标位置
  5. 官网下载windows系统
  6. linux系统安装systemback,使用systemback制作Ubuntu自定义系统镜像和系统备份(抄)...
  7. zabbix 内存溢出 解决
  8. 数学在计算机方面的应用论文参考文献,数学论文参考文献
  9. 僵尸国度.Z.Nation
  10. 科学划定“三区三线” 严格保护与合理利用自然资源