找回密码
 立即注册

QQ登录

只需一步,快速开始

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

诚心求解答!关于利用stc15单片机制作俯卧撑计数装置的问题

[复制链接]
跳转到指定楼层
楼主
400黑币
楼主单片机小白一名。正在学习stc15w4k32s4这一款单片机。目前想利用超声波传感器做一个俯卧撑计数的装置。但是遇到了种种问题,经过长时间的调试仍未好转,诚心求大佬解答!
项目具体描述如下:stc15单片机与两个HC-SR04超声波连接,通电后超声波测距并在12864液晶上实时显示,通过监测超声波返回的距离变化来统计做了俯卧撑的个数。当距离超出一定范围时蜂鸣器就会报警,提示别人姿势错误。测量的距离同时通过串口返回给电脑。
遇到的问题:目前给单片机上电后在绝大多数情况下单片机无法正常工作,液晶只亮不显示,串口助手无数据返回,蜂鸣器不响。像是没有进入到主函数中,单片机像是“僵死”了。楼主不知道是代码的问题还是硬件焊接的问题实物图如下:


单片机代码如下:
  1. #include<stc15w.h>
  2. #include<intrins.h>
  3. #include<stdio.h>
  4. #include<math.h>
  5. #define uchar unsigned char
  6. #define uint unsigned int
  7. #define Part P1 //P0接8位数据线
  8. sbit LCD_RS=P2^6;  //定义12864液晶RS端,寄存器选择信号 H:数据寄存器 L:指令寄存器   
  9. sbit LCD_RW=P2^5;  //定义12864液晶RW端,读/写信号  H:读   L:写   
  10. sbit LCD_EN=P2^4;  //定义12864液晶LCDEN端, 片选信号  下降沿触发,锁存数据   
  11. sbit LCD_PSB=P2^3;  //定义12864液晶PSB端, H:并行 L:串行  
  12. sbit Echo1=P0^0;//超声波测距模块Echo1连接的IO
  13. sbit Trig1=P0^1;//超声波测距模块Trig1连接的IO
  14. sbit Echo2=P0^2;//超声波测距模块Echo2连接的IO
  15. sbit Trig2=P0^3;//超声波测距模块Trig2连接的IO
  16. sbit Beep=P2^7;//蜂鸣器连接的IO口
  17. uchar show1[]="chest:0000mm";
  18. uchar show2[]="waist:0000mm";
  19. uchar show3[]="gap:000mm";
  20. uchar show4[]="times:000";
  21. uint xdata distance1=600,distance2=600,time,num=0;
  22. uchar xdata urdat,k=1;
  23. float xdata ratio;
  24. char xdata m=1;
  25. int xdata gap;
  26. void SendData(unsigned char dat);
  27. void delayms(uint xms)
  28. {        
  29.         uint i,j;
  30.         for(i=xms;i>0;i--)
  31.                 for(j=110;j>0;j--);
  32. }
  33. void Delay20us()                //@11.0592MHz
  34. {
  35.         unsigned char i;

  36.         _nop_();
  37.         _nop_();
  38.         _nop_();
  39.         i = 52;
  40.         while (--i);
  41. }
  42. //====================================  
  43. //LCD忙检测函数  
  44. bit lcd_busy()  
  45. {  
  46. bit result;  
  47.     LCD_RS=0;   
  48.   LCD_RW=1;  
  49.   LCD_EN= 1;  
  50.    result=(bit)(Part & 0x80);  
  51.    LCD_EN=0;  
  52. return result;  
  53. }  
  54. //=====================================  
  55. //液晶写命令函数  
  56. void lcd_write_cmd(uchar com)  
  57. {  
  58. while(lcd_busy());  
  59. LCD_RS=0;  //选择指令寄存器  
  60. LCD_RW=0;  //写  
  61. LCD_EN=0;   
  62. Part=com;    //指令值赋给P1口  
  63. delayms(5);  
  64. LCD_EN=1;  
  65. delayms(5);  
  66. LCD_EN=0;   
  67. }  
  68. //=====================================  
  69. //液晶写一个字符数据函数  
  70. void lcd_write_dat(uchar date)  
  71. {  
  72. while(lcd_busy());  
  73. LCD_RS=1;  //选择数据寄存器  
  74. LCD_RW=0;  //写  
  75. LCD_EN=0;  
  76. P1=date;    //数据值赋给P1口  
  77. delayms(5);  
  78. LCD_EN=1;  
  79. delayms(5);  
  80. LCD_EN=0;  
  81. }  
  82. //=====================================  
  83. //液晶写一个字符串函数  
  84. //void lcd_write_string(uchar *str)  
  85. //{  
  86. //while(*str!='\0')  //未结束  
  87. // {  
  88. //  lcd_write_dat(*str++);  
  89. //  delayms(5);  
  90. // }  
  91. //}  
  92. //=====================================  
  93. //液晶显示位置函数  
  94. void lcd_pos(uchar x,uchar y)  //从第X行的第Y位置开始显示  
  95. {  
  96. uchar pos;  
  97. if(x==1)        //第一行  
  98. { x=0x80;}  
  99. else if(x==2)  //第二行  
  100. { x=0x90;}  
  101. else if(x==3)  //第三行  
  102. { x=0x88;}  
  103. else if(x==4)  //第四行  
  104. { x=0x98;}  
  105. pos=x+y-1;     //首地址为0X80  
  106. lcd_write_cmd(pos);  
  107. }  
  108. //=====================================  
  109. //液晶初始化函数  
  110. void lcd_init()  
  111. {  
  112. LCD_PSB=1;  //并行方式  
  113. lcd_write_cmd(0x30);  
  114. delayms(5);  
  115. lcd_write_cmd(0x0c);  //开显示,不显示光标  
  116. delayms(5);  
  117. lcd_write_cmd(0x06);  //写一个字符后地址指针自动加1  
  118. delayms(5);  
  119. lcd_write_cmd(0x01);   //清屏  
  120. delayms(5);  
  121. }  
  122. //=====================================
  123. void Display1()
  124. {
  125.         uint xdata i;
  126.         lcd_pos(1,1);  
  127.         for(i=0;i<13;i++)
  128.   {lcd_write_dat(show1[i]); }  
  129. }
  130. void Display2()
  131. {
  132.         uint xdata i;
  133.   lcd_pos(2,1);  
  134.         for(i=0;i<13;i++)  
  135.   {lcd_write_dat(show2[i]); }      
  136. }
  137. void Display3()
  138. {
  139.         uint xdata i;
  140.   lcd_pos(3,1);  
  141.         for(i=0;i<10;i++)   
  142.   {lcd_write_dat(show3[i]); }  
  143. }
  144. void Display4()
  145. {
  146.         uint xdata i;
  147.   lcd_pos(4,1);  
  148.         for(i=0;i<9;i++)   
  149.   {lcd_write_dat(show4[i]); }  
  150. }
  151. void UartInit(void)
  152. {
  153.         SCON=0x50;//工作方式选择:8位UART波特率可变
  154.         AUXR&=0x80;
  155.         TMOD=0x00;
  156.         TL1=0xe8;
  157.         TH1=0xff;
  158.         TR1=1;
  159.         ES=1;
  160.         EA=1;
  161. }//配置波特率,对数据采样
  162. void Uart() interrupt 4 using 1//定时器1,16位自动重装模式
  163. {
  164.         if(RI)
  165.         {
  166.                 urdat=SBUF;//从缓冲区读取数据
  167.                 RI=0;//响应中断请求后清零
  168.                 SendData(urdat);
  169.         }
  170. }
  171. void SendData(unsigned char dat)
  172. {
  173.         SBUF=dat;//将数据传入PC机
  174.         while(TI==0);//等待发送中断请求
  175.         TI=0;//响应中断后TI清零
  176. }
  177. char putchar(char c)
  178. {
  179.         SendData(c);
  180.         return c;
  181. }//输出成对象
  182. void INT_init1 (void)
  183. {
  184.         TMOD&=0x01;//定时器0,16位不可重装载工作方式
  185.         TH0=0;//定时器0清零
  186.         TL0=0;//定时器0清零
  187.         EA = 1;//总中断开
  188.         Trig1=0;//拉低为下次触发做准备
  189.         Trig2=0;
  190. }
  191. void dist (void)//测量距离程序
  192. {
  193.         if(m==1)
  194.         {
  195.         Trig1=1;        
  196.         Delay20us();   //延时20us
  197.         Trig1=0;         //Trig输出20us高电平触发测距
  198.         while(Echo1==0); //等待Echo回波引脚变高电平
  199.         TR0=1;//程序运行到此处时说明Echo脚变成了高电平,此时启动T0开始计时
  200.         while(Echo1==1); //等待Echo回波引脚高电平结束               
  201.         TR0=0;//程序运行到此处时说明Echo脚变成了低电平,此时T0停止计时
  202.         time=TH0*256+TL0;
  203.         distance1=time*0.272;  //测量距离
  204.         TH0 = 0;  //重置计时器
  205.         TL0 = 0;
  206.         }
  207.         if(m==-1)
  208.         {
  209.         Trig2=1;        
  210.         Delay20us();   //延时20us
  211.         Trig2=0;         //Trig输出20us高电平触发测距
  212.         while(Echo2==0); //等待Echo回波引脚变高电平
  213.         TR0=1;//程序运行到此处时说明Echo脚变成了高电平,此时启动T0开始计时
  214.         while(Echo2==1); //等待Echo回波引脚高电平结束               
  215.         TR0=0;//程序运行到此处时说明Echo脚变成了低电平,此时T0停止计时
  216.         time=TH0*256+TL0;
  217.         distance2=time*0.24;  //测量距离
  218.         TH0 = 0;  //重置计时器
  219.         TL0 = 0;
  220.         }
  221.         m=-m;//轮流测量距离12
  222. }

  223. void main()//主函数  
  224. {
  225.         P0M0=0x00;P0M1=0x00;
  226.         P1M0=0x00;P1M1=0x00;
  227.         P2M0=0x00;P2M1=0x00;
  228.         P3M0=0x00;P3M1=0x00;//单片机IO口工作方式初始化
  229.         INT_init1();//T0初始化
  230.         UartInit();//串口初始化
  231.         lcd_init();//液晶初始化
  232.         while(1)        
  233.         {        
  234.                 dist();//定时器测量距离
  235.                 printf("dis1=%d\n",distance1);
  236.                 printf("dis2=%d\n",distance2);
  237.                 gap=distance1-distance2;
  238.                 gap=abs(gap);
  239.                 ratio=distance1/distance2;
  240.                 printf("gap=%d",gap);
  241.                 if(gap<=200)
  242.                 {
  243.                                 if(distance1<190&&distance2<180)
  244.                                 {
  245.                                         k=0;
  246.                                         Beep=0;
  247.                                         delayms(50);
  248.                                         Beep=1;
  249.                                 }
  250.                                 else if(distance1>200&&distance2>250&&k==0)
  251.                                 {
  252.                                         k=1;
  253.                                         Beep=0;
  254.                                         delayms(50);
  255.                                         Beep=1;
  256.                                         num++;
  257.                                 }
  258. //                                else continue;
  259.                 }
  260.                 else if(gap>200&&gap<400)
  261.                 {
  262.                         Beep=0;
  263.                         delayms(120);
  264.                         Beep=1;
  265.                 }
  266. //                else
  267. //                {
  268. //                        continue;
  269. //                }
  270.                 printf("times=%d\n",num);
  271.                 printf("     ");
  272.                 show1[6]=distance1/1000+0x30;
  273.                 show1[7]=distance1%1000/100+0x30;
  274.                 show1[8]=distance1%1000%100/10+0x30;
  275.                 show1[9]=distance1%10+0x30;
  276.                 show2[6]=distance2/1000+0x30;
  277.                 show2[7]=distance2%1000/100+0x30;
  278.                 show2[8]=distance2%1000%100/10+0x30;
  279.                 show2[9]=distance2%10+0x30;
  280.                 show3[4]=abs(gap)/100+0x30;
  281.                 show3[5]=abs(gap)%100/10+0x30;
  282.                 show3[6]=abs(gap)%10+0x30;
  283.                 show4[7]=num/100+0x30;
  284.                 show4[8]=num%100/10+0x30;
  285.                 show4[9]=num%10+0x30;
  286.           Display1();
  287.                 Display2();
  288.                 Display3();
  289.                 Display4();
  290.         }
  291. }
复制代码

楼主立志做一名工程师,努力学习电子制作,虽然在项目的制作中屡屡受挫,但是仍不气馁,我相信总有好心人为我指点迷津,是否可以大致指出我的项目哪里有什么硬伤?出现上述问题的可能原因是什么?如有则不胜感激!

最佳答案

查看完整内容

1,你要用printf的话,串口初始化要加上 TI = 1; 2,while(Echo1==0);这里最好改成 while(Echo1==0 && TR0 == 1);超时判断,因为如果超声模块接收不到回声,就会一直卡在while(Echo1==0);循环里面导致单片机卡死。 3,建议先单独测试LCD屏幕能不能正常工作,再加上其他代码,同理其他模块得先确保能单独工作的情况下,再把所有程序集成在一起。 4,超声波测量周期建议100MS以上,否则会影响超声波的下次测量结果,建议开个定时 ...
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:514901 发表于 2020-11-15 15:24 | 只看该作者
1,你要用printf的话,串口初始化要加上 TI = 1;
2,while(Echo1==0);这里最好改成 while(Echo1==0 && TR0 == 1);超时判断,因为如果超声模块接收不到回声,就会一直卡在while(Echo1==0);循环里面导致单片机卡死。
3,建议先单独测试LCD屏幕能不能正常工作,再加上其他代码,同理其他模块得先确保能单独工作的情况下,再把所有程序集成在一起。
4,超声波测量周期建议100MS以上,否则会影响超声波的下次测量结果,建议开个定时器来触发超声波测距
回复

使用道具 举报

板凳
ID:648281 发表于 2020-11-15 16:39 | 只看该作者
你好!
首先把你的接线先整理一遍吧,接插件用的太多了,很容易造成断路;
具体功能的实现,可以进行交流,软硬件工程可以帮你完成。
回复

使用道具 举报

地板
ID:160500 发表于 2020-11-15 18:44 | 只看该作者
绝大多数情况下单片机无法正常工作,意思就是有时候是可以正常工作的。这种问题就是线路连接的问题
回复

使用道具 举报

5#
ID:736475 发表于 2020-11-16 22:51 | 只看该作者
51hei**1140 发表于 2020-11-15 16:39
你好!
首先把你的接线先整理一遍吧,接插件用的太多了,很容易造成断路;
具体功能的实现,可以进行交流 ...

谢谢!
回复

使用道具 举报

6#
ID:736475 发表于 2020-11-16 22:52 | 只看该作者
liuzx66 发表于 2020-11-15 18:44
绝大多数情况下单片机无法正常工作,意思就是有时候是可以正常工作的。这种问题就是线路连接的问题

确实,我也怀疑是线路的问题!因为我的线路全暴露在外面,我得考虑换一下杜邦线然后把他们焊在一起
回复

使用道具 举报

7#
ID:736475 发表于 2020-11-16 22:52 | 只看该作者
郑汉松 发表于 2020-11-16 10:57
1,你要用printf的话,串口初始化要加上 TI = 1;
2,while(Echo1==0);这里最好改成 while(Echo1==0 && TR ...

非常感谢有耐心帮我看代码!
回复

使用道具 举报

8#
ID:736475 发表于 2020-11-16 22:59 | 只看该作者
郑汉松 发表于 2020-11-16 10:57
1,你要用printf的话,串口初始化要加上 TI = 1;
2,while(Echo1==0);这里最好改成 while(Echo1==0 && TR ...

可以用一个定时器来进行分频,轮流触发超声波和液晶吗?
回复

使用道具 举报

9#
ID:736475 发表于 2020-11-16 23:15 | 只看该作者
郑汉松 发表于 2020-11-16 10:57
1,你要用printf的话,串口初始化要加上 TI = 1;
2,while(Echo1==0);这里最好改成 while(Echo1==0 && TR ...

Timer0 function()
{
        static key_count=0;
        static display_count=0;
         key_count++;
        display_count++;
        if(key_count==10)
                {
                        key_count=0;
                        keyflag=1;
                }
        if(display_count==3)
                {
                        display_count==0;
                        display();
                }
}
类似于这样
回复

使用道具 举报

10#
ID:367934 发表于 2020-11-17 09:11 | 只看该作者
系统都是由简单到复杂,想要知道问题出在哪里可以做一下简单的测试。
1.找个万用表测试一下电压是否正常。可能是电压问题。接错或者反接一点机率会导致整个系统出问题。
2.程序下载。测试测试单片机是否出问题。如果没有进行下一步。
3.找一个简单的串口例程测试单片机是否有问题。或者把现在的程序把其他的功能先屏蔽掉,保留最简单的串口通信程序。测试看有没有问题。如果没有进行下一步。
4.测试超声波传感器,使用串口可以进行测试。就这样一步一步的把所有外设调试通过就好了。
回复

使用道具 举报

11#
ID:426861 发表于 2020-11-17 09:31 | 只看该作者
软件先只放一个功能的,然后测试硬件电路,只到调通了再调下一个,不要一起测试
回复

使用道具 举报

12#
ID:89515 发表于 2020-11-17 09:41 来自手机 | 只看该作者
把液晶屏换为串行通信嘛,这样数据线只有一条,并行线太多太长接触不良都有可能出现问题,而且不好找。就你的这个实验用红外对管不是更好做吗?
回复

使用道具 举报

13#
ID:342954 发表于 2020-11-17 09:42 | 只看该作者
查硬件,检查电源,和单片机复位脚
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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