蓝桥杯2024/1/26-----AT24C02笔记

每次建好工程文件夹,里边包含User(放工程文件,mian.c,可以在这里写如同我这个文章的文本文档)、Driver(存放底层文件如Led.c,Led.h等)
新建的工程先搭建框架,可以先书写底层函数(此次书写了五个函数并包含相应的头文件共十个底层文件)


底层函数内容:

1.初始化底层驱动专用文件

比如先用3个IO口控制74HC138译码器,控制Y4为低电平;当Y4为低电平时,或非门74HC02控制Y4C为高电平,使74HC573的OE端口有效,OE端口有效时,可使用P0口控制LED的亮灭。
可以去多了解74HC138译码器,74HC02或非门,74HC573八路输出透明锁存器的相关内容会更好理解
#include <Init.h>

//关闭外设
void System_Init()
{
    P0 = 0xff;
    P2 = P2 & 0x1f | 0x80;
    P2 &= 0x1f;
    P0 = 0x00;
    P2 = P2 & 0x1f | 0xa0;
    P2 &= 0x1f;
}
//头文件
#include <STC15F2K60S2.H>
void System_Init();

2.Led底层驱动专用文件

与初始化底层驱动专用文件同理,需要了解对应的锁存器控制,可以在使用的芯片数据手册查看
#include <Led.h>

void Led_Disp(unsigned char addr,enable)//LED
{
    static unsigned char temp = 0x00;
    static unsigned char temp_Old = 0xff;
    if(enable)
        temp |=0x01 << addr;
    else
        temp&= ~ (0x01 << addr);
    if(temp != temp_Old)
    {
        P0 = ~ temp;
        P2 = P2 & 0x1f | 0x80;
        P2 &= 0x1f;
        temp_Old = temp;
    }
}
void Beep(unsigned char flag)//蜂鸣器
{
    static unsigned char temp = 0x00;
    static unsigned char temp_Old = 0xff;
    if(flag)
        temp |=0x40 ;
    else
        temp &= ~ 0x40 ;
    if(temp != temp_Old)
    {
        P0 = ~ temp;
        P2 = P2 & 0x1f | 0xa0;
        P2 &= 0x1f;
        temp_Old = temp;
    }
}
void Relay(unsigned char flag)//继电器
{
    static unsigned char temp = 0x00;
    static unsigned char temp_Old = 0xff;
    if(flag)
        temp |= 0x10 ;
    else
        temp &= ~ 0x10 ;
    if(temp != temp_Old)
    {
        P0 = ~ temp;
        P2 = P2 & 0x1f | 0xa0;
        P2 &= 0x1f;
        temp_Old = temp;
    }
}

//头文件
#include <STC15F2K60S2.H>
void Led_Disp(unsigned char addr,enable);

3.按键底层驱动专用文件

(板子上的按键从按键4开始到按键19,可根据实际硬件修改)
#include <Key.h>

unsigned char Key_Read()
{
    unsigned char temp = 0;
    P44 = 0;P42 = 1; P35 = 1;P34 = 1;//这个仿真没有P4口,不适用,但是实际运行使用这个
    P37 = 0; P36 = 1; P35 = 1; P34 = 1;
    if(P33 == 0) temp = 4;
    if(P32 == 0) temp = 5;
    if(P31 == 0) temp = 6;
    if(P30 == 0) temp = 7;
    P37 = 1; P36 = 0; P35 = 1; P34 = 1;
    if(P33 == 0) temp = 8;
    if(P32 == 0) temp = 9;
    if(P31 == 0) temp = 10;
    if(P30 == 0) temp = 11;
    P37 = 1; P36 = 1; P35 = 0; P34 = 1;
    if(P33 == 0) temp = 12;
    if(P32 == 0) temp = 13;
    if(P31 == 0) temp = 14;
    if(P30 == 0) temp = 15;
    P37 = 1; P36 = 1; P35 = 1; P34 = 0;
    if(P33 == 0) temp = 16;
    if(P32 == 0) temp = 17;
    if(P31 == 0) temp = 18;
    if(P30 == 0) temp = 19;
    return temp;
    
}
//头文件
#include <STC15F2K60S2.H>

unsigned char Key_Read();

4.数码管底层驱动专用文件

#include <Seg.h>

unsigned char Seg_Dula[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf};//数码管段码储存数组
unsigned char Seg_Wela[] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//数码管位码储存数组

void Seg_Disp(unsigned char wela,dula,point)
{
    P0 = 0xff; //
    P2 = P2 & 0x1f |0xe0;
    P2 &= 0x1f;
    P0 = Seg_Wela[wela];
    P2 = P2 & 0x1f |0xc0;
    P2 &= 0x1f;
    P0 = Seg_Dula[dula];
    if(point)
        P0 &= 0x7f;
    P2 = P2 & 0x1f |0xe0;
    P2 &= 0x1f;
}
//头文件
#include <STC15F2K60S2.H>

void Seg_Disp(unsigned char wela,dula,point);

5.IIC总线驱动程序文件

/*
  程序说明: IIC总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台 8051,12MHz
  日    期: 2011-8-9
*/

#include "iic.h"


#include "intrins.h"

#define DELAY_TIME 5

#define Photo_Res_Channel 0x41
#define Adj_Res_Channel 0x43


//总线引脚定义


sbit SDA = P2^1;  /* 数据线 */
sbit SCL = P2^0;  /* 时钟线 */

void IIC_Delay(unsigned char i)
{
    do{_nop_();}
    while(i--);        
}

//总线启动条件


void IIC_Start(void)
{
    SDA = 1;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 0;
    IIC_Delay(DELAY_TIME);
    SCL = 0;    
}

//总线停止条件


void IIC_Stop(void)
{
    SDA = 0;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//发送应答


void IIC_SendAck(bit ackbit)
{
    SCL = 0;
    SDA = ackbit;                      // 0:应答,1:非应答
    IIC_Delay(DELAY_TIME);
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SCL = 0; 
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//等待应答


bit IIC_WaitAck(void)
{
    bit ackbit;
    
    SCL  = 1;
    IIC_Delay(DELAY_TIME);
    ackbit = SDA;
    SCL = 0;
    IIC_Delay(DELAY_TIME);
    return ackbit;
}

//通过I2C总线发送数据


void IIC_SendByte(unsigned char byt)
{
    unsigned char i;

    for(i=0; i<8; i++)
    {
        SCL  = 0;
        IIC_Delay(DELAY_TIME);
        if(byt & 0x80) SDA  = 1;
        else SDA  = 0;
        IIC_Delay(DELAY_TIME);
        SCL = 1;
        byt <<= 1;
        IIC_Delay(DELAY_TIME);
    }
    SCL  = 0;  
}

//从I2C总线上接收数据


unsigned char IIC_RecByte(void)
{
    unsigned char i, da;
    for(i=0; i<8; i++)
    {   
        SCL = 1;
    IIC_Delay(DELAY_TIME);
    da <<= 1;
    if(SDA) da |= 1;
    SCL = 0;
    IIC_Delay(DELAY_TIME);
    }
    return da;    
}

//函数名:ADC转换函数


//入口参数:要进行转换的通道控制位
//返回值:ADC转换的数值
//函数功能:对指定的通道进行ADC转换,函数返回转换的数值
unsigned char Pcf8591_Adc(unsigned char channel_num_contrl)
{
    unsigned char temp;
    
    IIC_Start();//发送开启信号
    IIC_SendByte(0x90);//选择PCF8591芯片,确定写的模式
    IIC_WaitAck();//等待PCF8591反馈
    
    IIC_SendByte(channel_num_contrl);//确定要转换的通道(顺便,使能DA转换)
    IIC_WaitAck();//等待PCF8591反馈    
    
    IIC_Start();//发送开启信号
    IIC_SendByte(0x91);//选择PCF8591芯片,确定读的模式
    IIC_WaitAck();//等待PCF8591反馈    
        
    temp = IIC_RecByte();//接收数据
    IIC_SendAck(1);//选择不应答
    IIC_Stop();//停止发送
    
    return temp;

}

//函数名:DAC转换函数


//入口参数:要进行转换的数值
//返回值:无
//函数功能:对入口参数要转换的DA数据进行转换
void Pcf8591_Dac(unsigned char trans_dat)
{
    IIC_Start();//发送开启信号
    IIC_SendByte(0x90);//选择PCF8591芯片,确定写的模式
    IIC_WaitAck();//等待PCF8591反馈
    
    IIC_SendByte(0x41);//使能DA转换(随便写通道编号,不影响,主要的功能是使能DA)
    IIC_WaitAck();//等待PCF8591反馈        

    IIC_SendByte(trans_dat);//将待转换的数据发送出去
    IIC_WaitAck();//等待PCF8591反馈    
    IIC_Stop();//停止发送    

}

//函数名:写EEPROM函数


//入口参数:需要写入的字符串,写入的地址(务必为8的倍数),写入数量
//返回值:无
//函数功能:向EERPOM的某个地址写入字符串中特定数量的字符。
void EEPROM_Write(unsigned char* EEPROM_String, unsigned char addr, unsigned char num)
{
    IIC_Start();//发送开启信号
    IIC_SendByte(0xA0);//选择EEPROM芯片,确定写的模式
    IIC_WaitAck();//等待EEPROM反馈
    
    IIC_SendByte(addr);//写入要存储的数据地址
    IIC_WaitAck();//等待EEPROM反馈        

    while(num--)
    {
        IIC_SendByte(*EEPROM_String++);//将要写入的信息写入
        IIC_WaitAck();//等待EEPROM反馈        
        IIC_Delay(200);    
    }
    IIC_Stop();//停止发送    
}


//函数名:读EEPROM函数


//入口参数:读到的数据需要存储的字符串,读取的地址(务必为8的倍数),读取的数量
//返回值:无
//函数功能:读取EERPOM的某个地址中的数据,并存放在字符串数组中。
void EEPROM_Read(unsigned char* EEPROM_String, unsigned char addr, unsigned char num)
{
    IIC_Start();//发送开启信号
    IIC_SendByte(0xA0);//选择EEPROM芯片,确定写的模式
    IIC_WaitAck();//等待EEPROM反馈
    
    IIC_SendByte(addr);//写入要读取的数据地址
    IIC_WaitAck();//等待EEPROM反馈        

    IIC_Start();//发送开启信号
    IIC_SendByte(0xA1);//选择EEPROM芯片,确定读的模式
    IIC_WaitAck();//等待EEPROM反馈    
    
    while(num--)
    {
        *EEPROM_String++ = IIC_RecByte();//将要写入的信息写入
        if(num) IIC_SendAck(0);//发送应答
            else IIC_SendAck(1);//不应答
    }
    
    IIC_Stop();//停止发送    
}


//头文件


# include "STC15F2K60S2.H"


void IIC_Start(void); 
void IIC_Stop(void);  
bit IIC_WaitAck(void);  
void IIC_SendAck(bit ackbit); 
void IIC_SendByte(unsigned char byt); 
unsigned char IIC_RecByte(void); 

//函数名:ADC转换函数
//入口参数:要进行转换的通道控制位
//返回值:ADC转换的数值
//函数功能:对指定的通道进行ADC转换,函数返回转换的数值
unsigned char Pcf8591_Adc(unsigned char channel_num_contrl);


//函数名:DAC转换函数
//入口参数:要进行转换的数值
//返回值:无
//函数功能:对入口参数要转换的DA数据进行转换
void Pcf8591_Dac(unsigned char trans_dat);

//函数名:写EEPROM函数
//入口参数:需要写入的字符串,写入的地址(务必为8的倍数),写入数量
//返回值:无
//函数功能:向EERPOM的某个地址写入字符串中特定数量的字符。
void EEPROM_Write(unsigned char* EEPROM_String, unsigned char addr, unsigned char num);


//函数名:读EEPROM函数
//入口参数:读到的数据需要存储的字符串,读取的地址(务必为8的倍数),读取的数量
//返回值:无
//函数功能:读取EERPOM的某个地址中的数据,并存放在字符串数组中。
void EEPROM_Read(unsigned char* EEPROM_String, unsigned char addr, unsigned char num);

工程主函数内容:

1.头文件声明(把需要用到的头文件添加进来)

/*头文件声明区*/

#include <STC15F2K60S2.H>
#include <Init.h>
#include <Led.h>
#include <Key.h>
#include <Seg.h>
#include "iic.h"

2.变量声明(把需要用到的所有变量现在这里进行声明)

/* 变量声明区 */
unsigned char Key_Val,Key_Old,Key_Down,Key_Up;
unsigned char Seg_Pos;
unsigned char Key_Slow_Down;
unsigned char Seg_Slow_Down;
unsigned char Seg_Buf[8] = {10,10,10,10,10,10,10,10};
unsigned char Seg_Point[8] = {0,0,0,0,0,0,0,0};
unsigned char ucLed[8] ={0,0,0,0,0,0,0,0};
unsigned char dat[2] = {30,60};
unsigned char a = 200;//int型会溢出,要使用必须把高位和低位拆开

3.按键处理函数(在这里编写按键控制的函数)

/*键盘处理函数*/
void Key_Proc()
{
    if(Key_Slow_Down)return;
    Key_Slow_Down = 1;
    Key_Val = Key_Read();
    Key_Down = Key_Val & (Key_Val ^ Key_Old);
    Key_Up = ~Key_Val & (Key_Val ^ Key_Old);
    Key_Old = Key_Val;
    
    switch(Key_Down)
    {
        case 19:
            //dat[0] -= 10;
        a += 10;
        break;
        case 18:
                    dat[1] -= 10;
        break;
        case 17:
            EEPROM_Write(dat,0,2);
        break;
        case 16:
            EEPROM_Write(&a,0,1);
        break;
    }
}

4.信息处理函数(需要使用到到的函数进行简单的预处理)

/*信息处理函数*/
void Seg_Proc()
{
    if(Seg_Slow_Down)return;
    Seg_Slow_Down = 1;
//    
//    Seg_Buf[0] = dat[0] / 10;
//    Seg_Buf[1] = dat[0] % 10;
//    
//    Seg_Buf[6] = dat[1] / 10;
//    Seg_Buf[7] = dat[1] % 10;
    
    Seg_Buf[0] = a / 100 % 10;
    Seg_Buf[1] = a / 10 % 10;
    Seg_Buf[2] = a % 10;

    Seg_Buf[6] = dat[1] / 10;
    Seg_Buf[7] = dat[1] % 10;
}


5.其他函数(其他编写的函数,在这里书写会比较方便理解)

/*其他函数*/
void Led_Proc()
    
{
    Beep(1);
}

6.定时器0中断初始化函数

(这个可以使用STC的定时器计算那里生成c代码,后面要自己添加ET0,EA打开中断)
/*定时器0初始化函数*/
void Timer0Init(void)        //1毫秒@12.000MHz
{
    AUXR &= 0x7F;        //定时器时钟12T模式
    TMOD &= 0xF0;        //设置定时器模式
    TL0 = 0x18;        //设置定时初值
    TH0 = 0xFC;        //设置定时初值
    TF0 = 0;        //清除TF0标志
    TR0 = 1;        //定时器0开始计时
    ET0 = 1;
    EA = 1;
}

7.定时器0中断服务函数

(为了定时执行特定的任务,如此处设置了定时的时间触发了数码管和LED产生特定反应)
/*定时器0中断服务函数*/
void Timer0Server() interrupt 1
{
    if(++Key_Slow_Down == 10)Key_Slow_Down = 0;
    if(++Seg_Slow_Down == 500)Seg_Slow_Down = 0;
    if(++Seg_Pos == 8)Seg_Pos = 0;
    Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);
    Led_Disp(Seg_Pos,ucLed[Seg_Pos]);
}

8.主函数Main(调用书写的函数实现所需的相应功能)

void main()
{
    //EEPROM_Read(dat,0,2);
    //EEPROM_Read(&a,0,1);//单变量要用&
    EEPROM_Read(&a,0,1);
    Sys_Init();
    Timer0Init();
    while(1)
        
    {
        Key_Proc();
        Seg_Proc();
        Led_Proc();
        
    }
}

关于AT24C02的相关资料:

这里的应用在内在结构是2k的,需要注意。

主要使用这个2k的就行,根据前面的信息可以知道A2-0都是接地为0,最后一位是0还是1,主要看我们是读还是写来修改。根据这个二进制转换为0xA0或0xA1,即为读这个芯片或写这个芯片。

有两种方式写入,每一页之内写8个字节,尽量从第0位,即最低位开始写。

三个入口参数,第二个参数传入的地址一定要是8的倍数,第三个参数为写入数据的数量,最好也是8的倍数。A0为写的模式

这也是有两种方式读取

一页最多只能写8个字节,这些是写入的类型所占的字节数

  • 15
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值