找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机双轮循迹小车控制程序(注释详细)

[复制链接]
跳转到指定楼层
楼主
一、概述
本双轮自动寻迹小车旨在实现对任意给定轨迹的快速精准跟踪,基于单片机控制技术,整合传感器检测、电机驱动及路径规划算法,构建具备高稳定性的自动寻迹小车。实物设计聚焦于硬件可靠性、软件逻辑的高效性及系统整体的安全性,适用于智能物流、教育科研及工业巡检等场景。
二、硬件设计方案
(一)主控芯片
选用STC89C52RC 单片机(STC 品牌,型号 89C52RC),其具备 8KB Flash ROM、256B RAM、3 个 16 位定时器 / 计数器及 6 个中断源,支持最高 24MHz 晶振频率,可满足多任务实时处理需求。搭配最小系统电路,包括 11.0592MHz 晶振与按键复位电路,确保芯片稳定运行。程序下载通过MAX232 电平转换芯片(MAXIM 品牌,型号 MAX232)连接 PC 端串口,支持 STC-ISP 软件离线下载。
(二)传感器模块
采用TCRT5000 反射式红外光电传感器,内置高功率红外发射管与高灵敏度光电晶体管,检测距离 4-13cm 可调,抗环境光干扰能力强。内置数模转换,将红外信号转换为数字量,实现对黑色轨迹线的精准识别。
(三)电机驱动模块
选用L298N 电机驱动芯片,支持双直流电机驱动,工作电压 5-46V,最大输出电流 2A。搭配12V/2000mAh 锂电池供电,通过 PWM 控制电机转速。电机选型为RS370直流减速电机(电压 12V,转速 3000rpm),满足双轮小车的驱动力与速度要求。
(四)电源模块
    12V 锂电池经 7809(输出 9V)、7805(输出 5V)稳压芯片,分别为电机驱动、传感器及单片机系统供电。电容滤波网络(10μF 贴片电容 + 0.1μF 瓷片电容)降低电源纹波,确保各模块稳定工作。

三、软件设计方案
(一)软件设计与代码实现
软件基于 STC89C52 单片机开发,采用 C 语言编程,通过 Keil uVision 环境编译生成 HEX 文件,利用 STC-ISP 工具下载至单片机。代码核心逻辑围绕 5 路红外传感器(P0.0-P0.4)的信号采集、电机差速控制及 PWM 调速
(二)传感器信号采集与状态编码
代码通过 P0 口读取 5 路红外传感器状态,未检测到黑线时引脚为高电平(逻辑 1),检测到黑线时为低电平(逻辑 0)。传感器状态被组合为 5 位二进制数存储于sensorValue变量,中间传感器触发时状态为0b11011(对应十六进制0x1B),右侧中间传感器触发时为0b11101(0x1D),左侧双传感器触发时为0b01111(0x0F)。代码通过Sensor_Read()函数完成状态采集,采用逐位赋值方式避免sbit类型直接移位运算,确保逻辑正确性。
(三)电机驱动与 PWM 调速
电机驱动采用 L298N 模块,通过 P2 口控制转向逻辑(IN1-IN4),并利用定时器 0 生成 PWM 信号调节转速(ENA/ENB)。定时器 0 工作于模式 1(16 位自动重装),配置初值实现约 100μs 定时周期,中断函数中通过pwmCounter计数器(0-100)生成 100Hz PWM 波形。左右电机占空比由cntPWM1(右电机)和cntPWM2(左电机)控制,直行时占空比设为 40%(cntPWM1=40、cntPWM2=40),偏左时右电机占空比提高至 55%-70%、左电机降低至 40%-55%,通过差速实现转向。
(四)路径跟踪逻辑实现
主函数循环调用XunJi()函数执行路径控制,通过switch-case语句匹配sensorValue状态。当状态为0b00000(全黑)或0b11111(全白)时执行停车逻辑;中间传感器触发(0b00100对应的flag=0)时调用Forward()函数双电机正转;左侧传感器触发(如0b10000对应的flag=3)时调用TurnLeft1()函数,右电机正转、左电机反转并设置较大转速差(cntPWM1=55、cntPWM2=70);右侧传感器触发时则调用TurnRight1()函数,通过右电机反转、左电机正转纠正偏移。代码通过固定转速差策略实现转向



单片机源程序如下:
  1. #include <reg52.h>          // 包含STC89C52单片机寄存器定义
  2. typedef unsigned int u16;   // 定义无符号16位整数类型
  3. typedef unsigned char u8;   // 定义无符号8位整数类型

  4. // ---------------------- 硬件接口定义 ----------------------
  5. // 电机驱动模块(L298N)接口
  6. sbit ENA = P2^0;           // 右电机使能引脚(PWM控制转速)
  7. sbit IN1 = P2^1;           // 右电机方向控制(1=正转,0=反转)
  8. sbit IN2 = P2^2;           // 右电机方向控制(1=正转,0=反转)
  9. sbit ENB = P2^5;           // 左电机使能引脚(PWM控制转速)
  10. sbit IN3 = P2^3;           // 左电机方向控制(1=正转,0=反转)
  11. sbit IN4 = P2^4;           // 左电机方向控制(1=正转,0=反转)

  12. // 红外传感器模块(TCRT5000)接口(5路布局:左外、左中、中间、右中、右外)
  13. // *未探测到黑线时输出高电平(默认状态),探测到黑线时输出低电平*
  14. sbit IR_LeftOuter = P0^0;  // 左侧外端传感器(S1)
  15. sbit IR_LeftMiddle = P0^1; // 左侧中间传感器(S2)
  16. sbit IR_Center = P0^2;     // 中间传感器(S3)
  17. sbit IR_RightMiddle = P0^3;// 右侧中间传感器(S4)
  18. sbit IR_RightOuter = P0^4; // 右侧外端传感器(S5)

  19. // ---------------------- 全局变量定义 ----------------------
  20. u8 pwmRight = 50;          // 右电机PWM占空比(默认50%,范围0-100)
  21. u8 pwmLeft = 50;           // 左电机PWM占空比(默认50%,范围0-100)
  22. u8 sensorValue = 0;        // 传感器状态值(5位二进制,高电平=未检测到黑线)

  23. // ---------------------- 函数声明 ----------------------
  24. void Timer0_Init();        // 定时器0初始化(PWM生成)
  25. void Motor_Stop();         // 电机停止
  26. void Motor_Forward();      // 电机前进
  27. void Motor_TurnLeft(u8 speed); // 左转(speed: 0-100 速度差)
  28. void Motor_TurnRight(u8 speed);// 右转(speed: 0-100 速度差)
  29. void Sensor_Read();        // 读取传感器状态
  30. void Path_Control();       // 路径控制逻辑

  31. // ---------------------- 主函数 ----------------------
  32. void main() {
  33.     Timer0_Init();          // 初始化定时器0(PWM功能)
  34.     while (1) {
  35.         Sensor_Read();      // 读取红外传感器状态
  36.         Path_Control();     // 执行路径跟踪控制逻辑
  37.     }
  38. }

  39. // ---------------------- 定时器0初始化函数 ----------------------
  40. void Timer0_Init() {
  41.     TMOD &= 0xF0;           // 清除定时器0模式位
  42.     TMOD |= 0x01;           // 设置为模式1(16位自动重装)
  43.     TH0 = 0xFF;             // 配置100μs定时周期(晶振12MHz时,计数2次)
  44.     TL0 = 0xFE;
  45.     ET0 = 1;                // 使能定时器0中断
  46.     EA = 1;                 // 使能全局中断
  47.     TR0 = 1;                // 启动定时器0
  48. }

  49. // ---------------------- 定时器0中断函数(PWM生成)----------------------
  50. void Timer0_Interrupt() interrupt 1 {
  51.     static u8 pwmCounter = 0; // PWM周期计数器(0-100,对应100ms周期)
  52.    
  53.     // 右电机PWM控制
  54.     if (pwmCounter < pwmRight) {
  55.         ENA = 1;
  56.     } else {
  57.         ENA = 0;
  58.     }
  59.    
  60.     // 左电机PWM控制
  61.     if (pwmCounter < pwmLeft) {
  62.         ENB = 1;
  63.     } else {
  64.         ENB = 0;
  65.     }
  66.    
  67.     pwmCounter++;
  68.     if (pwmCounter >= 100) { // 周期结束,重置计数器
  69.         pwmCounter = 0;
  70.     }
  71.    
  72.     // 重装定时器初值
  73.     TH0 = 0xFF;
  74.     TL0 = 0xFE;
  75. }

  76. // ---------------------- 传感器读取函数 ----------------------
  77. void Sensor_Read() {
  78.     u8 temp = 0; // 临时变量,存储5路传感器状态(高电平=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. // ---------------------- 路径控制函数----------------------
  94. void Path_Control() {
  95.     switch (sensorValue) {
  96.         // 中间传感器触发(二进制11011 → 十进制27 → 十六进制0x1B)
  97.         case 0x1B:  
  98.             Motor_Forward();
  99.             pwmRight = 60;
  100.             pwmLeft = 60;
  101.             break;
  102.         
  103.         // 左侧单传感器触发(二进制11101 → 十进制29 → 十六进制0x1D)
  104.         case 0x1D:  
  105.             pwmRight = 70; // 右轮加速
  106.             pwmLeft = 50; // 左轮减速
  107.             Motor_Forward();
  108.             break;
  109.         
  110.         // 全白状态(二进制11111 → 十进制31 → 十六进制0x1F)
  111.         case 0x1F:  
  112.             Motor_Stop(); // 停车
  113.             break;
  114.         
  115.         default:
  116.             break;
  117.     }
  118. }

  119. // ---------------------- 电机控制函数 ----------------------
  120. void Motor_Forward() {
  121.     IN1 = 1;  // 右电机正转
  122.     IN2 = 0;
  123.     IN3 = 1;  // 左电机正转
  124.     IN4 = 0;
  125. }

  126. void Motor_Stop() {
  127.     IN1 = 0;  // 电机停转
  128.     IN2 = 0;
  129.     IN3 = 0;
  130.     IN4 = 0;
  131. }
复制代码

以上Keil代码下载: 双轮循迹小车.7z (20.25 KB, 下载次数: 0)
原理图:无
PCB:无

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

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

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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