使用普中科技51单片机进行(I^2)C总线操作

/*C51单片机学习打卡*/

/*观看郭天祥老师教学视频,使用普中科技51单片机开发板进行学习(I^2)C总线操作*/

/*功能:在开发版上进行999秒计时,在单片机掉电情况下可以记录最后一秒的数据*/

#include
#define uint unsigned int
#define uchar unsigned char
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
sbit SDK=P2^0;
sbit SCL=P2^1;
void Delayms(uint xms);      //延时xms
void delay();      //延时几微秒
void Display(uchar x,uchar y);     //数码管显示函数,y为显示的数码管位数,x为显示的内容
void Initialize();            //初始化函数
void Start();               //起始函数
void Response();                  //应答函数
void Stop();                     //停止函数,表示全部数据已经发送完成
void Write_bite(uchar date);               //写一个字节的数据(一个字节八个位)
uchar Read_bite();                        //读取一个字节的数据(一个字节八个位)
void Write_address(uchar address,uchar date);      //写数据
uchar Read_address(uchar date);            //读数据


uchar num,hundred,ten,digit,write;
uint temp;
uchar code table[]={0x3f,0x06,0x5b,0x4f,
                      0x66,0x6d,0x7d,0x07,
                      0x7f,0x6f,0x77,0x7c,
                      0x39,0x5e,0x79,0x71};//显示0~F的值


void main()
{
    Initialize();
//    Write_address(2,5);
//    Delayms(10);
    temp=Read_address(2);
    if(temp>1)
        temp=0;
    while(1)
    {    
        hundred=temp/100;
        ten=temp%100/10;
        digit=temp%10;
        Display(hundred,4);
        Display(ten,3);
        Display(digit,2);
        if(write==1)
            {
                write=0;
                Write_address(2,temp);
            }
    }
     

}

 

     
void T0_Timer() interrupt 1          //每50ms溢出一次
{
    TH0=(65536-46080)/256;
    TL0=(65536-46080)%256;
    num++;
    if(num==20)
        {
            num=0;
        temp++;
            write=1;
            if(temp>999)
                temp=0;    
        }

}     

 void Display(uchar x,uchar y)
{
    switch(y)
    {
            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位
            case(4):
                LSA=0;LSB=0;LSC=1; break;//显示第4位
            case(5):
                LSA=1;LSB=0;LSC=1; break;//显示第5位
            case(6):
                LSA=0;LSB=1;LSC=1; break;//显示第6位
            case(7):
                LSA=1;LSB=1;LSC=1; break;//显示第7位    
    }
       P0=table[x];
    Delayms(10);
    P0=0x00;

}

void delay()      //延时几微秒

    ;
    ; 
}

void Delayms(uint xms)      //延时xms
{
    uint i;
    uchar j;
    for(i=xms;i>0;i--)
        for(j=110;j>0;j--);    
}

void Initialize()            //初始化函数
{
    SCL=1;                     //初始化时已经默认SCL与SDK为高电平,在之后的程序编写时,理应注意这点
    delay();                  //我觉得这个初始化完全没有意义,所需要的SCL和SDK的定义都会在其他子函数中,得到定义
    SDK=1;                      //最多只是为了确定一个初态
    delay();


    TMOD=0x01;                    //定时器0设定
    TH0=(65536-46080)/256;
    TL0=(65536-46080)%256;
    EA=1;                       //开总中断
    ET0=1;                       //开定时器0中断
    ET1=1;                        //启动定时器0
    TR0=1;
    
         
    temp=0;
    num=0;
}

void Start()               //开始信号
{
    SDK=1;                  //在SCL为高电平时,SDK由高电平变为低电平,即为开始信号
    delay();
    SCL=1;                  //增强程序的移植性,虽然初始化时已经将SDK和SCL拉为高电平
    delay();
    SDK=0;
    delay();

}

void Responses()                  //应答信号
{                                     //前提是SDK此时已经为高电平
    uchar i;                        
    SCL=1;                           //应答信号:在SCL时钟线是高电平的前提下,SDK数据线由高电平转化为低电平
    delay();                       //若已经完成数据写入操作,SDK理应被拉成高电平
    while((SDK==1)&&(i<250))       //SDK被拉为0,【或SDK没有被拉为0,而程序在此停留到i==250时表示应答(无应答表示默认收到数据)】
        i++;                       //注:按照本次设计,方括号内情况不应出现,但为了严谨性,故加以编写
    SCL=0;                           //将SCL拉为低电平,使下一步子函数操作更清晰
    delay();
}

void Stop()                     //停止信号,表示全部数据已经发送完成
{
    SDK=0;                     //当SCL为高电平时,SDK由低电平变为高电平,表示全部数据已经发送完毕,即停止信号
    delay();
    SCL=1;
    delay();
    SDK=1;
    delay();
}

void Write_byte(uchar date)               //写一个字节的数据(一个字节八个位)
{
    uchar temp,i;
    temp=date;
    for(i=8;i>0;i--)
    {                           //时钟信号为高点平时,SDK数据线上的信号不允许改变
        temp=temp<<1;           //而此时SDK是高电平还是低电平,并不影响
        SCL=0;                   //将时钟信号改为低电平,此时SDK数据线可以开始写入数据
        delay();
        SDK=CY;                    //SDK按位写入数据
        delay();
        SCL=1;                    //SCL时钟信号拉为高电平,关闭数据写入
        delay();

    }
    SCL=0;                       //注意:不明白为何要拉为低电平,应答信号时又拉成高电平,似是前后矛盾,可能是写入完成的标志
    delay();
    SDK=1;                       //恢复初始化状态,为其他子函数的编写提供便利
    delay();
}

uchar Read_byte()                        //读取一个字节的数据(一个字节八个位)
{
    uchar k,i;
    SCL=0;
    delay();
//    SDK=1;
//    delay();
    for(i=8;i>0;i--)
    {
        SCL=1;                          //当SCL置高时,SDK不可改变
        delay();
        k=(k<<1)|SDK;                  // 此时用“移位”和“按位或”的方法,将SDK上的八位数据一位位的复制给变量k
        SCL=0;
        delay();
    }
    return k;
}

void Write_address(uchar address,uchar date)      //由时序图得
{
    Start();
    Write_byte(0xa0);
    Responses();
    Write_byte(address);
    Responses();
    Write_byte(date);
    Responses();
    Stop();
}

uchar Read_address(uchar address)              //由时序图得
{
    uchar date;
    Start();
    Write_byte(0xa0);
    Responses();

    Write_byte(address);
    Responses();
    
    Start();
    Write_byte(0xa1);
    Responses();

    date=Read_byte();
    Stop();
    return date;
        
}
 

你可能感兴趣的:(使用普中科技51单片机进行(I^2)C总线操作)