久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 7479|回復: 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 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏4 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
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 | 只看該作者
贊,感謝分享!
回復

使用道具 舉報

5#
ID:434283 發表于 2020-3-2 17:25 | 只看該作者
謝謝分享
回復

使用道具 舉報

6#
ID:736988 發表于 2020-5-16 22:32 | 只看該作者
謝謝分享
回復

使用道具 舉報

7#
ID:779690 發表于 2020-6-15 21:27 | 只看該作者
謝謝分享
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

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

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 久久一区二区三区四区 | 福利在线看 | 欧美一区二区三区在线播放 | 91免费在线视频 | 成人无遮挡毛片免费看 | 美女天天干| 亚洲国产精品99久久久久久久久 | 精品久久久久久亚洲精品 | 精品一区国产 | 亚洲成人精品 | 久久99精品久久久久久 | 天天射夜夜操 | 精品国产18久久久久久二百 | 91社区在线观看高清 | 欧产日产国产精品v | 国产精品久久国产精品久久 | 黄色毛片视频 | 亚洲国产成人精品女人久久久野战 | 自拍偷拍第一页 | 中文字幕一区二区三区乱码在线 | 手机在线一区二区三区 | 国产一级免费视频 | 国产精品不卡 | 亚洲精品视频免费看 | 久久久国 | 日本福利片 | 色橹橹欧美在线观看视频高清 | 色综合天天天天做夜夜夜夜做 | 美女一级毛片 | 好姑娘高清在线观看电影 | 国产精品免费在线 | 日韩中文字幕在线 | 色综合欧美 | 欧美午夜一区 | 日韩精品免费视频 | 欧美色综合一区二区三区 | aa级毛片毛片免费观看久 | 日本精品一区二区 | 久久九七| 天天干狠狠操 | 中文字幕亚洲欧美 |