标题: DS18B20怎么调用I2C通讯协议实现闸值的掉电存储 [打印本页]

作者: 菜鸟9    时间: 2023-6-28 21:01
标题: DS18B20怎么调用I2C通讯协议实现闸值的掉电存储
#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;
        }

望解答,急用!!!!!



作者: hange_v    时间: 2023-6-28 21:31
你学杂了吧,18b20和I2C是一块用的吗?
作者: 菜鸟9    时间: 2023-6-28 21:54
hange_v 发表于 2023-6-28 21:31
你学杂了吧,18b20和I2C是一块用的吗?

DS18B20单线肯定不能用啊,只不过我问的是存储的是闸值跟AC24C02的交换,就相当于数码管或者LCD(或者说是I/O口)与AC24C02的调用。我再说明白一点就是,怎么把改变的上下限存到AC24C02,又怎么取出来。
作者: wulin    时间: 2023-6-29 07:18
单纯就DS18B20温度上下限报警功能而言,不需要用24c02保存报警阈值。DS18B20 内部含有 EEPROM ,在系统掉电以后,它仍可保存分辨率及报警温度的设定值。只是网上大多数示例程序没有使用这一块。
作者: zhuls    时间: 2023-6-29 08:48
18B20与I2C,风马牛不相及~~
作者: 菜鸟9    时间: 2023-6-29 11:54
wulin 发表于 2023-6-29 07:18
单纯就DS18B20温度上下限报警功能而言,不需要用24c02保存报警阈值。DS18B20 内部含有 EEPROM ,在系统掉电 ...

大体思路是有了,谢谢!




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1