找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6516|回复: 6
收起左侧

基于51单片机和L298N的小车制作(二)

  [复制链接]
ID:235664 发表于 2017-9-29 09:57 | 显示全部楼层 |阅读模式
上一篇文章讲了可以利用PWM脉冲来控制电机的转速,  并且占空比越高电机转速越快。 前面说的是利用按键来控制PWM脉冲信号的输出, 但是在实际小车中总不能一直跟着小车跑吧, 那样多没意思。 所以这次我用红外通信(遥控器)来进行对小车的控制。 外部中断0服务函数来对红外信号进行接收, 并且让小车作出相应的处理。 利用定时器T0来控制PWM脉冲信号的形成(即控制小车的转速), 我在利用定时器控制PWM脉冲形成时遇到了一个问题:我原本想的是用两个定时器来控制两个电机的转动, 但是因为优先级的原因一直没有成功, 在这里浪费了很多时间, 最后和其他人的讨论中发现用一个定时器也可以对两个电机进行控制, 让其独立的转动。 到现在 我的小车已经能准确的接收到遥控器接收的指令并按照指令进行相应的运动。 虽然在这个过程中出现了一些小插曲:比如昨天晚上51单片机烧了, 额, 连着开发板一块烧了 (捂脸), 还有实验室有多余的 (哈哈)。
        到现在我的小车已经具备基本的功能了, 前进、后退、转弯等, 虽然精度很差(因为程序是自己写的), 但是也可以按照我的意愿跑了。  接下来应该会在这各个小车的基础上做一个寻迹的小车。 什么是在这个小车的基础上呢? 就是这个小车功能不会删除, 在加一个寻迹的功能; 然后可以在红外控制和寻迹之间自由切换; 想玩哪个就玩那个。

代码全部在附件里面。 由于附件不能添加.c文件, 所以代码时用的.doc。 需要的朋友请自己复制到编译器上面, 以免影响阅读

红外小车控制程序.doc

40.5 KB, 下载次数: 37, 下载积分: 黑币 -5

评分

参与人数 1黑币 +100 收起 理由
admin + 100 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:1 发表于 2017-9-29 15:48 | 显示全部楼层
给大家省点黑币
楼主的代码如下:
  1. /*******************************************
  2. 程序名称:红外控制小车程序
  3. 功能:可以实现小车的前进、后退、小车左右电机的转速相互独立
  4.           利用PWM脉冲实现对速度的分级(1级最慢, 10级最快)
  5. 单片机型号:STC89C52.  
  6. *******************************************/

  7. # include <reg52.h>

  8. // I/O口定义
  9. sbit PWM1 = P2^0;
  10. sbit PWM2 = P2^1;
  11. sbit PWM3 = P2^2;
  12. sbit PWM4 = P2^3;
  13. sbit IRIN = P3^2;

  14. typedef unsigned int u16;
  15. typedef unsigned char u8;

  16. u8 infrared_arr[6];
  17. u16 TIME;                         // 外部中断0中的计时
  18. u16 count0 = 0;                        // 定时器T0中的计时
  19. u16 count1 = 0;                        // 定时器T1中的计时
  20. u8  flag1 = 0;                // 电机1正反转的标志位
  21. u8  flag2 = 0;                // 电机2正反转的标志位
  22. u8  rank1;                        // 电机速度等级, 一共10级
  23. u8  rank2;                        // 电机速度等级, 一共10级

  24. //函数声明
  25. void func(u8 choose);
  26. void advance ();
  27. void back();
  28. void turn_left();
  29. void turn_right();
  30. void left_motor_add();
  31. void right_motor_add();
  32. void left_motor_less();
  33. void right_motor_less();
  34. void stop();

  35. // 外部中断0、定时器中断0 初始化
  36. void init0()
  37. {
  38.         EA = 1;                // 开启总中断
  39.         EX0 = 1;        // 允许外部中断0中断
  40.         IT0 = 1;        // 下降沿触发中断
  41.         IRIN = 1;        // 初始化红外通信端口

  42.         ET0 = 1;        // 定时器0中断
  43.         TH0 = (65536 - 10) / 256;                // 赋初值, 10us
  44.         TL0 = (65536 - 10) % 256;
  45.         TMOD = 0x01;        // 选择方式一
  46.         TR0 = 1;                // 打开定时器中断0

  47. }
  48. // i = 1时, 大概延时10us
  49. void delay(u16 i)
  50. {
  51.         while (i--);
  52. }

  53. int main (void)
  54. {
  55.         init0();
  56.         while (1);
  57.         return 0;
  58. }

  59. // 这个中断服务函数功能是接收红外数据, 选择执行的功能。
  60. void outer0_inter() interrupt 0
  61. {        
  62.         u16        err;
  63.         u8         j, k;
  64.         TIME = 0;
  65.         delay(700);                // 延迟7ms         起始码有9ms的低电平
  66.         if (IRIN == 0)        // 确定接收到的是真的信号
  67.         {
  68.                 err = 1000;
  69.                 while ((err > 0) && (IRIN == 0))
  70.                 {
  71.                         // 起始码前面的低电平信号已经过去;
  72.                         delay(1);
  73.                         err -- ;
  74.                 }
  75.                 if (1 == IRIN)
  76.                 {
  77.                         // 高电平信号4.5ms的到来
  78.                         err = 500;
  79.                         while ((err > 0) && (1 == IRIN))
  80.                         {
  81.                                 // 起始码完全过去
  82.                                 delay(1);
  83.                                 err -- ;
  84.                         }
  85.                         for (j = 0; j < 4; j++)
  86.                         {
  87.                                 for (k = 0; k < 8; k++)
  88.                                 {
  89.                                 // 因为无论是'0', 还是 '1', 前面都有0.56ms的低电平。
  90.                                 // 所以只有当这0.56ms的低电平过去之后才好判断是'0' or '1'
  91.                                         err = 60;
  92.                                         while ((0 == IRIN) && (err > 0))
  93.                                         {
  94.                                                 delay (1);         
  95.                                                 err -- ;
  96.                                         }
  97.                                         // 检测高电平的时间长短, 用TIME变量存储
  98.                                         err = 50;
  99.                                         while ((1 == IRIN) && (err > 0))
  100.                                         {
  101.                                                 delay (10);         // 0.1ms,  '0' :高电平时间为0.565ms; '1' : 高电平时间为1.69ms
  102.                                                 TIME ++;
  103.                                                 err -- ;
  104.                                        
  105.                                                 if (TIME > 30)          // 说明不是要接收的信号
  106.                                                 {
  107.                                                         return ;
  108.                                                 }
  109.                                         }               
  110.                                         infrared_arr[j] >>= 1;
  111.                                         if (TIME >= 8)                  // 将大于0.8ms的定义为 '1'
  112.                                         {
  113.                                                 infrared_arr[j] |= 0x80;
  114.                                         }
  115.                                         TIME = 0;        
  116.                                 }
  117.                         }
  118.                 }
  119.                 if (infrared_arr[2] != ~infrared_arr[3])
  120.                 {
  121.                         return ;
  122.                 }
  123.                 func(infrared_arr[2]);         // 选择小车的功能
  124.         }
  125. }
  126. void func(u8 choose)
  127. {
  128.         switch(choose)
  129.                 {
  130.                 case 0x18:                        // 前进
  131.                         advance();
  132.                         break;
  133.                 case 0x52:                        // 后退
  134.                         back();
  135.                         break;
  136.                 case 0x08:                        //左转
  137.                         turn_left();
  138.                         break;
  139.                 case 0x5a:                        //右转
  140.                         turn_right();
  141.                         break;
  142.                 case 0x0c:                         // 左边电机加速转动
  143.                         left_motor_add();
  144.                         break;
  145.                 case 0x42:                          // 左边电机减速转动
  146.                         left_motor_less();
  147.                         break;
  148.                 case 0x5e:                                // 右边电机加速转动                                 
  149.                         right_motor_add();
  150.                         break;
  151.                 case 0x4a:                                // 右边电机减速转动
  152.                         right_motor_less();
  153.                         break;
  154.                 case 0x1c:                                // 小车停止
  155.                         stop();        
  156.                         break;
  157.                 }        
  158. }

  159. void T0_inter() interrupt 1
  160. {
  161.         TR0 = 0;
  162.         TH0 = (65536 - 10)/256;
  163.         TL0 = (65536 - 10)%256;
  164.         TR0 = 1;

  165.         count0 ++;
  166.         if (count0 >= 100)
  167.         {
  168.                 count0 = 0;
  169.         }
  170.         if (count0 < (rank1 * 10))
  171.         {
  172.                 if (flag1 == 0)
  173.                 {
  174.                         PWM1 = 1;
  175.                         PWM2 = 0;
  176.                 }
  177.                 else
  178.                 {
  179.                         PWM1 = 0;
  180.                         PWM2 = 1;
  181.                 }
  182.         }        
  183.         else
  184.         {
  185.                 PWM1 = 1;
  186.                 PWM2 = 1;
  187.         }
  188.         if (count0 < (rank2 * 10))
  189.         {
  190.                 if (flag2 == 0)
  191.                 {
  192.                         PWM3 = 1;
  193.                         PWM4 = 0;
  194.                 }
  195.                 else
  196.                 {
  197.                         PWM3 = 0;
  198.                         PWM4 = 1;
  199.                 }
  200.         }
  201.         else
  202.         {
  203.                 PWM3 = 1;
  204.                 PWM4 = 1;
  205.         }
  206. }

  207. // 小车前进函数, 速率为最大值的一半
  208. void advance()
  209. {
  210.         rank1 = 5;
  211.         rank2 = 5;
  212.         flag1 = 1;
  213.         flag2 = 1;                        
  214. }
  215. // 小车后退函数, 速率为最大值的一半
  216. void back()
  217. {
  218.         rank1 = 5;
  219.         rank2 = 5;
  220.         flag1 = 0;
  221.         flag2 = 0;        
  222. }
  223. // 小车左急转弯函数, 左边电机正转, 右边电机反转
  224. void turn_left()
  225. {
  226.         flag1 = 1;
  227.         flag2 = 0;
  228. }
  229. // 小车右急转弯函数, 右边电机正转, 左边电机反转
  230. void turn_right()
  231. {                        
  232.         flag1 = 0;
  233.         flag2 = 1;
  234. }
  235. // 小车左转函数, 右边电机转动比左边电机快
  236. void right_motor_add()
  237. {        
  238.         if (rank1 == 10)
  239.         {
  240.                 rank1 = 5;
  241.         }
  242.         rank1++;         
  243. }
  244. // 右边电机加速
  245. void right_motor_less()
  246. {  
  247.         if (rank1 == 0)
  248.         {
  249.                 rank1 = 5;
  250.         }
  251.         rank1--;
  252. }
  253. // 小车右转函数, 左边电机转动比左边电机快
  254. void left_motor_add()
  255. {
  256.         if (rank2 == 10)
  257.         {
  258.                 rank2 = 5;
  259.         }
  260.         rank2++;         
  261. }
  262. // 左边电机减速
  263. void left_motor_less()
  264. {        
  265.         if (rank2 == 0)
  266.         {
  267.                 rank2 = 5;
  268.         }
  269.         rank2--;        
  270. }
  271. // 小车停止函数
  272. void stop()
  273. {
  274.         rank1 = 0;
  275.         rank2 = 0;
  276. }
复制代码
回复

使用道具 举报

ID:235664 发表于 2017-9-29 17:39 | 显示全部楼层
admin 发表于 2017-9-29 15:48
给大家省点黑币
楼主的代码如下:

谢谢管理员, 我主要是觉得代码放在帖子里不怎么好看。 以后我的相关文章也会采取这种方式, 将代码放在第一楼

评分

参与人数 1黑币 +1 收起 理由
Dongdaren,哈哈 + 1 很给力!

查看全部评分

回复

使用道具 举报

ID:550878 发表于 2019-5-30 10:52 | 显示全部楼层
赞,感谢分享!
回复

使用道具 举报

ID:434283 发表于 2020-3-2 17:25 | 显示全部楼层
谢谢分享
回复

使用道具 举报

ID:736988 发表于 2020-5-16 22:32 | 显示全部楼层
谢谢分享
回复

使用道具 举报

ID:779690 发表于 2020-6-15 21:27 | 显示全部楼层
谢谢分享
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表