找回密码
 立即注册

QQ登录

只需一步,快速开始

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

用51单片同时测温度(DS18B20)和频率(外部中断测),单独运行两程序时没问题

[复制链接]
跳转到指定楼层
楼主
ID:79874 发表于 2020-2-3 10:43 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
void main()//主函数
{           
    delay1ms(1000);     
        lcd_init();//液晶显示初始化
        init_play();

while(1)
{        
     EA=0; //因DS18B20对时序要求高且受中断影响,故先关闭总中断
     read_temp();//读取温度
     ds1820disp();//显示
     CT_init();//定时计数器初始化     
     EA=1;//开总中断
         EX0=1;//允许外部中断
         IT0=1;//设置外部中断方式为下降沿触发
         P3=0xff;                                                        
         t0=(u*65536+x)*(12/22.1);//计算脉冲时间宽度(单位:ms)
         f=1000000/(2*t0);//计算频率                        
         if(f>8000&&tflag==1)         
          init_play1();         //显示Frozen
   else init_play2(); //显示Not frozen
}
}
这是主函数,初步怀疑是中断测频率时和温度传感器读取数据相影响,怎么解决 ?
方法1:读频率实时性要求不高的话,就开这个关那个,轮流来,其他没招了
先测1秒温度,然后测1秒频率,再测一秒温度?
方法2:我给你个参考程序,也是单总线的数据采集(时钟11.0592)。
在你的主循环中不要关闭中断,调用读温度时,有校验码确定数据的有效性(如果读温度程序中间有中断,数据可能会是无效的)。
#include <INTRINS.H>
#include "public.h"

sbit DS2401Bus  = P3^5;

//DS2401.c
//  首先对单总线发复位:
//        总线保持低电平超过480us;总线上的所有器件将复位
//        主机释放总线,并进入接收模式
//        从机等待15-60us,接着拉低总线60-240us,以产生应答脉冲
//    写0x33H命令: 仅适合于单节点(读ROM[0x33]命令)
//                  所有写(0或1)时隙至少需要60us 且在两次独立的写时隙之间至少需要1us的恢复时间
//                  两种写时隙均起始于主机拉低总线
//                          写1时隙: 主机在拉低总线后接着必须在15us之内释放总线,由5k上拉电阻将总线拉至高电平
//                           写0时隙: 主机拉低总线后只需在整个时隙期间保持低电平即可至少60us
//                           -- 在写时隙起始后15-60us期间,单总线器件采样总线电平状态(0或1)
//           读时隙
//                   器件仅在主机发出读时隙时才向主机传输数据。所以在主机发出读数据命令后必须马上产生读时隙
//                  所有读时隙至少需要60us 且在两次独立的读时隙之间至少需要1us的恢复时间
//                  每个读时隙都由主机发起,至少拉低总线1us
//                  在主机发起读时隙之后单总线器件才开始在总线上发送0或1
//                  从机发出的数据在起始时隙之后保持有效时间15us
//                  因而,主机在读时隙期间必须释放总线并且在时隙起始后的15us之内采样总线状态
//
#pragma ot(4,SPEED)

void delay_500us(void)   
{   
    unsigned char data i;         
    for(i = 0; i < 56; i++) ;   
}   
void delay_250us(void)   
{   
    unsigned char data i;         
    for(i = 0; i < 28; i++) ;   
}   
void delay_90us(void)   
{   
    unsigned char data i;         
    for(i = 0; i < 9; i++) ;   
}   
void delay_60us(void)   
{   
    unsigned char data i;         
    for(i = 0; i < 6; i++) ;   
}   

unsigned char InitDS2401(void)  //复位DS2401
{
        unsigned char tmp;
        DS2401Bus = 0;                   // 输出:0;总线保持低电平超过480us
        delay_500us();                  // 498us
        DS2401Bus = 1;                   // 释放总线,由5k上拉电阻将总线拉至高电平
        delay_60us();            // 64us,等待器件发出应答脉冲
        tmp = DS2401Bus;        // 检查应答脉冲
        delay_250us();                // 255us,延时240us以上
        if(tmp)                                // 读取数据
                return 0;
        else
                return 1;
}

void WriteDS2401(unsigned char d)//写2401命令
{
        unsigned char i;
        for(i=0;i<8;i++) {
                DS2401Bus = 0;                   // 主机在拉低总线后接着必须在15us之内释放总线
                _nop_(); _nop_(); _nop_();        // 每个nop估计耗时 1.085us
                if(d & 1) {                           // 输出:数据位
                        DS2401Bus = 1;
                }
                d >>= 1;
                delay_60us();                // 至少保持60us
                DS2401Bus = 1;            // 将总线拉至高电平, 至少需要1us的恢复时间
                _nop_();_nop_();_nop_();                  
        }
}

unsigned char ReadDS2401()         //读2401数据
{
        unsigned char i,d;
        for(i=0;i<8;i++) {
                d >>= 1;
                DS2401Bus = 0;                    // 至少拉低总线1us
                _nop_();_nop_();_nop_();            
                DS2401Bus = 1;            // 释放总线
                _nop_();_nop_();_nop_();_nop_();_nop_();
                if(DS2401Bus == 1) d |= 0x80;           // 读取数据
                delay_90us();                // 90us
        }
        return d;
}

unsigned char crctest()         //进行CRC校验
{
        unsigned char i1, i2, crc=0;
        for(i1=0; i1<8; i1++) {
                crc ^= DS2401IDBuf[i1];
                for(i2=0; i2<8; i2++) {
                        if (crc & 0x01)
                                crc = (crc >> 1) ^ 0x8C;
                        else
                                crc >>= 1;
                }
        }
        return (crc);
}

unsigned char ReadRS2401ID()         //读出DS2401的
{
        unsigned char i;
        if (!InitDS2401()) return(0);
        WriteDS2401(0x33);
        for(i=0;i<8;i++) DS2401IDBuf[i]=ReadDS2401();
        if (crctest() != 0) return(0);
        return(1);         //CRC校验成功
}

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:344780 发表于 2020-2-10 11:03 | 只看该作者
中断会影响dsb20的时序  dsb20对时许要求比较严格 我现在也遇到了这个问题
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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