当前位置:   article > 正文

51智能小车超声波避障_超声波避障小车程序c51

超声波避障小车程序c51
  1. #include <REGX52.H>
  2. #include <intrins.h>
  3. #include <QXA51.H>
  4. sbit DU = P2^6;//数码管段选
  5. sbit RX = P2^0;//ECHO超声波模块回响端
  6. sbit TX = P2^1;//TRIG超声波模块触发端
  7. sbit LCM_RW = P3^6; //定义LCD引脚
  8. sbit LCM_RS = P3^5;
  9. sbit LCM_E = P3^4;
  10. #define LCM_Data P0 //定义液晶屏数据口
  11. #define Busy 0x80 //用于检测LCM状态字中的Busy标识
  12. unsigned char pwm_left_val = 180;//左电机占空比值 取值范围0-1700最快
  13. unsigned char pwm_right_val = 180;//右电机占空比值取值范围0-170 ,0最快
  14. unsigned char pwm_t;//周期
  15. unsigned int time = 0;//传输时间
  16. unsigned long S = 0;//距离
  17. bit flag = 0;//超出测量范围标志位
  18. unsigned char code Range[] ="==Range Finder==";//LCD1602显示格式
  19. unsigned char code ASCII[13] = "0123456789.-M";
  20. unsigned char code table[]="Distance:000.0cm";
  21. unsigned char code table1[]="!!! Out of range";
  22. unsigned char disbuff[4] = { 0,0,0,0};//距离显示缓存
  23. void delay(unsigned int z)//毫秒级延时
  24. {
  25. unsigned int x,y;
  26. for(x = z; x > 0; x--)
  27. for(y = 114; y > 0 ; y--);
  28. }
  29. void Delay10us(unsigned char i) //10us延时函数 启动超声波模块时使用
  30. {
  31. unsigned char j;
  32. do{
  33. j = 10;
  34. do{
  35. _nop_();
  36. }while(--j);
  37. }while(--i);
  38. }
  39. void cmg88()//关数共阴极码管
  40. {
  41. DU=1;
  42. P0=0X00;//共阴极数码管阳极给低电平,全部熄灭
  43. DU=0;
  44. }
  45. /************************************LCD1602液晶屏驱动函数************************************************/
  46. //*******************读状态*************************//
  47. unsigned char ReadStatusLCM(void)
  48. {
  49. LCM_Data = 0xFF;
  50. LCM_RS = 0;
  51. Delay10us(1);
  52. LCM_RW = 1;
  53. Delay10us(1);
  54. do{
  55. LCM_E = 0;
  56. Delay10us(1);
  57. LCM_E = 0;
  58. Delay10us(1);
  59. LCM_E = 1;
  60. Delay10us(1);
  61. }
  62. while (LCM_Data & Busy); //检测忙信号
  63. return(LCM_Data);
  64. }
  65. /****************写数据************************/
  66. void WriteDataLCM(unsigned char WDLCM)
  67. {
  68. ReadStatusLCM(); //检测忙
  69. LCM_Data = WDLCM;
  70. LCM_RS = 1;
  71. Delay10us(1);
  72. LCM_RW = 0;
  73. Delay10us(1);
  74. LCM_E = 0; //若晶振速度太高可以在这后加小的延时
  75. Delay10us(1);
  76. LCM_E = 0; //延时
  77. Delay10us(1);
  78. LCM_E = 1;
  79. Delay10us(1);
  80. }
  81. //****************写指令*************************//
  82. void WriteCommandLCM(unsigned char WCLCM,BuysC) //BuysC为0时忽略忙检测
  83. {
  84. if (BuysC) ReadStatusLCM(); //根据需要检测忙
  85. LCM_Data = WCLCM;
  86. LCM_RS = 0;
  87. Delay10us(1);
  88. LCM_RW = 0;
  89. Delay10us(1);
  90. LCM_E = 0;
  91. Delay10us(1);
  92. LCM_E = 0;
  93. Delay10us(1);
  94. LCM_E = 1;
  95. Delay10us(1);
  96. }
  97. //*******************LCM初始化**********************//
  98. void LCMInit(void)
  99. {
  100. LCM_Data = 0;
  101. WriteCommandLCM(0x38,0); //三次显示模式设置,不检测忙信号
  102. delay(5);
  103. WriteCommandLCM(0x38,0);
  104. delay(5);
  105. WriteCommandLCM(0x38,0);
  106. delay(5);
  107. WriteCommandLCM(0x38,1); //显示模式设置,开始要求每次检测忙信号
  108. WriteCommandLCM(0x08,1); //关闭显示
  109. WriteCommandLCM(0x01,1); //显示清屏
  110. WriteCommandLCM(0x06,1); // 显示光标移动设置
  111. WriteCommandLCM(0x0c,1); // 显示开及光标设置
  112. }
  113. //*********************按指定位置显示一个字符***********************//
  114. void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
  115. {
  116. Y &= 0x1;
  117. X &= 0xF; //限制X不能大于15,Y不能大于1
  118. if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
  119. X |= 0x80; //算出指令码
  120. WriteCommandLCM(X, 1); //发命令字
  121. WriteDataLCM(DData); //发数据
  122. }
  123. //**********************按指定位置显示一串字符*************************//
  124. void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
  125. {
  126. unsigned char ListLength;
  127. ListLength = 0;
  128. Y &= 0x1;
  129. X &= 0xF; //限制X不能大于15,Y不能大于1
  130. while (DData[ListLength]>0x19) //若到达字串尾则退出
  131. {
  132. if (X <= 0xF) //X坐标应小于0xF
  133. {
  134. DisplayOneChar(X, Y, DData[ListLength]); //显示单个字符
  135. ListLength++;
  136. X++;
  137. }
  138. }
  139. }
  140. /***************************************************************************/
  141. /*定时器0中断*/
  142. void timer0() interrupt 1 //T0中断用来计数器溢出,超过测距范围
  143. {
  144. flag=1; //中断溢出标志
  145. }
  146. void StartModule() //启动超声波模块
  147. {
  148. TX=1; //启动一次模块
  149. Delay10us(2);
  150. TX=0;
  151. }
  152. /*小车前进*/
  153. void forward()
  154. {
  155. left_motor_go; //左电机前进
  156. right_motor_go; //右电机前进
  157. }
  158. /*PWM控制使能 小车后退*/
  159. void backward()
  160. {
  161. left_motor_back; //左电机后退
  162. right_motor_back; //右电机后退
  163. }
  164. /*小车停止*/
  165. void stop()
  166. {
  167. right_motor_stops;//右电机停止
  168. left_motor_stops; //左电机停止
  169. }
  170. /*PWM控制使能 小车高速左转*/
  171. void left_rapidly()
  172. {
  173. left_motor_back;
  174. right_motor_go;
  175. }
  176. /*定时器1中断输出PWM信号*/
  177. void timer1() interrupt 3
  178. {
  179. pwm_t++;//周期计时加
  180. if(pwm_t == 255)
  181. pwm_t = EN1 = EN2 = 0;
  182. if(pwm_left_val == pwm_t)//左电机占空比
  183. EN1 = 1;
  184. if(pwm_right_val == pwm_t)//右电机占空比
  185. EN2 = 1;
  186. }
  187. /*判断S2是否被按下*/
  188. void keyscan()
  189. {
  190. for(;;) //死循环
  191. {
  192. if(key_s2 == 0)// 实时检测S2按键是否被按下
  193. {
  194. delay(5); //软件消抖
  195. if(key_s2 == 0)//再检测S2是否被按下
  196. {
  197. while(!key_s2);//松手检测
  198. beep = 0; //使能有源蜂鸣器
  199. delay(200);//200毫秒延时
  200. beep = 1; //关闭有源蜂鸣器
  201. break; //退出FOR死循环
  202. }
  203. }
  204. }
  205. }
  206. /*计算超声波所测距离并显示*/
  207. void Conut(void)
  208. {
  209. time=TH0*256+TL0;
  210. TH0=0;
  211. TL0=0;
  212. S=(float)(time*1.085)*0.17; //算出来是MM
  213. if((S>=7000)||flag==1) //超出测量范围
  214. {
  215. flag=0;
  216. DisplayListChar(0, 1, table1);//1602显示数组table1
  217. }
  218. else
  219. {
  220. disbuff[0]=S/1000; //距离数值千位
  221. disbuff[1]=S%1000/100;//距离数值百位
  222. disbuff[2]=S%100/10;//距离数值十位
  223. disbuff[3]=S%10; //距离数值个位
  224. DisplayListChar(0, 1, table); //显示:Distance:000.0cm
  225. DisplayOneChar(9, 1, ASCII[disbuff[0]]); //显示千位
  226. DisplayOneChar(10, 1, ASCII[disbuff[1]]);
  227. DisplayOneChar(11, 1, ASCII[disbuff[2]]);
  228. DisplayOneChar(12, 1, ASCII[10]); //显示 .
  229. DisplayOneChar(13, 1, ASCII[disbuff[3]]);
  230. }
  231. }
  232. /*超声波避障*/
  233. void Avoid()
  234. {
  235. if(S < 400)//设置避障距离 ,单位毫米 刹车距离
  236. {
  237. beep = 0;//使能蜂鸣器
  238. stop();//停车
  239. backward();//后退
  240. delay(100);//后退时间越长、距离越远。后退是为了留出车辆转向的空间
  241. do{
  242. left_rapidly();//高速左转
  243. delay(70);//时间越长 转向角度越大,与实际行驶环境有关
  244. stop();//停车
  245. delay(200);//时间越长 停止时间越久长
  246. StartModule(); //启动模块测距,再次判断是否
  247. while(!RX); //当RX(ECHO信号回响)为零时等待
  248. TR0=1; //开启计数
  249. while(RX); //当RX为1计数并等待
  250. TR0=0; //关闭计数
  251. Conut(); //计算距离
  252. }while(S < 280);//判断前面障碍物距离
  253. beep = 1;//关闭蜂鸣器
  254. }
  255. else
  256. {
  257. forward();//前进
  258. }
  259. }
  260. void main()
  261. {
  262. cmg88();//关数码管
  263. LCMInit(); //LCM初始化
  264. delay(5);//延时片刻
  265. DisplayListChar(0, 0, Range);//1602第一行显示Range数组内容
  266. DisplayListChar(0, 1, table);//1602第二行显示table数组内容
  267. keyscan();//等待按下S2启动小车
  268. delay(1000);//延时1
  269. TMOD |= 0x20;//定时器1工作模式2,8位自动重装。用于产生PWM
  270. TMOD |= 0x01;//定时器0工作模块1,16位定时模式。T0用测ECH0脉冲长度
  271. TH1 = 220; //
  272. TL1 = 220; //100HZ T1
  273. TH0 = 0;
  274. TL0 = 0;//T0,16位定时计数用于记录ECHO高电平时间
  275. ET1 = 1;//允许T1中断
  276. ET0 = 1;//允许T0中断
  277. TR1 = 1;//启动定时器1
  278. EA = 1;//启动总中断
  279. while(1)
  280. {
  281. StartModule(); //启动模块测距
  282. while(!RX); //当RX(ECHO信号回响)为零时等待
  283. TR0=1; //开启计数
  284. while(RX); //当RX为1计数并等待
  285. TR0=0; //关闭计数
  286. Conut(); //计算距离
  287. Avoid(); //避障
  288. delay(65); //测试周期不低于60MS
  289. }
  290. }
  1. #ifndef __QXA51_H__
  2. #define __QXA51_H__
  3. /*电机驱动IO定义*/
  4. sbit IN1=P1^2; //1 左电机反转
  5. sbit IN2=P1^3; //1 左电机正转
  6. sbit IN3=P1^6; //1 右电机正转
  7. sbit IN4=P1^7; //1 右电机反转
  8. sbit EN1=P1^4; //1 左电机使能
  9. sbit EN2=P1^5; //1 右电机使能
  10. sbit left_led1=P3^3;//左寻迹信号 为0没有识别到黑线 为1识别到黑线
  11. sbit right_led1=P3^2;//右寻迹信号 为0没有识别到黑线 为1识别到黑线
  12. sbit left_led2=P3^4;//左避障信号 为0识别到障碍物 为1没有识别到障碍物
  13. sbit right_led2=P3^5;//右避障信号 为0识别到障碍物 为1没有识别到障碍物
  14. sbit beep=P2^3;
  15. sbit key_s2=P3^0;
  16. sbit key_s3=P3^1;
  17. #define left_motor_en EN1=1 //左电机使能
  18. #define left_motor_stops EN1=0 //左电机停止
  19. #define right_motor_en EN2=1 //右电机使能
  20. #define right_motor_stops EN2=0 //右电机停止
  21. #define left_motor_go IN1=0,IN2=1 //左电机正转
  22. #define left_motor_back IN1=1,IN2=0 //左电机反转
  23. #define right_motor_go IN3=1,IN4=0 //右电机正转
  24. #define right_motor_back IN3=0,IN4=1 //右电机反转
  25. #endif

这里运用了LCD1602的显示数据,按键启动,超声波测距,蜂鸣器,定时器,中断功能,

避障原理:运用超声波测距来检测距离如果距离小于指定距离的话,蜂鸣器开始响,然后停车开始向后退,高速左转后停车,然后继续运用超声波模块测距,如果大于指定距离继续前进

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/article/detail/46313
推荐阅读
相关标签
  

闽ICP备14008679号