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

GD32F103x IIC通信

1. IIC通信

1.IIC的介绍

   IIC总线有两条串行线,其一是时钟线SCK(同步),其二是数据线SDA。只有一条数据线属于半双工。应用中,单片机常常作为主机,外围器件可以挂载多个。(当然主机也可以有多个。多个主机都要访问从机需要仲裁机制。)每一个从机器件都拥有唯一的一个地址。  这样才能区分主机与哪个从机通信。如下图:

有两个从机与一个主机。


由于在设置SDA,SCL两个串行时GPIO时都会设置成开漏模式。开漏模式需要通过上拉电阻拉到高电平。

那么为什么不用复用推挽呢?都知道推挽能输出稳定的高低电平。当某一主机SDA为高,某一从机SDA为低。那么很可能短路。如果是开漏带上拉电阻的。就直接上拉电阻流向从机SDA低。这样是比较安全的。开漏模式组成线与的关系,任何一个器件都可以拉低电平。

2. IIC的时序图 

分为起始信号,数据传输,应答信号,停止信号

1. 起始信号 ,停止信号

2. 数据传输信号 

在SCL高电平时SDA必须稳定不变。等待从机读取。所以在SCL低电平时才可以改变。

3.应答信号。 

总结:我们在起始信号之后,主机开始发送传输的数据;在串行时钟线 SCL 为低电平状态时,SDA 允许改变传输的数据位(1 为高电平,0 为低电平),在SCL 为高电平状态时,SDA 要求保持稳定,相当于一个时钟周期传输 1bit 数据,经过8 个时钟周期后,传输了 8bit 数据,即一个字节。第8 个时钟周期末,主机释放SDA 以使从机应答,在第 9 个时钟周期,从机将 SDA 拉低以应答;如果第 9 个时钟周期,SCL 为高电平时,SDA 未被检测到为低电,视为非应答,表明此次数据传输失败。第 9 个时钟周期末,从机释放 SDA 以使主机继续传输数据,如果主机发送停止信号,此次传输结束。我们要注意的是数据以8bit 即一个字节为单位串行发出,其最先发送的是字节的最高位。 

3.IIC具体详细的数据帧格式

具体注意主机给从机呢还是从机给主机发送。看颜色的不同。

 4. IIC 实现的方式

对于有些51单片机可能没有IIC的硬件驱动。要用模拟GPIO的方式来实现。但现在的单片机都会有

硬件的IIC驱动。直接用就好了。

2. LM75温度传感器 

1.LM75的概述

1. LM75的AD转换原理 

内部的温度传感器感知一个模拟信号。

2. LM75框图

内部有一个温度传感器。通过操作指针寄存器读取温度传感器的值。

3. 温度怎么保存及怎么计算。 

 4. LM75寄存器介绍。

1. 配置寄存器

总结:具体详细的看LM75的手册。

3. doem (IIC 读取LM75温度)

用模拟IIC的方式来获取LM75的温度。通过串口打印出来。

硬件电路:用PB6,PB7GPIO口来模拟。

 

1. LM75的唯一地址(查手册)

1001  A0 = 1   A1 = 1  A2 =1 = 0x9E

2. 指针寄存器操作

指针寄存器包含一个 8 位的数据字节,低 2 位是其它 4 个寄存器的指针值,高 6 位等于 0 ,见指针寄 存器表格(表 3 )和指针值表格(表 4 )。指针寄存器对于用户来说是不可访问的,但通过将指针数据字节 包含到总线命令中可选择进行读/ 写操作的数据寄存器。

 配置寄存器(01):

3. 读温度寄存器的流程

 

4. 写配置寄存器的流程

 

总结:代码都是按流程来的。配合流程一起看。 

my_i2c_soft.h

#ifndef MY_I2C_SOFT_H
#define MY_I2C_SOFT_H
/**
@brief: 软件I2C的实现
*/#include "gd32f10x.h"#define I2C_SOFT_RCU       RCU_GPIOB
#define I2C_SOFT_PORT      GPIOB
#define I2C_SOFT_SCL_PIN   GPIO_PIN_6
#define I2C_SOFT_SDA_PIN   GPIO_PIN_7void my_i2c_init(void);    /* i2c的初始化 */void my_i2c_start(void);   /* i2c的起始 */
void my_i2c_stop(void);    /* i2c的结束 */void my_i2c_send_byte(uint8_t byte_to_send);  /* SDA发送一个byte */
uint8_t my_i2c_read_byte(void);               /* SDA读取一个byte */void my_i2c_ack(void);         /* 主机应答 */
void my_i2c_nack(void);        /* 主机非应答 */
uint8_t my_i2c_read_ack(void); /* 从机应答 */#endif

my_i2c_soft.c

#include "my_i2c_soft.h"
#include "systick.h"void my_i2c_w_SDA(uint8_t bit_value)
{gpio_bit_write(I2C_SOFT_PORT, I2C_SOFT_SDA_PIN, (bit_status)bit_value);delay_1us(10);
}void my_i2c_w_SCL(uint8_t bit_value)
{gpio_bit_write(I2C_SOFT_PORT, I2C_SOFT_SCL_PIN, (bit_status)bit_value);delay_1us(10);
}uint8_t my_i2c_r_SDA(void){return gpio_input_bit_get(I2C_SOFT_PORT, I2C_SOFT_SDA_PIN);
}//初始化函数
void my_i2c_init(void){rcu_periph_clock_enable(I2C_SOFT_RCU);/* 开漏模式 */gpio_init(I2C_SOFT_PORT, GPIO_MODE_OUT_OD, GPIO_OSPEED_50MHZ, I2C_SOFT_SCL_PIN|I2C_SOFT_SDA_PIN);gpio_bit_set(I2C_SOFT_PORT, I2C_SOFT_SCL_PIN|I2C_SOFT_SDA_PIN);
}//i2c的起始
void my_i2c_start(void){//SDA高,SCL高,SDA低,SCL低;   my_i2c_w_SDA(1);my_i2c_w_SCL(1);my_i2c_w_SDA(0);my_i2c_w_SCL(0); /* 为传输数据做准备,只有SCL才可以改变数据 */
}//i2c的结束
void my_i2c_stop(void){my_i2c_w_SDA(0);my_i2c_w_SCL(1);my_i2c_w_SDA(1);
}//SDA发送一个byte
void my_i2c_send_byte(uint8_t byte_to_send){uint8_t i;for(i = 0; i < 8; i++){my_i2c_w_SDA(byte_to_send & (0x80>>i));my_i2c_w_SCL(1); /* 从机来读 */my_i2c_w_SCL(0);}
}//SDA读一个byte
uint8_t my_i2c_read_byte(void){uint8_t result = 0x00;my_i2c_w_SDA(1); /* 主机释放 */uint8_t i;for(i = 0; i < 8; i++){my_i2c_w_SCL(1);if(my_i2c_r_SDA())result = result | (0x80 >> i);//读SDA的bit值my_i2c_w_SCL(0);}return result;
}//主机应答
void my_i2c_ack(void){my_i2c_w_SCL(0);my_i2c_w_SDA(0);my_i2c_w_SCL(1);my_i2c_w_SCL(0);
}//主机非应答
void my_i2c_nack(void){my_i2c_w_SCL(0);my_i2c_w_SDA(1);my_i2c_w_SCL(1);my_i2c_w_SCL(0);
}//主机读应答
uint8_t my_i2c_read_ack(void){uint8_t ack_result;my_i2c_w_SDA(1); /* 主机释放 */my_i2c_w_SCL(1);ack_result = my_i2c_r_SDA();my_i2c_w_SCL(0);return ack_result;	
}

 lm75a_temp.h

#ifndef __LM75A_TEMP_H
#define __LM75A_TEMP_H#include "gd32f10x.h"
#include "my_i2c_soft.h"#define LM75A_I2C_ADDR  0x9E   /* LM75A的从机地址 */#define LM75A_TEMP_REG  0x00   /* 温度寄存器的指针地址 */
#define LM75A_CONF_REG  0x01   /* 配置寄存器(Conf)*/
#define LM75A_THYST_REG 0x10   /* 滞后寄存器(Thyst) */
#define LM75A_TOS_REG   0x11   /* 过热关断寄存器(Tos) */#define IIC_WRITE 0
#define IIC_READ 1void lm75a_init(void);float lm75a_get_temp(void);     //获取温度传感器的温度值void lm75a_poweroff(uint8_t id_rw,uint8_t reg_addr,uint8_t data);        //关断温度传感器void lm75a_read_reg(uint8_t lm75a_id, uint8_t reg, uint8_t *p, uint8_t len);  //读温度寄存器的值
uint8_t lm75a_write_addr(uint8_t id_rw, uint8_t reg_addr);#endif

 lm75a_temp.c

#include "lm75a_temp.h"
#include "systick.h"void lm75a_init(void){my_i2c_init();
}// 读温度传感器的温度寄存器的值并转换为温度值
float lm75a_get_temp(void){float temp_result;//读温度寄存器值uint8_t byte_data[2];lm75a_poweroff(LM75A_I2C_ADDR | IIC_WRITE, LM75A_CONF_REG,0x00); /* 开启LM75 */lm75a_read_reg(LM75A_I2C_ADDR, LM75A_TEMP_REG, byte_data, 2);delay_1ms(100); /* 需要延时100ms */lm75a_poweroff(LM75A_I2C_ADDR | IIC_WRITE, LM75A_CONF_REG,0x01); /* 关闭LM75 *///将温度寄存器值转为温度值uint16_t temp_reg = byte_data[0]<<3 | byte_data[1]>>5;/* 判断D10是正负还是负数 0:正 1::负数 */if((temp_reg & 0x0400) == 0){temp_result = temp_reg * 0.125;}else{temp_reg = (~((temp_reg&0x03ff)-1)) & 0x03ff;    //补码到原码转换temp_result = temp_reg * (-0.125);}return temp_result;
}/***
功能:读温度寄存器的值
输入:uint8_t lm75a_id: lm75a的iic从机地址uint8_t reg:要操作的寄存器的指针uint8_t *p:读取结果存放的位置uint8_t len:寄存器的字节长度(1 or 2)
返回:无
*****/
void lm75a_read_reg(uint8_t lm75a_id, uint8_t reg, uint8_t *p, uint8_t len){//向iic总线上写入器件地址、指针字节lm75a_write_addr(lm75a_id|IIC_WRITE, reg);my_i2c_start();my_i2c_send_byte(lm75a_id|IIC_READ);my_i2c_read_ack();uint8_t i;for(i = 0; i < len; i++){*p++ = my_i2c_read_byte();if(i != (len-1))my_i2c_ack();}my_i2c_nack();my_i2c_stop();
}/***
输入:uint8_t id_rw:从机地址|读写标识
**/
uint8_t lm75a_write_addr(uint8_t id_rw, uint8_t reg_addr){my_i2c_start();my_i2c_send_byte(id_rw);my_i2c_read_ack();my_i2c_send_byte(reg_addr);my_i2c_read_ack();return 0;
}void lm75a_poweroff(uint8_t id_rw,uint8_t reg_addr,uint8_t data)      //关断温度传感器
{lm75a_write_addr(id_rw, reg_addr);my_i2c_send_byte(data);my_i2c_read_ack();my_i2c_stop();}

 main.c

#include <stdio.h>
#include "systick.h"
#include "usart_comm.h"
#include "lm75a_temp.h"int main(){systick_config();usart0_init(9600);float temp_result;char temp_string[80];lm75a_init();while(1){temp_result = lm75a_get_temp();sprintf(temp_string, "temperature is: %.3f C.\n", temp_result); /* 把浮点转成字符 */usart0_send_string((uint8_t *)temp_string); /* 打印温度 */delay_1ms(1000);  //等待1s}
}

 最终结果打印:

相关文章:

GD32F103x IIC通信

1. IIC通信 1.IIC的介绍 IIC总线有两条串行线&#xff0c;其一是时钟线SCK&#xff08;同步&#xff09;&#xff0c;其二是数据线SDA。只有一条数据线属于半双工。应用中&#xff0c;单片机常常作为主机&#xff0c;外围器件可以挂载多个。&#xff08;当然主机也可以有多个。…...

什么是FOSS

FOSS 是指 自由和开放源码软件(Free and Open Source Software)。这并不意味着软件是免费的。它意味着软件的源代码是开放的&#xff0c;任何人都可以自由使用、研究和修改代码。这个原则允许人们像一个社区一样为软件的开发和改进做出贡献。...

C++语言GDAL批量裁剪多波段栅格图像:基于像元个数裁剪

本文介绍基于C 语言的GDAL模块&#xff0c;按照给定的像元行数与列数&#xff0c;批量裁剪大量多波段栅格遥感影像文件&#xff0c;并将所得到的裁剪后新的多波段遥感影像文件保存在指定路径中的方法。 在之前的文章中&#xff0c;我们多次介绍了在不同平台&#xff0c;或基于不…...

简单丝的tab切换栏(html/CSS)

#html <!DOCTYPE html> <html lang"en" > <head><meta charset"UTF-8"><title>CSS实现左右滑动选项卡效果</title><link rel"stylesheet" href"https://cdnjs.cloudflare.com/ajax/libs/meyer-res…...

LabVIEW开发带式谱感测技术

LabVIEW开发带式谱感测技术 如今&#xff0c;通过无线网络传输的数据量正在迅速增加&#xff0c;并导致频谱稀缺。超过数十亿的无线设备将被连接起来&#xff0c;并需要互联网接入。因此&#xff0c;无线电频谱管理方案的效率不足以授予对所有设备的访问权限。在频谱分配中&am…...

认识柔性数组

在C99中&#xff0c;结构中的最后一个元素允许是未知大小的数组&#xff0c;这就叫做柔性数组成员 限制条件是&#xff1a; 结构体中最后一个成员未知大小的数组 1.柔性数组的形式 那么我们怎样写一个柔性数组呢 typedef struct st_type {int i;int a[0];//柔性数组成员 }ty…...

熔断、限流、降级 —— SpringCloud Alibaba Sentinel

Sentinel 简介 Sentinel 是阿里中间件团队开源的&#xff0c;面向分布式服务架构的高可用流量防护组件&#xff0c;主要以流量为切入点&#xff0c;从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性 Sentinel 提供了两个服务组件…...

python经典百题之反向输出数字

题目:输入一个整数&#xff0c;并将其反转后输出。 程序分析 我们需要对输入的整数进行反转&#xff0c;即将整数的数字反向排列。 方法1&#xff1a;使用字符串反转 解题思路 将整数转换为字符串&#xff0c;然后对字符串进行反转。 代码实现 def reverse_integer_usin…...

复习Day08:哈希表part01:242.有效的字母异位词、349. 两个数组的交集、1. 两数之和、160. 相交链表

之前的blog&#xff1a;https://blog.csdn.net/weixin_43303286/article/details/131765317 我用的方法是在leetcode再过一遍例题&#xff0c;明显会的就复制粘贴&#xff0c;之前没写出来就重写&#xff0c;然后从拓展题目中找题目来写。辅以Labuladong的文章看。然后刷题不用…...

用 Pytest+Allure 生成漂亮的 HTML 图形化测试报告

本篇文章将介绍如何使用开源的测试报告生成框架 Allure 生成规范、格式统一、美观的测试报告。 通过这篇文章的介绍&#xff0c;你将能够&#xff1a; 将 Allure 与 Pytest 测试框架相结合&#xff1b; 如何定制化测试报告内容 执行测试之后&#xff0c;生成 Allure 格式的测…...

Python字符串索引解码乱码谜题

输入数行“数字字母”字符组成的乱码字符串&#xff0c;根据谜题规则解码出乱码字符串中隐藏的单词信息。 (本笔记适合熟悉python字符串索引操作的 coder 翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”…...

协议栈——收发数据(拼接网络包,自动重发,滑动窗口机制)

目录 协议栈何时发送数据&#xff5e; 数据长度 IP模块的分片功能 发送频率 网络包序号&#xff5e;利用syn拼接网络包ack确认网络包完整 确定偏移量 服务器ack确定收到数据总长度 序号作用 双端告知各自序号 协议栈自动重发机制 大致流程 ack等待时间如何调整 是…...

传输层协议——TCP、UDP

目录 1、UDP 协议&#xff08;用户数据报协议&#xff09; 协议特点 报文首部格式 2、TCP 协议&#xff08;传输控制协议&#xff09; 协议特点 报文首部格式 TCP连接建立时的三次握手 TCP拆除连接的四次挥手 TCP的流量控制 TCP的拥塞控制 3、传输层端口号 三类端口…...

优化您的Spring应用程序:缓存注解的精要指南

优化您的Spring应用程序&#xff1a;缓存注解的精要指南 前言详细说明1. Cacheable&#xff1a;2. CacheEvict&#xff1a;3. CachePut&#xff1a;4. Caching&#xff1a;5. CacheConfig&#xff1a; 项目中的实现前提使用 前言 当我们构建和运行Spring应用程序时&#xff0c…...

Java之原子性问题的解决

2. 原子性 2.1 volatile-问题 代码分析 : package com.itheima.myvolatile; ​ public class Demo {public static void main(String[] args) {MyThread1 t1 new MyThread1();t1.setName("小路同学");t1.start(); ​MyThread2 t2 new MyThread2();t2.setName(&q…...

实时目标检测:基于YOLOv3和OpenCV的摄像头应用

一、前言 随着人工智能和计算机视觉技术的不断发展,目标检测成为了智能监控、自动驾驶、机器人等领域的关键技术之一。实时目标检测更是对系统的反应速度和准确度提出了更高的要求。本文介绍使用OpenCV和YOLOv3实现实时目标检测的方法,演示如何使用OpenCV调用YOLOv3模型进行…...

【软考】4.2 关系代数

《 关系代数 》 表和表之间的逻辑运算 笛卡尔积&#xff1a;S1 x S2 投影&#xff1a;π&#xff1b;选择某一列&#xff08;属性&#xff09;&#xff1b;一个关系R的投影操作结果也是一个关系&#xff0c;记作Πa&#xff0c;它由从关系R中选出的A列元素构成&#xff1b;选择…...

STM32F4学习笔记读取芯片UID和MAC地址

一、简介 在嵌入式设备开发过程中有时会需要为设备设置唯一的ID用以标识设备唯一&#xff0c;比如要求同一总线上的所有设备ID不能重复&#xff0c;要求设备具体唯一的MAC地址等等。每个STM32微控制器都自带一个96位的唯一ID&#xff0c;这个ID在任何情况下都是唯一且不允许修…...

webpack优化策略

这三点是webpack优化策略的一部分&#xff0c;具体解释如下&#xff1a; 优化正则匹配&#xff08;Test&#xff09;&#xff1a;在webpack的配置中&#xff0c;test属性是一个正则表达式&#xff0c;用于匹配需要应用该loader的文件的扩展名。在您提供的代码中&#xff0c;te…...

讲讲项目里的仪表盘编辑器(三)布局组件

布局容器处理 看完前面两章的讲解&#xff0c;我们对仪表盘系统有了一个大概的理解。接着我们讲讲更深入的应用。 上文讲解的编辑器只是局限于平铺的组件集。而在编辑器中&#xff0c;还会有一种组件是布局容器。它允许其他组件拖拽进入在里面形成自己的一套布局。典型的有分页…...

3分钟搞定Mac外接显示器控制:MonitorControl完全指南

3分钟搞定Mac外接显示器控制&#xff1a;MonitorControl完全指南 【免费下载链接】MonitorControl MonitorControl/MonitorControl: MonitorControl 是一款开源的Mac应用程序&#xff0c;允许用户直接控制外部显示器的亮度、对比度和其他设置&#xff0c;而无需依赖原厂提供的软…...

探索Unity全功能的开源方案:UniHacker跨平台功能扩展工具深度指南

探索Unity全功能的开源方案&#xff1a;UniHacker跨平台功能扩展工具深度指南 【免费下载链接】UniHacker 为Windows、MacOS、Linux和Docker修补所有版本的Unity3D和UnityHub 项目地址: https://gitcode.com/GitHub_Trending/un/UniHacker Unity作为游戏开发领域的行业标…...

QwQ-32B在ollama中的推理效果展示:数学定理推导、算法设计全过程

QwQ-32B在ollama中的推理效果展示&#xff1a;数学定理推导、算法设计全过程 1. 模型简介与部署准备 QwQ-32B是Qwen系列中专注于推理能力的语言模型&#xff0c;与传统指令调优模型相比&#xff0c;它在解决复杂问题和推理任务方面表现突出。这款中等规模模型拥有325亿参数&a…...

vue-beautiful-chat避坑指南:从安装配置到WebSocket实时通信的全流程解析

Vue2实时聊天组件深度实践&#xff1a;从vue-beautiful-chat配置到WebSocket全链路优化 当我们需要在Vue2项目中快速实现一个专业级聊天界面时&#xff0c;vue-beautiful-chat组件无疑是优雅的解决方案。但许多开发者在集成WebSocket实时通信功能时&#xff0c;常会遇到各种&q…...

GitHub访问加速终极指南:5分钟告别龟速访问的完整解决方案

GitHub访问加速终极指南&#xff1a;5分钟告别龟速访问的完整解决方案 【免费下载链接】fetch-github-hosts &#x1f30f; 同步github的hosts工具&#xff0c;支持多平台的图形化和命令行&#xff0c;内置客户端和服务端两种模式~ | Synchronize GitHub hosts tool, support m…...

【开发工具】Trae IDE 解决 Windows 下 C 工程无法跳转定义问题

1. 概要 &#x1f44b; 作为 Trae IDE 使用者&#xff0c;在 Windows 环境打开本地 C 工程时&#xff0c;习惯用 Ctrl 鼠标左键 快速跳转函数 / 变量定义却失效&#xff0c;仅能做文本匹配&#xff0c;无法精准定位语义定义。核心原因是 Trae 依赖 LSP&#xff08;语言服务器协…...

PTA编程题‘Person抽象类’避坑指南:变量命名冲突、多态指针数组与输出格式化的那些坑

PTA编程题‘Person抽象类’避坑指南&#xff1a;变量命名冲突、多态指针数组与输出格式化的那些坑 在C面向对象编程的实战中&#xff0c;抽象类和派生类的设计看似简单&#xff0c;却暗藏诸多陷阱。许多初学者在完成PTA/LeetCode这类编程题时&#xff0c;往往因为一些看似微不足…...

深度学习迁移学习:从原理到实践

深度学习迁移学习&#xff1a;从原理到实践 1. 背景与动机 深度学习模型在各种任务上取得了显著的性能提升&#xff0c;但这些模型通常需要大量的标注数据和计算资源进行训练。在实际应用中&#xff0c;我们经常面临以下挑战&#xff1a; 数据不足&#xff1a;某些任务的标注数…...

Mac上PPT讲稿一键变文稿:用AppleScript自动化导出备注到TXT(附完整代码)

Mac上PPT讲稿一键变文稿&#xff1a;用AppleScript自动化导出备注到TXT&#xff08;附完整代码&#xff09; 每次做完PPT&#xff0c;看着密密麻麻的备注栏&#xff0c;你是不是也头疼怎么把这些零散的讲稿整理成连贯的文档&#xff1f;作为一位经常需要准备培训材料的讲师&…...

vLLM-v0.17.1应用场景:智能硬件语音助手离线LLM推理部署

vLLM-v0.17.1应用场景&#xff1a;智能硬件语音助手离线LLM推理部署 1. 技术背景与需求分析 智能硬件语音助手正在经历从云端依赖向本地化处理的转变。传统方案面临三大痛点&#xff1a; 网络延迟问题&#xff1a;云端API调用导致响应速度受限隐私安全顾虑&#xff1a;用户对…...