找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3412|回复: 0
收起左侧

51单片机追踪机器人(小车)程序

[复制链接]
ID:497103 发表于 2019-3-24 09:59 | 显示全部楼层 |阅读模式
之前做的时候苟了一周编出来的程序
QX-A51小车跟随前方障碍物运动
s2控制小车前进后退左转右转
s3跟踪
s4光敏
功能蛮全的,跟踪不是特别灵敏,跟小车硬件有关,可以再调整。

单片机源程序如下:
  1. #include <reg52.h>
  2. #include <intrins.h>
  3. #include <C:\Users\Administrator\Desktop\QXA51.h>

  4. unsigned char pwm_left_val =180;//左电机占空比值 取值范围0-170,0最快
  5. unsigned char pwm_right_val = 175;//右电机占空比值取值范围0-170 ,0最快
  6. unsigned char pwm_t;//周期

  7. #define MAIN_Fosc                11059200UL        //宏定义主时钟HZ
  8. #define PCF8591_ADDR        0x90                //PCF8591地址
  9. #define DACOUT_EN                0x40                //DAC输出使能

  10. typedef unsigned char INT8U;
  11. typedef unsigned char uchar;
  12. typedef unsigned int INT16U;
  13. typedef unsigned int uint;

  14. sbit SDA = P2^0;   //I2C串行数据
  15. sbit SCL = P2^1;   //I2C串行时钟
  16. sbit we = P2^7;        //位定义数码管位选锁存器接口
  17. sbit du = P2^6;         //位定义数码管位选锁存器接口
  18. sbit LED0 = P1^0;
  19. sbit LED1 = P1^1;
  20. sbit LED2 = P1^2;
  21. sbit LED3 = P1^3;
  22. sbit LED4 = P1^4;
  23. sbit LED5 = P1^5;
  24. sbit LED6 = P1^6;
  25. sbit LED7 = P1^7;//led流水灯

  26. uchar code leddata[]={  
  27.                                 0x3F,  //"0"
  28.                                 0x06,  //"1"
  29.                                 0x5B,  //"2"
  30.                                 0x4F,  //"3"
  31.                                 0x66,  //"4"
  32.                                 0x6D,  //"5"
  33.                                 0x7D,  //"6"
  34.                                 0x07,  //"7"
  35.                                 0x7F,  //"8"
  36.                                 0x6F,  //"9"
  37.                                 0x00,  //熄灭
  38.                                 0x00  //自定义
  39.                                          };         //数码管段选表

  40. uchar AD_Value;        //存储AD转换回的数字量
  41. uint i=0,a=0,b=0,c=0;

  42. void Delay_Ms(INT16U ms)
  43. {
  44.      INT16U i;
  45.          do{
  46.               i = MAIN_Fosc / 96000;
  47.                   while(--i);   //96T per loop
  48.      }while(--ms);
  49. }

  50. void Delay5us()
  51. {
  52.         #if MAIN_Fosc == 11059200
  53.                 _nop_();
  54.         #elif MAIN_Fosc == 12000000
  55.                 _nop_();
  56.         #elif MAIN_Fosc == 22118400
  57.                 _nop_(); _nop_(); _nop_();
  58.         #endif
  59. }

  60. /*====================================
  61. 函数:I2C_init()
  62. 描述:I2C总线初始化
  63. ====================================*/
  64. void I2C_init()
  65. {
  66.         SDA = 1;   //数据总线高
  67.         _nop_();
  68.         SCL = 1;   //时钟总线高
  69.         _nop_();
  70. }

  71. /*====================================
  72. 函数:I2C_Start()
  73. 描述:I2C起始信号
  74. ====================================*/
  75. void I2C_Start()  
  76. {
  77.         SCL = 1;
  78.         _nop_();
  79.         SDA = 1;
  80.         Delay5us();
  81.         SDA = 0;
  82.         Delay5us();
  83. }

  84. /*====================================
  85. 函数:I2C_Stop()
  86. 描述:I2C停止信号
  87. ====================================*/
  88. void I2C_Stop()
  89. {
  90.         SDA = 0;
  91.         _nop_();
  92.         SCL = 1;
  93.         Delay5us();
  94.         SDA = 1;
  95.         Delay5us();
  96. }

  97. /*====================================
  98. 函数:Master_ACK(bit i)
  99. 参数:i 为0时发送非应答 为1时发送应答
  100. 描述:I2C主机发送应答
  101. ====================================*/
  102. void Master_ACK(bit i)       
  103. {
  104.         SCL = 0; // 拉低时钟总线允许SDA数据总线上的数据变化
  105.         _nop_(); // 让总线稳定
  106.         if (i)         //如果i = 1 那么拉低数据总线 表示主机应答
  107.         {
  108.                 SDA = 0;
  109.         }
  110.         else         
  111.         {
  112.                 SDA = 1;         //发送非应答
  113.         }
  114.         _nop_();//让总线稳定
  115.         SCL = 1;//拉高时钟总线 让从机从SDA线上读走 主机的应答信号
  116.         _nop_();
  117.         SCL = 0;//拉低时钟总线, 占用总线继续通信
  118.         _nop_();
  119.         SDA = 1;//释放SDA数据总线。
  120.         _nop_();
  121. }

  122. /*====================================
  123. 函数:Test_ACK()
  124. 返回:0为非应答 1为应答
  125. 描述:I2C检测从机应答
  126. ====================================*/
  127. bit Test_ACK()         // 检测从机应答
  128. {
  129.         SCL = 1;//时钟总线为高电平期间可以读取从机应答信号
  130.         Delay5us();
  131.         if (SDA)
  132.         {
  133.                 SCL = 0;
  134.                 I2C_Stop();
  135.                 return(0);
  136.         }
  137.         else
  138.         {
  139.                 SCL = 0;
  140.                 return(1);
  141.         }
  142. }

  143. /*====================================
  144. 函数:I2C_send_byte(uchar byte)
  145. 参数:byte 要发送的字节
  146. 描述:I2C发送一个字节
  147. ====================================*/
  148. void I2C_send_byte(uchar byte)
  149. {
  150.         uchar i;
  151.         for(i = 0 ; i < 8 ; i++)
  152.         {
  153.                 SCL = 0;
  154.                 _nop_();
  155.                 if (byte & 0x80)        //
  156.                 {
  157.                         SDA = 1;
  158.                         _nop_();
  159.                 }
  160.                 else
  161.                 {
  162.                         SDA = 0;
  163.                         _nop_();
  164.                 }
  165.                 SCL = 1;
  166.                 _nop_();
  167.                 byte <<= 1;
  168.         }
  169.         SCL = 0;
  170.         _nop_();
  171.         SDA = 1;
  172.         _nop_();       
  173. }

  174. /*====================================
  175. 函数:I2C_read_byte()
  176. 返回:读取的字节
  177. 描述:I2C读一个字节
  178. ====================================*/
  179. uchar I2C_read_byte()
  180. {
  181.         uchar i, dat;
  182.         SCL = 0 ;
  183.         _nop_();
  184.         SDA = 1;
  185.         _nop_();
  186.         for(i = 0 ; i < 8 ; i++)
  187.         {
  188.                 SCL = 1;
  189.                 _nop_();
  190.                 dat <<= 1;          
  191.                 if (SDA)
  192.                 {
  193.                         dat |= 0x01;  
  194.                 }
  195.                 _nop_();
  196.                 SCL = 0;
  197.                 _nop_();
  198.         }
  199.         return(dat);
  200. }

  201. /*DAC输出*/
  202. bit DAC_OUT(uchar DAT)
  203. {
  204.         I2C_Start();
  205.         I2C_send_byte(PCF8591_ADDR+0);
  206.         if (!Test_ACK())
  207.         {
  208.                 return(0);
  209.         }
  210.         I2C_send_byte(DACOUT_EN);        //DA输出使能
  211.         if (!Test_ACK())
  212.         {
  213.                 return(0);
  214.         }
  215.         I2C_send_byte(DAT);
  216.         if (!Test_ACK())
  217.         {
  218.                 return(0);
  219.         }
  220.         I2C_Stop();
  221.         return(1);       
  222. }

  223. /*读AD数据*/
  224. bit ADC_Read(uchar CON)
  225. {
  226.         I2C_Start();
  227.         I2C_send_byte(PCF8591_ADDR+0);
  228.         if (!Test_ACK())
  229.         {
  230.                 return(0);
  231.         }
  232.         I2C_send_byte(CON);
  233.         Master_ACK(0);
  234.         I2C_Start();
  235.         I2C_send_byte(PCF8591_ADDR+1);
  236.         if (!Test_ACK())
  237.         {
  238.                 return(0);
  239.         }
  240.         AD_Value = I2C_read_byte();
  241.         Master_ACK(0);
  242.         I2C_Stop();
  243.         return(1);       
  244. }

  245. /*小车前进*/
  246. void forward()
  247. {
  248.         left_motor_en; //左电机使能
  249.         right_motor_en;//右电机使能
  250.         left_motor_go; //左电机前进
  251.         right_motor_go; //右电机前进
  252. }
  253. /*小车后退*/
  254. void backward()
  255. {
  256.         left_motor_en; //左电机使能
  257.         right_motor_en;//右电机使能
  258.         left_motor_back; //左电机后退
  259.         right_motor_back; //右电机后退       
  260. }
  261. /*小车左转*/
  262. void left()
  263. {
  264.         left_motor_stops; //左电机停止
  265.         right_motor_en;//右电机使能
  266.         right_motor_go; //右电机前进       
  267. }
  268. /*小车右转*/
  269. void right()
  270. {
  271.         right_motor_stops;//右电机停止
  272.         left_motor_en;    //左电机使能
  273.         left_motor_go;    //左电机前进
  274. }
  275. /*小车停止*/
  276. void stop()
  277. {
  278.         right_motor_stops;//右电机停止
  279.         left_motor_stops; //左电机停止       
  280. }       

  281. void timer0() interrupt 1
  282. {
  283.         pwm_t++;//周期计时加
  284.         if(pwm_t == 255)
  285.                 pwm_t = EN1 = EN2 = 0;
  286.         if(pwm_left_val == pwm_t)//左电机占空比       
  287.                 EN1 = 1;               
  288.         if(pwm_right_val == pwm_t)//右电机占空比
  289.                 EN2 = 1;                         
  290. }

  291. void main()
  292. {
  293.         unsigned char j;
  294.         for(;;)
  295.         {         
  296.         while(1)
  297.         {
  298.                 if(key_s2 == 0)//判断S2是否按下
  299.                 {
  300.                         Delay_Ms(5);//软件消抖
  301.                         if(key_s2 == 0)
  302.                         {
  303.                                 while(!key_s2);//松手检测
  304.                                 beep = 0;
  305.                                 Delay_Ms(1000);
  306.                                 beep = 1;
  307.                             
  308.                                 TMOD |= 0x02;//8位自动重装模块
  309.                                 TH0 = 220;
  310.                                 TL0 = 220;//11.0592M晶振下占空比最大比值是256,输出100HZ
  311.                                 TR0 = 1;//启动定时器0
  312.                                 ET0 = 1;//允许定时器0中断
  313.                                 EA        = 1;
  314.        
  315.                                 forward();//小车前进
  316.                                 Delay_Ms(1000);//毫秒级延时
  317.                                                        
  318.                                 stop();//小车停止
  319.                                 Delay_Ms(1000);//毫秒级延时
  320.                                                
  321.                                 backward();//小车后退
  322.                                 beep = 0;//蜂鸣器鸣叫
  323.                                 Delay_Ms(1000);//毫秒级延时
  324.                                                                
  325.                                 stop();//小车停止
  326.                                 beep = 1;//蜂鸣器停止鸣叫               
  327.                                 Delay_Ms(1000);//毫秒级延时
  328.                                                        
  329.                                 left();        // 小车左转
  330.                                 beep = 0;//蜂鸣器鸣叫
  331.                                 Delay_Ms(1000);//毫秒级延时
  332.                                                                
  333.                                 stop();//小车停止
  334.                                 beep = 1;//蜂鸣器停止鸣叫
  335.                                 Delay_Ms(1000);//毫秒级延时
  336.                                
  337.                                 right();// 小车右转延时
  338.                                 beep = 0;//蜂鸣器鸣叫
  339.                                 Delay_Ms(1000);//毫秒级延时
  340.                                
  341.                                 stop();//小车停止
  342.                                 beep=1;//蜂鸣器停止鸣叫
  343.                                 Delay_Ms(1000);//毫秒级延时               
  344.                         }
  345.                 }

  346.             if(key_s3 == 0)//判断S3是否按下
  347.                 {               
  348.                         Delay_Ms(5);//软件消抖
  349.                         if(key_s3 == 0)
  350.                         {
  351.                                 while(!key_s3);//松手检测
  352.                                 beep = 0;//蜂鸣器鸣叫
  353.                                 Delay_Ms(1000);//毫秒级延时
  354.                                 beep = 1;//蜂鸣器停止鸣叫

  355.                                 TMOD |= 0x02;//8位自动重装模块
  356.                                 TH0 = 220;
  357.                                 TL0 = 220;//11.0592M晶振下占空比最大比值是256,输出100HZ
  358.                                 TR0 = 1;//启动定时器0
  359.                                 ET0 = 1;//允许定时器0中断
  360.                                 EA        = 1;

  361.                 I2C_init();
  362.                                 while(1)
  363.                                 {               
  364.                                         if (ADC_Read(0x00))               
  365.                                         if (DAC_OUT(AD_Value))       
  366.                                         if (AD_Value > 150)        {stop(); }
  367.                                         else        {forward(); }
  368.                                         Delay_Ms(5);
  369.                                 }
  370.                         }
  371.                 }

  372.                 if(key_s4 == 0)// 实时检测S3按键是否被按下
  373.                 {
  374.                         Delay_Ms(5);//软件消抖
  375.                         if(key_s4 == 0)//再检测S3是否被按下
  376.                         {
  377.                                 while(!key_s4);//松手检测
  378.                                 beep = 0;        //使能有源蜂鸣器
  379.                                 Delay_Ms(1000);//200毫秒延时
  380.                                 beep = 1;        //关闭有源蜂鸣器

  381.                              TMOD |= 0x02;//8位自动重装模块
  382.                                 TH0 = 220;
  383.                                 TL0 = 220;//11.0592M晶振下占空比最大比值是256,输出100HZ
  384.                                 TR0 = 1;//启动定时器0
  385.                                 ET0 = 1;//允许定时器0中断
  386.                                 EA        = 1;//总中断允许
  387.                        
  388.                                 while(1)
  389.                                 {         
  390.                                         we = 1;//打开位选
  391.                                         P0 = 0xfe;//,注意数码管的排序,P0.0对应连接的是左边第一位数码管
  392.                                         we = 0;        //关闭位选
  393.                                 du = 1;        //打开段选
  394.                                         P0 = leddata[b];
  395.                                         du = 0;        //关闭段选
  396.                                         Delay_Ms(1);
  397.                                                                
  398.                                         we = 1;//打开位选
  399.                                     P0 = 0xfd;//,注意数码管的排序,P0.0对应连接的是左边第一位数码管
  400.                                      we = 0;        //关闭位选
  401.                                 du = 1;        //打开段选
  402.                                         P0 = leddata[i];
  403.                                         du = 0;        //关闭段选
  404.                                         Delay_Ms(1);               
  405.                                
  406.                                         if(left_led2 == 1 && right_led2 == 1)//为0 识别障碍物 为1没有识别到障碍物
  407.                                         {        stop();
  408.                                         }
  409.                  
  410.                                         if(left_led2 == 0 && right_led2 == 0)//左右识别到障碍物,前进跟随
  411.                                         {
  412.                                                 forward();
  413.                                                 for(c=0;c<=27000;c++)
  414.                                                 {
  415.                                                         if(c==27000)
  416.                                                         {        j++;
  417.                                                                  a++;}
  418.                                                 }               
  419.                                         }

  420.                                         if(left_led2 == 1 && right_led2 == 0)//小车右侧识别到障碍物,右转跟随
  421.                                         {
  422.                                                 right();
  423.                                                 for(c=0;c<=27000;c++)
  424.                                                 {
  425.                                                         if(c==27000)
  426.                                                         {        j++;
  427.                                                                 a++;}
  428.                                                 }
  429.                                         }
  430.                 
  431.                                         if(left_led2 == 0 && right_led2 == 1)//小车左侧识别到障碍物,左转跟随
  432.                                         {
  433.                                                 left();
  434.                                                 for(c=0;c<=27000;c++)
  435.                                                 {
  436.                                                         if(c==27000)
  437.                                                         {        j++;
  438.                                                                 a++;}
  439.                                                 }
  440.                                         }
  441.        
  442.                                         if(j==10)        //当数值为10时,清零
  443.                                         {
  444.                                                 j=0;
  445.                                                 b++;
  446.                                         }
  447.                                         if(b==9)
  448.                                         {        b=0;}
  449.                                         if(a==90)
  450.                                         {
  451.                                                 a=0;
  452.                                                 j=0;
  453.                                                 b=0;
  454.                                         }
  455.                                 }
  456.                         }  
  457.                 }          
  458.         }
  459. break;
  460.         }
  461. }       
复制代码

所有资料51hei提供下载:
程序.rar (35.83 KB, 下载次数: 16)
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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