引言
在嵌入式系統領域,51單片機因其簡單易用、成本低廉的特點,一直是入門學習的理想平臺。今天我將分享一個基于51單片機的多功能智能小車項目,它集成了按鍵PWM調速、障礙物跟蹤、紅外循跡和數碼管顯示四大功能。這個項目不僅涵蓋了嵌入式開發的核心技術點,也是理解實時控制系統的絕佳案例。
項目概述
該智能小車系統通過以下硬件和軟件模塊協同工作:
-
主控制器:STC89C52RC(經典51內核單片機)
-
驅動模塊:L298N電機驅動板
-
感知模塊:紅外循跡傳感器×3,超聲波測距模塊
-
交互模塊:4位共陰數碼管,獨立按鍵×3
-
電源模塊:18650鋰電池組(7.4V)
關鍵硬件說明
-
L298N驅動電路:
-
雙H橋設計,可同時控制兩個直流電機
-
支持PWM調速和正反轉控制
-
最大輸出電流2A,滿足小車動力需求
-
-
紅外循跡傳感器:
-
基于TCRT5000反射式紅外傳感器
-
檢測距離2-10mm可調
-
數字輸出(0/1)簡化處理邏輯
-
-
超聲波測距:
-
HC-SR04模塊,測量范圍2cm-400cm
-
精度可達3mm
-
用于障礙物檢測和跟蹤
-
軟件架構
主程序流程圖
核心模塊實現
1.? 按鍵檢測
? 采用狀態機思想在定時器中斷中利用中斷周期跳轉時間進行消抖
#include <reg52.h>
#include "key.h"sbit key_s1 = P3^0 ;sbit key_s2 = P3^1 ;sbit key_s3 = P3^2 ;sbit key_s4 = P3^3 ;struct keys key[4]={{0,0,0},{0,0,0},{0,0,0},{0,0,0},
};
void getkey(void)
{unsigned char i;key[0].key_sta = key_s1;key[1].key_sta = key_s2;key[2].key_sta = key_s3;key[3].key_sta = key_s4;for( i=0;i<4;i++) {switch (key[i].judge_sta) {case 0:{if(key[i].key_sta==0) key[i].judge_sta=1;} // 第一次判斷按鍵是否按下break;case 1:{if(key[i].key_sta==0) {key[i].judge_sta=2;key[i].single_flag=1;}else key[i].judge_sta=0;} // 10ms(因為定時器終端周期設置為10ms)后判斷按鍵是否真的按下break;case 2:{if(key[i].key_sta==1){key[i].judge_sta=0;}} // 回到初始化break;}}}
2.??PWM調速系統
unsigned char cunt,com=80;
// 定時器0初始化(10ms中斷)
void carrun(unsigned char );
void Timer0_Init(void) { //初始化小車TMOD &= 0xF0; // 清除T0控制位 TMOD |= 0x01; // 設置T0為模式1(16位定時器)TH0 = 0xDC; // 10ms定時初值(11.0592MHz晶振)TL0 = 0x00;ET0 = 1; // 使能T0中斷TR0 = 1; // 啟動T0
}
// 定時器0中斷服務函數
void Timer0_ISR(void) interrupt 1 {TH0 = 0xDC; // 重裝初值TL0 = 0x00; getkey();if(key[0].single_flag==1) //檢測按鍵按下增加占空比{if(com<100){com+=10;}else com=10;key[0].single_flag=0;key[1].single_flag=0;}if(key[1].single_flag==1) // 按鍵2按下改變 車輛行駛狀態{log++;log %=4;}
}// 100us中斷
void Timer1_Init(void) { TMOD &= 0xF0; // 清除T1控制位 TMOD |= 0x10; // 設置T1為模式1(16位定時器)TH1 = 0xFF; // 10ms定時初值(11.0592MHz晶振)TL1 = 0x9C;ET1 = 1; // 使能T1中斷TR1 = 1; // 啟動T1
}
// 定時器0中斷服務函數
void Timer1_ISR(void) interrupt 3 { //模擬pwm波TH1 = 0xFF; // 重裝初值TL1 = 0x9C; cunt++;cunt%=100; //占空比調速s2=led2;s3=led3; //循跡s4=led4;s5=led5; // 跟隨紅外感應狀態if(cunt<com) // 調整占空比 {carrun(0);}else{carrun(1);}
}
void carrun(unsigned char en)
{EN1 = en; //為1 左電機使能EN2 = en; //為1 右電機使能
}
3.??障礙物跟蹤算法
// 超聲波測距函數
float Get_Distance() {unsigned int time = 0;float distance = 0;TRIG = 0;delay_us(2);TRIG = 1;delay_us(10);TRIG = 0;while(!ECHO); // 等待回波高電平TR1 = 1; // 啟動定時器1while(ECHO); // 等待回波結束TR1 = 0; // 停止定時器1time = TH1 * 256 + TL1;TH1 = 0;TL1 = 0;distance = time * 0.017; // 計算距離 (cm)return distance;
}// 障礙物跟蹤控制
void Obstacle_Tracking() {float dist = Get_Distance();if(dist < 10) { // 前方障礙物太近 - 后退Motor_Backward();} else if(dist < 30) {// 理想跟蹤距離 - 前進Motor_Forward();}else {// 尋找障礙物 - 旋轉Motor_Turn_Right();}
}
4.? ?紅外循跡算法
void Line_Tracking() {u8 track_status = (TRACK_L << 2) | (TRACK_M << 1) | TRACK_R;switch(track_status) {case 0b000: // 000 - 無線Motor_Forward();break;case 0b001: // 001 - 右偏Motor_Turn_Left();break;case 0b010: // 010 - 居中Motor_Forward();break;case 0b011: // 011 - 右偏Motor_Turn_Left();break;case 0b100: // 100 - 左偏Motor_Turn_Right();break;case 0b101: // 101 - T字路口Motor_Forward();break;case 0b110: // 110 - 左偏Motor_Turn_Right();break;case 0b111: // 111 - 十字路口Motor_Forward();break;}
}
?注:? ?傳感器數據都在定時器中斷里實時更新
實現效果?
51小車按鍵調速效果
51按鍵調速效果
51小車紅外循跡效果
51小車紅外循跡效果
51下車障礙物跟隨效果
紅外循跡
結語
通過這個51單片機智能小車項目,我們實踐了:
-
定時器中斷配置
-
PWM波形生成
-
多傳感器數據融合
-
實時控制系統設計
-
人機交互實現
雖然51單片機資源有限,但通過精心設計仍然可以實現復雜的嵌入式系統。該項目不僅鍛煉了硬件設計能力,也提升了軟件優化技巧,是嵌入式開發入門的絕佳實踐。