51单片机-AT24CXX存储器工作原理

news/2025/2/26 3:08:22

1、AT24CXX存储器工作原理

1.1、特点:

  • 与400KHz,I2C总线兼容
  • 1.8到6.0伏工作电压范围
  • 低功耗CMOS技术
  • 写保护功能当WP为高电平时进入写保护状态
  • 页写缓冲器
  • 自定时擦写周期
  • 100万次编程/擦除周期
  • 可保存数据100年
  • 8脚DIP SOIC或TSSOP封装
  • 温度范围商业级和工业级

1.2、概述

CAT24WC01/02/04/08/16是一个1K/2K/4K/8K/16K位串行CMOS,EEPROM内部含有128/256/512/1024/2048个8位字节CATALYST公司的先进CMOS技术实质上减少了器件的功耗,CAT24WC01有一个8字节页写缓冲器CAT24WC02/04/08/16有一个16字节页写缓冲器,该器件通过I2C总线接口进行操作有一个专门的写保护功能。

 

 总线时序

 

1.3、驱动程序编写

//<main.c>

#include "reg52.h"
#include "i2c.h"

typedef unsigned int u16;
typedef unsigned char u8;

//使用单片机上四个独立按键
sbit k1=P3^1; //保存显示的数据
sbit k2=P3^0; //读取上次保存的数据
sbit k3=P3^2; //对显示的数据进行累加
sbit k4=P3^1; //清零

// 38译码器
sbit LBA=P2^2;
sbit LBB=P2^3;
sbit LBC=P2^4;

u8 num=0,
disp[4]; //4位数码管显示

// 发生字码:code关键词,保持变量到flash里面,如果没有code保持在data里面
u8 code  smgduan[16] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

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 = At24c02read(1);
       }
       while(!k2); //判断按键是否松开
    }

   if(k3=0)
    {
       delay(1000); //按键消抖
       if(k3==0)
       {
         num++;
         if(num>255) num=0;
       }
       while(!k3); //判断按键是否松开
    }

    if(k4=0)
    {
       delay(1000); //按键消抖
       if(k4==0)
       {
           num=0;
       }
       while(!k4); //判断按键是否松开
    }
}

void datapros()
{
   disp[0]=smgduan[num/1000]; //因为数码管四位,所以最高显示9999
   disp[1]=smgduan[num%1000/100]; //取百位
   disp[2]=smgduan[num%1000%100/10];
   disp[3]=smgduan[num%1000%100%10];
}

void Digplsplay()
{
    u8 i;
    for(i=0;i<4;i++){
      switch(i)
      {
          case 0:
             LSA = 0;LSB = 0;LSC = 0;break;
          case 1:
             LSA = 1;LSB = 0;LSC = 0;break;
          case 2:
             LSA = 0;LSB = 1;LSC = 0;break;
          case 3:
             LSA = 0;LSB = 0;LSC = 1;break;
      }
      P0=disp[3-i];
      delay(100);
      p0=0x00;
    }
}

void main()
{
    while(1){
      Keypros();
      datapros();
      Digplsplay();
    }
}
//<i2c.h>

#ifndef _I2C_H
#define _I2C_H

#include <reg52.h>


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


void At24c02Write(unsigned char addr,unsigned char dat);
unsigned char At24c02Read(unsigned char addr);


#endif
//<i2c.c>文件

#include "i2c.h"


/**
编写单片机时序,单片机小精灵工具生成
12MHZ晶振,延迟10us
*/
void Delay10us(void)
{
   unsigned char a,b;
   for(b=1;b>0;b--)
     for(a=2;a>0;a--)
}


//起始信号S
void I2cStart()
{
   SDA=1;
   Delay10us();
   SCL=1;
   Delay10us();
   SDA=0;
   Delay10us();
   SCL=0;
   Delay10us();
}


//终止信号
void I2cStop()
{
   SDA=0;
   Delay10us();
   SCL=1;
   Delay10us();
   SDA=1;
   Delay10us();
}

//发送字节,一个个发送,先发送高位后发送地位,应答 “0”
unsigned char I2cSendByte(unsigned char dat)
{
   unsigned char a=0,b;
   for(a=0;a<8;a++){
      SDA=dat>>7;  //传送最高位
      dat=dat<<1;  //右移一位,次高位变成最高位
      Delay10us(); //延迟10us
   
     //SCL为低电平可以变化,为高电平保持稳定
     SCL=1; //移位的数据就会保持稳定
     Delay10us();
     SCL=0; //数据可以改变
     Delay10us();    
   }
   //将数据线和时钟线释放出来
   SDA=1;
   Delay10us();    
   SCL=1;
   while(SDA) //如果从机对主机发送的字节产生应答SDA会变成 0
   {
     //发送失败SDA始终为高电平
     b++ //设置个等待时间
     if(b>200){ //至少200us,1条指令1us
        SCL=0;
        Delay10us();
        return 0; 
     }
   }
   //产生应答 SCL=0拉低
   SCL=0;
   Delay10us();  
   return 1;
}

/**
接收数据
*/
unsigned char I2cReadByte()
{
   unsigned char a=0,dat=0;
   SDA=1;  //拉高SDA使处于空闲状态
   Delay10us();
   for(a=0;a<0;a++)
   {
     SCL=1;
     Delay10us();
     dat<<=1;  // dat=0 00  01  10
     dat|=SDA; //    01     11   把SDA的值给dat
     Delay10us();
     SCL=0;
     Delay10us();
   }
   return dat;
}

/**针对AT24C02的读写函数

S-器件地址+0 A  写入首地址 A Data1 A  .....  Data0  A  P

*/

void At24c02Write(unsigned char addr,unsigned char dat)

{ 

     I2cStart(); //起始信号
     I2cSendByte(0xa0); //器件地址
     I2cSendByte(addr); // 首地址
     I2cSendByte(dat); // 发送数据
     I2cStop(); //停止
}

unsigned char At24c02Read(unsigned char addr)
{
     unsigned char num;
     I2cStart(); //起始信号
     I2cSendByte(0xa0); //器件地址
     I2cSendByte(addr); // 首地址
     
     //在传送过程中,当需要改变传送方向时,起始信号和从机地址都被重复产生一次,但两次读/写方向位正好反相
     I2cStart(); //起始信号
     I2cSendByte(0xa1); //器件地址
     num=I2cReadByte();
     I2cStop();
     return num;
}

http://www.niftyadmin.cn/n/5867107.html

相关文章

Git-速查

Git 安装 Git 之后&#xff0c;你可以… 配置全局用户信息&#xff08;推荐&#xff09; 全局设置&#xff0c;创建本地仓库时默认分支名称为 main&#xff08;你需要什么名称就该什么名称&#xff09;【推荐配置为 main 】 git config --global init.defaultBranch main全…

[Linux]从零开始的STM32MP157 U-Boot网络命令讲解及相关配置

一、前言 在上一次的STM32MP157的教程中&#xff0c;教大家STM32MP157基础命令的使用&#xff0c;同时也验证了我们STM32MP157U-Boot的部分功能。因为U-Boot的网络配置部分比较复杂&#xff0c;所以在上一次的教程中并没有涉及。那么本次教程&#xff0c;我会为大家详细的讲解U…

面试八股文--数据库基础知识总结(1)

1、数据库的定义 数据库&#xff08;DataBase&#xff0c;DB&#xff09;简单来说就是数据的集合数据库管理系统&#xff08;Database Management System&#xff0c;DBMS&#xff09;是一种操纵和管理数据库的大型软件&#xff0c;通常用于建立、使用和维护数据库。数据库系统…

在scss中使用for循环生成头像/icon

在业务中有时会出现相同样式不同icon的情况出现&#xff0c;如果我们使用scss中的for循环的话这个问题很好解决 先列出标签结构 <div v-for"item in function_data" :key"item.id" class"signal_btn"><div :class"btn_avatar (…

Eureka、ZooKeeper 和 Nacos 之间的对比

Eureka、ZooKeeper 和 Nacos 都是分布式系统中常用的服务注册与发现工具&#xff0c;但它们的定位、功能和适用场景有所不同。作为一名开发者&#xff0c;理解它们之间的对比有助于选择合适的技术栈。以下从多个维度进行详细比较&#xff1a; 1. 基本概述 Eureka 来源&#xff…

LeetCode - 23 合并 K 个升序链表

题目来源 23. 合并 K 个升序链表 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给你一个链表数组&#xff0c;每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中&#xff0c;返回合并后的链表。 示例 示例 1&#xff1a; 输入&#xff1a;lists [[1,4,…

JS作用域+this指向 【JavaScript】

JS作用域&#xff1a; 在JavaScript中&#xff0c;作用域指的是程序中变量、函数和对象可访问的上下文环境。JavaScript主要有三种作用域&#xff1a;全局作用域、函数作用域和块作用域&#xff08;ES6引入&#xff09;。 全局作用域&#xff1a;全局作用域中的变量在页面上的…

自由学习记录(38)

python语法 def def print_receipt (store_name, items, total_price, cashier"Self-Checkout", payment_method"Credit Card"): Python 的 函数定义 语法 def print_receipt(...) → 定义了一个名为 print_receipt 的函数。store_name, items, total_…