找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1575|回复: 12
收起左侧

这个单片机超声波程序,别的占用一个定时器怎么解决?为什么定时器0的中断进不...

[复制链接]
回帖奖励 10 黑币 回复本帖可获得 1 黑币奖励! 每人限 10 次
ID:515826 发表于 2022-4-1 16:01 | 显示全部楼层 |阅读模式
#include<reg51.h>        //包含头文件
#include"18b20.h"        //包含温度读取文件
#include<stdio.h>
#include<intrins.h>

#define uchar unsigned char
#define uint unsigned int

//--定义使用的IO--//
#define GPIO_DIG P0                 //定义GPIO_DIG代替P0

sbit servorControl =P1^6;  //舵机的控制引脚
sbit Trig=P1^7;            //控制端
sbit Echo=P3^3;          //接收端

sbit K1=P3^4;
sbit K2=P3^5;
sbit K3=P3^6;                         //按键定义
sbit HE=P3^2;                         //霍尔传感器
sbit BUZZ=P1^2;                         //蜂鸣器
sbit relay=P1^4;                 //吹风继电器
sbit relay_w=P1^3;                 //加热继电器


//--定义全局变量
unsigned char code DIG_CODE[17]={
0x5f,0x44,0x9d,0xd5,0xc6,0xd3,0xdb,0x45,
0xdf,0xd7,0x77,0x7c,0x39,0x5e,0x79,0x8b};
//0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F的显示码
unsigned char DisplayData[8];
//用来存放要显示的8位数的值
//--声明全局变量--//

uchar control=5;
uchar servorTime=0;

unsigned char key_num;
unsigned char flag_d;
unsigned int count_HE;
unsigned int flag_HE;
unsigned char sec_bj=0,sec_gb=0,m=0;
int TH;
bit flag_js_gb=0;
bit flag_js_bj=0;
bit flag_bj=0;
//--声明全局函数--//
void LcdDisplay(int,unsigned char);
void DigDisplay();
void delay(unsigned int xms)         //延时函数
{
  unsigned int i;
  unsigned char j;
  for(i=0;i<xms;i++)
  for(j=0;j<110;j++);
}

void Delay_us(unsigned char t)
{
        while(--t);
}         //大约延时t*2+5us         超声波模块用

void keyscan()                                   //按键函数
{
        if(K1==0)                                   //设置按键按下
        {
                delay(20);                           //延时去抖
                if(K1==0)                           //再次判断按键按下
                {
                        key_num=!key_num;  //设置变量取反,也就是按一下设置键进入设置,再按一下就退出设置状态
                        while(K1==0)           //按键是否松开,没有松开就执行下面的程序,松开后跳出
                        {
                                if(key_num==1)                        //设置状态
                                LcdDisplay(TH*100,1);        //显示上限值
                                else
                                LcdDisplay(tvalue,0);        //否则显示正常值
                        }
                }
        }
        if(K2==0&&key_num==1)                          //设置状态时加按键按下
        {
                delay(20);                                          //延时去抖
                if(K2==0&&key_num==1)                  //设置状态时按键按下
                {
                        if(TH<98)                                  //上限如果小于98,就让变量加,也就是最大可以加到99
                        TH++;                                          //上限加
                        else                                          //否则
                        TH=20;                                          //上限值赋值20
                        while(K2==0) LcdDisplay(TH*100,1);           //按键松开后显示设置值
                }
        }
        if(K3==0&&key_num==1)                                         //注释同加按键
        {
                delay(20);
                if(K3==0)
                {
                        if(TH>1)                //大于1就减
                        TH--;
                        else
                        TH=99;
                        while(K3==0)LcdDisplay(TH*100,1);
                }
        }
}
/*******************************************************************************
* 函 数 名         : main
* 函数功能                   : 主函数
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/

void main()
{

        unsigned int time,distance;        
        uchar a=0,b=0,c=0,d=0,i=0;

        TH=30;                  //上电初始值30
        EX0=0;                  //关闭外部中断
        IT0=1;                  //下降沿有效
        EA=1;                  //打开中断系统总开关
        TMOD=0x11;          //定时器工作方式
        TH0=0x3c;
        TL0=0xb0;          //定时器0赋初值50ms
        TH1=0xff;
        TL1=0x9c;
        ET0=1;                  //T0中断允许
        ET1=1;
        TR0=1;                  //开启T0计时
        servorTime=0;
        Trig=0;
        Echo=0;
        while(1)          //进入while循环
        {

                Trig=1;
                Delay_us(5);
                Trig=0;
                while(Echo==0);                                
                a=TL0;
                b=TH0;
                while(Echo);
                c=TL0;
                d=TH0;
                time=(d-b)*256+(c-a);
                distance=(int)(time*0.017);                           //计算路程 单位为cm

                read_wendu();                         //读温度
                keyscan();                                 //按键扫描
                if(key_num==0)                         //判断状态,是否是设置状态
                LcdDisplay(tvalue,0);         //显示正常值
                else
                LcdDisplay(TH*100,1);         //显示设置值
                if(distance<=30)                                 //红外传感器有信号
                {

                        relay_w=0;                         //加热继电器打开
                        flag_js_bj=1;                 //计时报警标志位置1
                        flag_js_gb=0;                 //计时关闭标志位清零
                        EX0=1;                                 //关闭外部中断

                        if(distance<=20)                                        //如果距离小于30cm 蜂鸣器响
                        {
                                if(distance<=10)                                        //如果距离小于30cm 蜂鸣器响
                                {
                                        control=15;   //使舵机向正摆动
                                    servorTime=0;
                                    TR1=1;
                                    delay(200);
                                    TR1=0;
                                }
                                else
                                {
                                        control=12;   //使舵机向正摆动
                                    servorTime=0;
                                    TR1=1;
                                    delay(200);                                
                                    TR1=0;
                                }
                        }
                        else
                        {
                                  control=9;   //使舵机向正摆动
                            servorTime=0;
                            TR1=1;
                            delay(200);                        
                            TR1=0;
                        }

                }
                else                                         //没有信号
                {
                        flag_js_gb=1;                 //计时关闭标志位值1
                        flag_js_bj=0;                 //计时报警标志位清零

                        control=5;   //使舵机向右摆动
                    servorTime=0;
                    TR1=1;
                    delay(200);               
                    TR1=0;
                        delay(200);                        
                }


                if(flag_d&&flag_HE==1)         //温度是否小于设置值
                {
                        relay=0;                         //打开加热继电器
                        count_HE=0;
                        flag_HE=0;
                }
                else
                {
                        count_HE++;                          //霍尔的状态计数变量,计到一定时间(此值不精确,就是一个短延时的作用)关闭继电器
                        if(count_HE>10&&relay==0||flag_d==0)  //计到时间或者温度达到设置值
                        relay=1;                                         //关闭继电器
                }
        }
}

/*******************************************************************************
* 函 数 名         : LcdDisplay()
* 函数功能                   : LCD显示读取到的温度
* 输    入         : v
* 输    出         : 无
*******************************************************************************/

void LcdDisplay(int temp,unsigned char flag)          //lcd显示
{
           float tp;  
        unsigned char i,k;
        unsigned int j;
        if(temp< 0&&flag==0)                                //当温度值为负数
          {
                DisplayData[1] = 0x80;
                //因为读取的温度是实际温度的补码,所以减1,再取反求出原码
                temp=temp-1;
                temp=~temp;
                tp=temp;
                temp=tp*0.0625*100+0.5;        
                flag_d=1;                  //负温度值时肯定需要加热,所以变量为1
                //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点
                //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就
                //算由?.5,还是在小数点后面。

          }
         else if(flag==0)
          {                        
               
                tp=temp;
                temp=tp*0.0625*100+0.5;        
            DisplayData[1] = DIG_CODE[temp / 10000];
                if(temp/10000==0)
                DisplayData[1]=0x00;
                if(temp<TH*100)         //温度值小于设置值
                flag_d=1;                 //变量置1
                else                         //大于等于设置值时
                flag_d=0;                 //为0
        }
        if(flag==1)
        DisplayData[1] = DIG_CODE[15];
        DisplayData[2] = DIG_CODE[temp % 10000 / 1000];
        if(temp<1000)
        DisplayData[2]=0x00;
        DisplayData[3] = DIG_CODE[temp % 1000 / 100] | 0x20;
        DisplayData[4] = DIG_CODE[temp % 100 / 10];
        DisplayData[5] = DIG_CODE[temp % 10];
         for(k=0;k<8;k++)
        for(i=0;i<4;i++)
        {
                switch(i)         //位选,选择点亮的数码管,
                {
                        case(0):
                                  P2=0xef; break;//显示第0位
                        case(1):
                                  P2=0xdf; break;//显示第1位
                        case(2):
                                  P2=0xbf; break;//显示第2位
                        case(3):
                                  P2=0x7f; break;//显示第3位
                }
                GPIO_DIG=DisplayData[i+1];//发送段码
                j=50;                                                 //扫描间隔时间设定
                while(j--);        
                GPIO_DIG=0x00;//消隐
        }
}
void waibu() interrupt 0          //外部中断服务函数,也就是霍尔元件检测到信号就会有外部中断
{
        if(flag_d)                                  //温度是否小于下限,小于就进入
                {
                relay=0;                          //启动吹风继电器
                count_HE=0;                          //霍尔计数变量清零
                flag_HE=0;                          //霍尔标志位清零
                }
}
void T0_time() interrupt 1          //T0函数
{
        TH0=0x3c;
        TL0=0xb0;                                  //重新赋初值
        m++;                                  //每50ms加一次
        if(m>=1)                                  //加到20次就是1秒
        {        
                m=0;                                  //清零
                if(flag_js_gb==1)          //计时关闭标志位
                {
                        sec_gb++;                  //关闭计时秒变量++
                        if(sec_gb>=3)          //加到3秒
                        {
                                sec_gb=0;          //清零
                                sec_bj=0;
                                flag_js_bj=0; //清零
                                flag_bj=0;
                                relay_w=1;
                                relay=1;          //关闭两个继电器
                                EX0=0;                  //关闭外部中断
                        }        
                }
                if(flag_js_bj==1)          //计时报警标志位
                {
                        sec_bj++;                  //报警计时秒变量++
                        if(sec_bj>=5)          //加到60秒
                        {
                                sec_bj=0;
                                sec_gb=0;          //两个变量都清零
                                flag_js_gb=0; //关闭标志位清零
                                flag_bj=1;          //启动报警标志位
                        }
                }
                if(flag_bj==1)                  //报警标志位为1
                {
                        BUZZ=!BUZZ;                  //蜂鸣器取反闪烁报警
                }
                else                                  //没有进入报警
                {
                        BUZZ=1;                          //关闭蜂鸣器
                }
        }
}
void T1_int(void) interrupt 3{   //产生舵机所需要的脉冲
  TH1=0xff;
  TL1=0x9c;
  servorTime++;
  if(servorTime<=control)
   servorControl=1;
  else
   servorControl=0;
   if(servorTime>=200)
   servorTime=0;
}

回复

使用道具 举报

ID:515826 发表于 2022-4-1 16:04 | 显示全部楼层
超声波模块计算距离的时候用到定时器0,但是程序还要一个定时器来进中断怎么办?定时器1给舵机用了
回复

使用道具 举报

ID:515826 发表于 2022-4-1 16:07 | 显示全部楼层
为什么定时器0的中断进不去,可是如果缩短定时器1的中断的时间舵机就不能启动怎么办?
回复

使用道具 举报

ID:515826 发表于 2022-4-1 16:40 | 显示全部楼层
进定时器0中断里的关闭标志位的那个延时三秒不行咋搞?
回复

使用道具 举报

ID:121859 发表于 2022-4-1 17:51 | 显示全部楼层
超声波测距用一个定时器就可以了。使用过程中如果定时器不够用,也可以分时使用的方法来实现。
回复

使用道具 举报

ID:515826 发表于 2022-4-1 18:11 | 显示全部楼层
zhxiufan 发表于 2022-4-1 17:51
超声波测距用一个定时器就可以了。使用过程中如果定时器不够用,也可以分时使用的方法来实现。

这个分时使用要怎么写 通过控制TR0实现码?
回复

使用道具 举报

ID:161164 发表于 2022-4-1 18:18 来自手机 | 显示全部楼层
liguohan 发表于 2022-4-1 16:04
超声波模块计算距离的时候用到定时器0,但是程序还要一个定时器来进中断怎么办?定时器1给舵机用了

那个中断是用来干什么滴?
回复

使用道具 举报

ID:515826 发表于 2022-4-1 18:33 | 显示全部楼层
lkc8210 发表于 2022-4-1 18:18
那个中断是用来干什么滴?

就是计时超过一分钟蜂鸣器响,还有超声波关闭后两个继电器延时三秒后关闭
回复

使用道具 举报

ID:161164 发表于 2022-4-2 09:38 来自手机 | 显示全部楼层
liguohan 发表于 2022-4-1 18:33
就是计时超过一分钟蜂鸣器响,还有超声波关闭后两个继电器延时三秒后关闭

可以用定时器1的中断啊~
每次进入中断就是100us
进入10000次就是一秒
然后用这个一秒又可以得出三秒和一分钟
回复

使用道具 举报

ID:507641 发表于 2022-4-2 09:57 | 显示全部楼层
你定时器1没开启
回复

使用道具 举报

ID:515826 发表于 2022-4-2 10:52 | 显示全部楼层
lkc8210 发表于 2022-4-2 09:38
可以用定时器1的中断啊~
每次进入中断就是100us
进入10000次就是一秒

定时器1已经给舵机用了
为什么舵机在用定时器1的时候定时器0好像不能用了,屏蔽1的时候0就好了
回复

使用道具 举报

ID:515826 发表于 2022-4-2 10:54 | 显示全部楼层

开了 在后面用舵机的时候开了
回复

使用道具 举报

ID:515826 发表于 2022-4-2 11:00 | 显示全部楼层
lkc8210 发表于 2022-4-2 09:38
可以用定时器1的中断啊~
每次进入中断就是100us
进入10000次就是一秒

有说是定时器初始化的时候1把0的参数破坏了,也有说是方式没设置好,咋弄啊帮我看一下
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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