当前位置: 首页 > news >正文

freertos-软件模拟IIC读写at24c02

参考:https://blog.csdn.net/qq_52952281/article/details/134364016
直接移植,实测用
在这里插入图片描述

在这里插入图片描述

at24c02_drv.c

// #include "24c02_drv.h"
// #include "stdint.h"//注意:初版PCB不支持硬件IIC
//先使用软件模拟IIC过渡------配合osDelay让出cpu资源
//后续改版后,使用硬件IIC+DMA//参考linux驱动的写法:https://www.elecfans.com/d/1894852.html//2K bit   ---> 2048bit----->2048/8 BYTE== 256BYTE;
//每页16字节//一共128页#include "24c02_drv.h"
#include "gpio.h"
#include "FreeRTOS.h"
#include "task.h"
#include "log_sys.h"
#include "stm32f4xx_hal.h"
#include "stm32f4xx_hal_def.h"/*@brief I2C驱动初始化,采用模拟IO的方式实现@param 无@return 无
*/#define AT24C02_ADDR_WRITE  0xA0
#define AT24C02_ADDR_READ   0xA1
/**@brief CPU发起I2C总线启动信号@param 无@return 无
*/
void IIC_Start(void)
{SDA_OUT_MODE();         // SDA线输出模式IIC_SDA_1();            	  	  IIC_SCL_1();osDelay(1);IIC_SDA_0();            // 当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号osDelay(1);    IIC_SCL_0();            // 钳住I2C总线,准备发送或接收数据 
}	/**@brief CPU发起I2C总线停止信号@param 无@return 无
*/
void IIC_Stop(void)
{SDA_OUT_MODE();         // SDA线输出模式IIC_SCL_0();IIC_SDA_0();          IIC_SCL_1();osDelay(1);IIC_SDA_1();            // 当SCL高电平时,SDA出现一个上跳沿表示I2C总线停止信号		osDelay(1);
}/**@brief CPU向I2C总线设备发送8bit数据@param ucByte -[in] 等待发送的字节@return 无
*/  
void IIC_SendByte(uint8_t ucByte)
{                        uint8_t i;  SDA_OUT_MODE();         // SDA线输出模式IIC_SCL_0();            // 拉低时钟开始数据传输for(i = 0; i < 8; i++){              if(ucByte & 0x80) 	{            IIC_SDA_1();}else{IIC_SDA_0();}ucByte <<= 1; 	osDelay(1);        IIC_SCL_1();osDelay(1);IIC_SCL_0();osDelay(1);        }	 
} /**@brief CPU从I2C总线设备读取8bit数据@param 无@return 读到的数据
*/ 
uint8_t IIC_ReadByte(void)
{uint8_t i = 0;uint8_t value = 0;SDA_IN_MODE();          // SDA线输入模式for(i = 0; i < 8; i++){value <<= 1;IIC_SCL_1();osDelay(1);if(IIC_SDA_READ()){value++;}            IIC_SCL_0(); osDelay(1); }					IIC_Ack();return value;
}/**@brief CPU产生一个时钟,并读取器件的ACK应答信号@param 无@return 返回0表示正确应答,1表示无器件响应
*/
uint8_t IIC_WaitAck(void)
{uint8_t result = 0; SDA_IN_MODE();          // SDA线输入模式IIC_SDA_1();            // CPU释放SDA总线osDelay(1); IIC_SCL_1();            // CPU驱动SCL = 1, 此时器件会返回ACK应答osDelay(1);if(IIC_SDA_READ()){result = 1;}else{result = 0;}IIC_SCL_0();osDelay(1);return result;  
} /**@brief CPU产生一个ACK信号@param 无@return 无
*/
void IIC_Ack(void)
{SDA_OUT_MODE();         // SDA线输出模式IIC_SDA_0();            // CPU驱动SDA = 0osDelay(1);IIC_SCL_1();            // CPU产生1个时钟osDelay(1);IIC_SCL_0();osDelay(1);IIC_SDA_1();            // CPU释放SDA总线
}/**@brief CPU产生1个NACK信号@param 无@return 无
*/    
void IIC_NAck(void)
{SDA_OUT_MODE();         // SDA线输出模式IIC_SDA_1();            // CPU驱动SDA = 1osDelay(1);IIC_SCL_1();            // CPU产生1个时钟osDelay(1);IIC_SCL_0();osDelay(1);
}void IIC_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};/* GPIO Ports Clock Enable */__HAL_RCC_GPIOB_CLK_ENABLE();/*Configure GPIO pin : PtPin */GPIO_InitStruct.Pin = IIC1_SCL_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(IIC1_SCL_GPIO_Port, &GPIO_InitStruct);  GPIO_InitStruct.Pin = IIC1_SDA_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(IIC1_SDA_GPIO_Port, &GPIO_InitStruct);IIC_Stop();             // 给一个停止信号, 复位I2C总线上的所有设备到待机模式
}/**@brief 检测I2C总线设备,CPU向发送设备地址,然后读取设备应答来判断该设备是否存在@param address -[in] 设备的I2C总线地址+读写控制bit(0 = w, 1 = r)@return 0 - 表示正确, 1 - 表示未探测到
*/  
uint8_t IIC_CheckDevice(uint8_t address)
{uint8_t ucAck;IIC_Init();             // 初始化I2CIIC_Start();            // 发送启动信号IIC_SendByte(address);  // 设备的I2C总线地址+读写控制bit(0 = w, 1 = r)ucAck = IIC_WaitAck();	// 检测设备的ACK应答IIC_Stop();             // 发送停止信号return ucAck;
}/********************************************************************** LOCAL FUNCTIONS*/
/**@brief SDA输出配置	@param 无@return 无
*/ 
static void SDA_OUT_MODE(void)
{GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.Pin = IIC1_SDA_Pin;GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(IIC1_SDA_GPIO_Port, &GPIO_InitStruct);}/**@brief SDA输入配置	@param 无@return 无
*/ 
static void SDA_IN_MODE(void)
{GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.Pin = IIC1_SDA_Pin;GPIO_InitStruct.Mode = GPIO_MODE_INPUT;HAL_GPIO_Init(IIC1_SDA_GPIO_Port, &GPIO_InitStruct);}void AT24CXX_soft_Init(void)
{IIC_Init();		
}void AT24CXX_soft_ReadOneByte(u16 ReadAddr, u8 *read_data)
{	IIC_Start();IIC_SendByte(AT24C02_ADDR_WRITE);IIC_WaitAck();IIC_SendByte(ReadAddr);IIC_WaitAck();IIC_Start();IIC_SendByte(AT24C02_ADDR_READ);IIC_WaitAck();*read_data = IIC_ReadByte();IIC_WaitAck();IIC_Stop();}void AT24CXX_soft_WriteOneByte(u16 WriteAddr,u8 DataToWrite)
{				   	  	    																 IIC_Start();IIC_SendByte(AT24C02_ADDR_WRITE);IIC_WaitAck();IIC_SendByte(WriteAddr);IIC_WaitAck();IIC_SendByte(DataToWrite);IIC_WaitAck();IIC_Stop();
}
void AT24CXX_soft_Read(u16 ReadAddr,u8 *pBuffer,u16 NumToRead)
{}  void AT24CXX_soft_Write(u16 WriteAddr,u8 *pBuffer,u16 NumToWrite)
{}/*** @brief 从AT24C02读取四字节数据* @param ReadAddr - 读取起始地址* @param read_data - 存储读取到的32位数据*/
void AT24CXX_soft_ReadFourBytes(u16 ReadAddr, uint32_t *read_data)
{uint8_t buf[4];// 确保地址不会越界if(ReadAddr > 0xFF - 3) {LOG_ERROR("AT24C02 read address out of range");*read_data = 0;return;}// 读取四个字节for(int i = 0; i < 4; i++) {AT24CXX_soft_ReadOneByte(ReadAddr + i, &buf[i]);osDelay(1);  // 适当延时}// 将四个字节组合成32位数据*read_data = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) | ((uint32_t)buf[2] << 8) | buf[3];
}/*** @brief 向AT24C02写入四字节数据* @param WriteAddr - 写入起始地址* @param DataToWrite - 要写入的32位数据*/
void AT24CXX_soft_WriteFourBytes(u16 WriteAddr, uint32_t DataToWrite)
{uint8_t buf[4];// 确保地址不会越界if(WriteAddr > 0xFF - 3) {LOG_ERROR("AT24C02 write address out of range");return;}// 分解32位数据为四个字节buf[0] = (DataToWrite >> 24) & 0xFF;  // 最高字节buf[1] = (DataToWrite >> 16) & 0xFF;buf[2] = (DataToWrite >> 8) & 0xFF;buf[3] = DataToWrite & 0xFF;          // 最低字节// 写入四个字节for(int i = 0; i < 4; i++) {AT24CXX_soft_WriteOneByte(WriteAddr + i, buf[i]);osDelay(5);  // 写入EEPROM需要时间,根据实际情况调整延时}
}void AT24C02_Test()
{{uint8_t data = 0;USART2_printf("will write\r\n");osDelay(1);AT24CXX_soft_WriteOneByte(0, 100);USART2_printf("weate data\r\n");osDelay(1);AT24CXX_soft_ReadOneByte(0,&data);USART2_printf("data:%d\r\n",data);}{int data_4_byte = 0;USART2_printf("will write\r\n");osDelay(1);AT24CXX_soft_WriteFourBytes(0, 0x11223344);USART2_printf("weate data\r\n");osDelay(1);AT24CXX_soft_ReadFourBytes(0,&data_4_byte);USART2_printf("data:%x\r\n",data_4_byte);        }}

at24c02.h

#ifndef _AT24c02_DRV_H
#define _AT24c02_DRV__H#include "stdint.h"
#include "stdbool.h"#define AT24C02		255
#define IIC1_SCL_GPIO_Port GPIOE
#define IIC1_SDA_GPIO_Port GPIOE
#define IIC1_SCL_Pin GPIO_PIN_0
#define IIC1_SDA_Pin GPIO_PIN_1typedef uint8_t u8;typedef uint16_t u16;#define IIC_SCL_0()         HAL_GPIO_WritePin(IIC1_SCL_GPIO_Port, IIC1_SCL_Pin, GPIO_PIN_RESET) 
#define IIC_SCL_1()         HAL_GPIO_WritePin(IIC1_SCL_GPIO_Port, IIC1_SCL_Pin, GPIO_PIN_SET)
#define IIC_SDA_0()         HAL_GPIO_WritePin(IIC1_SDA_GPIO_Port, IIC1_SDA_Pin, GPIO_PIN_RESET) 
#define IIC_SDA_1()         HAL_GPIO_WritePin(IIC1_SDA_GPIO_Port, IIC1_SDA_Pin, GPIO_PIN_SET) 
#define IIC_SDA_READ()      HAL_GPIO_ReadPin(IIC1_SDA_GPIO_Port, IIC1_SDA_Pin) /********************************************************************** API FUNCTIONS*/
void IIC_Init(void);			 
void IIC_Start(void);
void IIC_Stop(void);
void IIC_SendByte(u8 ucByte);
u8 IIC_ReadByte(void);
u8 IIC_WaitAck(void);
void IIC_Ack(void);
void IIC_NAck(void);
u8 IIC_CheckDevice(u8 address);static void SDA_OUT_MODE(void);
static void SDA_IN_MODE(void);#endif
http://www.dtcms.com/a/465661.html

相关文章:

  • 优化 Service 层架构:从高耦合到清晰分层的实战重构指南
  • 电子商务网站的运营一般需要做哪些准备怎么建设网站平台
  • AI × RWA 本地生活品牌数字资产管理与增长平台
  • 银行测试:第三方支付平台业务流,功能/性能/安全测试方法
  • JavaWeb零基础学习Day2——JS Vue
  • 网络网站知识app小程序可以自己开发吗
  • Google 智能体设计模式:Agent 间通信(A2A)
  • Google 智能体设计模式:目标设定与监控
  • C++设计模式之行为型模式:迭代器模式(Iterator)
  • 临沂做网站推广的公司有网站建设中管理员登录的代码怎么写
  • 基于小波变换的图像特征提取与畸变校正实现
  • uniapp AES 加密解密
  • 内蒙古城乡建设厅网站资质公告白云区pc端网站建设
  • 在JavaScript / HTML中,line-height是一个CSS属性
  • 程序员除了做软件是不是就做网站品牌策划 品牌年度服务
  • 网站登录注册页面模板网站开发 erp系统开发
  • LeetCode 面试经典 150_哈希表_最长连续序列(47_128_C++_中等)
  • Qt 为什么控件要用指针创建?
  • PostgreSQL的数据集成之路:ETL+CDC实现实时多源聚合
  • 【环境配置 】WSL2 +ubuntu20.04 +Qt配置+Kits配置
  • 设计架构:模型推理+生成证据视频 (一)
  • Webpack 微应用 vs Vite 微应用:从 __webpack_public_path__ 到 vite-plugin-qiankun
  • 精品网站别墅装修公司排名
  • 构建基于PyTorch的社交媒体情感倾向分析系统:从数据处理到模型部署
  • 经典SQL 50题 | 附带优化方案(更新中)
  • 做网站图结构微信里的小程序怎么打不开
  • SELECT*FROMarticlesLIMIT1;这个日常SQL如何排查潜在陷阱?MySQL数据库使用技巧解析
  • 百度搜索网站图片建设银行小微企业网站进不了
  • 官网设计比较好看的网站php学生管理系统源码免费
  • AWS云上ClickHouse数据仓库部署方案详解