基于STC89C52RC的IIC通信控制AT24C02芯片存储数据,以及定时器扫描数码管、独立按键控制

主函数,分别调用各个模块化

#include <REGX52.H>
#include "Timer0.h"
#include "Nixie.h"
#include "AT24C02.h"
#include "Delayms.h"
#include "Key.h"

#define uchar unsigned char
#define uint unsigned int

uchar Receive_Data,Write_Data = 0xaa;
uchar Keynumber;
void main()
{
    Timer0_Init();
    AT24C02_WriteData(1,Write_Data);  //写入数据,在第一个位置写入数据
    Delay1ms(5);  //写数据过程必须要延时5ms等待数据写入
    Receive_Data = AT24C02_ReadData(1);  //读取第一个位置的数据
    while(1)
    {
        P2 = Receive_Data;  //经过测试,的确能够读取到已存进去的值
        Keynumber = Get_Keynum();
        if(Keynumber){
            Nixie_SetBuf(1,9);   // 按下按键,在第一个位置显示数字9
        }
    }
}

void Timer0_Rountine()  interrupt 1
{
    static uchar T0count=0;
    TL0 = 0x66;        
    TH0 = 0xFC;    //设置定时初值
    T0count++;  //每次计数1ms
    if(T0count>=2){
        T0count=0;
        Nixie_Loop();     //使用定时器0扫描数码管
    }
}

—————————————————以下是各个模块———————————————————

延时函数:

、、、、、、、、、、、、、、、、、、头文件、、、、、、、、、、、、、、、、、、、、、、

#ifndef __DELAYMS_H__ 
#define __DELAYMS_H__

void Delay1ms(unsigned char xms);

#endif

、、、、、、、、、、、、、、、、、、、函数体、、、、、、、、、、、、、、、、、、、、、

#include <INTRINS.H>

void Delay1ms(unsigned char xms)        //@11.0592MHz 每次1ms
{
    unsigned char i, j;

    while(xms--)
    {
        _nop_();
        i = 2;
        j = 199;
        do
        {
            while (--j);
        } while (--i);
    }
}

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

数码管:

、、、、、、、、、、、、、、、、、、头文件、、、、、、、、、、、、、、、、、、、、、、

#ifndef __NIXIE_H__ 
#define __NIXIE_H__

void Nixie_SetBuf(unsigned char Location,Number);
void Nixie_Scan(unsigned char Location,Number);
void Nixie_Loop();

#endif

、、、、、、、、、、、、、、、、、、、函数体、、、、、、、、、、、、、、、、、、、、、

#include <REGX52.H>

//数据缓存区
unsigned char Nixie_Buf[9] = {0,10,10,10,10,10,10,10,10};

//段码表 ,第十个为灭,第十一个为“-”
unsigned char Nixie_Table[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40};

//外部调用函数
void Nixie_SetBuf(unsigned char Location,Number)
{
    Nixie_Buf[Location] = Number;  //外部传入要显示的位置以及数字,存储在缓存区
}

//显示函数
void Nixie_Scan(unsigned char Location,Number)
{
    P0 = 0x00; // 数码管消隐
    switch(Location){
        case 1 : {P2_4 = 1;P2_3 = 1;P2_2 = 1;break;}  //一定要记得写break跳出
        case 2 : {P2_4 = 1;P2_3 = 1;P2_2 = 0;break;} 
        case 3 : {P2_4 = 1;P2_3 = 0;P2_2 = 1;break;} 
        case 4 : {P2_4 = 1;P2_3 = 0;P2_2 = 0;break;} 
        case 5 : {P2_4 = 0;P2_3 = 1;P2_2 = 1;break;} 
        case 6 : {P2_4 = 0;P2_3 = 1;P2_2 = 0;break;} 
        case 7 : {P2_4 = 0;P2_3 = 0;P2_2 = 1;break;} 
        case 8 : {P2_4 = 0;P2_3 = 0;P2_2 = 0;break;} 
    }
    P0 = Nixie_Table[Number];
}

//定时器调用函数
void Nixie_Loop()
{
    static unsigned char i = 1;  //静态变量,保证每次调用时,i的值不会被再次赋值
    Nixie_Scan(i,Nixie_Buf[i]);
    i++;
    if(i >= 9) {i = 1;}
}

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

按键函数:

、、、、、、、、、、、、、、、、、、头文件、、、、、、、、、、、、、、、、、、、、、、

#ifndef __KEY_H__ 
#define __KEY_H__

unsigned char Get_Keynum();

#endif

、、、、、、、、、、、、、、、、、、、函数体、、、、、、、、、、、、、、、、、、、、、

#include <REGX52.H>
#include "Delayms.h"


unsigned char Get_Keynum()
{
    unsigned char Keynum;
    if(P3_1 == 0) {Delay1ms(20); while(P3_1 == 0); Delay1ms(20); Keynum = 1;}
    //延时20ms,以用来消除机械抖动
    if(P3_0 == 0) {Delay1ms(20); while(P3_0 == 0); Delay1ms(20); Keynum = 2;}
    if(P3_2 == 0) {Delay1ms(20); while(P3_2 == 0); Delay1ms(20); Keynum = 3;}
    if(P3_3 == 0) {Delay1ms(20); while(P3_3 == 0); Delay1ms(20); Keynum = 4;}
    return Keynum;  //返回按键值
}

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

I2C通信函数:

、、、、、、、、、、、、、、、、、、头文件、、、、、、、、、、、、、、、、、、、、、、

#ifndef __I2C_H__ 
#define __I2C_H__

void I2C_Start();
void I2C_Stop();
void I2C_SendByte(unsigned char Byte);
unsigned char I2C_ReceiveByte();
void I2C_SendAck(unsigned char AckBit);
unsigned char I2C_ReceiveAck();

#endif

、、、、、、、、、、、、、、、、、、、函数体、、、、、、、、、、、、、、、、、、、、、

#include <REGX52.H>

sbit I2C_SDA = P2^0;
sbit I2C_SCL = P2^1;

/*由于STC89C52RC的运行速度较慢,所以可以不必在上升沿(or下降沿)过程加延时*/

//开始
void I2C_Start()
{
    I2C_SDA = 1;
    I2C_SCL = 1;
    I2C_SDA = 0;  //scl为1期间,sda下降沿表示开始
    I2C_SCL = 0;   //每次操作完之后都要拉低时钟线
}

//停止
void I2C_Stop()
{
    I2C_SDA = 0;
    I2C_SCL = 1;
    I2C_SDA = 1;  //scl为1期间,sda上升表示结束
    I2C_SCL = 0;   
}

//主机向从机发送一个字节
void I2C_SendByte(unsigned char Byte)
{
    unsigned char i;
    for(i=0;i<8;i++)
    {
        I2C_SDA = Byte & (0x80>>i);  //将Byte的8位逐次取出

因为 将一个字节赋值给一个位的时候,只要字节值不为0x00,位就是1,所以可以通过将Byte或0x80的右移来得到Byte的各个位。
        I2C_SCL = 1;
        I2C_SCL = 0;
    }
}

//主机向从机接收一个字节
unsigned char I2C_ReceiveByte()
{
    unsigned char i,Byte=0x00;
    I2C_SDA = 1;  //保证此时数据线没有被拉低
    for(i=0;i<8;i++)
    {
        I2C_SCL = 1;
        if(I2C_SDA) {Byte |= (0x80>>i);} //与发送字节同理,如果sda为1,那么将Byte的对应位置1,否则,对应位依然为0
        I2C_SCL = 0;
    }
    return Byte;
}

//主机发送应答(主机从从机接收完数据后,向从机发送应答)
void I2C_SendAck(unsigned char AckBit)
{
    I2C_SDA = AckBit; //0表示应答,1表示非应答
    I2C_SCL = 1;
    I2C_SCL = 0;
}

//主机接收应答(主机向从机发送完数据后,接收应答)
unsigned char I2C_ReceiveAck()
{
    unsigned char AckBit;
    I2C_SDA = 1;   //保证此时数据线没有被拉低
    I2C_SCL = 1;
    AckBit = I2C_SDA;
    I2C_SCL = 0;
    return AckBit;
}

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

AT24C02(EEPROM)函数:

、、、、、、、、、、、、、、、、、、头文件、、、、、、、、、、、、、、、、、、、、、、

#ifndef __AT24C02_H__
#define __AT24C02_H__

void AT24C02_WriteData(unsigned char WordAddress,Data);
unsigned char AT24C02_ReadData(unsigned char WordAddress);

#endif

、、、、、、、、、、、、、、、、、、、函数体、、、、、、、、、、、、、、、、、、、、、

#include <REGX52.H>
#include "I2C.h"

#define AT24C02_ADDRESS 0xa0   //宏定义地址,可以通过查找芯片手册获取

//写入一个字节
void AT24C02_WriteData(unsigned char WordAddress,Data)  //第一个参数为字地址
{
    I2C_Start();
    I2C_SendByte(AT24C02_ADDRESS);  //指定接收器件的地址,也就是“跟谁通信”
    I2C_ReceiveAck();   //接收应答,返回值可以先不管
    I2C_SendByte(WordAddress); //写入字地址,也就是“数据要写在哪里”
    I2C_ReceiveAck();
    I2C_SendByte(Data);  //写入数据“写什么”
    I2C_ReceiveAck();
    I2C_Stop();  
}

//读取一个字节
unsigned char AT24C02_ReadData(unsigned char WordAddress) // 读哪里?输入字地址
{
    unsigned char Data;
    I2C_Start();
    I2C_SendByte(AT24C02_ADDRESS);  //指定接收器件的地址,“跟谁通信”
    I2C_ReceiveAck();
    I2C_SendByte(WordAddress); //写入字地址,也就是“数据要从哪里读”
    I2C_ReceiveAck();
    I2C_Start();     //此时开始读取数据 
    I2C_SendByte(AT24C02_ADDRESS | 0x01);  //最后一位为1,表示此时为读模式,为0则表示写模式
    I2C_ReceiveAck();
    Data = I2C_ReceiveByte();
    I2C_SendAck(1);  //1为不应答,主机无需向从机应答
    I2C_Stop();  
    return Data;
}

、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值