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

嵌入式软件--DAY8 IIC通讯下 硬件实现

正常写项目,用硬件只会更快。51没有IIC外设,我们需要软件模拟,在STM32中我们可以大胆使用硬件,只需要操作IIC外设对应的寄存器即可。

1.硬件电路设计

1.1配置

可以看到IIC模块挂在APB1系统总线上。

复用引脚PB10 PB11,底层协议硬件实现了,我们自己做好配置外设,他会自动根据协议产生通讯信号,收发数据并缓存起来,CPU只要检测该外设的状态和访问数据寄存器ODR,就能完成数据收发。

STM32外设的iic外设可用作主机和从机,没有明确规定。支持两种速率:100kbit/s,400kbit/s。

支持7位、10位设备地址,支持DMA数据传输,并具有数据校验功能。

iic外设还支持SMBUS2.0协议,SMBUS与IIC类似。

1.2功能框图

控制寄存器2个 CR1 CR2

状态寄存器2个 SR1 SR2

2.寄存器初始化配置

用PB10 PB11与EEPROM进行通讯。

2.1寄存器详解

2.1.1控制寄存器CR

PE最后一步开

只要产生起始条件了,就可以成为主设备

SWRST:软件复位

2.1.2时钟控制寄存器 I2C_CCR

占空比:高电平占周期比例

TRISE:上升折线所占时钟周期

3.硬件实现IIC,寄存器案例

3.1 初始化配置

配置成复用开漏模式,开启内部上拉电阻。开启IO和IIC时钟使能。配置速率。

void I2C_Init(void)
{// 1. 配置时钟RCC->APB2ENR |= RCC_APB2ENR_IOPBEN;RCC->APB1ENR |= RCC_APB1ENR_I2C2EN;// 2. GPIO配置,PB10、PB11 复用开漏输出,MODE - 11, CNF - 11GPIOB->CRH |= (GPIO_CRH_MODE10 | GPIO_CRH_MODE11 | GPIO_CRH_CNF10 | GPIO_CRH_CNF11);// 3. I2C 配置// 3.1 硬件工作模式配置I2C2->CR1 &= ~I2C_CR1_SMBUS; // I2C模式I2C2->CCR &= ~I2C_CCR_FS;    // 标准模式// 3.2 时钟频率 36MHzI2C2->CR2 |= 36 << 0;// 3.3 高电平时间:5us - 180个时钟周期;100kbpsI2C2->CCR |= 180 << 0;// 3.4 上升沿时间 1us - 36个时钟周期I2C2->TRISE |= 37;// 3.5 使能I2C模块I2C2->CR1 |= I2C_CR1_PE;
}

3.2 时序 

// 主机发出起始信号
uint8_t I2C_Start(void)
{// 产生起始信号I2C2->CR1 |= I2C_CR1_START;// 等待起始信号发出uint16_t timeout = 0xffff; // 超时时间while ((I2C2->SR1 & I2C_SR1_SB) == 0 && timeout){timeout--;}return timeout ? OK : FAIL;
}// 主机设置收发完数据之后发出停止信号
void I2C_Stop(void)
{I2C2->CR1 |= I2C_CR1_STOP;
}// 主机设置发送应答/非应答信号
void I2C_Ack(void)
{I2C2->CR1 |= I2C_CR1_ACK;
}
void I2C_NAck(void)
{I2C2->CR1 &= ~I2C_CR1_ACK;
}// 主机发送设备地址
uint8_t I2C_SendAddr(uint8_t addr)
{// 将要发送的地址写入DR,自动发送I2C2->DR = addr;// 等待地址成功发出(等待应答)uint16_t timeout = 0xffff; // 超时时间while ((I2C2->SR1 & I2C_SR1_ADDR) == 0 && timeout){timeout--;}I2C2->SR2; // 清除 ADDR 标志位return timeout ? OK : FAIL;
}// 主机发送一个字节
uint8_t I2C_SendByte(uint8_t byte)
{// 将要发送的数据写入DR,自动发送I2C2->DR = byte;// 等待字节发送完成(等待应答)uint16_t timeout = 0xffff; // 超时时间while ((I2C2->SR1 & I2C_SR1_BTF) == 0 && timeout){timeout--;}I2C2->DR; // 清除 BTF 标志位return timeout ? OK : FAIL;
}// 主机从SDA读取一个字节
uint8_t I2C_ReadByte(void)
{// 等待字节接收完成uint16_t timeout = 0xffff; // 超时时间while ((I2C2->SR1 & I2C_SR1_RXNE) == 0 && timeout){timeout--;}return timeout ? I2C2->DR : FAIL;
}

4.硬件实现IIC,HAL库写法

4.1 CUBEMX图形化界面配置

配置IIC引脚

IIC轻松配置完毕。

命名

因为与EEPROM通讯,最后需要对传输的数据进行窗口显示,开启串口

出现打开项目的窗口,一定先打开。会出现KEIL文件工程。

4.2 keil编译器配置

我们不能在图形化界面中生成EEPROM文件,我们需要自己添加。

之后就是老一套。勾勾减减即可。之后我们用VSCode打开。

4.3 代码编写

我们首先要将fputc重新写一下。这是基本操作了。

在usart.c里写fputc

int fputc(int ch, FILE *file)
{HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 1000);return ch;
}

因为M24c02不是cubemx生成,所以与我们生成的文件在函数声明上存在差异,逻辑一致,但只要把声明改改。

/** @Author: wushengran* @Date: 2024-09-23 14:07:07* @Description:** Copyright (c) 2024 by atguigu, All Rights Reserved.*/
#include "m24c02.h"// 初始化
void M24C02_Init(void)
{MX_I2C2_Init();
}// 写入一个字节,指定要写入的内部地址
void M24C02_WriteByte(uint8_t innerAddr, uint8_t byte)
{HAL_I2C_Mem_Write(&hi2c2, W_ADDR, innerAddr, I2C_MEMADD_SIZE_8BIT, &byte, 1, 1000);// 加入延迟,等待写入EEPROM完成HAL_Delay(5);
}// 读取一个字节(随机地址读)
uint8_t M24C02_ReadByte(uint8_t innerAddr)
{uint8_t byte;HAL_I2C_Mem_Read(&hi2c2, R_ADDR, innerAddr, I2C_MEMADD_SIZE_8BIT, &byte, 1, 1000);return byte;
}// 连续写入多个字节(页写)
void M24C02_WriteBytes(uint8_t innerAddr, uint8_t *bytes, uint8_t size)
{HAL_I2C_Mem_Write(&hi2c2, W_ADDR, innerAddr, I2C_MEMADD_SIZE_8BIT, bytes, size, 1000);// 加入延迟,等待写入EEPROM完成HAL_Delay(5);
}// 连续读取多个字节
void M24C02_ReadBytes(uint8_t innerAddr, uint8_t *bytes, uint8_t size)
{HAL_I2C_Mem_Read(&hi2c2, R_ADDR, innerAddr, I2C_MEMADD_SIZE_8BIT, bytes, size, 1000);
}

串口这里就没问题了,如果想验证,可以打印一些数据。

在main里引入

构建并烧写

串口传输没有问题。

然后可以针对性对字节写入,字节读取进行测验。

http://www.xdnf.cn/news/634717.html

相关文章:

  • 解决WPF短暂的白色闪烁(白色闪屏)
  • 从智能提效到产品赋能的架构实践
  • Pycharm and Flask 的学习心得(9)
  • PCB 通孔是电容性的,但不一定是电容器
  • CSS相关知识
  • 基于PyTorch的残差网络图像分类实现指南
  • 如何理解Pytorch中前向传播的计算过程
  • 小土堆pytorch--神经网络搭建小实战Sequential的使用
  • 高可用 Redis 服务架构分析与搭建
  • 【C/C++】从零开始掌握Kafka
  • P2676 [USACO07DEC] Bookshelf B
  • 电商小程序店铺详情页:头部无限分类与筛选功能实现
  • LabVIEW实战项目推荐与学习建议
  • 打卡第28天:装饰器
  • 【HarmonyOS5】DevEco Studio 预览器与模拟工具详解
  • 掌握聚合函数:COUNT,MAX,MIN,SUM,AVG,GROUP BY和HAVING子句的用法,Where和HAVING的区别
  • TIGER - 一个轻量高效的语音分离模型,支持人声伴奏分离、音频说话人分离等 支持50系显卡 本地一键整合包下载
  • 【Android】非System用户下Persist应用不自动拉起
  • 破解C/C++内存分配与管理:内存对象模型硬核剖析
  • LeetCode-图论-岛屿数量+腐烂的橘子
  • Leetcode 3103. 查找热门话题标签 II
  • 仓鼠找sugar--lca+图论判断点在路径
  • LangChain02-Agent与Memory模块
  • git子模块--命令--列表版
  • 机器学习——支持向量机SVM
  • 类欧几里得算法(floor_sum)
  • uni-app学习笔记十四-vue3中emit的使用
  • Lua 脚本在 Redis 中的运用-23(Lua 脚本语法教程)
  • 计算机视觉中的可重复性:深入案例分析与Python代码实现
  • 【MySQL成神之路】MySQL函数总结