找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 367|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

51單片機(jī)雙輪循跡小車控制程序(注釋詳細(xì))

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
一、概述
本雙輪自動尋跡小車旨在實(shí)現(xiàn)對任意給定軌跡的快速精準(zhǔn)跟蹤,基于單片機(jī)控制技術(shù),整合傳感器檢測、電機(jī)驅(qū)動及路徑規(guī)劃算法,構(gòu)建具備高穩(wěn)定性的自動尋跡小車。實(shí)物設(shè)計聚焦于硬件可靠性、軟件邏輯的高效性及系統(tǒng)整體的安全性,適用于智能物流、教育科研及工業(yè)巡檢等場景。
二、硬件設(shè)計方案
(一)主控芯片
選用STC89C52RC 單片機(jī)(STC 品牌,型號 89C52RC),其具備 8KB Flash ROM、256B RAM、3 個 16 位定時器 / 計數(shù)器及 6 個中斷源,支持最高 24MHz 晶振頻率,可滿足多任務(wù)實(shí)時處理需求。搭配最小系統(tǒng)電路,包括 11.0592MHz 晶振與按鍵復(fù)位電路,確保芯片穩(wěn)定運(yùn)行。程序下載通過MAX232 電平轉(zhuǎn)換芯片(MAXIM 品牌,型號 MAX232)連接 PC 端串口,支持 STC-ISP 軟件離線下載。
(二)傳感器模塊
采用TCRT5000 反射式紅外光電傳感器,內(nèi)置高功率紅外發(fā)射管與高靈敏度光電晶體管,檢測距離 4-13cm 可調(diào),抗環(huán)境光干擾能力強(qiáng)。內(nèi)置數(shù)模轉(zhuǎn)換,將紅外信號轉(zhuǎn)換為數(shù)字量,實(shí)現(xiàn)對黑色軌跡線的精準(zhǔn)識別。
(三)電機(jī)驅(qū)動模塊
選用L298N 電機(jī)驅(qū)動芯片,支持雙直流電機(jī)驅(qū)動,工作電壓 5-46V,最大輸出電流 2A。搭配12V/2000mAh 鋰電池供電,通過 PWM 控制電機(jī)轉(zhuǎn)速。電機(jī)選型為RS370直流減速電機(jī)(電壓 12V,轉(zhuǎn)速 3000rpm),滿足雙輪小車的驅(qū)動力與速度要求。
(四)電源模塊
    12V 鋰電池經(jīng) 7809(輸出 9V)、7805(輸出 5V)穩(wěn)壓芯片,分別為電機(jī)驅(qū)動、傳感器及單片機(jī)系統(tǒng)供電。電容濾波網(wǎng)絡(luò)(10μF 貼片電容 + 0.1μF 瓷片電容)降低電源紋波,確保各模塊穩(wěn)定工作。

三、軟件設(shè)計方案
(一)軟件設(shè)計與代碼實(shí)現(xiàn)
軟件基于 STC89C52 單片機(jī)開發(fā),采用 C 語言編程,通過 Keil uVision 環(huán)境編譯生成 HEX 文件,利用 STC-ISP 工具下載至單片機(jī)。代碼核心邏輯圍繞 5 路紅外傳感器(P0.0-P0.4)的信號采集、電機(jī)差速控制及 PWM 調(diào)速。
(二)傳感器信號采集與狀態(tài)編碼
代碼通過 P0 口讀取 5 路紅外傳感器狀態(tài),未檢測到黑線時引腳為高電平(邏輯 1),檢測到黑線時為低電平(邏輯 0)。傳感器狀態(tài)被組合為 5 位二進(jìn)制數(shù)存儲于sensorValue變量,中間傳感器觸發(fā)時狀態(tài)為0b11011(對應(yīng)十六進(jìn)制0x1B),右側(cè)中間傳感器觸發(fā)時為0b11101(0x1D),左側(cè)雙傳感器觸發(fā)時為0b01111(0x0F)。代碼通過Sensor_Read()函數(shù)完成狀態(tài)采集,采用逐位賦值方式避免sbit類型直接移位運(yùn)算,確保邏輯正確性。
(三)電機(jī)驅(qū)動與 PWM 調(diào)速
電機(jī)驅(qū)動采用 L298N 模塊,通過 P2 口控制轉(zhuǎn)向邏輯(IN1-IN4),并利用定時器 0 生成 PWM 信號調(diào)節(jié)轉(zhuǎn)速(ENA/ENB)。定時器 0 工作于模式 1(16 位自動重裝),配置初值實(shí)現(xiàn)約 100μs 定時周期,中斷函數(shù)中通過pwmCounter計數(shù)器(0-100)生成 100Hz PWM 波形。左右電機(jī)占空比由cntPWM1(右電機(jī))和cntPWM2(左電機(jī))控制,直行時占空比設(shè)為 40%(cntPWM1=40、cntPWM2=40),偏左時右電機(jī)占空比提高至 55%-70%、左電機(jī)降低至 40%-55%,通過差速實(shí)現(xiàn)轉(zhuǎn)向。
(四)路徑跟蹤邏輯實(shí)現(xiàn)
主函數(shù)循環(huán)調(diào)用XunJi()函數(shù)執(zhí)行路徑控制,通過switch-case語句匹配sensorValue狀態(tài)。當(dāng)狀態(tài)為0b00000(全黑)或0b11111(全白)時執(zhí)行停車邏輯;中間傳感器觸發(fā)(0b00100對應(yīng)的flag=0)時調(diào)用Forward()函數(shù)雙電機(jī)正轉(zhuǎn);左側(cè)傳感器觸發(fā)(如0b10000對應(yīng)的flag=3)時調(diào)用TurnLeft1()函數(shù),右電機(jī)正轉(zhuǎn)、左電機(jī)反轉(zhuǎn)并設(shè)置較大轉(zhuǎn)速差(cntPWM1=55、cntPWM2=70);右側(cè)傳感器觸發(fā)時則調(diào)用TurnRight1()函數(shù),通過右電機(jī)反轉(zhuǎn)、左電機(jī)正轉(zhuǎn)糾正偏移。代碼通過固定轉(zhuǎn)速差策略實(shí)現(xiàn)轉(zhuǎn)向



單片機(jī)源程序如下:
  1. #include <reg52.h>          // 包含STC89C52單片機(jī)寄存器定義
  2. typedef unsigned int u16;   // 定義無符號16位整數(shù)類型
  3. typedef unsigned char u8;   // 定義無符號8位整數(shù)類型

  4. // ---------------------- 硬件接口定義 ----------------------
  5. // 電機(jī)驅(qū)動模塊(L298N)接口
  6. sbit ENA = P2^0;           // 右電機(jī)使能引腳(PWM控制轉(zhuǎn)速)
  7. sbit IN1 = P2^1;           // 右電機(jī)方向控制(1=正轉(zhuǎn),0=反轉(zhuǎn))
  8. sbit IN2 = P2^2;           // 右電機(jī)方向控制(1=正轉(zhuǎn),0=反轉(zhuǎn))
  9. sbit ENB = P2^5;           // 左電機(jī)使能引腳(PWM控制轉(zhuǎn)速)
  10. sbit IN3 = P2^3;           // 左電機(jī)方向控制(1=正轉(zhuǎn),0=反轉(zhuǎn))
  11. sbit IN4 = P2^4;           // 左電機(jī)方向控制(1=正轉(zhuǎn),0=反轉(zhuǎn))

  12. // 紅外傳感器模塊(TCRT5000)接口(5路布局:左外、左中、中間、右中、右外)
  13. // *未探測到黑線時輸出高電平(默認(rèn)狀態(tài)),探測到黑線時輸出低電平*
  14. sbit IR_LeftOuter = P0^0;  // 左側(cè)外端傳感器(S1)
  15. sbit IR_LeftMiddle = P0^1; // 左側(cè)中間傳感器(S2)
  16. sbit IR_Center = P0^2;     // 中間傳感器(S3)
  17. sbit IR_RightMiddle = P0^3;// 右側(cè)中間傳感器(S4)
  18. sbit IR_RightOuter = P0^4; // 右側(cè)外端傳感器(S5)

  19. // ---------------------- 全局變量定義 ----------------------
  20. u8 pwmRight = 50;          // 右電機(jī)PWM占空比(默認(rèn)50%,范圍0-100)
  21. u8 pwmLeft = 50;           // 左電機(jī)PWM占空比(默認(rèn)50%,范圍0-100)
  22. u8 sensorValue = 0;        // 傳感器狀態(tài)值(5位二進(jìn)制,高電平=未檢測到黑線)

  23. // ---------------------- 函數(shù)聲明 ----------------------
  24. void Timer0_Init();        // 定時器0初始化(PWM生成)
  25. void Motor_Stop();         // 電機(jī)停止
  26. void Motor_Forward();      // 電機(jī)前進(jìn)
  27. void Motor_TurnLeft(u8 speed); // 左轉(zhuǎn)(speed: 0-100 速度差)
  28. void Motor_TurnRight(u8 speed);// 右轉(zhuǎn)(speed: 0-100 速度差)
  29. void Sensor_Read();        // 讀取傳感器狀態(tài)
  30. void Path_Control();       // 路徑控制邏輯

  31. // ---------------------- 主函數(shù) ----------------------
  32. void main() {
  33.     Timer0_Init();          // 初始化定時器0(PWM功能)
  34.     while (1) {
  35.         Sensor_Read();      // 讀取紅外傳感器狀態(tài)
  36.         Path_Control();     // 執(zhí)行路徑跟蹤控制邏輯
  37.     }
  38. }

  39. // ---------------------- 定時器0初始化函數(shù) ----------------------
  40. void Timer0_Init() {
  41.     TMOD &= 0xF0;           // 清除定時器0模式位
  42.     TMOD |= 0x01;           // 設(shè)置為模式1(16位自動重裝)
  43.     TH0 = 0xFF;             // 配置100μs定時周期(晶振12MHz時,計數(shù)2次)
  44.     TL0 = 0xFE;
  45.     ET0 = 1;                // 使能定時器0中斷
  46.     EA = 1;                 // 使能全局中斷
  47.     TR0 = 1;                // 啟動定時器0
  48. }

  49. // ---------------------- 定時器0中斷函數(shù)(PWM生成)----------------------
  50. void Timer0_Interrupt() interrupt 1 {
  51.     static u8 pwmCounter = 0; // PWM周期計數(shù)器(0-100,對應(yīng)100ms周期)
  52.    
  53.     // 右電機(jī)PWM控制
  54.     if (pwmCounter < pwmRight) {
  55.         ENA = 1;
  56.     } else {
  57.         ENA = 0;
  58.     }
  59.    
  60.     // 左電機(jī)PWM控制
  61.     if (pwmCounter < pwmLeft) {
  62.         ENB = 1;
  63.     } else {
  64.         ENB = 0;
  65.     }
  66.    
  67.     pwmCounter++;
  68.     if (pwmCounter >= 100) { // 周期結(jié)束,重置計數(shù)器
  69.         pwmCounter = 0;
  70.     }
  71.    
  72.     // 重裝定時器初值
  73.     TH0 = 0xFF;
  74.     TL0 = 0xFE;
  75. }

  76. // ---------------------- 傳感器讀取函數(shù) ----------------------
  77. void Sensor_Read() {
  78.     u8 temp = 0; // 臨時變量,存儲5路傳感器狀態(tài)(高電平=1,低電平=0)
  79.    
  80.     // 左外傳感器(P0.0):未檢測到黑線時為1,檢測到為0
  81.     temp |= (IR_LeftOuter ? 1 : 0) << 4; // 最高位(第4位)
  82.     // 左中傳感器(P0.1)
  83.     temp |= (IR_LeftMiddle ? 1 : 0) << 3; // 第3位
  84.     // 中間傳感器(P0.2)
  85.     temp |= (IR_Center ? 1 : 0) << 2; // 第2位(中間位)
  86.     // 右中傳感器(P0.3)
  87.     temp |= (IR_RightMiddle ? 1 : 0) << 1; // 第1位
  88.     // 右外傳感器(P0.4):最低位(第0位)
  89.     temp |= (IR_RightOuter ? 1 : 0) << 0;
  90.    
  91.     sensorValue = temp; // 賦值給全局變量
  92. }

  93. // ---------------------- 路徑控制函數(shù)----------------------
  94. void Path_Control() {
  95.     switch (sensorValue) {
  96.         // 中間傳感器觸發(fā)(二進(jìn)制11011 → 十進(jìn)制27 → 十六進(jìn)制0x1B)
  97.         case 0x1B:  
  98.             Motor_Forward();
  99.             pwmRight = 60;
  100.             pwmLeft = 60;
  101.             break;
  102.         
  103.         // 左側(cè)單傳感器觸發(fā)(二進(jìn)制11101 → 十進(jìn)制29 → 十六進(jìn)制0x1D)
  104.         case 0x1D:  
  105.             pwmRight = 70; // 右輪加速
  106.             pwmLeft = 50; // 左輪減速
  107.             Motor_Forward();
  108.             break;
  109.         
  110.         // 全白狀態(tài)(二進(jìn)制11111 → 十進(jìn)制31 → 十六進(jìn)制0x1F)
  111.         case 0x1F:  
  112.             Motor_Stop(); // 停車
  113.             break;
  114.         
  115.         default:
  116.             break;
  117.     }
  118. }

  119. // ---------------------- 電機(jī)控制函數(shù) ----------------------
  120. void Motor_Forward() {
  121.     IN1 = 1;  // 右電機(jī)正轉(zhuǎn)
  122.     IN2 = 0;
  123.     IN3 = 1;  // 左電機(jī)正轉(zhuǎn)
  124.     IN4 = 0;
  125. }

  126. void Motor_Stop() {
  127.     IN1 = 0;  // 電機(jī)停轉(zhuǎn)
  128.     IN2 = 0;
  129.     IN3 = 0;
  130.     IN4 = 0;
  131. }
復(fù)制代碼

以上Keil代碼下載: 雙輪循跡小車.7z (20.25 KB, 下載次數(shù): 0)
原理圖:無
PCB:無

評分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

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

使用道具 舉報

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

本版積分規(guī)則

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

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

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