基于普中A2实验板,ds18b20温度传感器与ds1302时钟芯片的冲突现象的探讨

这篇具有很好参考价值的文章主要介绍了基于普中A2实验板,ds18b20温度传感器与ds1302时钟芯片的冲突现象的探讨。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在普中板上进行写较综合的项目时,是否会出现温度传感器经常出错的问题,明明是严格按照时序图所编写的程序就是无法读出正确的值(全为0),或许温度底层在其他工程里能正常运行,而到了某些工程中却总是出错。这些就是我经常遇到的问题。

那么问题的根源是什么?如果在排除了温度传感器底层编写上的问题,那就如标题所说,是ds18b20温度传感器与ds1302冲突的原因,严格意义上来说,是在普中A2实验板上,才是这两个芯片冲突的原因。或许有人会觉得不可思议,甚至觉得我在胡说八道,两个相互独立的芯片怎么可能互相冲突。那在这就直接上代码,此处代码来源 weixin_68427965所发的问题

 
#include "reg52.h"
#include<intrins.h>
typedef unsigned char u8;  // x<=255
typedef unsigned int u16;
 
sbit DQ=P3^7;
sbit k1=P3^1; sbit k2=P3^0;
sbit LSA=P2^2;sbit LSB=P2^3;sbit LSC=P2^4;
sbit CLK=P3^6;sbit CE=P3^5;sbit IO_ds1302=P3^4;
 
void delay(u16 t) {while(t--);}
 
u8 code smgd[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,
    0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
 
unsigned char code read_addr[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
unsigned char code write_addr[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
//秒分时日周年
unsigned char  TIME[7]={0x00,0x00,0x00,0x01,0x01,0x01,0x00};
//0000年1月1日星期一00点00分00秒
unsigned char a[22];
 
 
void dtsmg(int i,int key,int num)
{
    LSA=i%2;
    LSB=(i/2)%2;
    LSC=i/4;
    if(key==0) P0=smgd[num];
    else  P0=key;
    delay(100);
    P0=0x00;
}
 
//DS1302写单字节
void DS1302_Write_Byte(unsigned dat)
{
    unsigned char i;
    for(i=0;i<8;i++)
    {
        IO_ds1302=dat&0x01;
        dat>>=1;
        CLK=1;
        _nop_();
        CLK=0;
        _nop_();
    }
}
//DS1302写入函数
void DS1302_Write(unsigned char addr,unsigned char dat)
{
    CE=0;
    _nop_();
    CLK=0;//拉低时钟,使CE(RST)能置高
    _nop_();
    CE=1;
    _nop_();
    DS1302_Write_Byte(addr);//写入地址
    DS1302_Write_Byte(dat);//操作地址数据
    CE=0;
    _nop_();
}
//DS1302读取单字节
unsigned char DS1302_Read_Byte()
{
    unsigned char i;
    unsigned char dat=0x00;
    for(i=0;i<8;i++)
    {
        dat>>=1;
        if(IO_ds1302) dat|=0x80;
        CLK=1;
        _nop_();
        CLK=0;
        _nop_();
    }
    return dat;
}
//DS1302读取函数 
unsigned char DS1302_Read(unsigned char addr)
{
    unsigned char data_a;
    CE=0;
    _nop_();
    CLK=0;
    _nop_();
    CE=1;
    _nop_();
    DS1302_Write_Byte(addr);
    _nop_();
    data_a=DS1302_Read_Byte();
    CE=0;
    _nop_();
    CLK=1;    //我也不知道这里为什么
    _nop_();
    IO_ds1302=0;
    _nop_();
    IO_ds1302=1;
    _nop_();
 
    return data_a;
}
 
void DS1302_Init()
{
    unsigned char i;
    DS1302_Write(0x8e,0x00);//关闭写保护
    for(i=0;i<7;i++)
    {
        DS1302_Write(write_addr[i],TIME[i]);//秒分时日月周年
    }DS1302_Write(0x8e,0x80);//打开写保护
}
 
void read_time()
{    char i;
    for(i=0;i<7;i++)
    {
        TIME[i]=DS1302_Read(read_addr[i]);
    }
}
 
 
//初始化 返回0位初始化成功
unsigned char Init_DS18B20()
{
    char x;
    DQ=0;
    delay(60);
    DQ=1;
    delay(2);
    x=DQ;
    delay(25);
    return x;
}
//写时序,写入一个字节
void Write_DS18B20(unsigned char dat)
{
    
    char i,x;
    DQ=1;//置位
    for(i=0;i<8;i++)
    {
        x=dat&0x01;
        DQ=0;
        DQ=x;
        dat>>=1;
        delay(10);
        DQ=1;//置位
        delay(1);
    }
 
    
}
 
//读时序,读取一个字节
unsigned char Read_DS18B20()
{
    
    unsigned char dat=0x00;
    char i,t;
    //DQ=1;
    for(i=0;i<8;i++)
    {    
        
        DQ=0;
        dat>>=1;
        DQ=1;
        t++;
        t++;
        if(DQ) dat|=0x80;
        delay(4);
        //DQ=1;     ???
    }return dat;
 
}
 
//读取温度
 int ReadTemperature()
{
    int temp=0;
    unsigned char tmh,tml;
    Init_DS18B20();
    delay(110);
    Write_DS18B20(0xcc);//跳过RAM
    Write_DS18B20(0x44);//温度转换
 
    Init_DS18B20();
    delay(110);
    Write_DS18B20(0xcc);
    Write_DS18B20(0xbe);//读取温度
 
    tml=Read_DS18B20();
    tmh=Read_DS18B20();
 
    temp=tmh;
    temp<<=8;
    temp|=tml;
 
    return temp;
 
}
 
void Trainsport_DS18B20(int temp)
{
    float tp;
    int i;
    u8 a[8]={0,0,0,0,0,0,0,0};
    if(temp<0)
    {
        a[7]=0x40;
        tp=~(temp-1);
        temp=tp*0.0625*100+0.5;
 
    }else
    {
        a[7]=0x00;
        tp=temp;
        temp=tp*0.0625*100+0.5;
    }
    a[2]=smgd[temp%10];
    a[3]=smgd[temp%100/10];
    a[4]=smgd[temp%1000/100];
    a[5]=smgd[temp%10000/1000];
    for(i=0;i<8;i++) dtsmg(i,a[i],16);
}
    
void main()
{
    //DS1302_Init();//这里注释掉初始化,如果不注释这一开始温度显示也为0000
    while(1)
    {
 
        Trainsport_DS18B20(ReadTemperature());
        if(k1==0)
        {
            if(k1==0)
            {    
                while(k2)
                {
                    read_time();
                    dtsmg(0,0,TIME[0]%16);
                    dtsmg(1,0,TIME[0]/16);
                    dtsmg(3,0,TIME[1]%16);
                    dtsmg(4,0,TIME[1]/16);
                    dtsmg(6,0,TIME[2]%16);
                    dtsmg(7,0,TIME[2]/16);
                    dtsmg(2,0x40,0);
                    dtsmg(5,0x40,0);
                }
            }
        }
 
        
    }
}

如运行结果所表示,在调用ds18b20底层前若运行过ds1302的代码,ds18b20所读出来的数据全是0,甚至会出现一开始能正常读,按键按下启用ds1302后ds18b20就立即出错了的情况。直接说解决方案:在ds1302底层函数中,在完成写入或读取的操作后,不要把CE使能口置0,或者在置0后重新置1,确保ds18b20函数调用时ds1302的CE口为1.

那么就会产生一个疑问,为什么两个独立的芯片会互相影响呢?事实上,两个引脚不复用的的芯片确实不会相互影响,而真正出问题的是普中A2实验板上的P3^7和P3^5引脚,从而使ds18b20与ds1302相互冲突。我们来做一个简单的实验,先把P3^7引脚置1,然后看看P3^5引脚的电平高低对P3^7的影响,如果P3^7为1,就点亮所有led,为0就都熄灭,代码如下:

#include <reg51.h>
sbit P37=P3^7;
sbit P35=P3^5;
sbit K1=P3^1;//K1按键
void main()
{
    P37=1;
    while(1)
    {
        if(K1==0)//K1按键按下
            P35=0;
        else     //K1按键释放
            P35=1;
        
        if(P37==1)
            P2=0x00;//LED点亮
        else
            P2=0xff;//LED熄灭
    }
}

在这个程序里,独立按键K1按下时P3^5就置0,不按下就是1。按理来说无论我们按键按不按下LED都应该是点亮的。而事实却是在按键K1不按下时LED点亮,K1按下时LED灭了!

如果我们把P3^7一开始置0呢?改完后无论按键是否按下led均熄灭。也就是在P3^5为0时,P3^7只能是0,反过来P3^7对P3^5却没有这个影响。而板子上P3^5接的是ds1302的CE使能端口,我们根据时序在用完ds1302的底层后会将CE置0,导致了连接P3^7的ds18b20无法正常使用。

这是板子的品控问题线路之间出错了吗?当我把同样的代码发同学时,现象跟上面描述的一模一样。那这就很玄学了,不过单片机玄学的事还少吗(狗头)。当我一头扎进stc89c52的参考手册里时,发现P3口有特殊的功能接口,这一发现让我兴奋起来,会不会是这个外部数据存储器搞的鬼,

基于普中A2实验板,ds18b20温度传感器与ds1302时钟芯片的冲突现象的探讨

然后兴奋地打开千度一查,“现在的芯片已经不接外部存储器了”,给我浇一头冷水。然后继续回来翻手册,发现51的IO有开漏输出功能。

基于普中A2实验板,ds18b20温度传感器与ds1302时钟芯片的冲突现象的探讨

会不会是IO口工作类型弄错了?然后继续兴奋的一查,stc89c51P3口默认上电为准双向口工作模式。又是一头冷水。然后就只能翻翻板子的原理图了,这一翻却找到了问题所在。

基于普中A2实验板,ds18b20温度传感器与ds1302时钟芯片的冲突现象的探讨

在板子里,P3^5口和P3^7口也连接到ET2046AD转换芯片上,翻开芯片手册一查,

基于普中A2实验板,ds18b20温度传感器与ds1302时钟芯片的冲突现象的探讨
基于普中A2实验板,ds18b20温度传感器与ds1302时钟芯片的冲突现象的探讨

P3^7口是AD芯片的数据输出端口,而P3^5口是片选信号,翻开时序图

基于普中A2实验板,ds18b20温度传感器与ds1302时钟芯片的冲突现象的探讨

不出所料,在CS置0时,DOUT自动置0,而CS置1时DOUT口为高阻状态不对P3^7口的电平造成影响,也就造成了P3^5引脚置0时P3^7引脚置为0,那么就破案了。由于普中A2实验板的P3^5和P3^7引脚在各自连接ds1302和ds18b20的同时连接了ET2046,由于ET2046芯片的原因,当P3^5引脚置0时P3^7引脚自动置为0,进而使板子上的ds18b20和ds1302冲突。文章来源地址https://www.toymoban.com/news/detail-510418.html

到了这里,关于基于普中A2实验板,ds18b20温度传感器与ds1302时钟芯片的冲突现象的探讨的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于51单片机多路温度检测proteus仿真 ds18b20

    本设计是基于51单片机多路温度检测proteus仿真_ds18b20(仿真+程序+原理图) 仿真图proteus 7.8 程序编译器:keil 4/keil 5 编程语言:C语言 设计编号:C0042 功能说明: 通过对多路DS18B20温度传感器的数据采集,实现8路/4路温度采集并将数值显示在LCD显示屏上; 通过按键设置温度报警

    2024年02月12日
    浏览(48)
  • 基于51单片机的DS18B20温度控制加热降温系统设计

    仿真图:proteus8.9以上 程序代码:KEIL4/KEIL5 原理图:AD 设计编号:A0007 结合实际情况,基于51单片机设计一个排队叫号系统设计。该系统应满足的功能要求为: 系统由51单片机、DS18B20温度传感器、LCD1602液晶显示屏、继电器、风扇、加热膜、按键、蜂鸣器组成。 可实现以下基本功能

    2023年04月09日
    浏览(79)
  • [stc89c52] DS18B20基于单总线协议的温度测量

    1.定义:主机和从机用一根总线进行通信,是一种半双工的通信方式,单线=时钟线+数据线+控制线( +电源线)。理想状况下一条总线上的从器件数量几乎不受数量限制。 2.特点:这是由达拉斯半导体公司推出的一项通信技术。它采用单根信号线,既可传输时钟,又能传输数据

    2024年02月10日
    浏览(53)
  • 017——DS18B20驱动开发(基于I.MX6uLL)

    目录 一、 模块介绍 1.1 简介 1.2 主要特点 1.3 存储器介绍 1.4 时序 1.5 命令 1.5.1 命令大全    1.5.2 命令使用 1.5.3 使用示例 1.6 原理图 二、 驱动程序 三、 应用程序 四、 测试         DS18B20 温度传感器具有线路简单、体积小的特点,用来测量温度非常简单,在一根通信线上

    2024年04月12日
    浏览(49)
  • DS18B20与单片机的通信、DS18B20采集温度、MODBUS协议、练习框架

    单总线数字温度计 异步的半双工的串行通信 测量范围从-55℃ ~ +125℃,增量值为0.5℃ 要用DS18B20采集温度,就要实现与单片机之间的通信,因此有两个问题 Bus master active low:主机执行低电平 DS1820 active low:DS18B20执行低电平 Both bus master and DS1820 active low:全都释放低电平 Resis

    2024年04月16日
    浏览(45)
  • 53、基于STC15W单片机的温度计(DS18B20)(Proteus仿真+程序)

          本设计由STC15W4K32S4单片机+DS18B20温度传感器+1602液晶显示模块+串口模块组成。 1、主控制器是STC15W4K32S4单片机 2、DS18B20温度传感器采集温度,精度0.1摄氏度 3、1602液晶显示温度。 4、测温范围-55~110摄氏度,误差±0.1℃ 5、温度值发送至串口助手显示。 Proteus软件: Proteus

    2024年02月03日
    浏览(67)
  • DS18B20测量温度

    一般在使用DS18B20时会按照以下步骤进行温度转换并读取: 1、主机发送复位脉冲 2、DS18B20响应 3、发送0xCC命令跳过ROM命令 4、发送功能命令 5、发送功能命令0x44启动温度转换 6、判断温度转换是否完成(为读取1Bit数据为1表示完成) 7、下一个初始化序列开始读取温度 8、然后按

    2023年04月08日
    浏览(44)
  • 【基于STM32F103C8T6的DS18b20温度检测系统】

    库函数是ST公司针对STM32系列微控制器提供的一套API,可以方便地实现各种功能。下面是一个基于STM32F103C8T6的温度检测系统的示例,使用了STM32F10x标准库函数。 硬件部分: - STM32F103C8T6微控制器 - 电源模块 - 温度传感器模块 软件部分: - Keil C编译器 - STM32F10x_StdPeriph_Driver库文件

    2024年01月20日
    浏览(49)
  • DS18B20使用说明

    基础介绍引脚介绍 DS18B20是单总线协议的典型代表,同时也是单总线协议最广泛的应用场景,是常用的数字温度传感器,其输出的是数字信号。具有体积小,硬件开销低,抗干扰能力强,精度高的特点。DS18B20数字温度传感器接线方便,封装成后可应用于多种场合。 DS18B20 的温

    2024年02月09日
    浏览(33)
  • stm32之DS18B20

            DS18B20与stm32之间也是通过单总线进行数据的传输的。单总线协议在DHT11中已经介绍过。虽说这两者外设都是单总线,但时序电路却很不一样,DS18B20是更为麻烦一点的。  举例(原码补码反码转换_原码反码补码转换_王小小鸭的博客-CSDN博客):  将这两个字节的数

    2024年02月10日
    浏览(40)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包