|
在主函數while(1)里面加上兩句代碼:
Distance = GetDistance();if(g_mode == MODE_AUTO)
我是在循跡的基礎上加的oled(循跡也有點小問題,時不能正常循跡
改了好久都解決不了,請大佬瞅一瞅,看一看。感覺oled占用太多的空間,整個代碼效率不高。
超聲波我用了定時器2,循跡使用了定時器0,藍牙串口使用了定時器1,代碼:
主函數:
#include <REGX52.H>
#include "config.h"
#include "motor.h"
#include "HCSR04.h"
#include "Track.h"
#include "Delay.H"
#include "Bluetooth.H"
#include <iic.H>
#include <oled.H>
//函數初始化
void System_Init();
void main() {
System_Init();
// 開機動畫
OLED_ShowStringWithTypewriter(24, 2, "Smart Car", 16);
Delay(500);
OLED_Clear();
while(1)
{
Distance = GetDistance();//超聲波測距
OLED_Refresh();//OLED顯示
if(g_mode == MODE_AUTO)
{
// 自動模式:循跡+避障
Track_Logic();
if(GetDistance() < SAFE_DIST)
{
ObstacleAvoidance();
}
}
else
{
// 藍牙模式
if(g_bt_cmd) // 狀態檢測
{
Bluetooth_Control(g_bt_cmd);
g_bt_cmd = 0; // 清除指令標志
}
}
Delay(20); // 適當延時
}
}
void System_Init() {
Motor_Init(); // 電機初始化
Timer0_Init(); // PWM定時器0
Timer2_Init(); // 超聲波定時器2
UART_Init(); // 串口初始化,定時器1
OLED_init(); // 初始化OLED
OLED_Clear(); // 清屏
OLED_Display_On();
}
超聲波:
#include <REGX52.H>
#include "config.h"
#include "HCSR04.h"
#include "intrins.h"
#include "Delay.H"
#include "Motor.h"
bit timeout = 0;
void Timer2_Init()
{
T2CON = 0; // 清零控制寄存器(默認16位自動重裝載模式)
T2MOD = 0; // 清零模式寄存器(遞增計數)
RCAP2H = 0; // 重裝載值高位(初始為0,用于超時計數)
RCAP2L = 0; // 重裝載值低位
TH2 = TL2 = 0; // 計數器初值歸零
ET2 = 1; // 開啟定時器2中斷
PT2 = 1; // 設置定時器2為高優先級
EA = 1; // 總中斷使能
}
unsigned int GetDistance()
{
unsigned int time_us = 0;
Trig = 1; // 觸發信號
Delay20us(); // 20us延時
Trig = 0;
while(!Echo); // 等待回波高電平
TR2 = 1; // 啟動定時器2
while(Echo && !timeout); // 等待回波結束或超時
TR2 = 0; // 停止計時
if(timeout) { // 超時處理
timeout = 0;
return 999; // 返回無效值
}
time_us = (TH2 << 8) | TL2; // 獲取計數值(注意:需在TR2=0時讀取)
TH2 = TL2 = 0; // 定時器復位
return (time_us * 0.017); // 計算距離(cm)
}
//小車避障
void ObstacleAvoidance()
{
// 停止運動
Motor_Control(STOP, STOP, 0, 0);
Delay(200);
// 后退避讓
Motor_Control(REV, REV, 70, 70);
Delay(500);
// 右轉尋找新路徑
Motor_Control(FWD, REV, 80, 80);
Delay(400);
// 恢復循跡
TH2 = TL2 = 0; // 超聲波定時器復位
}
/* 定時器2中斷處理超時*/
void Timer2_ISR() interrupt 5
{
static unsigned int timeout_cnt = 0;
TF2 = 0; // 必須手動清除中斷標志
if(++timeout_cnt > 60000) { // 約350ms超時
timeout_cnt = 0;
timeout = 1;
}
}
藍牙串口:
#include <REGX52.H>
#include "Bluetooth.H"
#include "Motor.h"
#include "config.h"
#include "Delay.H"
#define BT_BAUD 9600 // 波特率
// 模式枚舉
volatile SystemMode g_mode = 0;
// 藍牙指令緩存
volatile char g_bt_cmd = 0;
//串口初始化
void UART_Init() {
// 定時器1配置
TMOD &= 0x0F; // 保留定時器0配置
TMOD |= 0x20; // 定時器1模式2(8位自動重載)
TH1 = TL1 = 0xFD; // 波特率9600@11.0592MHz
TR1 = 1; // 啟動定時器1
// 串口配置
PCON &= 0x7F;
SCON = 0x50; // 模式1,允許接收
ES = 1; // 使能串口中斷
EA = 1; // 總中斷使能
}
// 串口中斷
void UART_ISR() interrupt 4 {
if(RI)
{
g_bt_cmd = SBUF; // 接收藍牙指令
RI = 0;
// 模式切換指令解析
switch(g_bt_cmd) {
case 'A': // 自動模式指令
g_mode = MODE_AUTO;
IN1 = IN2 = IN3 = IN4 =0;//先注釋
break;
case 'B': // 藍牙模式指令
g_mode = MODE_BT;
IN1 = IN2 = IN3 = IN4 =0;
break;
}
}
}
void Bluetooth_Control(char cmd) {
switch(cmd) {
case '1': // 前進
Motor_Control(FWD, FWD, 70, 70);
Delay(50);
break;
case '2': // 后退
Motor_Control(REV, REV, 70, 70);
Delay(50);
break;
case '3': // 左轉
Motor_Control(FWD, REV, 70, 70);
Delay(50);
break;
case '4': // 右轉
Motor_Control(REV, FWD, 70, 70);
Delay(50);
break;
case '0': // 停止
Motor_Control(STOP, STOP, 0, 0);
Delay(50);
break;
}
}
oled部分代碼:
/* 打字機效果顯示函數 */
void OLED_ShowStringWithTypewriter(unsigned char x, unsigned char y, char *str, unsigned char Char_size)
{
while(*str) {
OLED_ShowChar(x, y, *str++, Char_size);
x += 8; // 字符寬度+間距
Delay(70); // 調整延時獲得打字速度
if(x > 120) { // 換行處理
x = 0;
y += 2;
}
}
}
/* 顯示紅外循跡狀態(二進制格式) */
void OLED_ShowTrackState(unsigned char x, unsigned char y)
{
char binary[5] = {0};
// 獲取低四位并轉換為二進制字符串
binary[0] = (Track_State & 0x08) ? '1' : '0';
binary[1] = (Track_State & 0x04) ? '1' : '0';
binary[2] = (Track_State & 0x02) ? '1' : '0';
binary[3] = (Track_State & 0x01) ? '1' : '0';
OLED_ShowString(x, y, binary, 16);
}
/* 主顯示更新函數 */
void OLED_Refresh()
{
char dispBuf[16];
// 第一行:顯示模式
OLED_Set_Pos(0,0);
switch(g_mode){
case MODE_AUTO: OLED_ShowString(0, 0, "Mode:Auto ", 16); break;
case MODE_BT: OLED_ShowString(0, 0, "Mode:BT ", 16); break;
}
// 第二行:顯示距離
sprintf(dispBuf, "Dist:%3dcm", Distance);
OLED_ShowString(0, 2, dispBuf, 16);
// 第三行:顯示循跡狀態
OLED_ShowString(0, 4, "Track:", 16);
OLED_ShowTrackState(48, 4);
}
|
-
-
循跡基礎加oled.zip
2025-5-23 22:03 上傳
點擊文件名下載附件
123.76 KB, 下載次數: 0
基于51循跡避障加oled顯示
|