IIC-EEPROM代码部分

简介: IIC-EEPROM代码部分

60dbb42ebb6b46758889d17791814d4c.png

理解:数码管开始显示0(假设为a,a=0);在按下K3时+1(a=0+1=1);如果想保存,则按下K1,掉电不丢失;开电后,按下K2,读取存储的数据;按K4清除a. 注:a 最大值为255.


在keil内创建文件不能用中文


多个项目,分开保存,App表示单片机控制外部设备(包括独立按键,数码管,iic,24c02),User表示主函数部分,Public表示所有函数都要有的部分(reg52.h 延时函数),Obj放置其他乱七八糟东西


.h文件放置定义,文件的包含等。固定格式 #ifndef _xxxx_H #define _xxxx_H #endif


Public.c部分:


#include "public.h"
void delay_10us(u16 ten_us)
{
    while(ten_us--);
}
void delay_ms(u16 ms)
{
    u16 i,j;
    for(i=ms;i>0;i--)
    {
        for(j==110;j>0;j--)
        {
            ;
        }
    }
}

Public.h部分:


#ifndef  _public_H
#define _public_H
#include "reg52.h"
typedef unsigned char u8;
typedef unsigned int u16;
void delay_10us(u16 ten_us);
void delay_ms(u16 ms);
#endif

smg.c部分(数码管)

#include "smg.h"
u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
                0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
void smg_display(u8 dat[],u8 pos)
{
    u8 i=0;
    u8 pos_temp=pos-1;
    for(i=pos_temp;i<8;i++)
    {
           switch(i)//位选
        {
            case 0: LSC=1;LSB=1;LSA=1;break;
            case 1: LSC=1;LSB=1;LSA=0;break;
            case 2: LSC=1;LSB=0;LSA=1;break;
            case 3: LSC=1;LSB=0;LSA=0;break;
            case 4: LSC=0;LSB=1;LSA=1;break;
            case 5: LSC=0;LSB=1;LSA=0;break;
            case 6: LSC=0;LSB=0;LSA=1;break;
            case 7: LSC=0;LSB=0;LSA=0;break;
        }
        SMG_A_DP_PORT=gsmg_code[dat[i-pos_temp]];//传送段选数据
        delay_10us(100);//延时一段时间,等待显示稳定
        SMG_A_DP_PORT=0x00;//消音
    }
}

smg.h部分


#ifndef _smg_H
#define _smg_H
#include "public.h"
#define SMG_A_DP_PORT    P0    //使用宏定义数码管段码口
//定义数码管位选信号控制脚
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
void smg_display(u8 dat[],u8 pos);
#endif

key.c(独立按键部分)

#include "key.h"
u8 key_scan(u8 mode)
{
    static u8 key=1;
    if(mode)key=1;
        if(key==1&&(KEY1==0||KEY2==0||KEY3==0||KEY4==0))
        {
            delay_10us(1000);
            key=0;
            if(KEY1==0)
                return KEY1_PRESS;
            if(KEY2==0)
                return KEY2_PRESS;
            if(KEY3==0)
                return KEY3_PRESS;
            if(KEY4==0)
                return KEY4_PRESS;
        }
        else if(KEY1==1&&KEY2==1&&KEY3==1&&KEY4==1)
        {
            key=1;
        }
            return KEY_UNPRESS;
    }

key.h部分


#ifndef _key_H
#define _key_H
#include "public.h"
sbit KEY1=P3^1;
sbit KEY2=P3^0;
sbit KEY3=P3^2;
sbit KEY4=P3^3;
#define KEY1_PRESS  1
#define KEY2_PRESS  2
#define KEY3_PRESS  3
#define KEY4_PRESS  4
#define KEY_UNPRESS 0
u8 key_scan(u8 mode);
#endif

iic.c部分


#include "iic.h"

210d1c88845b45a281ddf94003113e88.png

// 产生IIC起始信号

void iic_start(void)
{
    IIC_SDA=1;//如果把该条语句放在SCL后面,第二次读写会出现问题
    delay_10us(1);
    IIC_SCL=1;
    delay_10us(1);
    IIC_SDA=0;    //当SCL为高电平时,SDA由高变为低
    delay_10us(1);
    IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
    delay_10us(1);
}

fca09cc6a8724f0f8b27f690ffb3cd90.png

//产生IIC停止信号


void iic_stop(void)
{    
    IIC_SDA=0;//如果把该条语句放在SCL后面,第二次读写会出现问题
    delay_10us(1);
    IIC_SCL=1;
    delay_10us(1);
    IIC_SDA=1;    //当SCL为高电平时,SDA由低变为高
    delay_10us(1);            
}

145fbf0ccbf6489f92e0568f0a52eb08.png

//产生ACK应答


void iic_ack(void)
{
    IIC_SCL=0;
    IIC_SDA=0;    //SDA为低电平
    delay_10us(1);
       IIC_SCL=1;
    delay_10us(1);
    IIC_SCL=0;
}


c11297421f3448679688f8092a4e87a0.png

//产生NACK非应答

void iic_nack(void)
{
    IIC_SCL=0;
    IIC_SDA=1;    //SDA为高电平
    delay_10us(1);
       IIC_SCL=1;
    delay_10us(1);
    IIC_SCL=0;    
}

8b11f55f0fd44235a491c65568d47d03.png

//等待应答信号到来,返回1成功,0失败

u8 iic_wait_ack(void)
{
    u8 time_temp=0;
    IIC_SCL=1;
    delay_10us(1);
    while(IIC_SDA)    //等待SDA为低电平
    {
        time_temp++;
        if(time_temp>100)//超时则强制结束IIC通信
        {    
            iic_stop();
            return 1;    
        }            
    }
    IIC_SCL=0;
    return 0;    
}

3e5abbb9ac814d43b7919de0b55a857b.png

//IIC发送一个字节


void iic_write_byte(u8 dat)
{                        
    u8 i=0; 
    IIC_SCL=0;
    for(i=0;i<8;i++)    //循环8次将一个字节传出,先传高再传低位
    {              
        if((dat&0x80)>0) 
            IIC_SDA=1;
        else
            IIC_SDA=0;
        dat<<=1;       
        delay_10us(1);  
        IIC_SCL=1;
        delay_10us(1); 
        IIC_SCL=0;    
        delay_10us(1);
    }     
}

//IIC读一个字节

u8 iic_read_byte(u8 ack)
{
    u8 i=0,receive=0;
    for(i=0;i<8;i++ )    //循环8次将一个字节读出,先读高再传低位
    {
        IIC_SCL=0; 
        delay_10us(1);
        IIC_SCL=1;
        receive<<=1;
        if(IIC_SDA)receive++;   
        delay_10us(1); 
    }                     
    if (!ack)
        iic_nack();
    else
        iic_ack();  
    return receive;
}

24c02.c部分:

#include "24c02.h"
#include "iic.h"
//在AT24CXX指定地址写入一个数据
//addr:写入数据的目的地址 dat:要写入的数据
void at24c02_write_one_byte(u8 addr,u8 dat)
{                                                                                                  
    iic_start();  
    iic_write_byte(0XA0);    //发送写命令              
    iic_wait_ack();       
    iic_write_byte(addr);    //发送写地址   
    iic_wait_ack();                                                           
    iic_write_byte(dat);    //发送字节                                   
    iic_wait_ack();                     
    iic_stop();                //产生一个停止条件
    delay_ms(10);     
}
//在AT24CXX指定地址读出一个数据
//输入addr:开始读数的地址 ,输出读到的数据
u8 at24c02_read_one_byte(u8 addr)
{                  
    u8 temp=0;                                                                                   
    iic_start();  
    iic_write_byte(0XA0);    //发送写命令       
    iic_wait_ack(); 
    iic_write_byte(addr);     //发送写地址  
    iic_wait_ack();        
    iic_start();              
    iic_write_byte(0XA1);     //进入接收模式                        
    iic_wait_ack();     
    temp=iic_read_byte(0);    //读取字节           
    iic_stop();                //产生一个停止条件    
    return temp;            //返回读取的数据
}

24c02.h部分:

#ifndef _24c02_H
#define _24c02_H
#include "public.h"
void at24c02_write_one_byte(u8 addr,u8 dat);//AT24C02指定地址写数据
u8 at24c02_read_one_byte(u8 addr);//AT24C02指定地址读数据
#endif


相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
XML Java 数据格式
Java用xpdf库获取pdf文件的指定范围文本内容
Java用xpdf库获取pdf文件的指定范围文本内容
208 1
|
Java Android开发
Android 切换壁纸代码流程追踪
Android 切换壁纸代码流程追踪
192 0
|
机器学习/深度学习 自然语言处理 算法
ChatGPT模型采样算法详解
采样算法对ChatGPT的文本生成质量至关重要。本文重点讲解ChatGPT中temperature和top_p的采样原理,以及它们对模型输出的影响。帮助大家生成更灵活生动的内容。
2213 0
ChatGPT模型采样算法详解
|
传感器 C语言 芯片
复习单片机:外部中断(内含:1.外部中断原理图+2 外部中断配置+3 硬件设计+4 软件设计+5.实验现象)
复习单片机:外部中断(内含:1.外部中断原理图+2 外部中断配置+3 硬件设计+4 软件设计+5.实验现象)
424 0
复习单片机:外部中断(内含:1.外部中断原理图+2 外部中断配置+3 硬件设计+4 软件设计+5.实验现象)
|
存储 移动开发 算法
一文理解淘宝购物车背后的逻辑
提升用户的使用体验才是产品升级的核心,本文将从业务发展以及技术沉淀两个方面来总结淘宝购物车的产品升级之路。
1483 0
一文理解淘宝购物车背后的逻辑
|
SQL 关系型数据库 MySQL
MySQL基础-创建数据库
查询所有数据库
152 0
|
3天前
|
存储 关系型数据库 分布式数据库
PostgreSQL 18 发布,快来 PolarDB 尝鲜!
PostgreSQL 18 发布,PolarDB for PostgreSQL 全面兼容。新版本支持异步I/O、UUIDv7、虚拟生成列、逻辑复制增强及OAuth认证,显著提升性能与安全。PolarDB-PG 18 支持存算分离架构,融合海量弹性存储与极致计算性能,搭配丰富插件生态,为企业提供高效、稳定、灵活的云数据库解决方案,助力企业数字化转型如虎添翼!
|
13天前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
1292 5