找回密码
 立即注册

QQ登录

只需一步,快速开始

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

DS18B20怎么调用I2C通讯协议实现闸值的掉电存储

[复制链接]
回帖奖励 20 黑币 回复本帖可获得 20 黑币奖励! 每人限 1 次
跳转到指定楼层
楼主
ID:1084388 发表于 2023-6-28 21:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#include <REGX51.H>
sbit I2C_SCL = P1^3;
sbit I2C_SDA = P1^4;

I2C:
//延时
void delay_us(unsigned char i)
{
        while(i--);
}

// 开始信号:在I2C_SCL时钟信号在高电平期间I2C_SDA信号产生一个下降沿
void I2C_Start()
{
        I2C_SDA=1;
        delay_us(1);
        I2C_SCL=1;
        delay_us(1);//保持时间>4.7us
        I2C_SDA=0;
        delay_us(1);//保持时间是>4us
        I2C_SCL=0;                       
        delay_us(1);               
}

//结束信号:在I2C_SCL时钟信号高电平期间I2C_SDA信号产生一个上升沿
void I2C_Stop()
{
        I2C_SDA=0;
        delay_us(1);
        I2C_SCL=1;
        delay_us(1);
        I2C_SDA=1;
        delay_us(1);               
}

//通过I2C发送一个字节。在I2C_SCL时钟信号高电平期间, 保持发送信号I2C_SDA保持稳定
unsigned char I2C_SendByte(unsigned char dat, unsigned char ack)
{
        unsigned char a = 0,b = 0;                       
        for(a=0; a<8; a++)//要发送8位,从最高位开始
        {
                I2C_SDA=dat>>7;         
                dat=dat<<1;//传输
                delay_us(1);
                I2C_SCL=1;
                delay_us(1);
                I2C_SCL=0;
                delay_us(1);       
        }
                I2C_SDA=1;
                delay_us(1);
                I2C_SCL=1;
                delay_us(1);
                while(I2C_SDA&&(ack==1))//等待应答
        {
                b++;
                if(b>255)         //如果超过255us没有应答发送失败,或者为非应答,表示接收结束
                {
                        I2C_SCL=0;
                        delay_us(1);
                        return 0;
                }
        }
        I2C_SCL=0;
        delay_us(1);
        return 1;       
}

// 使用I2c读取一个字节
unsigned char I2C_ReadByte()
{
        unsigned char a = 0,dat = 0;
        I2C_SDA = 1;//时序
        delay_us(1);       
        for(a=0; a<8; a++)//接收8个字节
        {
                I2C_SCL = 1;
                delay_us(1);       
                dat<<=1;
                dat|=I2C_SDA;
                delay_us(1);       
                I2C_SCL=0;
                delay_us(1);       
        }
        return dat;               
}

//往24c02的一个地址写入一个数据
void At24c02Write(unsigned char addr,unsigned char dat)
{
        I2C_Start();
        I2C_SendByte(0xa0,1);//发送写器件地址
        I2C_SendByte(addr,1);//发送要写入内存地址
        I2C_SendByte(dat,0);        //发送数据
        I2C_Stop();
}

// 读取24c02的一个地址的一个数据
unsigned char At24c02Read(unsigned char addr)
{
        unsigned char num;
        I2C_Start();
        I2C_SendByte(0xa0, 1); //发送写器件地址
        I2C_SendByte(addr, 1); //发送要读取的地址
        I2C_Start();
        I2C_SendByte(0xa1, 1); //发送读器件地址
        num=I2C_ReadByte(); //读取数据
        I2C_Stop();
        return num;       
}
这个I2C时序应该没写错吧,下面是我的掉电存储函数:
从主函数中截出来的
unsigned int shangxian=35;unsigned int xiaxian=10;
unsigned char set_st=0;
unsigned char As=0,Ds=0;//As是第二个按键(加一ADD)按下的次数,Ds是第三个按键(减一)按下的次数
//{
//        while(1)
//        {
//                if(set_st==0)                 //设置按键按下,等待
//                        while(1);
//                else if(set_st==1)//转到上限设置
//                                {
//                                        if(As--){
//                                                shangxian=shangxian+As;
//                                                At24c02Write(2,shangxian);
//                                        shangxian=At24c02Read(2);}
//                                        else if(Ds--){
//                                                shangxian=shangxian-Ds;
//                                                At24c02Write(3,shangxian);
//                                        shangxian=At24c02Read(3);}
//                                        }
//                        else if(set_st==2)//转到下限设置
//                                {
//                                        if(As--){
//                                                xiaxian=xiaxian+As;
//                                                At24c02Write(4,xiaxian);
//                                        xiaxian=At24c02Read(4);}
//                                        else if(Ds--){
//                                                xiaxian=xiaxian-Ds;
//                                                At24c02Write(5,xiaxian);
//                                        xiaxian=At24c02Read(5);}
//                                        }
//                        }
//}

而As的外部中断函数:
void Xint0 () interrupt 0//外部中断0------
{
        EX0=0;
        if(ADD==0&&set_st==1){//进入上限第二个按键按下,增大上限值
        do{
                display_anjian(shangxian,set_st);
        }
                while(ADD==0);//设置范围
        As++;
        shangxian=shangxian+1;
        if(shangxian>99)
                shangxian=99;}
        else if(ADD==0&&set_st==2)//进入下限第二个按键按下,增大下限值
        {
                do{
                        display_anjian(xiaxian,set_st);
                }
                        while(ADD==0);//设置范围
                xiaxian=xiaxian+1;
                if(xiaxian>shangxian)
                        xiaxian=shangxian;
        }

望解答,急用!!!!!


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

使用道具 举报

沙发
ID:190832 发表于 2023-6-28 21:31 | 只看该作者
你学杂了吧,18b20和I2C是一块用的吗?
回复

使用道具 举报

板凳
ID:1084388 发表于 2023-6-28 21:54 | 只看该作者
hange_v 发表于 2023-6-28 21:31
你学杂了吧,18b20和I2C是一块用的吗?

DS18B20单线肯定不能用啊,只不过我问的是存储的是闸值跟AC24C02的交换,就相当于数码管或者LCD(或者说是I/O口)与AC24C02的调用。我再说明白一点就是,怎么把改变的上下限存到AC24C02,又怎么取出来。
回复

使用道具 举报

地板
ID:213173 发表于 2023-6-29 07:18 | 只看该作者
单纯就DS18B20温度上下限报警功能而言,不需要用24c02保存报警阈值。DS18B20 内部含有 EEPROM ,在系统掉电以后,它仍可保存分辨率及报警温度的设定值。只是网上大多数示例程序没有使用这一块。
回复

使用道具 举报

5#
ID:69038 发表于 2023-6-29 08:48 | 只看该作者
18B20与I2C,风马牛不相及~~
回复

使用道具 举报

6#
ID:1084388 发表于 2023-6-29 11:54 | 只看该作者
wulin 发表于 2023-6-29 07:18
单纯就DS18B20温度上下限报警功能而言,不需要用24c02保存报警阈值。DS18B20 内部含有 EEPROM ,在系统掉电 ...

大体思路是有了,谢谢!
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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