找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 911|回复: 3
收起左侧

单片机超声波测距程序加入了舵机控制后无法实时测量?

[复制链接]
ID:582255 发表于 2022-4-17 22:35 | 显示全部楼层 |阅读模式
51单片机超声波测距,通过DHT11测温进行修正,距离小于1时控制舵机转动,为什么总是不能实时刷新数据?通过控制中断开关能够刷新数据(没办法的办法),但是单片机有抖动,请教一下高手怎么解决实时刷新的问题啊
#include <reg51.h>        
#include "lcd.h"
#include <intrins.h>
/*对数据类型进行声明定义*/
typedef unsigned int u16;         
typedef unsigned char u8;
/*外设IO定义*/
sbit Data = P3^7; //定义DHT11数据线
sbit Trig = P1^2;
sbit Yellow = P2^3;
sbit Echo = P1^3;
sbit  Distance1 = P1^0;
/*尾部超声波定义*/

sbit Red = P2^4;
sbit Green = P2^2;
sbit pwm = P2^0;
/*变量定义*/
u16 Distance=0;

//sbit Yellow = 0 ;
bit flag =0;                 
u8 TEMP = 25 ,HR,count=0,ct,angle=1;//采集值

void DHT11_delay_ms(u16 z)
{
   u16 i,j;
   for(i=z;i>0;i--)
      for(j=110;j>0;j--);
}
void DHT11_delay_us(u8 n)
{
    while(--n);
}

void DHT11_start()
{
   Data=1;
   DHT11_delay_us(2);
   Data=0;
   DHT11_delay_ms(30);   //延时18ms以上
   Data=1;
   DHT11_delay_us(30);
}

u8 DHT11_rec_byte()      //接收一个字节
{
   u8 i,dat=0;
   for(i=0;i<8;i++)    //从高到低依次接收8位数据
   {         
      while(!Data);   ////等待50us低电平过去
      DHT11_delay_us(8);     //延时60us,如果还为高则数据为1,否则为0
      dat<<=1;           //移位使正确接收8位数据,数据为0时直接移位
      if(Data==1)    //数据为1时,使dat加1来接收数据1
         dat+=1;
      while(Data);  //等待数据线拉低   
    }  
    return dat;
}

void DHT11_receive()      //接收40位的数据
{
        u8 R_H,R_L,T_H,T_L,RH,RL,TH,TL,revise;
  DHT11_start();
  if(Data==0)
        {
                while(Data==0);   //等待拉高     
                DHT11_delay_us(40);  //拉高后延时80us
                R_H=DHT11_rec_byte();    //接收湿度高八位  
                R_L=DHT11_rec_byte();    //接收湿度低八位  
                T_H=DHT11_rec_byte();    //接收温度高八位  
                T_L=DHT11_rec_byte();    //接收温度低八位
                revise=DHT11_rec_byte(); //接收校正位
                DHT11_delay_us(25);    //结束
                if((R_H+R_L+T_H+T_L)==revise)      //校正
                {
                                RH=R_H;
                                RL=R_L;
                                TH=T_H;
                                TL=T_L;
                }
                /*数据处理,方便显示*/
                TEMP=TH;
                HR=RH;
        }
        DisplayOneChar(5,0,'0'+(TEMP/10));
        DisplayOneChar(6,0,'0'+(TEMP%10));
        DisplayOneChar(12,0,'0'+(HR/10));
        DisplayOneChar(13,0,'0'+(HR%10));
}
void GetDistance() //超声波测距
{
        static u16 time=0;
        count++;
        TH0=0;
    TL0=0;
        
        Trig=1; //启动一次模块
  //时间要求很严格,否则会影响精度
        _nop_(); _nop_();_nop_(); _nop_(); _nop_(); _nop_();_nop_();
        _nop_(); _nop_();_nop_(); _nop_(); _nop_(); _nop_();_nop_();
        _nop_(); _nop_();_nop_(); _nop_(); _nop_(); _nop_();_nop_();
        Trig=0;
        
        while(!Echo);                //当RX为零时等待
        TR0=1;                            //开启计数
        while(Echo);                //当RX为1计数并等待
        TR0=0;                                  //关闭计数
               
        time=TH0*256+TL0;//计算时间
        TH0=0;
        TL0=0;
        Distance=(time*(331.4+0.607*TEMP))/20000;//算出来是CM,带温度补偿

        if((Distance>=330)||flag==1) //超出测量范围显示“-”
        {         
                flag=0;
                DisplayOneChar(5, 1, '-');
                DisplayOneChar(6, 1, '-');
                DisplayOneChar(7, 1, '-');
        }
        else
        {
                DisplayOneChar(5, 1, Distance/100+'0');
                DisplayOneChar(6, 1, '.');
                DisplayOneChar(7, 1, Distance%100/10+'0');
                DisplayOneChar(8, 1, Distance%10+'0');
        }
        

}

void Timer0Init()//定时器0初始化
{
        //TMOD|=0x01;                   //设T0为方式1,GATE=1;
        TMOD=0x11;
        TH0=0;
        TL0=0;         
        ET0=1;        //允许T0中断
        EA=1;                           //开启总中断
                TH1=0xfc;        
                TL1=0x66;         
                        ET1=1;
                        TR1= 1;                                
}

void main(void)
{
        Distance1=1;
        Timer0Init();
        LcdInit();        
        Trig=0;//初始化必不可少!!!

        DisplayListChar(0,0,"TEMP:");DisplayOneChar(7,0,'C');DisplayListChar(9,0,"HR:");DisplayOneChar(14,0,'%');
  DisplayListChar(0,1,"DIS:");DisplayListChar(9,1,"M");
    //EA=0;
        while(1)
        {        
                EA=1;
                GetDistance(); //超声波测距

                if((Distance<100) && (Distance1 == 1) )
                   {
                     Yellow = 0 ;
                         Red = 1 ;
                         Green = 1 ;
                         angle = 1 ;
                         EA=0;
                   }
                if   ((Distance<100) && (Distance1 == 0) )
                    {
                     Yellow = 1 ;
                         Red = 0 ;
                         Green = 1 ;
                         angle = 2 ;
                         EA=0;
                    }
                if   (Distance>100)
                        {
                     Yellow = 1 ;
                         Red = 1 ;
                         Green = 0 ;
                         angle = 1 ;
                         EA=0;
                    }
               
                //DHT11_delay_ms(20);
                if(count>20)
                {
                   DHT11_receive();//温湿度显示
                   count = 0;
                }
        }
                        
}
void Timer0() interrupt 1                  //T0中断用来计数器溢出,超过测距范围
{
        flag=1;        //中断溢出标志
}
void Time1_Int() interrupt 3//舵机
{
        
        TH1=0xfc;         
        TL1=0x66;         
        if(ct<angle)//判断1ms次数是否小于角度标识
    pwm=1;//确实小于,pwm输出高电平
    else
    pwm=0;//大于则输出低电平
        ct=(ct+1);//1ms次数加1
        ct=ct%20;//次数始终保持为20即保持周期为20ms
        //if(count>=20)count=0;
}


回复

使用道具 举报

ID:582255 发表于 2022-4-18 13:17 | 显示全部楼层
为什么不能实时刷新
回复

使用道具 举报

ID:123289 发表于 2022-4-18 16:19 | 显示全部楼层
没有细看,提示:时序上有冲突吗?(如在某个时刻,干着A,B干不成了。)
回复

使用道具 举报

ID:161164 发表于 2022-4-19 14:37 | 显示全部楼层
舵机定时器的中断延误了DHT11的电平检测
导致程序在while(Data)死循环了
在用while(XXX)的时候应加上超时条件
以防止死循环
例:
  1. u8 DHT11_rec_byte()      //接收一个字节
  2. {
  3.    u8 i,dat=0, j=0;
  4.    for(i=0;i<8;i++)    //从高到低依次接收8位数据
  5.    {         
  6.       while(!Data);   ////等待50us低电平过去
  7.       DHT11_delay_us(8);     //延时60us,如果还为高则数据为1,否则为0
  8.       dat<<=1;           //移位使正确接收8位数据,数据为0时直接移位
  9.       if(Data==1)    //数据为1时,使dat加1来接收数据1
  10.          dat+=1;
  11.                         j=0;
  12.       while(Data && j++<250);  //等待数据线拉低   
  13.     }  
  14.     return dat;
  15. }
复制代码




回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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