GD32F103x IIC通信

news2024/11/21 2:23:29

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_7

void 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 1

void 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.coloradmin.cn/o/1058865.html

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

相关文章

【小程序 - 加强】自定义组件、使用npm包、全局数据共享、分包_05

目录 一、自定义组件 1. 组件的创建与引用 1.1 创建组件 1.2 引用组件 1.2.1 局部引用组件 1.2.2 全局引用组件 1.2.3 全局引用 VS 局部引用 1.2.4 组件和页面的区别 2. 样式 2.1 组件样式隔离 2.2 组件样式隔离的注意点 2.3 修改组件的样式隔离选项 2.4 styleIso…

stable diffusion学习笔记【2023-10-2】

L1&#xff1a;界面 CFG Scale&#xff1a;提示词相关性 denoising&#xff1a;重绘幅度 L2&#xff1a;文生图 女性常用的负面词 nsfw,NSFW,(NSFW:2),legs apart, paintings, sketches, (worst quality:2), (low quality:2), (normal quality:2), lowres, normal quality, (…

位置编码器

目录 1、位置编码器的作用 2、代码演示 &#xff08;1&#xff09;、使用unsqueeze扩展维度 &#xff08;2&#xff09;、使用squeeze降维 &#xff08;3&#xff09;、显示张量维度 &#xff08;4&#xff09;、随机失活张量中的数值 3、定义位置编码器类&#xff0c;我…

SpringBoot 可以同时处理多少请求

一、前言 首先&#xff0c;在Spring Boot应用中&#xff0c;我们可以使用 Tomcat、Jetty、Undertow 等嵌入式 Web 服务器作为应用程序的运行容器。这些服务器都支持并发请求处理的能力。另外&#xff0c;Spring Boot 还提供了一些配置参数&#xff0c;可以对 Web 服务器进行调…

传输层协议——TCP、UDP

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

一维数组和二维数组的使用(int类型)

目录 导读1. 一维数组1.1 一维数组的创建1.2 数组的初始化1.3 一维数组的使用1.4 一维数组在内存中的存储 2. 二维数组2.1 二维数组的创建2.2 二维数组的初始化2.3 二维数组的使用2.4 二维数组在内存中的存储 博主有话说 导读 本篇主要讲解一维数组和二维数组的创建和使用&…

【软考】4.2 关系代数

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

React18入门(第二篇)——React18+Ts项目配置husky、eslint、pretttier、commitLint

前言 我的项目版本如下&#xff1a; React&#xff1a; V18.2.0Node.js: V16.14.0TypeScript&#xff1a;最新版工具&#xff1a; VsCode 本文将采用图文详解的方式&#xff0c;手把手带你快速完成在React项目中配置husky、prettier、commitLint&#xff0c;实现编码规范的统…

OpenNebula的配置与应用(一)

学习了OpenNebula的安装之后&#xff0c;接下来就是配置OpenNebula&#xff0c;内容包括配置Sunstone&#xff0c;VDC和集群&#xff0c;设置影像&#xff0c;模板管理&#xff0c;虚拟机管理等。OpenNebula还有大量的工作要做&#xff0c;这些工作主要来自映像、模板和虚拟机管…

[架构之路-225]:计算机硬件与体系结构 - 分类方法大汇总: RISC, CISC

目录 一、分类方法汇总 二、指令流和数据流的关系分类 三、Flynn 分类&#xff1a;指令并行处理 四、根据指令集架构&#xff08;ISA&#xff09;分类 4.1 分类 4.2 开源的RISC-V与封闭的RISC指令集架构比较 4.3 RISC-V的演进路径 4.4 RISC-V与中国芯片自研 4.4 五阶流…

服务网关Gateway_入门案例

创建cloud-gateway-gateway9527工程 pom文件引入依赖 <dependencies><!-- 引入网关Gateway依赖 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></depe…

基于SpringBoot的社区医院管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

修改npm全局安装的插件(下载目录指向)

我们先打开终端 然后执行 npm config get prefix查看npm 的下载地址 一般都会在C盘 但是 我们都知道 C盘下东西多了是很不好的 所以 我们可以执行 npm config set prefix “E:\npmfile”将 npm 的下载地址 改变成 E盘下的 npmfile目录 这样 以后 默认全局安装的插件就会都到…

Mesa新版来袭

Mesa 17.1.6 发布了&#xff0c;Mesa 是一个三维&#xff08;3D&#xff09;图形库的开源集合&#xff0c;其主要目标是在 Linux / UNIX 操作系统下实现各种 API&#xff08;应用程序编程接口&#xff09;和 OpenGL 规范。 它面向 3D 计算机图形&#xff0c;硬件加速 3D 渲染和…

获取上证50的所有股票代码

我们可以从网页&#xff08;板块 - 上证50_ - 股票行情中心 - 搜狐证券&#xff09;中获取&#xff0c; 然后打印出来&#xff1a; import requests from bs4 import BeautifulSoupurl "https://q.stock.sohu.com/cn/bk_4272.shtml" response requests.get(url) …

Python数据透视表

Python数据透视表 1、Excel数据透视表2、Python数据透视表 1、Excel数据透视表 数据透视表&#xff08;Pivot Table&#xff09;是一种交互式的表&#xff0c;可以进行某些计算&#xff0c;如求和与计数等。所进行的计算与数据跟数据透视表中的排列有关 之所以称为数据透视表…

世界前沿技术发展报告2023《世界航天技术发展报告》(四)载人航天技术

&#xff08;四&#xff09;载人航天技术 1. 概述2. 美国多家商业公司开展载人航天发射和测试任务2.1 美国SpaceX公司载人“龙”飞船开展常态化载人任务&#xff0c;并完成首次全商业性太空载人任务2.2 美国蓝色起源公司成功开展两次亚轨道载人飞行任务2.3 美国波音公司“星际客…

Leecode121: 买卖股票的最佳时机1 2 3

第一个思路是从前往后进行遍历&#xff0c;记录一个最小值&#xff0c;然后往后维护一个最大值&#xff0c;不停的减去即可。 买卖股票的最佳时机2&#xff1a; prices [7,1,2,5,6,4] 在第二天买入&#xff0c;在第五天卖出&#xff0c;和不断买入卖出是一样的&#xff0c;所…

Vue中如何进行数据导出与Excel导出

当在Vue.js应用程序中需要进行数据导出并生成Excel文件时&#xff0c;你可以使用一些库和技术来实现这一功能。在本文中&#xff0c;我们将介绍如何在Vue.js中进行数据导出&#xff0c;以及如何将数据导出到Excel文件。我们将使用vue-json-excel库&#xff0c;它是一个用于将JS…

小狐狸ChatGPT付费创作系统V2.3.4独立版 +WEB端+ H5端 + 小程序最新前端安装测试教程

播播资源提供的GPT付费体验系统最新版系统是一款基于ThinkPHP框架开发的AI问答小程序&#xff0c;是基于国外很火的ChatGPT进行开发的Ai智能问答小程序。播播资源整体测试下来非常完美&#xff0c;本次播播资源提供的ChatGPT付费创作系统V2.3.4版本优化了很多细节&#xff0c;如…