STM32软件模拟I2C的实现方式(一)

文章目录

  • 关键代码:
  • 关键技术点
    • 时钟信号的稳定性和准确性:
    • 数据同步问题:
    • 应答位的处理:
    • 起始和停止条件的精确控制:

关键代码:

//产生IIC起始信号
static void IIC_Start(void)
{
IIC_SDA(1);
IIC_SCL(1);
delay_us(4);
IIC_SDA(0);//START:when CLK is high,DATA change form high to low
delay_us(4);
IIC_SCL(0);//钳住I2C总线,准备发送或接收数据
}
//产生IIC停止信号
static void IIC_Stop(void)
{
// Set_SDA_Output_Mode();//sda线输出
IIC_SCL(0);
IIC_SDA(0);//STOP:when CLK is high DATA change form low to high
delay_us(4);
IIC_SCL(1);
IIC_SDA(1);//发送I2C总线结束信号
delay_us(4);
}
//等待应答信号到来
//返回值:1,接收应答失败
// 0,接收应答成功
static u8 IIC_Wait_Ack(void)
{
u8 ucErrTime=0;
IIC_SDA(1);delay_us(1);
IIC_SCL(1);delay_us(1);
while(IIC_READ_SDA){
ucErrTime++;
if(ucErrTime>250){
IIC_Stop();
return 1;
}
}
IIC_SCL(0);//时钟输出0
return 0;
}
//产生ACK应答
static void IIC_Ack(void)
{
IIC_SCL(0);
IIC_SDA(0);
delay_us(2);
IIC_SCL(1);
delay_us(2);
IIC_SCL(0);
}
//不产生ACK应答
static void IIC_NAck(void)
{
IIC_SCL(0);
// Set_SDA_Output_Mode();
IIC_SDA(1);
delay_us(2);
IIC_SCL(1);
delay_us(2);
IIC_SCL(0);
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
static void IIC_Send_Byte(u8 txd)
{
u8 t;
IIC_SCL(0);//拉低时钟开始数据传输
for(t=0;t<8;t++){
if((txd&0x80))
IIC_SDA(1);
else
IIC_SDA(0);
txd<<=1;
delay_us; //对TEA5767这三个延时都是必须的
IIC_SCL(1);
delay_us;
IIC_SCL(0);
}
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
static u8 IIC_Read_Byte(unsigned char ack)
{
unsigned char i,receive=0;
for(i=0;i<8;i++ ){
IIC_SCL(0);
delay_us;
IIC_SCL(1);
receive<<=1;
if(IIC_READ_SDA)receive++;
delay_us(1);
}
if (!ack)
IIC_NAck();//发送nACK
else
IIC_Ack(); //发送ACK
return receive;
}
//reg_addr:开始读数的地址
//返回值 :读到的数据
static u8 IIC_ReadOneByte(uint8_t i2c_addr, uint8_t reg_addr)
{
u8 temp=0;
u8 i2c_address = i2c_addr;
u8 reg_address = reg_addr;
IIC_Start();
IIC_Send_Byte(i2c_address); //发送器件地址,写数据
IIC_Wait_Ack();
IIC_Send_Byte(reg_address); //发送
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(i2c_address|0x01); //进入接收模式
IIC_Wait_Ack();
temp=IIC_Read_Byte(0);
IIC_Stop();//产生一个停止条件
return temp;
}
//reg_addr :写入数据的目的地址
//reg_data:要写入的数据
static void IIC_WriteOneByte(uint8_t i2c_addr, uint8_t reg_addr, uint8_t reg_data)
{
u8 i2c_address = i2c_addr;
u8 reg_address = reg_addr;
IIC_Start();
IIC_Send_Byte(i2c_address); //发送器件地址,写数据
IIC_Wait_Ack();
IIC_Send_Byte(reg_address); //发送低地址
IIC_Wait_Ack();
IIC_Send_Byte(reg_data); //发送字节
IIC_Wait_Ack();
IIC_Stop();//产生一个停止条件
}
static void Dev_i2c_read(uint8_t Addr, uint8_t Reg, uint8_t *pBuffer, uint16_t Length)
{
u8 temp=0;
u8 i=0;
u8 i2c_address = Addr;
u8 reg_address = Reg;
IIC_Start();
IIC_Send_Byte(i2c_address); //发送器件地址,写数据
IIC_Wait_Ack();
IIC_Send_Byte(reg_address); //发送
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(i2c_address|0x01); //进入接收模式
IIC_Wait_Ack();
for(i = 0; i <Length; i++){
*pBuffer=IIC_Read_Byte(0);
pBuffer++;
}
IIC_Stop();//产生一个停止条件
}
static void Dev_i2c_write(uint8_t Addr, uint8_t Reg, uint8_t *pBuffer, uint16_t Length)
{
u8 i2c_address = Addr;
u8 reg_address = Reg;
IIC_Start();
IIC_Send_Byte(i2c_address); //发送器件地址,写数据
IIC_Wait_Ack();
IIC_Send_Byte(reg_address); //发送低地址
IIC_Wait_Ack();
while(Length–){
IIC_Send_Byte(*pBuffer); //发送字节
pBuffer++;
IIC_Wait_Ack();
}
IIC_Stop();//产生一个停止条件
}

关键技术点

时钟信号的稳定性和准确性:

时钟信号的稳定性和准确性对I2C通信的可靠性至关重要。在软件模拟中,需要确保时钟信号的频率和占空比在可接受的范围内。

数据同步问题:

在SCL高电平时,SDA线的状态必须保持稳定以防止数据读取错误。这要求在软件实现中严格控制数据的发送和接收时机。

应答位的处理:

应答位的处理是I2C通信中的一个重要环节。主机需要根据从机的应答情况来决定是否继续发送数据或采取其他措施。

起始和停止条件的精确控制:

起始和停止条件是I2C通信的边界条件,需要精确控制SCL和SDA线的电平变化以确保通信的顺利进行。

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

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

相关文章

回归预测||时序预测||基于灰狼优化的时域卷积TCN连接Transformer-BiLSTM的数据回归预测|时序预测Matlab程序

回归预测||时序预测||基于灰狼优化的时域卷积TCN连接Transformer-BiLSTM的数据回归预测|时序预测Matlab程序 文章目录 一、基本原理一、基本概念二、原理和流程1. 数据准备2. 模型构建3. 灰狼优化算法设计4. 模型训练与优化5. 模型评估与预测 三、优势与应用四、总结 二、实验结…

Docker 用例:15 种最常见的 Docker 使用方法

容器化应用程序而不是将它们托管在虚拟机上是过去几年一直流行的概念&#xff0c;使容器管理流行起来。Docker 处于这一转变的核心&#xff0c;帮助组织无缝地采用容器化技术。最近&#xff0c;Docker 用例遍布所有行业&#xff0c;无论规模大小和性质如何。 什么是Docker&…

Windows--使用node.js的免安装版本

原文网址&#xff1a;Windows--使用node.js的免安装版本_IT利刃出鞘的博客-CSDN博客 简介 本文介绍Windows下如何使用node.js的免安装版本。 下载 1.访问官网 https://nodejs.org/en 记住这个版本号&#xff0c;这个是长期支持的版本。 2.找到压缩包 点击其他下载&#…

windows系统中,在cmd窗口演练 Redis 基本操作命令

文章目录 一、Redis 介绍1.1 Redis 的应用场景1.2 Redis 的特点 二、Windows版Redis安装三、Redis Desktop Manager安装四、Redis 常用基本操作4.1 查看操作4.2 操作string类型的命令4.2.1 设置获取Key4.2.2 MSET&#xff08;Multi&#xff09;支持批量设置key、MGET支持批量获…

平时使用Xshell能连接虚拟机,现在突然连接不上

问题&#xff1a;平时使用Xshell能连接虚拟机&#xff0c;现在突然连接不上&#xff0c;使用ip addr 命令查看ip地址 ens33 接口状态为 DOWN&#xff0c;没有分配IP地址&#xff0c;这通常意味着该网络接口未激活或存在配置问题。&#xff08;因为平时能连接&#xff0c;就说明…

DNS代理是什么?浅析DNS代理的工作原理及应用

DNS代理作为计算机网络中重要的一环&#xff0c;扮演着连接用户和互联网服务的关键角色。来了解DNS代理的定义、功能、工作原理以及在网络中的应用场景和重要性吧。 一、理解DNS代理。 DNS代理充当在用户和真正的DNS服务器之间的中介。它接收来自用户端的DNS查询请求&#xf…

std::function和bind绑定器

本文来自《深入应用C11 代码优化与工程级应用》 std::function和std::bind&#xff0c;使我们使用标准库函数时更加方便&#xff0c;且还能方便地实现延迟求值。 1.可调用对象(Callable Objects) 可调用对象有如下几种定义&#xff1a; (1)是一个函数指针 #include<ios…

php elasticsearch/elasticsearch使用apikey访问接口

此处使用的windows版es和kibana。 1.前提&#xff1a;以安装好es和kibana并正常运行&#xff0c;记得保存es安装完成时提示的账号密码。 2.登录kibana,创建索引并加入几条数据,可以通过kibana界面添加或者通过调用接口添加&#xff0c;非重点不赘述了。 3.添加ApiKey, 使用…

Linux 部署 Harbor 镜像仓库详解

文章目录 安装 Docker安装 Harbor访问 Harbor 安装 Docker 本次部署流程使用的是1台阿里云ECS&#xff0c;Ubuntu 22.04&#xff0c;2核4G。 首先需要做的是在当前服务器上&#xff0c;安装好 Docker&#xff0c;参考链接如下&#xff1a; https://blog.csdn.net/weixin_4659…

ESD防静电闸机如何保护汽车电子产品

随着汽车电子技术的快速发展&#xff0c;汽车中集成了越来越多的电子设备&#xff0c;如车载信息娱乐系统、自动驾驶传感器、驾驶辅助系统等。静电放电可能导致电子组件的损坏、性能下降&#xff0c;甚至使整个系统失效。因此&#xff0c;如何有效保护汽车电子产品免受静电损害…

【【自动驾驶】车辆运动学模型】

【自动驾驶】车辆运动学模型 1. 引言2. 以车辆重心为中心的单车模型2.1 模型介绍2.2 滑移角 β \beta β 的推导2.2 航向角 ψ \psi ψ推导过程&#xff1a;2.3 滑移角 β \beta β2.3 Python代码实现2.4 C代码实现 3. 前轮驱动的单车模型3.1 模型介绍3.3 Python代码实现3.4 …

软件I2C的代码

I2C的函数 GPIO的配置——scl和sda都配置为开漏输出 void MyI2C_Init(void) {RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);GPIO_InitTypeDef GPIO_InitStruture;GPIO_InitStruture.GPIO_Mode GPIO_Mode_Out_OD;GPIO_InitStruture.GPIO_PinGPIO_Pin_10 | GPIO_Pin_…

Debug-029-el-table实现自动滚动分批请求数据

前情提要 最近做了一个小优化&#xff0c;还是关于展示大屏方面的。大屏中使用el-table展示列表数据&#xff0c;最初的方案是将数据全部返回&#xff0c;确实随着数据变多有性能问题&#xff0c;有时请求时间比较长。这里做的优化就是实现列表的滚动到距离底部一定高度时再次请…

【银河麒麟高级服务器操作系统实例】金融行业TCP连接数猛增场景的系统优化

了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer.kylinos.cn 文档中心&#xff1a;https://documentkylinos.cn 服务器环境以及配置 物理机/虚拟机/云/容器 物理…

项目实战:Qt+OpenCV仿射变换工具v1.1.0(支持打开图片、输出棋盘角点、调整偏移点、导出变换后的图等等)

若该文为原创文章&#xff0c;转载请注明出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/143105881 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、Op…

python中frida的安装+frida-server(雷电模拟器)保姆级安装教程

一.安装雷电模拟器 雷电模拟器官网 直接下载安装即可 &#xff08;1&#xff09;打开必要权限 雷电模拟器的设置已完毕 二.安装adb工具 本文以autox.js来实现adb操作 &#xff08;1&#xff09;vscode中下载auto.js插件 &#xff08;2&#xff09;雷电模拟器下载autox.j…

【大模型实战篇】大模型分词算法Unigram及代码示例

1. 算法原理介绍 与 BPE 分词&#xff08;参考《BPE原理及代码示例》&#xff09;和 WordPiece 分词&#xff08;参考《WordPiece原理及代码示例》&#xff09;不同&#xff0c;Unigram 分词方法【1】是从一个包含足够多字符串或词元的初始集合开始&#xff0c;迭代地删除其中的…

Spring Boot Druid 数据库连接池入门

1. Druid 单数据源 1.1 引入依赖 在 pom.xml 文件中&#xff0c;引入相关依赖。 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-insta…

《异常处理与资源管理:构建稳定程序的关键纽带》

#1024程序员节&#xff5c;征文# 在软件开发的广袤领域中&#xff0c;异常处理和资源管理如同两座坚实的基石&#xff0c;共同支撑着程序的稳定运行。它们之间的关系紧密而微妙&#xff0c;对于构建可靠、高效的软件系统起着至关重要的作用。让我们深入探讨异常处理和资源管理…

idea项目搭建的四种方式: 一(以idea2017为例)

目录 1. 普通java项目 2. 普通JavaWEB项目 3. maven的JavaWEB项目 4. maven的java项目 1. 普通java项目 ①点击“Create New Project”&#xff1b; ②选择“Java”&#xff0c;选择自己安装的jdk&#xff0c;点击“Next”&#xff1b; ③填好项目名称和路径&#xff1b;…