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}
}

 最终结果打印:

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

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

相关文章

想要精通算法和SQL的成长之路 - 验证二叉树的前序序列化

想要精通算法和SQL的成长之路 - 验证二叉树的前序序列化 前言一. 验证二叉树的前序序列化 前言 想要精通算法和SQL的成长之路 - 系列导航 一. 验证二叉树的前序序列化 原题链接 思路&#xff08;参考负雪明图&#xff09;&#xff1a; 首先我们看题目所给的字符串&#xff…

【Diffusion】DDPM - (2)公式推导 之 前向扩散

1、加噪过程 1、将 图像 x 0 x_0 x0​ 像素值映射到 [-1, 1] 之间 x 255 2 − 1 , w h e r e    x 为图像中的像素值 \quad \frac{x}{255} \times 2-1, \quad where \; x 为图像中的像素值 255x​2−1,wherex为图像中的像素值 \quad 2、生成一张尺寸相同的噪声图片,像…

边缘计算网关

一、项目整体框架图 二、项目整体描述 边缘计算网关项目主要实现了智能家居场景和工业物联网场景下设备的数据采集和控制。 整个项目分为三大层&#xff1a;用户接口层、网关层、设备层。 其中用户层通过QT客户端、WEB界面及阿里云提供数据展示和用户接口。 网关使用虚拟机代替…

Django之十二:模板的继承+用户列表

模板的继承 新建layout.html&#xff1a; {% load static %} <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><link rel"stylesheet" href"{% static plugins…

231003-四步MacOS-iPadOS设置无线竖屏随航SideCar

Step 0&#xff1a;MacOS到iPad无线竖屏随航显示&#xff0c;最终效果 Step 1&#xff1a; 下载 Better Display Step 2&#xff1a;在设置中新建虚拟屏幕&#xff0c;创建虚拟屏幕 Step 3&#xff1a;进行如下设置 Step 4&#xff1a;注意事项 ⚠️ 设置后的虚拟屏幕与Sideca…

nodejs+vue晓海网上订餐系统elementui

管理员功能需求 管理员登陆后&#xff0c;主要模块包括首页、个人中心、用户管理、菜单信息管理等功能。 第三章 系统分析 10 3.1需求分析 10 3.2可行性分析 10 3.2.1技术可行性&#xff1a;技术背景 10 3.2.2经济可行性 11 3.2.3操作可行性&#xff1a; 11 3.3性能分析 11 3.4…

IntelliJ IDEA配置Cplex12.6.3详细步骤

Cplex12.6.3版IntelliJ IDEA配置详细步骤 一、Cplex12.6.3版下载地址二、Cplex安装步骤三、IDEA配置CPLEX3.1 添加CPLEX安装目录的cplex.jar包到项目文件中3.2 将CPLEX的x64_win64文件夹添加到IDEA的VM options中 四、检查IDEA中Cplex是否安装成功卸载Cplex 一、Cplex12.6.3版下…

我用PYQT5做的第一个实用的上位机项目(三)

基本的程序框架&#xff1a; 因为自己不是专业的程序员&#xff0c;只是一个搞电气控制的“票友”&#xff0c;所以尽量减少手动输入 代码量&#xff0c;能在Qt Dsigner里面完成的组态就不要放在代码里面完成。 在框架的建设方面&#xff0c;尽量做到集中和整合&#xff0c;位…

科技+智慧+颜值,智慧公厕黑科技提升城市形象

现代社会的科技和智慧正以惊人的速度渗透到我们生活的各个方面&#xff0c;包括公共设施。而作为城市形象的重要组成部分之一&#xff0c;公厕也在不断创新中迎来了智慧的时代。 在传统的公厕中&#xff0c;一些问题一直困扰着我们&#xff0c;比如厕位的占用情况、空气质量的…

Git多账号管理通过ssh 公钥的方式,git,gitlab,gitee

按照目前国内访问git&#xff0c;如果不科学上网&#xff0c;我们很大可能访问会超时。基于这个&#xff0c;所以我现在的git 配置已经增加到了3个了 一个公司gitlab&#xff0c;一个git&#xff0c;一个gitee. 以下基于这个环境&#xff0c;我们来说明下如何创建配置ssh公钥。…

UE中制作棋盘格材质效果

在UE中通过这个小技巧制作棋盘格材质效果&#xff0c;可以快速预览UV拉伸情况&#xff0c;方便调试导入的模型。 1.操作步骤 1.1 首先新建材质&#xff0c;Shading Model&#xff08;着色模式&#xff09;设置为Unlit&#xff08;无光照&#xff09;&#xff1a; 1.2 我们…

前端相关题目随笔

Vh虽然获取到了视口高度&#xff0c;但是vh会随着屏幕的、大小变化&#xff0c;所以当减去一个数字之后&#xff0c;就会显示错误。 生成id 如果没有设置id&#xff0c;则可以通过new Date.getTime()获取一个时间&#xff0c;作为一个单独的id&#xff0c;也可以通过下载uuid生…

JavaScript系列从入门到精通系列第十二篇:JavaScript中对象的简介和对象的基本操作以及JavaScript中的属性值和属性名

文章目录 前言 一&#xff1a;对象分类 1&#xff1a;内建对象 2&#xff1a;宿主对象 3&#xff1a;自建对象 二&#xff1a;对象的基本操作 1&#xff1a;创建对象 2&#xff1a;向对象中添加属性 3&#xff1a;读取对象中的属性 4&#xff1a;修改对象中的属性 三…

机器学习7:逻辑回归

一、说明 逻辑回归模型是处理分类问题的最常见机器学习模型之一。二项式逻辑回归只是逻辑回归模型的一种类型。它指的是两个变量的分类&#xff0c;其中概率用于确定二元结果&#xff0c;因此“二项式”中的“bi”。结果为真或假 — 0 或 1。 二项式逻辑回归的一个例子是预测人…

【PickerView案例12-info_plist-PCH文件介绍 Objective-C语言】

一、给大家介绍一下我们项目的一些文件: 1.这个呢,是项目的基础文件: 一些类啊: 一些图片啊: 还有加载图片, 最主要,就是这个东西:info.plist:文件 info.plist: 2.那,需要大家了解一点,关于它的历史啊: 我们现在用的时候,都是从xcode6.4开始的, 或者说,直…

Python 数据分析与挖掘(一)

Python 数据分析与挖掘&#xff08;数据探索&#xff09; 数据探索 1.1 需要掌握的工具&#xff08;库&#xff09; 1.1.1 Nump库 Numpy 提供多维数组对象和各种派生对象&#xff08;类矩阵&#xff09;&#xff0c;利用应用程序接口可以实现大量且繁琐的数据运算。可以构建…

Linux 5种网络模型

[参考]&#xff1a;《黑马程序员Redis》https://www.bilibili.com/video/BV1cr4y1671t/?p166&share_sourcecopy_web&vd_source9e65300ccca322aeb367bb1eb677b0fc [参考]&#xff1a;《操作系统》 [参考]&#xff1a;《UNIX网络编程》 为了避免用户应用导致冲突甚至内…

基于SSM的奶茶店管理系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

WebSocket实战之三遇上PAC

一、前言 前两天销售数据实时刷新功能开发测试完成&#xff0c;开开心心部署到生产环境&#xff0c;然后直接懵逼傻眼了&#xff0c;竟然连接不上WebSocket服务端&#xff0c;浏览器端请求头报 Provisional headers are shown 信息&#xff0c;然后采用一系列操作排查问题。 …

89、Redis 的 value 所支持的数据类型(String、List、Set、Zset、Hash)---->Zset 相关命令

本次讲解要点&#xff1a; ** Set相关命令&#xff1a;是指value中的数据类型** 启动redis服务器&#xff1a; 打开小黑窗&#xff1a; C:\Users\JH>e: E:>cd E:\install\Redis6.0\Redis-x64-6.0.14\bin E:\install\Redis6.0\Redis-x64-6.0.14\bin>redis-server.exe …