七、I2C通信读取LM75B温度

7.1 概述

I2C(Inter-Integrated Circuit)是一种同步、多主从、串行通信协议,由飞利浦公司开发,主要用于短距离通信,尤其在集成电路之间。

7.1.1 主要特点

两线制:仅需SDA(数据线)和SCL(时钟线)两根线。

多主从结构:支持多个主设备和从设备。

地址寻址:每个从设备有唯一地址,主设备通过地址选择通信对象。

低速到中速:标准模式100 kbps,快速模式400 kbps,高速模式3.4 Mbps。

7.1.2 通信过程

I²C 总线可以连接多个从设备,每个从设备都有一个唯一的地址(7 位或 10 位)。

主设备通过发送从设备地址来选择与之通信的从设备。

当主设备发送从设备地址时,从设备会将自己的地址与接收到的地址进行比较。

如果地址匹配,从设备会响应主设备并参与后续通信;如果不匹配,从设备会忽略通信。

主机发送起始信号 拉低总线,然后再发送一个字节来指明跟哪个从机通信(从机地址 )以及通信的方向(主机收信息还是主机发信息 ),然后被寻址的从机发送应答信号回应主机,之后就开始发收了,主发从收,或者从收主发,发送器发一个,接收器应答一下。在发送完后,主机发送停止信号释放总线。

起始条件:SCL高电平时,SDA从高到低跳变。

地址传输:主设备发送7位或10位从设备地址和读写位。

数据传输:每8位数据后跟一个ACK/NACK确认位,即9位。

停止条件:SCL高电平时,SDA从低到高跳变。

在发送过程中,数据只在SCL为高电平时发送,每一个SCL的高电平发送一位(位数高到低),除了起始和停止信号,在数据传输期间,SCL为高电平时,SDA必须保持稳定,不允许改变,在SCL低电平时才可以进行变化。

发送器发8个信号,接收器应答一下,应答为低电平,非应答高电平,可能没收到,或者不收了

7.2 引脚及温度传感器介绍

7.2.1 SCL、SDA

如下图左边,SCL对应CPU引脚为PIO0_4, SDA对应CPU引脚为PIO0_5。

7.2.2 LM75B温度传感器

将测量到的温度通过数据线发出,发两次,高8位,低8位,拼接起来就行

7.3 寄存器

7.3.1 控制置位寄存器 I2C0CONSET

通过写1使相应位置位,写0无效

|-----|------|--------------------------------------------|
| 位 | 符号 | 描述 |
| 1:0 | | 保留 |
| 2 | AA | 声明应答标志,为0返回非应答信号 |
| 3 | SI | I2C中断标志,I2C状态改变时SI置位 |
| 4 | STO | 停止标志,总线检测到停止条件自动清零 主模式下发送停止条件 从模式下从错误状态中恢复 |
| 5 | STA | 开始标志,进入主模式,发送起始条件或重复起始条件 |
| 6 | I2EN | 接口使能 |
| 7 | | 保留 |

7.3.2 I2C控制清零寄存器 I2C0CONCLR

写1将I2C0CONSET中的寄存器相应位清零

|-----|-------|------------|
| 位 | 符号 | 描述 |
| 1:0 | | 保留 |
| 2 | AAC | 声明应答清零 |
| 3 | SIC | 中断清零 |
| 4 | | 保留 |
| 5 | STAC | START标志位清零 |
| 6 | I2ENC | 接口禁能 |
| 7 | | 保留 |

7.3.3 状态寄存器 I2C0STAT

只读寄存器。 [7:3]位存状态码,0xF8时SI不置位,其他状态码对应一个I2C状态,这些状态对应其中任一状态时,SI置位。

7.3.4 数据寄存器 I2C0DAT

包含要发送的数据或刚接收的数据。收发都是从右向左移位,先高位7MSB,再低位

7:0\]存已接收或将要发送的数据值 ### 7.3.5 监控模式寄存器 I2C0MMCTRL 在I2C总线的监控模式下,设备可以监视I2C总线上正在进行的所有通信活动,包括读取数据、写入数据等,但不会对总线进行控制。 |---|----------|---------------------------------------------------------------| | 位 | | 1有效 | | 0 | MM_ENA | 监控模式使能 SDA输出被强制为高电平,防止I2C模块向总线输出数据 | | 1 | ENA_SCL | SCL输出使能 模块可以与正常操作中相同方式控制时钟线 可以使得有足够时间相应I2C中断 | | 3 | MATCHALL | 选择中断寄存器匹配 0:只有在4个地址寄存器中的一个出现匹配才产生中断 1:可在任意接收地址上产生中断,监控总线上所有通信 | ### 7.3.6 数据缓冲寄存器 I2C0DATABUFFER \[7:0\]位保存I2C0DAT数据寄存器中高8位内容 在监控模式下,ENA_SCL不置位,则I2C模块不能控制时钟线,接收数据的时间有限,I2C0DAT中老内容会被覆盖,为使处理器有更多时间相应,就在总线每接收9位(8位数据1位应答),就把高8位内容自动传输到DATABUFFER ### 7.3.7 从地址寄存器 I2C0ADR\[0, 1, 2, 3

I2C从模式下可用,主模式无效

在 I²C 通信中,从地址寄存器(Slave Address Register)用于存储 I²C 从设备(Slave Device)的地址。这个地址是 I²C 主设备(Master Device)与从设备通信时的重要标识。

|-----|----|-----------------------------------------------------|
| 位 | 符号 | |
| 0 | GC | 通用调用使能位,识别通用调用地址0x00 |
| 7:1 | 地址 | 从模式的I2C器件地址,若值为0x00,则 总线上任意地址匹配(课本上不与好像错了) |

7.3.8 屏蔽寄存器 I2C0MASK[0, 1, 2, 3]

进行地址匹配时会把屏蔽寄存器中的地址忽略,也就是我如果是从机,我屏蔽了我的地址I2C0ADR,那么我就当没有这个地址,主机匹配这个地址时匹配不到我

四个屏蔽寄存器各包含7个有效位**[7:1]**

通用调用地址0x00无法屏蔽,因为默认就是屏蔽这个地址,有违通用调用之名

7.3.9 高电平占空比寄存器,低电平占空比寄存器 I2C0SCLH,I2C0SCLL

I2C时钟不分频就是系统时钟 48MHz 标准480 快速120 快速plus48

I2C0SCLH,I2C0SCLL值可以随便取,但是单个值必须大于等于4

7.4 获取温度

获取LM75中的温度

照样,移植上次的UART工程,修改代码如下

main.c

cpp 复制代码
#include <LPC11xx.h>
#include "LED.h"
#include "Button.h"
#include "TIMER.h"
#include "UART.h"
#include "string.h"
#include "I2C.h"
char buf[7];

void Get_temputerature(void);
int32_t Temputerature_Test(void);

int main(void)
{
	LED_Init();
    LED_ON();
    UART_Init();
    I2CInit();
	
	// 定义要发送的数据
    char message[] = "Hello, world!";

    // 计算数据长度,不包括结束符 '\0'
    int length = strlen(message);
	// 调用UART_Send函数发送数据
    UART_Send(message, length);	
	
	//发送换行
	UART_Send_Bit(0x0d);
	UART_Send_Bit(0x0a);
	
    while (1)
    {
		Get_temputerature();
		UART_Send("Temputerature = ",16);
		UART_Send(buf,7);  //发送温度到pc
		UART_Send_Bit('C');
		delay_ms(1000);
    }
}


/*
*********************************************************************************************************
*	函 数 名: Temputerature_Test()
*	功能说明: 读取温度数据
*	形    参:无
*	返 回 值: 温度值*1000的整数值
*********************************************************************************************************
*/
int32_t Temputerature_Test(void)
{
	uint16_t Temputerature_8,Temputerature_16;
	float Temputerature;
	I2C_Start();//start
	I2C_Send_Byte(0x91);//读
	LPC_I2C->CONSET =(1<<2);//AA=1
	Temputerature_8=I2C_Recieve_Byte();//高八位
	LPC_I2C->CONCLR =(1<<2);//AA=0
	Temputerature_16=(Temputerature_8<<8)+I2C_Recieve_Byte();//合成温度
	I2C_Stop();//STOP
	//温度转换
	Temputerature_16=Temputerature_16>>5;
	if(Temputerature_16&0x0400)
	{
		Temputerature=-(~(Temputerature_16&0x03ff)+1)*0.125;
	}else
	{
		Temputerature=0.125*(float)(Temputerature_16);
	}
	return (int32_t)(Temputerature*1000);
}

/*
*********************************************************************************************************
*	函 数 名: Get_temputerature()
*	功能说明: 温度数据转化为十进制
*	形    参: 无
*	返 回 值: 无
*********************************************************************************************************
*/
void Get_temputerature(void)
{
	int32_t temp;
	temp=Temputerature_Test();//获得温度
	//将int 转为char 同时'0'对应00000000 对数值无影响
	buf[0]=temp/100000+'0';//
	if((temp/100000)==0) buf[0]=' ';//不显示0
	else if(temp < 0) buf[0] = '-'; // 小于零
	
	buf[1]=temp/10000%10+'0';
	buf[2]=temp/1000%10+'0';
	buf[3]='.';
	buf[4]=temp/100%10+'0';
	buf[5]=temp/10%10+'0';
	buf[6]=temp%10+'0';
}

I2C.c

cpp 复制代码
#include "I2C.h"

/*
*********************************************************************************************************
*	函 数 名: I2CInit()
*	功能说明: I2C 初始化
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
void I2CInit(void)
{
	LPC_SYSCON->PRESETCTRL |= (1<<1); //复位取消
	LPC_SYSCON->SYSAHBCLKCTRL |=(1<<5);//使能I2C
	LPC_SYSCON->SYSAHBCLKCTRL |=(1<<16);//使能IO配置块
	//选择快速模式
	LPC_IOCON->PIO0_4 &=~(0X3F); //选择快速模式
	LPC_IOCON->PIO0_4 |=0X01;//选择SCL
	LPC_IOCON->PIO0_5 &=~(0X3F); //选择快速模式
	LPC_IOCON->PIO0_5 |=0X01;//选择SDA
	//设置SCL频率为400kHZ
	LPC_I2C->SCLH=40;
	LPC_I2C->SCLL=80;
	//使能I2C 同时将其他控制位清0
	LPC_I2C->CONCLR=0XFF;     //清所有标志
	LPC_I2C->CONSET |=(1<<6);    //使能I2C接口
}


/*
*********************************************************************************************************
*	函 数 名: I2C_Start()
*	功能说明: 发送开始信号
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
void I2C_Start(void)
{
	LPC_I2C->CONSET =(1<<5);// 发送开始信号 5位STA起始
	while(!(LPC_I2C->CONSET&(1<<3)));//等待开始信号发送完成 SI置位
	LPC_I2C->CONCLR =(1<<5|1<<3); //清零START 和SI 3位SI中断标志
}


/*
*********************************************************************************************************
*	函 数 名: I2C_Stop()
*	功能说明: 发送停止信号
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
void I2C_Stop(void)
{
	LPC_I2C->CONCLR =(1<<3);
	LPC_I2C->CONSET =(1<<4);// 发送停止信号
	while((LPC_I2C->CONSET&(1<<4)));//等待停止信号发送完成 SI置位
}

/*
*********************************************************************************************************
*	函 数 名: I2C_Send_Byte(uint8_t data)
*	功能说明: 发送一个字节
*	形    参:data 1字节数据
*	返 回 值: 无
*********************************************************************************************************
*/
void I2C_Send_Byte(uint8_t data)
{
	LPC_I2C->DAT=data;
	LPC_I2C->CONCLR =(1<<3); //开始发送数据 清SI
	while(!(LPC_I2C->CONSET&(1<<3)));//等待数据发送完成 SI置位
}

/*
*********************************************************************************************************
*	函 数 名: I2C_Recieve_Byte()
*	功能说明: 接收一个字节
*	形    参:无
*	返 回 值: 一字节接收数据
*********************************************************************************************************
*/
uint8_t I2C_Recieve_Byte(void)
{
	LPC_I2C->CONCLR =(1<<3);//开始接受数据  清SI
	while(!(LPC_I2C->CONSET&(1<<3)));//等待接受数据完成 SI置位
	return (uint8_t)LPC_I2C->DAT;
}

I2C.h

cpp 复制代码
#ifndef _I2C_H_
#define _I2C_H_

#include <LPC11xx.h>

void I2CInit(void);
void I2C_Start(void);
void I2C_Stop(void);
void I2C_Send_Byte(uint8_t data);
uint8_t I2C_Recieve_Byte(void);

#endif

打开串口,效果如下

相关推荐
智商偏低5 小时前
单片机之helloworld
单片机·嵌入式硬件
青牛科技-Allen6 小时前
GC3910S:一款高性能双通道直流电机驱动芯片
stm32·单片机·嵌入式硬件·机器人·医疗器械·水泵、
森焱森8 小时前
无人机三轴稳定控制(2)____根据目标俯仰角,实现俯仰稳定化控制,计算出升降舵输出
c语言·单片机·算法·架构·无人机
白鱼不小白8 小时前
stm32 USART串口协议与外设(程序)——江协教程踩坑经验分享
stm32·单片机·嵌入式硬件
S,D9 小时前
MCU引脚的漏电流、灌电流、拉电流区别是什么
驱动开发·stm32·单片机·嵌入式硬件·mcu·物联网·硬件工程
芯岭技术12 小时前
PY32F002A单片机 低成本控制器解决方案,提供多种封装
单片机·嵌入式硬件
youmdt12 小时前
Arduino IDE ESP8266连接0.96寸SSD1306 IIC单色屏显示北京时间
单片机·嵌入式硬件
嘿·嘘13 小时前
第七章 STM32内部FLASH读写
stm32·单片机·嵌入式硬件
Meraki.Zhang13 小时前
【STM32实践篇】:I2C驱动编写
stm32·单片机·iic·驱动·i2c
几个几个n15 小时前
STM32-第二节-GPIO输入(按键,传感器)
单片机·嵌入式硬件