首页 > 其他分享 >关于AT24C02的学习

关于AT24C02的学习

时间:2024-11-13 19:46:58浏览次数:1  
标签:Pin USART 学习 InitStructure AT24C02 IIC GPIO USART1 关于

一、基本概念

image


二、特性说明

image


三、内存结构

image


四、器件地址

image


五、指令描述

image


/***********************************************************************************
* @file    main.c 
* @author  [email protected]
* @version V1
* @date    2024-11-13
* @brief   AT24C02存储IC的指令设计
***********************************************************************************/

#include "stm32f4xx.h"
#include <stdio.h>
#include <stdbool.h>

//使用IO口来模拟IIC时序,从而控制从器件
#define  IIC_SDA(n)  (n) ? GPIO_SetBits(GPIOB,GPIO_Pin_9) : GPIO_ResetBits(GPIOB,GPIO_Pin_9)
#define  IIC_SCL(n)  (n) ? GPIO_SetBits(GPIOB,GPIO_Pin_8) : GPIO_ResetBits(GPIOB,GPIO_Pin_8)

#define  IIC_READ		 GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_9)


//延时微秒  注意:24bit计数器  不能798915us
void delay_us(u32 nus)
{
	SysTick->CTRL = 0; 					// 关闭定时器
	SysTick->LOAD = nus*21 - 1; // 设置重载值
	SysTick->VAL 	= 0; 					// 清除计数值
	SysTick->CTRL = 1; 					// 开启定时器  21MHZ  
	while ((SysTick->CTRL & 0x00010000)==0);// 等待时间到达
	SysTick->CTRL = 0; 					// 关闭定时器
}

//延时毫秒  注意:24bit计数器  不能798ms
void delay_ms(u32 nms)
{
	SysTick->CTRL = 0; 					// 关闭定时器
	SysTick->LOAD = nms*21000 - 1; // 设置重载值
	SysTick->VAL 	= 0; 					// 清除计数值
	SysTick->CTRL = 1; 					// 开启定时器  21MHZ  
	while ((SysTick->CTRL & 0x00010000)==0);// 等待时间到达
	SysTick->CTRL = 0; 					// 关闭定时器
}

//串口1的初始化
void USART1_Config(u32 baud)
{
  USART_InitTypeDef USART_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
  
  //1.打开GPIO端口  PA9 PA10  
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
  
  //2.打开串口时钟  USART1 -- APB2
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  
  //3.选择引脚的复用功能
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource9  , GPIO_AF_USART1);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource10 , GPIO_AF_USART1);
  
  //4.配置GPIO引脚参数并初始化
  GPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_AF;			 			//复用模式
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 			//输出速度
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;		 			//推挽复用
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;			 			//上拉电阻
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_10|GPIO_Pin_9;	//引脚编号
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
	//5.配置USART1的参数并初始化
  USART_InitStructure.USART_BaudRate 		= baud;										//波特率
  USART_InitStructure.USART_WordLength 	= USART_WordLength_8b;		//数据位
  USART_InitStructure.USART_StopBits 		= USART_StopBits_1;				//停止位
  USART_InitStructure.USART_Parity 			= USART_Parity_No;				//检验位
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//无硬件流控
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
  USART_Init(USART1, &USART_InitStructure);
  
  //6.配置中断参数并初始化
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;								//中断通道编号
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;				//抢占优先级
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;							//子优先级
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;									//打开中断通道
  NVIC_Init(&NVIC_InitStructure);
  
	//7.选择中断源   接收到数据则触发中断
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

  //8.打开USART1
  USART_Cmd(USART1, ENABLE);
}



//发送字符串的函数
void USART1_SendString(char *str)
{ 
	//循环发送字符
  while( *str != '\0' )
	{
		USART_SendData(USART1,*str++);
		while( USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET ); //等待发送数据寄存器为空  表示发送完成		
	}
}

//IIC时序: 起始信号 + 发送字节 + 从机应答 + 读取字节 + 主机应答 + 停止信号

//IIC的初始化
void IIC_Config(void)
{
	 GPIO_InitTypeDef GPIO_InitStructure;
		
	 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
	
	 GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;			 			//输出模式
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 			//输出速度
   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;		 			  //推挽复用
   GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;			 			//上拉电阻
	
   GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;							//引脚编号
   GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	 GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_8;							//引脚编号
   GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	 //确保SDA和SCL都处于空闲状态
	 IIC_SDA(1);
	 IIC_SCL(1);
}	

//SDA设置为输出模式
static void IIC_SDASetOutputMode(void)
{
	 GPIO_InitTypeDef GPIO_InitStructure;
		
	 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
	
	 GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;			 			//输出模式
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 			//输出速度
   GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;		 			  //推挽复用
   GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;			 			//上拉电阻
	
   GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;							//引脚编号
   GPIO_Init(GPIOB, &GPIO_InitStructure);

}

//SDA设置为输入模式
static void IIC_SDASetInputMode(void)
{
	 GPIO_InitTypeDef GPIO_InitStructure;
		
	 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
	
	 GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;			 			//输入模式
   GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;			 			//上拉电阻
	
   GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;							//引脚编号
   GPIO_Init(GPIOB, &GPIO_InitStructure);

}

//IIC的开始信号
void IIC_Start(void)
{
	//1.SDA引脚设置为输出模式
	IIC_SDASetOutputMode();
	
	//2.确保SDA和SCL为空闲状态  高电平
	IIC_SDA(1);
	IIC_SCL(1);
	delay_us(5);
	
	//3.在SCL高电平期间,把SDA电平拉低
	IIC_SDA(0);
	delay_us(5);
	
	//4.把SCL时钟线的电平拉低
	IIC_SCL(0);
	delay_us(5);
}

//IIC发送字节
void IIC_SendByte(uint8_t data)
{
	uint8_t i = 0;
	
	//1.SDA引脚设置为输出模式
	IIC_SDASetOutputMode();

	//2.把SCL时钟线电平拉低
	IIC_SCL(0);
	delay_us(5);
	
	//3.循环发送8bit数据
	for(i=0;i<8;i++)
	{
		//4.分析待发送数据的最高位 MSB
		if( data & 0x80 )
			IIC_SDA(1);
		else
			IIC_SDA(0);
		
		data <<= 1; //数据左移1bit
		delay_us(5);
		
		//5.把SCL时钟线的电平拉高,此时从机可以读取
		IIC_SCL(1);
		delay_us(5);
		
		//6.把SCL时钟线的电平拉低,此时主机可以准备
		IIC_SCL(0);
		delay_us(5);
	}
}


//IIC的等待从器件应答
bool IIC_WaitSlaveAck(void)
{
	//1.设置SDA数据线为输入模式
	IIC_SDASetInputMode();
	
	//2.把SCL时钟线的电平拉低,此时从机可以准备
	IIC_SCL(0);
	delay_us(5);
	
	//3.把SCL时钟线的电平拉高,此时从机可以读取
	IIC_SCL(1);
	delay_us(5);
	
	//4.主器件读取SDA数据线的电平状态
	if( IIC_READ )
		return false;
	else
		return true;

}

//IIC读取字节
uint8_t IIC_ReadByte(void)
{
	uint8_t data = 0;
	uint8_t i = 0;
	
	//1.设置SDA数据线为输入模式
	IIC_SDASetInputMode();
	
	
	//2.把SCL时钟线的电平拉低,此时从机可以准备
	IIC_SCL(0);
	delay_us(5);
	
	//3.循环读取8bit数据并存储在变量
	for(i=0;i<8;i++)
	{
		//4.把SCL时钟线的电平拉高,此时主机可以读取
		IIC_SCL(1);
		delay_us(5);
		
		//5.读取SDA数据线的电平状态  MSB
		data <<= 1;
		data |= IIC_READ;
		
		//6.把SCL时钟线的电平拉低,此时从机可以准备
	  IIC_SCL(0);
	  delay_us(5);
	}
	
	return data;
}

//IIC主机发送应答
void IIC_MasterSendAck(uint8_t ack)
{
	//1.SDA引脚设置为输出模式
	IIC_SDASetOutputMode();
	
	//2.把SCL时钟线的电平拉低,此时主机可以准备
	IIC_SCL(0);
	delay_us(5);
	
	//3.主机进行应答
	if( ack )
		IIC_SDA(1); //表示不应答
	else
		IIC_SDA(0); //表示应答了
	
	delay_us(5);
	
	//4.把SCL时钟线的电平拉高,此时从机可以读取
	IIC_SCL(1);
	delay_us(5);
}


//IIC发送停止信号
void IIC_Stop(void)
{
	//1.SDA引脚设置为输出模式
	IIC_SDASetOutputMode();
	
	//2.确保SDA和SCL都输出低电平
	IIC_SDA(0);
	IIC_SCL(0);
	delay_us(5);
	
	//3.把SCL时钟线的电平拉高
	IIC_SCL(1);
	delay_us(5);
	
	//4.把SDA时钟线的电平拉高
	IIC_SDA(1);
	delay_us(5);
}

//AT24C02初始化
void AT24C02_Config(void)
{
	IIC_Config();
}

//AT24C02字节写入指令
void AT24C02_ByteWrite(uint8_t Addr,uint8_t Data)
{
	//1.主机发送开始信号
	IIC_Start();
	
	//2.主机发送器件地址
	IIC_SendByte(0xA0);
	
	//3.等待从机应答
	while( IIC_WaitSlaveAck() == false );
	
	//4.主机发送存储地址
	IIC_SendByte(Addr);
	
	//5.等待从机应答
	while( IIC_WaitSlaveAck() == false );
	
	//6.主机发送存储内容
	IIC_SendByte(Data);
	
	//7.等待从机应答
	while( IIC_WaitSlaveAck() == false );
	
	//8.主机发送停止信号
	IIC_Stop();
}



//程序入口
int main()
{

	
	//1.硬件初始化
	USART1_Config(9600); 
	AT24C02_Config();
	

	while(1)
	{	
		
	
	}
}

void USART1_IRQHandler(void)
{
	uint8_t data = 0;
	//判断中断是否触发
	if( USART_GetITStatus(USART1, USART_IT_RXNE) == SET )
	{
		data = USART_ReceiveData(USART1); //一次只能接收1个字节
		USART_SendData(USART1,data);      //通过USART1发送1字节
	}
}




标签:Pin,USART,学习,InitStructure,AT24C02,IIC,GPIO,USART1,关于
From: https://www.cnblogs.com/hhail08/p/18544669

相关文章

  • 网络学习第四篇
    引言: 我们在第三篇的时候出现了错误,我们要就行排错,那么我们要知道一下怎么配置静态路由实现ping通,这样子我们才知道下一跳到底是什么,为什么这样子做。实验目的理解和掌握静态路由的基本概念和配置方法。实现两个不同网络之间的通信。实验环境两台路由器(AR5和AR6)。三台P......
  • NUXT3学习日记(一)
    Nuxt3是一个基于Vue3的现代框架,用于构建服务器端渲染(SSR)和静态生成的应用程序。它提供了一种简化的方式来创建高性能的Vue应用,具有许多强大的功能和优点。以下是Nuxt3的一些主要应用和优点:一、应用场景服务器端渲染(SSR):Nuxt3可以轻松构建服务器端渲染的应用,这样......
  • 前端技术html中对表单元素的学习
    表单元素目录表单元素基本结构常见的表单元素示例form表单元素在HTML中用于收集用户输入的数据,以便将数据发送到服务器进行处理。表单可以包含多种类型的输入元素,如文本字段、密码字段、单选按钮、复选框、下拉选择菜单、提交按钮等。用户填写表单后,通常通过点击提交按钮将......
  • 【深度学习|课程笔记1】何恺明大神在MIT的秋季最新课程!附课程地址
    【深度学习|课程笔记1】何恺明大神在MIT的秋季最新课程!附课程地址【深度学习|课程笔记1】何恺明大神在MIT的秋季最新课程!附课程地址文章目录【深度学习|课程笔记1】何恺明大神在MIT的秋季最新课程!附课程地址课程概览欢迎宝子们点赞、关注、收藏!欢迎宝子们批评指......
  • rust学习八、包和模块
    总体上,也没有什么特别的地方,和其它语言比较起来。我们可以看懂熟悉的字眼:包括、模块、use、公共等等如果是英文,则需要知道crate、pub。本章节对应相关书籍的第七章节.一、一个rust可执行程序的大体结构就本章节而言,尚未接触到一个非常复杂的工程结构,据说有什么工作空间。不......
  • 大数据学习13之Scala基础语法(重点)
    1.简介        Scala是ScalableLanguage的简写,是一门多范式的编程语言。创始人为MartinOdersky马丁·奥德斯基。        Scala这个名字来源于ScalableLanguage(可伸缩的语言),它是一门基于JVM的多范式编程语言,通俗的说:Scala是一种运行在JVM上的......
  • starrycan的pwn学习记录1
    一.Introducation0x01简介CTF0x02什么是pwn”Pwn”是一个黑客语法的俚语词,是指攻破设备或者系统。发音类似“砰”,对黑客而言这就是成功实施黑客攻击的声音--砰的一声,被“黑”的电脑或手机就被你操纵了。CTF中的pwnCTF中的PWN主要是针对于二进制漏洞挖掘与利用,通常情况下选......
  • VS Code 关于C++代码运行时,工作目录不在于当前目录的问题(cwd)
    我在用C++练习流的使用时遇到了当前目录与工作目录不符的问题,导致使用相对路径时无法读取文件。这是我的工作目录其中1.txt内容为当我选择不使用插件执行代码时(如下)终端输出为:此时并没有将1.txt的内容输出出来,于是我运行,测试代码,输出当前的工作目录#include<iostream>......
  • 楼板的厚度、隔音效果和安全级别通常会受到建筑设计规范、建筑用途、楼层高度以及所在
    楼板的厚度、隔音效果和安全级别通常会受到建筑设计规范、建筑用途、楼层高度以及所在地区的建筑标准等多种因素的影响。以下是楼板相关的标准要求,特别是关于厚度、隔音和安全级别的标准信息的一个表格化总结:标准类别要求/标准参考标准/规范说明楼板厚度住宅楼板厚度......
  • 学术论文写作丨机器学习与深度学习
    目录第一章、ChatGPT-4o使用方法与技巧第二章、ChatGPT-4o辅助文献检索、总结与分析第三章、ChatGPT-4o辅助学术论文选题、创新点挖掘与实验方案设计第四章、ChatGPT-4o辅助学术论文开题与大纲生成第五章、ChatGPT-4o辅助学术论文写作马拉松活动介绍第六章、ChatGPT-4o辅......