STM32之IIC总线控制ATC24C04

一、存储器介绍

1、电子密码存储概述

单片机的电子密码存储是一种将密码信息以电子形式存储在单片机内部的技术。它通常用于需要保护敏感信息或限制访问权限的应用程序,如安全系统、门禁系统、电子锁等。

电子密码存储可以通过多种方式实现,以下是其中一种常见的概述:

(1)存储器选择:选择适合存储密码的内部或外部存储器。内部存储器通常是非易失性存储器(如闪存),可以在断电情况下保持数据。外部存储器可以是EEPROM(可擦写可编程只读存储器)或其他非易失性存储器(FLASH)。

(2)加密算法:为了增加密码的安全性,可以使用加密算法对密码进行加密。常见的加密算法包括DES(数据加密标准)、AES(高级加密标准)等。密码存储之前,将密码使用加密算法进行加密,然后再存储在存储器中。

(3)存储密码:将经过加密的密码存储在选择的存储器中。可以根据具体需求选择存储密码所需的存储空间大小。

(4)访问控制:为了安全地访问存储的密码,通常需要实现访问控制机制。这可以包括密码验证、访问权限设置等。例如,在门禁系统中,用户可能需要输入正确的密码才能获得访问权限。

(5)密码修改:为了方便用户,通常需要提供一种方式允许用户修改已存储的密码。这可以通过输入当前密码和新密码来实现。

总之,单片机的电子密码存储是通过选择适当的存储器、加密算法和访问控制机制,将密码以电子形式存储在单片机内部的技术。这种技术提供了一种安全可靠的方法来存储和管理密码信息。

2、EEPROM存储器和Flash存储器区别

EEPROM存储器和Flash存储器都属于电可擦除存储器,但由于内部的构成它们有着以下几点区别:
擦写次数:EEPROM存储器能擦写10万次以上,而FLASH存储器一般为1万次以下。
存储容量:在体积(芯片封装大小)相等情况下FLASH存储器的容量大。
适用范围:EEPROM存储器常用于存储经常修改的一些参数(如用户的一些设定值),而FLASH存储器则一般用于存储程序或者一些只读性数据。
通信协议:EEPROM存储器使用IIC通信协议,FLASH存储器使用SPI通信协议。

二、AT24Cxx存储芯片

1、AT24Cxx芯片概述

AT24Cxx是Atmel公司生产的低功耗CMOS型EEPROM存储芯片,采用I2C总线方式进行数据读写,可工作于标准模式、快速模式和高速模式。主要特点是可读可写,掉电数据不丢失。目前常用的有24C02、24C04、24C08、24C16、24C32。

2、AT24C04芯片功能

AT24C04内含4K bit,即512字节存储空间,分成32每页16个字节。并且AT24C04内部把512字节的存储空间分为2部分,每部分256Byte。AT24C04芯片采用I2C总线方式进行数据读写,可工作于标准模式、快速模式和高速模式。AT24Cxx的写周期约为5ms,也就是在写操作后5ms才能正常读出数据

3、AT24C04芯片管脚描述

图AT24Cxx芯片功能管脚

管脚编号管脚名称功能管脚说明
1A0空管脚
2A1

地址输入脚。地址输入脚根据硬件原理图的连接确定,如果管脚接电源,则为1,

接地则为0。

3A2
5SCLI2C通讯接口的串行数据线
6SDAI2C通讯接口的串行时钟线
7WP

为读写保护管脚,低电平时,可以对整个AT24C04器件的512个字节进行读写操作;

高电平后,器件前256个地址的数据被保护,只能读,不可写入,后256个字节数据

可进行读写操作。

4、8GND、VCC芯片电源负极和电源正极

三、AT24C04存储芯片应用

1、AT24C04地址寻址

(1)芯片器件寻址
AT24C04的芯片地址为1010,其地址控制格式为1010A2A1P0R/W。其中A2、A1为可编程地址选择位(A0为空引脚),数据空间由P0位决定,当P0位为“0”时,将对AT24C04的0~255空间数据进行操作;当P0位为“1”时,将对AT24C04的256~511空间数据进行操作。A2、A1引脚接高、低电平得到确定的两位编码加上P0位的数据与芯片地址(1010)形成7位器件的地址码,在7位地址编码最后1位加上数据方向为则构成了AT24C04芯片器件寻址的控制字节(如图12.11所示)。
操作0-255数据空间器件地址 + 写方向 = 10100000 == 0xA0
操作0-255数据空间器件地址 + 读方向 = 10100000 == 0xA1

AT24CXX控制字节格式

(2)片内子地址寻址
芯片片内寻址可对内部512Byte中的任意1个字节进行读/写操作,其寻址范围为00~1FF,共512个寻址单位。但在操作数据寻址的时候需要注意,由于AT24C04芯片分为2个数据区,使用P0为加以区别,当P0 = 0时,操作的是0~255的地址单元,当P0 = 1时,操作的是256~511的地址单元。

2、AT24C04芯片时序操作

(1)单字节写操作时序

  单字节写操作要求在发送起始命令和从器件地址信息(R/W位清零)给从器件后,等待从器件产生应答信号,主器件发送1个字节子地址,即存储器内部地址,因AT24C04容量为512字节,所以子地址为0~512(需要注意P0位的参数,如果P0位参数为0,则无法操作256~511的地址)。主器件在收到从器件的另一个应答信号后,在接下来的时钟周期里主机发送8位数据,EEPROM再次应答,并在主器件产生停止信号后开始内部数据的擦写。在内部擦写过程中EEPROM不再应答主器件的任何请求。

AT24CXX单字节操作时序

起始条件 --> 器件地址 + 写方向 -->接收AT24C04的应答 --> 就是8位的数据(代表要写到这个AT24C04的哪个位置)-->接收AT24C04的应答 --> 发送8位的数据--> 接收AT24C04的应答-->停止条件

(2)页写操作时序

AT24C04提供32个16字节的页空间,用页写AT24C04可以一次写入16个字节数据,页写操作初始化与字节写相同,但在EEPROM接受到1字节数据后单片机并不发送停止条件,而是继续发送15字节数据,在每接受一字节数据,EEPROM发送一位应答。在发送完8字节数据后,单片机需发送停止信号以终止操作
在进行页写操作时,存储器的子地址低三位会自动增一,但由于高位并不自增,所以在子地址加到页空间边界,即写入16字节后,下一字节会自动写入该页空间的第一字节,覆盖之前的数据,并且如果连续写入数据的地址超过256,地址将从0地址重新开始,从0地址开始的数据将覆盖之前的数据。AT42C04在接收到n+1字节数据和主器件发送的停止信号后启动内部写周期将数据写到数据区,所有接收的数据在一个写周期内写入EEPROM芯片内部。

AT24CXX页写操作时序

起始条件 --> 器件地址 + 写方向 -->接收AT24C04的应答 --> 就是8位的数据(代表要写到这个AT24C04的哪个位置)-->接收AT24C04的应答 --> 不断发送8位的数据(不能超过当前这一页的地址,否则会回到开头覆盖写入)--> 接收AT24C04的应答-->停止条件

(3)单字节读操作时序

主器件首先通过发送起始信号,接着发送从器件地址,在接收到应答后,再发送想读取的字节数据的地址执行一个伪写操作。在AT24C04应答之后,主器件重新发送发送起始信号和从器件地址(此时的器件地址最低位为1,表示读操作),此时子地址指向的为之前定义的值,AT24C04响应并发送应答信号,然后输出所要求的一个 8 位字节数据,主器件在接收到数据后发送非应答信号,并产生停止条件。

AT24CXX单字节读操作时序

起始条件 --> 器件地址 + 写方向 -->接收AT24C04的应答 --> 就是8位的数据(代表要读到这个AT24C04的哪个位置)--> 接收AT24C04的应答 -->起始条件 --> 器件地址 + 读方向 -->接收AT24C04的应答 -->接收AT24c04发送过来的数据 -->读完了回非应答信号 --> 停止条件

(4)连续读操作时序

  连续读操作初始部分与单字节操作相同,在AT24C04发送完一个8 位字节数据后,主器件产生一个应答信号来响应,告知AT24C04主器件要求更多的数据。对应每个主机产生的应答信号,AT24C04将发送一个 8 位数据字节,当主器件发送非应答信号并发送停止位时结束此读操作。读操作可以连续进行,EEPROM内部地址会自动增加,这样整个寄存器区域在可在一个读操作内全部读出。当读取的字节超过最大地址时,地址计数器将翻转到0并继续输出数据字节。

AT24CXX连续读操作时序

起始条件 --> 器件地址 + 写方向 -->接收AT24C04的应答 --> 就是8位的数据(代表要读到这个AT24C04的哪个位置)-->接收AT24C04的应答 -->起始条件 --> 器件地址 + 读方向 -->接收AT24C04的应答 -->不断接收AT24c04发送过来的数据 -->直到回非应答信号才结束这次的接收 --> 停止条件

四、实例

#include "iic.h"/****************************
函数功能:初始化IIC总线的IO口
函数形参:void
函数返回值:void
函数说明:
PA8 -- SCL -- 推挽输出
PC9 -- SDA 
1.输入输出模式切换
SDA线既可以接收数据也可以发送数据
输入模式的时候不能输出数据
输出模式的时候可以读取数据
2.开漏输出
开漏输出:只能输出低电平
如果输出高电平就是断开输出电路
****************************/
void Iic_PortInit(void)
{GPIO_InitTypeDef  GPIO_InitStruct;//定义了一个结构体变量//1. 打开GPIOB的时钟RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);//2. 配置GPIO口功能GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;//配置输出模式GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;//配置为推挽GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;//选择8号管脚GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;//无上下拉GPIO_InitStruct.GPIO_Speed = GPIO_Low_Speed;//低速GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;//配置为开漏GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;//选择9号管脚GPIO_Init(GPIOC, &GPIO_InitStruct); 
}/****************************
函数功能:起始条件
函数形参:void
函数返回值:void
函数说明:在时钟线高电平期间,数据线产生下降沿
****************************/
void IIC_Start(void)
{SDA_H;SCL_H;Delay_Us(2);//起始条件的建立时间SDA_L; Delay_Us(2);//起始条件的保持时间SCL_L;//保证周期完整
}/****************************
函数功能:停止条件
函数形参:void
函数返回值:void
函数说明:在时钟线高电平期间,数据线产生上升沿
****************************/
void IIC_Stop(void)
{SDA_L;SCL_H;Delay_Us(2);//停止条件的建立时间SDA_H;Delay_Us(2);//停止和启动条件之间的总线空闲时间
}/****************************
函数功能:发送应答位
函数形参:u8 ack
函数返回值:void
函数说明:0:代表应答
1:代表非应答
****************************/
void Send_Ack(u8 ack)
{SCL_L;//发送方准备发送数据if(ack){SDA_H;}else{SDA_L;}Delay_Us(2);//发送数据所需要的时间SCL_H;Delay_Us(2);//接收数据所需要的时间SCL_L;Delay_Us(2);//保证一个完整的周期
}/****************************
函数功能:接收应答位
函数形参:void
函数返回值:u8
函数说明:0:代表应答1:代表非应答
****************************/
u8 Receive_Ack(void)
{u8 ack = 0;SDA_H;//断开输出电路SCL_L;//发送方准备发送数据Delay_Us(2);//发送数据所需要的时间SCL_H;if(SDA){ack = 1;}Delay_Us(2);//接收数据所需要的时间SCL_L;Delay_Us(2);//保证一个完整的周期return ack;
}/****************************
函数功能:发送一个字节并接收一个应答位
函数形参:u8 data
函数返回值:u8
函数说明:0:代表应答1:代表非应答
****************************/
u8 Send_Byte_Receive_Ack(u8 data)
{u8 i,ack = 0;for(i = 0; i < 8; i++){SCL_L;//发送方准备发送数据//1100 0011//0100 0000if(data & 0x80 >> i){SDA_H;}elseSDA_L;Delay_Us(2);//发送数据所需要的时间SCL_H;Delay_Us(2);//接收数据所需要的时间}ack = Receive_Ack();return ack;
}/****************************
函数功能:接收一个字节并发送一个应答位
函数形参:u8 data
函数返回值:u8
函数说明:0:代表应答1:代表非应答
****************************/
u8 Receive_Byte_Send_Ack(u8 ack)
{u8 i = 0;u8 data = 0;for(i = 0; i < 8; i++){SCL_L;//发送方准备发送数据Delay_Us(2);//发送数据所需要的时间SDA_H;//断开输出电路SCL_H;data <<= 1;//空出最低位if(SDA){data |= 1;}Delay_Us(2);//接收数据所需要的时间}Send_Ack(ack);return data;
}
#include "at24c04.h"/****************************
函数功能:页写
函数形参:u8 addr---写入的地址
u8 *str---写入的数据
u8 num--写入的个数
函数返回值:u8
函数说明:
****************************/
u8 AT24C04_PAGE_WRITE(u8 addr,u8 *str, u8 num)
{IIC_Start();if(Send_Byte_Receive_Ack(AT24C04_WRITEADDRESS))//先发器件地址写方向{IIC_Stop();return 1;}if(Send_Byte_Receive_Ack(addr))//发送写入的地址{IIC_Stop();return 2;}while(num--)//不断发送数据{if(Send_Byte_Receive_Ack(*str)){IIC_Stop();return 3;}str++;}IIC_Stop();Delay_ms(5);return 0;
}
/****************************
函数功能:读数据
函数形参:u8 addr---写入的地址
u8 *str---写入的数据
u8 num--写入的个数
函数返回值:u8
函数说明:****************************/
u8 AT24C04_READ(u8 addr,u8 *str, u8 num)
{IIC_Start();if(Send_Byte_Receive_Ack(AT24C04_WRITEADDRESS))//先发器件地址写方向{IIC_Stop();return 4;}if(Send_Byte_Receive_Ack(addr))//发送写入的地址{IIC_Stop();return 5;}IIC_Start();//起始条件if(Send_Byte_Receive_Ack(AT24C04_READADDRESS))//发送读的地址{IIC_Stop();return 6;}	num = num - 1;while(num--){*str = Receive_Byte_Send_Ack(0);//前面的数据都发应答str++;}*str = Receive_Byte_Send_Ack(1);//后面的数据发非应答IIC_Stop();return 0;
}
#ifndef __IIC_H_
#define __IIC_H_#include "stm32f4xx.h"
#include "delay.h"#define SCL_H  GPIO_SetBits(GPIOA,GPIO_Pin_8)
#define SCL_L  GPIO_ResetBits(GPIOA,GPIO_Pin_8)
#define SDA_H  GPIO_SetBits(GPIOC,GPIO_Pin_9)
#define SDA_L  GPIO_ResetBits(GPIOC,GPIO_Pin_9)
#define SDA    GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_9)void Iic_PortInit(void);
void IIC_Start(void);
void IIC_Stop(void);
u8 Send_Byte_Receive_Ack(u8 data);
u8 Receive_Byte_Send_Ack(u8 ack);#endif
#ifndef __AT24C04_H_
#define __AT24C04_H_#include "stm32f4xx.h"
#include "iic.h"#define AT24C04_WRITEADDRESS 0XA0
#define AT24C04_READADDRESS 0XA1u8 AT24C04_READ(u8 addr,u8 *str, u8 num);
u8 AT24C04_PAGE_WRITE(u8 addr,u8 *str, u8 num);#endif

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/437730.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

黑马程序员-瑞吉外卖-day6

目录 做下面两个功能: 1.写实体类 2. Mapper 3.Service 4.controller 5.将分类管理表的进行分页查询返回给前端 6.套餐分类 7.修改套餐分类 后台系统中可以管理分类信息&#xff0c;分类包括两种类型&#xff0c;分别是 **菜品分类** 和 **套餐分类** 。当我们在后台…

Nginx负载均衡下的webshell连接

一、上传AntSword-Labs-master搭建负载均衡实验环境 搭建好docker环境&#xff0c;并且配置好docker-compose 我的Redhat的docker版本&#xff1a; 查看当前环境下的文件是否正确&#xff1a; 接着执行docker compose up -d 拉取环境 访问成功页面&#xff1a; 进入docker容器…

图形绘制-仪表盘(2)

本章节我们介绍如何如何绘制刻度对应的数字及指针。效果如下&#xff1a; 关于通过继承重写QWidget的绘制事件paintEvent()&#xff0c;来绘制仪表盘的基础操作&#xff0c;请看上一章节《图形绘制-仪表盘&#xff08;1&#xff09;-CSDN博客》介绍。 在paintEvent()中继续写以…

【JAVE SE】---运算符和程序逻辑控制语句

1.运算符 算数运算符 - * / % 注意&#xff1a;1.Java的%符号左右两边可以是小数&#xff0c;也可以是负数 //运算符float a1.0f;float b2.0f;float c-1.5f;System.out.println(a%b); //1.0System.out.println(a%c); //1.0 2.Java中除数不可以为0&#xff0c…

一些著名的软件都用什么语言编写?

1、操作系统 Microsoft Windows &#xff1a;汇编 -> C -> C 备注&#xff1a;曾经在智能手机的操作系统&#xff08;Windows Mobile&#xff09;考虑掺点C#写的程序&#xff0c;比如软键盘&#xff0c;结果因为写出来的程序太慢&#xff0c;实在无法和别的模块合并&…

前端实现弹小球功能

这篇文章将会做弹小球游戏&#xff0c;弹小球游戏大家小时候都玩过&#xff0c;玩家需要在小球到达游戏区域底部时候控制砖块去承接小球&#xff0c;并不断的将小球弹出去。 首先看一下实现的效果。 效果演示 玩家需要通过控制鼠标来实现砖块的移动&#xff0c;保证在小球下落…

burp靶场--CSRF

burp靶场–CSRF https://portswigger.net/web-security/csrf#what-is-csrf ### 什么是 CSRF&#xff1f; 跨站请求伪造&#xff08;也称为 CSRF&#xff09;是一种 Web 安全漏洞&#xff0c;允许攻击者诱导用户执行他们不打算执行的操作。它允许攻击者部分规避同源策略&#…

xcode安装visionOS Simulator模拟器报错解决方法手动安装方法

手动安装方法&#xff1a; 手动下载visionOS Simulator模拟器地址&#xff1a; https://developer.apple.com/download/all/ 选择 Xcode 版本 sudo xcode-select -s /Applications/Xcode.app # 用 Xcode-beta 的话是&#xff1a; # xcode-select -s /Applications/Xcode-beta…

【ArcGIS微课1000例】0098:查询河流流经过的格网

本实验讲述,ArcGIS中查询河流流经过的格网,如黄河流经过的格网、县城、乡镇、省份等。 文章目录 一、加载数据二、空间查询三、结果导出四、注意事项一、加载数据 加载实验配套数据0098.rar中的河流(黄河)和格网数据,如下图所示: 接下来,将查询河流流经过的格网有哪些并…

3338 蓝桥杯 wyz的数组IV 简单

3338 蓝桥杯 wyz的数组IV 简单 //C风格解法1&#xff0c;通过率50% #include<bits/stdc.h>int main(){std::ios::sync_with_stdio(false);std::cin.tie(nullptr);std::cout.tie(nullptr);int n; std::cin >> n;int ans 0;std::vector<int>a(n);for(auto &am…

Java语言名字由来

文章目录 一、1990年代初Java雏形初诞生&#xff0c;第一个名称是Greentalk二、创始人办公室前有棵橡树&#xff0c;后来改名叫“oak&#xff08;橡树&#xff09;”三、在家电行业失败进入互联网行业&#xff0c;发现商标被抢注被迫换名四、创始团队成员在喝咖啡时灵机一动&am…

Mysql-ReadView + MVCC-RR 与 RC

实验准备 创建脚本 CREATE TABLE user (id int(11) NOT NULL AUTO_INCREMENT,name varchar(16) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,age int(11) NULL DEFAULT NULL,addr varchar(256) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,PRIMARY …