美文网首页
单片机小白学习之路(二十九)---EPROOM代码编写(二)

单片机小白学习之路(二十九)---EPROOM代码编写(二)

作者: 飞向深空 | 来源:发表于2018-09-23 19:56 被阅读0次

代码编写(二):

注意:I2C和EPROOM是两个东西,EEPROM (Electrically Erasable Programmable read only memory),带电可擦可编程只读存储器--一种掉电后数据不丢失的存储芯片。 EEPROM 可以在电脑上或专用设备上擦除已有信息,重新编程。一般用在即插即用。而单片机和EEPROM的通讯方式就是I2C协议,EEPROM用来存储数据而I2C就是个通讯协议


1、EEPROM写数据流程
第一步,首先是I2C的起始信号,接着跟上首字节,也就是我们前边讲的I2C的器件地
址(EERPOM),并且在读写方向上选择“写”操作。
第二步,发送数据的存储地址。我们24C02一共256个字节的存储空间,地址从0x00到0xFF,我们想把数据存储在哪个位置,此刻写的就是哪个地址。
第三步,发送要存储的数据第一个字节,第二个字节......注意在写数据的过程中,EEPROM每个字节都会回应一个“应答位0”,来告诉我们写EEPROM数据成功,如果没有回应答位,说明写入不成功。
在写数据的过程中,每成功写入一个字节,EEPROM存储空间的地址就会自动加1,当加到0xFF后,再写一个字节,地址会溢出又变成了0x00。


void At24c02Write(unsigned char addr, unsigned char dat)   //往24c02(EEPROM)的一个地址写入一个数据
{
    I2CStart();
    I2cSendByte(0xa0);  //发送EEPROM所在地址
    I2cSendByte(addr);  //发送要写入的内存地址(是写入EEPROM,在EEPROM里的地址)
    I2cSendByte(dat);   //发送数据
    I2CStop();
}

I2总线在操控器件时首先要先发送器件(24c02)的地址,24景列的EEPROM也不列外,在每次读写命令前发送一个器件地址和读写标志,也可称为器件录址

24C02
地址

因为E0, E1, E2被接地了,而地址的高四位又被固定成1010 所以24c02 的地址是0xa0(是写模式时,读模式是0xa1)


2、EEPROM读数据流程
第一步,首先是I2C的起始信号,接着跟上首字节,也就是我们前边讲的I2C的器件地
址(EERPOM),并且在读写方向上选择“写”操作。这个地方可能有同学会诧异,我们明明是读数据为何方向也要选“写”呢?刚才说过了,我们24C02一共有256个地址,我们选择写操作,是为了把所要读的数据的存储地址先写进去,告诉EEPROM我们要读取哪个地址的数据。这就如同我们打电话,先拨总机号码(EEPROM器件地址),而后还要继续拨分机号码(数据地址),而拨分机号码这个动作,主机仍然是发送方,方向依然是“写”。
第二步,发送要读取的数据的地址,注意是地址而非存在EEPROM中的数据,通知EEPROM我要哪个分机的信息。
第三步,重新发送I2C起始信号和器件地址,并且在方向位选择“读”操作。
这三步当中,每一个字节实际上都是在“写”,所以每一个字节EEPROM都会回应一个“应答位0”。
第四步,读取从器件发回的数据,读一个字节,如果还想继续读下一个字节,就发送一个“应答位ACK(0)”,如果不想读了,告诉EEPROM,我不想要数据了,别再发数据了,那就发送一个“非应答位NACK(1)”


unsigned char At24c02Read(unsigned char addr)
{
    unsigned char num;
    I2CStart();
    I2cSendByte(0xa0);  //发送EEPROM(24c02)器件所在地址,此时EEPROOM是写指令因为要先写入读取的地址
    I2cSendByte(addr); //发送要读取的地址,该地址也是在EEPROM内
    I2CStart();
    I2cSendByte(0xa1); //再发送一遍EEPROM的地址,此时是读指令
    num = I2cReadByte();    //用num接收读取到的指令
    I2CStop();
    return num;
}

梳理一下几个要点:A、在本例中单片机是主机,24C02是从机;B、无论是读是写,SCL始终都是由主机控制的;C、写的时候应答信号由从机给出,表示从机是否正确接收了数据;D、读的时候应答信号则由主机给出,表示是否继续读下去


名字是I2c.h的头文件
#ifndef _iic_H  //if not define
#define _iic_H   //为了源文件方便调用

#include <reg52.h>

sbit SCL=P2^1;
sbit SDA=P2^0;

void I2CStart();
void I2CStop();
unsigned char I2cSendByte(unsigned char dat);
unsigned char I2cReadByte();
unsigned char At24c02Read(unsigned char addr);
void At24c02Write(unsigned char addr, unsigned char dat);

#endif

单片机运行目标: 系统运行时,数码管后4位显示0,按K1将数据写入到EEPROM内保存,按K2显示数据清零,按K3读取EEPROM内保存的数据,按K4显示数据加1。最大能写入的数据是255。

#include "reg52.h"
#include <intrins.h>
#include "iic.h"


typedef unsigned char u8;
typedef unsigned int u16;

sbit LSA = P2^2;
sbit LSB = P2^3;
sbit LSC = P2^4;

sbit k1 = P1^4;
sbit k2 = P1^6;
sbit k3 = P3^2;
sbit k4 = P1^7;

char num = 0;
u8 disp[4];
u8 code smgduan[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

void delay(u16 i) //延时函数
{
    while(i--);
}

void Keypros()  //按键处理函数
{
    if(k1==0){
        delay(1000); //消抖
        if(k1==0){
            At24c02Write(1,num);
        }
        while(!k1);
    }
    if(k2==0){
        delay(1000);
        if(k2==0){
            num=0;
        }
        while(!k2);
    }
    if(k3==0){
        delay(1000);
        if(k3==0){
            num=At24c02Read(1);   //读取EEPROM地址1内的数据保存在num中  
        }
        while(!k3);
    }
    if(k4==0){
        delay(1000);
        if(k4==0){
            num++;
            if(num>255)num=0;
        }
        while(!k4);
    }
}

void datapros()  //数据处理函数
{
    disp[0] = smgduan[num/1000]; //取数据的千位
    disp[1] = smgduan[num%1000/100]; //取百位
    disp[2] = smgduan[num%1000%100/10]; //十位
    disp[3] = smgduan[num%1000%100%10]; // 个位
}

void DigDisplay()
{
    u8 i;
    for(i=0;i<4;i++){
        switch(i){
            case(0):
                LSA=0;LSB=0;LSC=0; break;//显示第0位
            case(1):
                LSA=1;LSB=0;LSC=0; break;//显示第1位
            case(2):
                LSA=0;LSB=1;LSC=0; break;//显示第2位
            case(3):
                LSA=1;LSB=1;LSC=0; break;//显示第3位
        }
        P0 = disp[i]; //发送数据
        delay(100);  //间隔一段时间扫描
        P0 = 0x00; //消隐       
    }
}

void main()
{   
    while(1)
    {
        Keypros();   //按键处理函数
        datapros();  //数据处理函数
        DigDisplay();//数码管显示函数      
    }       
}

相关文章

网友评论

      本文标题:单片机小白学习之路(二十九)---EPROOM代码编写(二)

      本文链接:https://www.haomeiwen.com/subject/kuvxoftx.html