当前位置:   article > 正文

【51单片机STC89C52】舵机控制综合篇_stc89c52超声波测距

stc89c52超声波测距

一、项目概述

1、功能描述

超声波模块,震动传感器,按键控制SG90舵机

检测靠近时,垃圾桶自动开盖并伴随滴一声, 2 秒后关盖
发生震动时,垃圾桶自动开盖并伴随滴一声, 2 秒后关盖
按下按键时,垃圾桶自动开盖并伴随滴一声, 2 秒后关盖

2、硬件部分

SG90舵机,超声波模块,震动传感器,蜂鸣器

3、接线说明

舵机(PWM)信号线 —> P1.1(定时器0)
超声波HC-SR04   Trig —> P1.5 、Echo —> P1.6 (定时器1)
震动传感器 —> P3.2(外部中断0)
蜂鸣器 —> P2.0

二、基础参考

【51单片机STC89C52】定时器(中断)控制LED_大头1213

【51单片机STC89C52】IO口模拟PWM控制SG90舵机_大头1213

【51单片机STC89C52】HC-SR04超声波模块测距_大头1213

三、部分代码

1、接线部分

  1. sbit D5 = P3^7;//根据原理图(电路图),设备变量led1指向P3组IO口的第7口
  2. sbit D6 = P3^6;//根据原理图(电路图),设备变量led2指向P3组IO口的第6口
  3. sbit KEY1 = P2^1;//按键KEY1
  4. sbit Trig = P1^5;
  5. sbit Echo = P1^6;
  6. sbit sg90_con = P1^1;
  7. sbit vibrate = P3^2;
  8. sbit beep = P2^0;

2、超声波测距

  1. double get_distance()
  2. {
  3. double time;
  4. //定时器数据清零,以便下一次测距
  5. TH1 = 0;
  6. TL1 = 0;
  7. //1. 让它发送波:给Trig端口至少10us的高电平
  8. startHC();
  9. //2. 开始发送波:Echo信号由低电平跳转到高电平
  10. while(Echo == 0);
  11. // 开始发送波,启动定时器
  12. TR1 = 1;
  13. //3. 接收返回波:Echo信号由高电平跳转回低电平
  14. while(Echo == 1);
  15. // 接收返回波,停止定时器
  16. TR1 = 0;
  17. //4. 计算时间
  18. time = (TH1 * 256 + TL1)*1.085;//us为单位
  19. //5. 距离 = 速度 (340m/s)* 时间/2
  20. return (time * 0.017);
  21. }

3、舵机——定时器0中断服务函数

  1. void Time0Handler() interrupt 1
  2. {
  3. cnt++; //统计溢出的次数
  4. //重新给初值
  5. TL0 = 0x33;
  6. TH0 = 0xFE;
  7. //控制PWM波
  8. if(cnt < angle){
  9. sg90_con = 1;
  10. }else{
  11. sg90_con = 0;
  12. }
  13. if(cnt == 40){ //当溢出40次,经过了20ms
  14. cnt = 0;
  15. sg90_con = 1;
  16. }
  17. }

4、震动传感器——外部中断0

打开外部中断

  1. void EX0_Init()
  2. {
  3. EX0 = 1;//打开外部中断
  4. IT0 = 0;//低电平触发
  5. }

中断服务函数

  1. void Ex0_Handler() interrupt 0
  2. {
  3. mark_vibrate = 1;
  4. }

5、开关盖函数

  1. void openDustbin()
  2. {
  3. char n;
  4. angle = 3; //90度 1.5ms高电平
  5. //舵机开盖
  6. if(angle_bak != angle){
  7. cnt = 0;
  8. beep = 0;
  9. Delay150ms();
  10. Delay150ms();
  11. beep = 1;
  12. Delay2000ms();
  13. }
  14. angle_bak = angle;
  15. }
  16. void closeDustbin()
  17. {
  18. //关盖
  19. angle = 1; //0度
  20. angle_bak = angle;
  21. cnt = 0;
  22. Delay150ms();
  23. }

四、整体代码

  1. #include "reg52.h"
  2. #include "intrins.h"
  3. sbit D5 = P3^7;//根据原理图(电路图),设备变量led1指向P3组IO口的第7口
  4. sbit D6 = P3^6;//根据原理图(电路图),设备变量led2指向P3组IO口的第6口
  5. sbit KEY1 = P2^1;//按键KEY1
  6. sbit Trig = P1^5;
  7. sbit Echo = P1^6;
  8. sbit sg90_con = P1^1;
  9. sbit vibrate = P3^2;
  10. sbit beep = P2^0;
  11. char angle;
  12. char angle_bak;
  13. char cnt = 0;
  14. char mark_vibrate = 0;
  15. void Delay150ms() //@11.0592MHz
  16. {
  17. unsigned char i, j, k;
  18. _nop_();
  19. i = 2;
  20. j = 13;
  21. k = 237;
  22. do
  23. {
  24. do
  25. {
  26. while (--k);
  27. } while (--j);
  28. } while (--i);
  29. }
  30. void Delay2000ms() //@11.0592MHz
  31. {
  32. unsigned char i, j, k;
  33. _nop_();
  34. i = 15;
  35. j = 2;
  36. k = 235;
  37. do
  38. {
  39. do
  40. {
  41. while (--k);
  42. } while (--j);
  43. } while (--i);
  44. }
  45. void Delay10us() //@11.0592MHz
  46. {
  47. unsigned char i;
  48. i = 2;
  49. while (--i);
  50. }
  51. void Timer0Init(void) //500微秒@11.0592MHz
  52. {
  53. //AUXR &= 0x7F;
  54. TMOD &= 0xF0; //设置定时器模式16位
  55. TMOD |= 0x01; //设置定时器模式
  56. TL0 = 0x33; //设置定时初始值0.5ms
  57. TH0 = 0xFE; //设置定时初始值
  58. TF0 = 0; //清除TF0标志
  59. TR0 = 1; //定时器0开始计时
  60. ET0 = 1; //打开定时器0中断
  61. EA = 1; //打开总中断EA
  62. }
  63. void Timer1Init() //设置定时器0工作模式1,初始值设定0开始数数,不着急启动定时器
  64. {
  65. TMOD &= 0x0F; //设置定时器模式
  66. TMOD |= 0x10;
  67. TH1 = 0;
  68. TL1 = 0;
  69. }
  70. void startHC()
  71. {
  72. Trig = 0;
  73. Trig = 1;
  74. Delay10us();
  75. Trig = 0;
  76. }
  77. double get_distance()
  78. {
  79. double time;
  80. //定时器数据清零,以便下一次测距
  81. TH1 = 0;
  82. TL1 = 0;
  83. //1. 让它发送波:给Trig端口至少10us的高电平
  84. startHC();
  85. //2. 开始发送波:Echo信号由低电平跳转到高电平
  86. while(Echo == 0);
  87. // 开始发送波,启动定时器
  88. TR1 = 1;
  89. //3. 接收返回波:Echo信号由高电平跳转回低电平
  90. while(Echo == 1);
  91. // 接收返回波,停止定时器
  92. TR1 = 0;
  93. //4. 计算时间
  94. time = (TH1 * 256 + TL1)*1.085;//us为单位
  95. //5. 距离 = 速度 (340m/s)* 时间/2
  96. return (time * 0.017);
  97. }
  98. void openStatusLight()
  99. {
  100. D5 = 0;
  101. D6 = 1;
  102. }
  103. void closeStatusLight()
  104. {
  105. D5 = 1;
  106. D6 = 0;
  107. }
  108. void initSG90_0()
  109. {
  110. angle = 1; //初始角度是0度,0.5ms,溢出1就是0.5ms高电平
  111. cnt = 0;
  112. sg90_con = 1;//一开始从高电平开始
  113. }
  114. void openDustbin()
  115. {
  116. char n;
  117. angle = 3; //90度 1.5ms高电平
  118. //舵机开盖
  119. if(angle_bak != angle){
  120. cnt = 0;
  121. beep = 0;
  122. for(n = 0; n < 2; n++)
  123. Delay150ms();
  124. beep = 1;
  125. Delay2000ms();
  126. }
  127. angle_bak = angle;
  128. }
  129. void closeDustbin()
  130. {
  131. //关盖
  132. angle = 1; //0度
  133. angle_bak = angle;
  134. cnt = 0;
  135. Delay150ms();
  136. }
  137. void EX0_Init()
  138. {
  139. EX0 = 1;//打开外部中断
  140. IT0 = 0;//低电平触发
  141. }
  142. void main()
  143. {
  144. double dis;
  145. Timer0Init();
  146. Timer1Init();
  147. EX0_Init();
  148. initSG90_0();//舵机的初始位置
  149. while(1){
  150. dis = get_distance();//超声波测距
  151. if(dis < 10 || KEY1 == 0 || mark_vibrate == 1){
  152. //开盖,灯状态,D5亮
  153. openStatusLight();
  154. openDustbin();
  155. mark_vibrate = 0;
  156. }else{
  157. //关盖,灯状态,D5灭
  158. closeStatusLight();
  159. closeDustbin();
  160. }
  161. }
  162. }
  163. void Time0Handler() interrupt 1
  164. {
  165. cnt++; //统计溢出的次数
  166. //重新给初值
  167. TL0 = 0x33;
  168. TH0 = 0xFE;
  169. //控制PWM波
  170. if(cnt < angle){
  171. sg90_con = 1;
  172. }else{
  173. sg90_con = 0;
  174. }
  175. if(cnt == 40){ //当溢出40次,经过了20ms
  176. cnt = 0;
  177. sg90_con = 1;
  178. }
  179. }
  180. void Ex0_Handler() interrupt 0
  181. {
  182. mark_vibrate = 1;
  183. }

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

闽ICP备14008679号