找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 7525|回復(fù): 6
收起左側(cè)

基于51單片機(jī)和L298N的小車制作(二)

  [復(fù)制鏈接]
ID:235664 發(fā)表于 2017-9-29 09:57 | 顯示全部樓層 |閱讀模式
上一篇文章講了可以利用PWM脈沖來(lái)控制電機(jī)的轉(zhuǎn)速,  并且占空比越高電機(jī)轉(zhuǎn)速越快。 前面說(shuō)的是利用按鍵來(lái)控制PWM脈沖信號(hào)的輸出, 但是在實(shí)際小車中總不能一直跟著小車跑吧, 那樣多沒(méi)意思。 所以這次我用紅外通信(遙控器)來(lái)進(jìn)行對(duì)小車的控制。 外部中斷0服務(wù)函數(shù)來(lái)對(duì)紅外信號(hào)進(jìn)行接收, 并且讓小車作出相應(yīng)的處理。 利用定時(shí)器T0來(lái)控制PWM脈沖信號(hào)的形成(即控制小車的轉(zhuǎn)速), 我在利用定時(shí)器控制PWM脈沖形成時(shí)遇到了一個(gè)問(wèn)題:我原本想的是用兩個(gè)定時(shí)器來(lái)控制兩個(gè)電機(jī)的轉(zhuǎn)動(dòng), 但是因?yàn)閮?yōu)先級(jí)的原因一直沒(méi)有成功, 在這里浪費(fèi)了很多時(shí)間, 最后和其他人的討論中發(fā)現(xiàn)用一個(gè)定時(shí)器也可以對(duì)兩個(gè)電機(jī)進(jìn)行控制, 讓其獨(dú)立的轉(zhuǎn)動(dòng)。 到現(xiàn)在 我的小車已經(jīng)能準(zhǔn)確的接收到遙控器接收的指令并按照指令進(jìn)行相應(yīng)的運(yùn)動(dòng)。 雖然在這個(gè)過(guò)程中出現(xiàn)了一些小插曲:比如昨天晚上51單片機(jī)燒了, 額, 連著開(kāi)發(fā)板一塊燒了 (捂臉), 還有實(shí)驗(yàn)室有多余的 (哈哈)。
        到現(xiàn)在我的小車已經(jīng)具備基本的功能了, 前進(jìn)、后退、轉(zhuǎn)彎等, 雖然精度很差(因?yàn)槌绦蚴亲约簩懙模?但是也可以按照我的意愿跑了。  接下來(lái)應(yīng)該會(huì)在這各個(gè)小車的基礎(chǔ)上做一個(gè)尋跡的小車。 什么是在這個(gè)小車的基礎(chǔ)上呢? 就是這個(gè)小車功能不會(huì)刪除, 在加一個(gè)尋跡的功能; 然后可以在紅外控制和尋跡之間自由切換; 想玩哪個(gè)就玩那個(gè)。

代碼全部在附件里面。 由于附件不能添加.c文件, 所以代碼時(shí)用的.doc。 需要的朋友請(qǐng)自己復(fù)制到編譯器上面, 以免影響閱讀

紅外小車控制程序.doc

40.5 KB, 下載次數(shù): 37, 下載積分: 黑幣 -5

評(píng)分

參與人數(shù) 1黑幣 +100 收起 理由
admin + 100 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:1 發(fā)表于 2017-9-29 15:48 | 顯示全部樓層
給大家省點(diǎn)黑幣
樓主的代碼如下:
  1. /*******************************************
  2. 程序名稱:紅外控制小車程序
  3. 功能:可以實(shí)現(xiàn)小車的前進(jìn)、后退、小車左右電機(jī)的轉(zhuǎn)速相互獨(dú)立
  4.           利用PWM脈沖實(shí)現(xiàn)對(duì)速度的分級(jí)(1級(jí)最慢, 10級(jí)最快)
  5. 單片機(jī)型號(hào):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中的計(jì)時(shí)
  18. u16 count0 = 0;                        // 定時(shí)器T0中的計(jì)時(shí)
  19. u16 count1 = 0;                        // 定時(shí)器T1中的計(jì)時(shí)
  20. u8  flag1 = 0;                // 電機(jī)1正反轉(zhuǎn)的標(biāo)志位
  21. u8  flag2 = 0;                // 電機(jī)2正反轉(zhuǎn)的標(biāo)志位
  22. u8  rank1;                        // 電機(jī)速度等級(jí), 一共10級(jí)
  23. u8  rank2;                        // 電機(jī)速度等級(jí), 一共10級(jí)

  24. //函數(shù)聲明
  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、定時(shí)器中斷0 初始化
  36. void init0()
  37. {
  38.         EA = 1;                // 開(kāi)啟總中斷
  39.         EX0 = 1;        // 允許外部中斷0中斷
  40.         IT0 = 1;        // 下降沿觸發(fā)中斷
  41.         IRIN = 1;        // 初始化紅外通信端口

  42.         ET0 = 1;        // 定時(shí)器0中斷
  43.         TH0 = (65536 - 10) / 256;                // 賦初值, 10us
  44.         TL0 = (65536 - 10) % 256;
  45.         TMOD = 0x01;        // 選擇方式一
  46.         TR0 = 1;                // 打開(kāi)定時(shí)器中斷0

  47. }
  48. // i = 1時(shí), 大概延時(shí)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. // 這個(gè)中斷服務(wù)函數(shù)功能是接收紅外數(shù)據(jù), 選擇執(zhí)行的功能。
  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)        // 確定接收到的是真的信號(hào)
  67.         {
  68.                 err = 1000;
  69.                 while ((err > 0) && (IRIN == 0))
  70.                 {
  71.                         // 起始碼前面的低電平信號(hào)已經(jīng)過(guò)去;
  72.                         delay(1);
  73.                         err -- ;
  74.                 }
  75.                 if (1 == IRIN)
  76.                 {
  77.                         // 高電平信號(hào)4.5ms的到來(lái)
  78.                         err = 500;
  79.                         while ((err > 0) && (1 == IRIN))
  80.                         {
  81.                                 // 起始碼完全過(guò)去
  82.                                 delay(1);
  83.                                 err -- ;
  84.                         }
  85.                         for (j = 0; j < 4; j++)
  86.                         {
  87.                                 for (k = 0; k < 8; k++)
  88.                                 {
  89.                                 // 因?yàn)闊o(wú)論是'0', 還是 '1', 前面都有0.56ms的低電平。
  90.                                 // 所以只有當(dāng)這0.56ms的低電平過(guò)去之后才好判斷是'0' or '1'
  91.                                         err = 60;
  92.                                         while ((0 == IRIN) && (err > 0))
  93.                                         {
  94.                                                 delay (1);         
  95.                                                 err -- ;
  96.                                         }
  97.                                         // 檢測(cè)高電平的時(shí)間長(zhǎng)短, 用TIME變量存儲(chǔ)
  98.                                         err = 50;
  99.                                         while ((1 == IRIN) && (err > 0))
  100.                                         {
  101.                                                 delay (10);         // 0.1ms,  '0' :高電平時(shí)間為0.565ms; '1' : 高電平時(shí)間為1.69ms
  102.                                                 TIME ++;
  103.                                                 err -- ;
  104.                                        
  105.                                                 if (TIME > 30)          // 說(shuō)明不是要接收的信號(hào)
  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:                        // 前進(jìn)
  131.                         advance();
  132.                         break;
  133.                 case 0x52:                        // 后退
  134.                         back();
  135.                         break;
  136.                 case 0x08:                        //左轉(zhuǎn)
  137.                         turn_left();
  138.                         break;
  139.                 case 0x5a:                        //右轉(zhuǎn)
  140.                         turn_right();
  141.                         break;
  142.                 case 0x0c:                         // 左邊電機(jī)加速轉(zhuǎn)動(dòng)
  143.                         left_motor_add();
  144.                         break;
  145.                 case 0x42:                          // 左邊電機(jī)減速轉(zhuǎn)動(dòng)
  146.                         left_motor_less();
  147.                         break;
  148.                 case 0x5e:                                // 右邊電機(jī)加速轉(zhuǎn)動(dòng)                                 
  149.                         right_motor_add();
  150.                         break;
  151.                 case 0x4a:                                // 右邊電機(jī)減速轉(zhuǎn)動(dòng)
  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. // 小車前進(jìn)函數(shù), 速率為最大值的一半
  208. void advance()
  209. {
  210.         rank1 = 5;
  211.         rank2 = 5;
  212.         flag1 = 1;
  213.         flag2 = 1;                        
  214. }
  215. // 小車后退函數(shù), 速率為最大值的一半
  216. void back()
  217. {
  218.         rank1 = 5;
  219.         rank2 = 5;
  220.         flag1 = 0;
  221.         flag2 = 0;        
  222. }
  223. // 小車左急轉(zhuǎn)彎函數(shù), 左邊電機(jī)正轉(zhuǎn), 右邊電機(jī)反轉(zhuǎn)
  224. void turn_left()
  225. {
  226.         flag1 = 1;
  227.         flag2 = 0;
  228. }
  229. // 小車右急轉(zhuǎn)彎函數(shù), 右邊電機(jī)正轉(zhuǎn), 左邊電機(jī)反轉(zhuǎn)
  230. void turn_right()
  231. {                        
  232.         flag1 = 0;
  233.         flag2 = 1;
  234. }
  235. // 小車左轉(zhuǎn)函數(shù), 右邊電機(jī)轉(zhuǎn)動(dòng)比左邊電機(jī)快
  236. void right_motor_add()
  237. {        
  238.         if (rank1 == 10)
  239.         {
  240.                 rank1 = 5;
  241.         }
  242.         rank1++;         
  243. }
  244. // 右邊電機(jī)加速
  245. void right_motor_less()
  246. {  
  247.         if (rank1 == 0)
  248.         {
  249.                 rank1 = 5;
  250.         }
  251.         rank1--;
  252. }
  253. // 小車右轉(zhuǎn)函數(shù), 左邊電機(jī)轉(zhuǎn)動(dòng)比左邊電機(jī)快
  254. void left_motor_add()
  255. {
  256.         if (rank2 == 10)
  257.         {
  258.                 rank2 = 5;
  259.         }
  260.         rank2++;         
  261. }
  262. // 左邊電機(jī)減速
  263. void left_motor_less()
  264. {        
  265.         if (rank2 == 0)
  266.         {
  267.                 rank2 = 5;
  268.         }
  269.         rank2--;        
  270. }
  271. // 小車停止函數(shù)
  272. void stop()
  273. {
  274.         rank1 = 0;
  275.         rank2 = 0;
  276. }
復(fù)制代碼
回復(fù)

使用道具 舉報(bào)

ID:235664 發(fā)表于 2017-9-29 17:39 | 顯示全部樓層
admin 發(fā)表于 2017-9-29 15:48
給大家省點(diǎn)黑幣
樓主的代碼如下:

謝謝管理員, 我主要是覺(jué)得代碼放在帖子里不怎么好看。 以后我的相關(guān)文章也會(huì)采取這種方式, 將代碼放在第一樓

評(píng)分

參與人數(shù) 1黑幣 +1 收起 理由
Dongdaren,哈哈 + 1 很給力!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:550878 發(fā)表于 2019-5-30 10:52 | 顯示全部樓層
贊,感謝分享!
回復(fù)

使用道具 舉報(bào)

ID:434283 發(fā)表于 2020-3-2 17:25 | 顯示全部樓層
謝謝分享
回復(fù)

使用道具 舉報(bào)

ID:736988 發(fā)表于 2020-5-16 22:32 | 顯示全部樓層
謝謝分享
回復(fù)

使用道具 舉報(bào)

ID:779690 發(fā)表于 2020-6-15 21:27 | 顯示全部樓層
謝謝分享
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表