找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 242|回复: 1
打印 上一主题 下一主题
收起左侧

基于STC89C52RC单片机芯片的智能小车加上oled显示就不能正常循迹

[复制链接]
回帖奖励 20 黑币 回复本帖可获得 20 黑币奖励! 每人限 1 次(中奖概率 10%)
跳转到指定楼层
楼主
ID:1147086 发表于 2025-5-23 22:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在主函数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

123.76 KB, 下载次数: 0

基于51循迹避障加oled显示

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1152543 发表于 2025-6-5 18:04 | 只看该作者
遇到了一样的问题
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表