ST官方的IIC实例解析(第一部分)

news/2024/11/20 16:15:26/

ST官方的IIC实例解析

LM75A的管脚描述

 

 

输入/输出(引脚属性)

引脚标识

描述

输入

VCC

供电电压

输入

GND

参考地

输入

A2~A0

低3位地址引脚

输入

SDA

IIC的数据总线

输入

SCL

IIC的时钟总线

输出

OS

开漏输出(低电平有效)

 

其中,我们看原理图就知道A0~A2的值:

 

LM75A 在 I2C 总线的从地址的一部分由应用到器件地址管脚A2、A1 和 A0 的逻辑来定义。这 3 个地址管脚可以连接到GND(逻辑 0)或 Vcc(逻辑 1)。它们代表了器件7 位地址中的低 3 位。地址的高4 位由 LM75A内部的硬连线预先设置为“1001‟。

 

下面是LM75A的实际电路连接图,我们将A0~A2连接到GND,因此我们的LM75A的从设备地址应该是:

1

0

0

1

0

0

0

因此,其I2C从设备地址为 0x90。

滞后温度值与热关断温度

 

温度类型

说明

滞后温度值

下限温度(可自定义)

热关断温度

上限温度(可自定义)

重要的寄存器

寄存器的访问地址

 

 

温度寄存器 Temp(地址 0x00)

温度寄存器是一个只读寄存器,包含2 个 8 位的数据字节,由一个高数据字节(MS)和一个低数据字节(LS)组成。这两个字节中只有 11 位用来存放分辨率为0.125℃的 Temp 数据(以二进制补码数据的形式),如表1 所示。对于 8 位的 I2C 总线来说,只要从 LM75A的“00地址”连续读两个字节即可(温度的高8 位在前)。

 

根据 11 位的 Temp 数据来计算Temp 值的方法:

1. 若 D10=0,温度值(℃)=+Temp 数据)×0.125℃;

2. 若 D10=1,温度值(℃)=-Temp 数据的二进制补码)×0.125℃。

下表给出了一些Temp 数据和温度值的例子。

 

配置寄存器(地址0x01)

配置寄存器为 8 位可读写寄存器,其位功能分配如下表所示。

 

 

滞后寄存器 Thyst(0x02)

滞后寄存器是读/写寄存器,也称为设定点寄存器,提供了温度控制范围的下限温度。每次转换结束后,Temp 数据(取其高 9 位)将会与存放在该寄存器中的数据相比较,当环境温度低于此温度的时候,LM75A 将根据当前模式(比较、中断)控制 OS 引脚做出相应反应。

该寄存器都包含2 个 8 位的数据字节,但 2 个字节中,只有 9 位用来存储设定点数据(分辨率为0.5℃的二进制补码),其数据格式如下表所示,如果不设置则默认为75℃。

 

过温关断阈值寄存器Tos(0x03)

过温关断寄存器提供了温度控制范围的上限温度。每次转换结束后,Temp 数据(取其高9 位)将会与存放在该寄存器中的数据相比较,当环境温度高于此温度的时候,LM75A将根据当前模式(比较、中断)控制OS 引脚做出相应反应。其数据格式如表 4 所示,如果不设置则默认为80℃。

 

注:9位二进制位由“1位符号位与8位数字位组成”,而且二进制转换为10进制后,需要在进行除2,因为unsigned char与char都是8位的,但是unsigned char的取值范围是[0,255],而char的取值范围为[-127,128]。

LM75A 的 OS 输出与 LM75A工作模式

LM75A 利用内置的分辨率为0.125℃的带隙传感器来测量器件的温度,并将模数转换得到的11 位的二进制数的补码数据存放到器件Temp 寄存器中。Temp 寄存器的数据可随时被I2C 总线上的控制器读出。读温度数据并不会影响在读操作过程中执行的转换操作。

LM75A 可设置成工作在两种模式:“正常工作模式”或“中断模式”

在正常工作模式中,每隔 100ms 执行一次温度-数字的转换,Temp 寄存器的内容在每次转换后更新。在关断模式中,器件变成空闲状态,数据转换禁止,Temp 寄存器保存着最后一次更新的结果;但是,在该模式下,器件的I2C 接口仍然有效,寄存器的读/写操作继续执行,也就是说此时虽然我们停止了LM75A的工作,但是LM75A还处于上电状态,因此LM75A中的数据还是存在的,其中保存的数据就是我们最近一次LM75A的工作状态与最近一次获取的数据。

从以上两段我们获得以下信息:

工作状态

比较模式(正常工作模式)

中断模式

温度读取时间

每100ms一次

器件的工作模式通过配置寄存器的可编程位B0 来设定。当器件上电或从关断模式进入正

常工作模式时启动温度转换。另外,为了设置器件OS 输出的状态,在正常模式下的每次转换结束时,Temp 寄存器中的温度数据(或 Temp)会自动与 Tos 寄存器中的过热关断阈值数据(或Tos)以及 Thyst 寄存器中存放的滞后数据(或Thyst)相比较。

Tos 和 Thyst 寄存器都是可读/写的,两者都是针对一个9 位的二进制数进行操作。为了与 9 位的数据操作相匹配,Temp 寄存器只使用11 位数据中的高9 位进行比较。OS 输出和比较操作的对应关系取决于配置位B1 选择的 OS 工作模式和配置位 B3 和 B4 定义的用户定义的故障队列。

OS两种工作模式解析

 

在 OS 比较器模式中,OS 输出的操作类似一个温度控制器。当 Temp 超过 Tos 时,OS 输出有效;当 Temp 降至低于Thyst 时,OS 输出复位。读器件的寄存器或使器件进入关断模式都不会改变OS 输出的状态。也就是说,只要LM75A还在处于上电状态,那么Temp的高9位就会与Tos和Thyst寄存器中的高9位相比较,输出相应的OS状态,完全不受其他操作的干扰,这时,OS 输出可用来控制冷却风扇或温控开关,当高于温度上限进行冷却(OS为有效电平),等到低于温度下限才停止冷却(OS为无效电平)。

在 OS 中断模式中,OS 输出用来产生温度中断。当器件上电时,OS 输出在 Temp 超过 Tos 时首次激活,然后无限期地保持有效状态,直至通过读取器件的寄存器或者关断LM75A来复位;同理,当Temp中的高9位低于Thyst时,OS输出有效电平,直至通过读取器件的寄存器或者关断LM75A来复位。

 

可以看出,当LM75A 工作在比较器模式时,当温度高于Tos 时,OS 输出低电平。此时采取了降温措施,启动降温设 备(如风扇),直到温度再降到 Thyst,则停止降温,因此在这种模式下,LM75A 可以通过OS电平来直接控制外部电路来保持环境温度; 而在中断模式,则在温度高于Tos 或低于 Thyst 时产生中断。注意:在中断模式下,只有当 MCU 对 LM75A 进行读操作后, 其中断信号才会消失(图中OS 变为高电平)。

LM75A的IIC通信注意事项

① 通信开始之前,I2C 总线必须空闲或者不忙。这就意味着总线上的所有器件都必须释放SCL 和 SDA 线,SCL 和 SDA 线被总线的上拉电阻拉高。

② 由主机来提供通信所需的SCL 时钟脉冲。在连续的9 个 SCL 时钟脉冲作用下,数据(8 位的数据字节以及紧跟其后的1个应答状态位)被传输。

③ 在数据传输过程中,除起始和停止信号外,SDA 信号必须保持稳定,而SCL 信号必须为高。这就表明SDA 信号只能在SCL 为低时改变。

LM75A程序代码解析

函数原型

说明

void LM75_DeInit(void)

LM75A引脚复位

void LM75_Init(void)

LM75A引脚初始化

ErrorStatus LM75_GetStatus(void)

获取LM75A的工作状态

uint16_t LM75_ReadTemp(void)

读取LM75A测得的温度值

uint16_t LM75_ReadReg(uint8_t RegName)

读LM75A对应寄存器的值

uint8_t LM75_WriteReg(uint8_t RegName, uint16_t RegValue)

写相应的LM75A的寄存器

uint8_t LM75_ReadConfReg(void)

读LM75A配置寄存器的值

uint8_t LM75_WriteConfReg(uint8_t RegValue)

写LM75A配置寄存器的值

uint8_t LM75_ShutDown(FunctionalState NewState)

配置LM75A的工作状态

LM75A引脚复位函数

LM75_DeInit函数:

void LM75_DeInit(void)  
{  LM75_LowLevel_DeInit();  
}  

 

LM75_LowLevel_DeInit函数:

void LM75_LowLevel_DeInit(void)  
{  GPIO_InitTypeDef  GPIO_InitStructure;  /* I2C2失能 */  I2C_Cmd(LM75_I2C, DISABLE);  /* 复位I2C2 */  I2C_DeInit(LM75_I2C);  /* I2C2总线时钟失能 */  RCC_APB1PeriphClockCmd(LM75_I2C_CLK, DISABLE);  /* 配置PB10-I2C2_SCL引脚的属性 */  GPIO_InitStructure.GPIO_Pin = LM75_I2C_SCL_PIN;  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;  GPIO_Init(LM75_I2C_SCL_GPIO_PORT, &GPIO_InitStructure);  /* 配置PB11-I2C2_SDA引脚的属性 */  GPIO_InitStructure.GPIO_Pin = LM75_I2C_SDA_PIN;  GPIO_Init(LM75_I2C_SDA_GPIO_PORT, &GPIO_InitStructure);  /* 配置PB12-I2C2_SMBA引脚属性 */  GPIO_InitStructure.GPIO_Pin = LM75_I2C_SMBUSALERT_PIN;  GPIO_Init(LM75_I2C_SMBUSALERT_GPIO_PORT, &GPIO_InitStructure);  
}  

 

LM75A初始化函数

void LM75_Init(void)  
{  I2C_InitTypeDef   I2C_InitStructure;  LM75_LowLevel_Init();  // 复位LM75A设备用到的引脚I2C_DeInit(LM75_I2C);  // 复位I2C2总线/* 配置I2C2的属性 */  I2C_InitStructure.I2C_Mode = I2C_Mode_SMBusHost;  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;  // 配置I2C的占空比I2C_InitStructure.I2C_OwnAddress1 = 0x00;  // 主设备地址I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;  // 主设备应答使能I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;  // 设备地址选择7bitsI2C_InitStructure.I2C_ClockSpeed = LM75_I2C_SPEED;  // I2C的速度(自定义)I2C_Init(LM75_I2C, &I2C_InitStructure);  /* 使能SMBus Alert中断 */  I2C_ITConfig(LM75_I2C, I2C_IT_ERR, ENABLE);  /* I2C2使能 */  I2C_Cmd(LM75_I2C, ENABLE);  
}  

 

LM75A设备状态检测函数

ErrorStatus LM75_GetStatus(void)  
{  uint32_t I2C_TimeOut = I2C_TIMEOUT;  /* 清除AF应答失败标志 */  I2C_ClearFlag(LM75_I2C, I2C_FLAG_AF);  /* 使能I2C的应答功能 */  I2C_AcknowledgeConfig(LM75_I2C, ENABLE);  /*---------------------------- Transmission Phase ---------------------------*/  /* 发送I2C传输的起始信号 */  I2C_GenerateSTART(LM75_I2C, ENABLE);  /* 不断循环直到“超过等待等待最大时限”或者“起始条件已经发送至SDA总线上” */  while ((!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_SB)) && I2C_TimeOut)  /*!< EV5 */  {  I2C_TimeOut--;  }  if (I2C_TimeOut == 0)  {  return ERROR;  }  I2C_TimeOut = I2C_TIMEOUT;  /* 发送LM75A的从设备地址并且配置数据传输方向为“主设备->从设备” */  I2C_Send7bitAddress(LM75_I2C, LM75_ADDR, I2C_Direction_Transmitter);  /* 不断轮询等待直到“超过等待最大时限”或者“主设备处于发送模式” */while ((!I2C_CheckEvent(LM75_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) && I2C_TimeOut)/* EV6 */  {  I2C_TimeOut--;  }  /* 如果“应答失败”或者“等待时间超过等待时间上限”,就返回ERROR */if ((I2C_GetFlagStatus(LM75_I2C, I2C_FLAG_AF) != 0x00) || (I2C_TimeOut == 0))  {  return ERROR;  }  else  /* 如果在规定时间内等到应答信号,则返回SUCCESS */{  return SUCCESS;  }  
}  

 

函数返回标志

说明

从设备成功被访问

SUCCESS

从设备未被成功访问

ERROR

读LM75A的配置寄存器的函数

uint8_t LM75_ReadConfReg(void)  
{     uint8_t LM75_BufferRX[2] ={0,0};   /* 不断轮询等待直至其他主设备释放I2C总线 */  LM75_Timeout = LM75_LONG_TIMEOUT;  while (I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BUSY))   {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 通过DMA将I2C2的DR寄存器的值传输至内存中 */  LM75_DMA_Config(LM75_DMA_RX, (uint8_t*)LM75_BufferRX, 2);    /* 使下一次DMA传输为最后一次DMA传输,即加上这次一共进行两次DMA传输 */  I2C_DMALastTransferCmd(LM75_I2C, ENABLE);  /* I2C2发送起始信号 */  I2C_GenerateSTART(LM75_I2C, ENABLE);  /* 不断轮询等待I2C2是否成功发送起始条件 */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_SB))   {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 发送从设备地址 */  I2C_Send7bitAddress(LM75_I2C, LM75_ADDR, I2C_Direction_Transmitter);  /* 主模式下,等待地址发送结束 */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while (!I2C_CheckEvent(LM75_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))   {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 发送需要操作的设备寄存器的地址 */  I2C_SendData(LM75_I2C, LM75_REG_CONF);    /* 不断轮询直至“字节发送完毕”并且“发送的数据非空” */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while ((!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_TXE)) && (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BTF)))    {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 传输I2C2的起始条件 */    I2C_GenerateSTART(LM75_I2C, ENABLE);  /* 不断轮询直至起始条件发送成功 */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_SB))   {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 发送LM75A的从设备地址,此时主设备配置为接收数据的状态 */  I2C_Send7bitAddress(LM75_I2C, LM75_ADDR, I2C_Direction_Receiver);  /* 不断轮询等待直至“主设备被设置为接受模式” */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while (!I2C_CheckEvent(LM75_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))     {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 使能DMA请求 */  I2C_DMACmd(LM75_I2C,ENABLE);  /*  配置对应的DMA通道 */  DMA_Cmd(LM75_DMA_RX_CHANNEL, ENABLE);  /* 等待DMA数据传输完毕 */  LM75_Timeout = LM75_LONG_TIMEOUT;  while (!DMA_GetFlagStatus(LM75_DMA_RX_TCFLAG))  {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }          /* 主设备发送停止信号 */  I2C_GenerateSTOP(LM75_I2C, ENABLE);  /* 失能相应的DMA通道 */  DMA_Cmd(LM75_DMA_RX_CHANNEL, DISABLE);  /* 关闭I2C的DMA请求 */    I2C_DMACmd(LM75_I2C,DISABLE);  /* 清除DMA数据传输完成标志 */  DMA_ClearFlag(LM75_DMA_RX_TCFLAG);  /* 返回内存中读取到的温度值 */  return (uint8_t)LM75_BufferRX[0];  
}  

 

其实这个程序的执行流程图如下:

 

写LM75A的配置寄存器的函数

uint8_t LM75_ReadConfReg(void)  
{     uint8_t LM75_BufferRX[2] ={0,0};   /* 不断轮询等待直至“超过最大等待时限”或者“总线被释放” */  LM75_Timeout = LM75_LONG_TIMEOUT;  while (I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BUSY))   {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 配置I2C2_TX的DMA数据传输通道 */  LM75_DMA_Config(LM75_DMA_RX, (uint8_t*)LM75_BufferRX, 2);    /* 使下一次DMA传输为最后一次DMA传输,即加上这次一共进行两次DMA传输 */  I2C_DMALastTransferCmd(LM75_I2C, ENABLE);  /* 使能I2C2的总线起始信号 */  I2C_GenerateSTART(LM75_I2C, ENABLE);  /* 不断轮询等待直至“传输完起始信号”或者“超过最大等待时限” */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_SB))   {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 发送从设备的地址为了下一步进行写操作 */  I2C_Send7bitAddress(LM75_I2C, LM75_ADDR, I2C_Direction_Transmitter);  /* 不断轮询等待直至“超过最大等待时限”或者“成功配置‘主发从收’模式” */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while (!I2C_CheckEvent(LM75_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))   {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 发送从设备的寄存器地址 */  I2C_SendData(LM75_I2C, LM75_REG_CONF);    /* 不断轮询等待直至“超过最大等待时限”或者“发送字节非空并且最后一个需要发送的字节发送完毕” */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while ((!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_TXE)) && (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BTF)))    {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 主设备再一次发送起始信号 */    I2C_GenerateSTART(LM75_I2C, ENABLE);  /* 不断轮询等待直至“传输完起始信号”或者“超过最大等待时限” */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_SB))   {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 发送从设备的地址 */  I2C_Send7bitAddress(LM75_I2C, LM75_ADDR, I2C_Direction_Receiver);  /* 不断轮询等待直至“超过最大等待时限”或者“模式成功配置为‘主收从发’” */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while (!I2C_CheckEvent(LM75_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))     {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 使能I2C2的DMA数据传输请求 */  I2C_DMACmd(LM75_I2C,ENABLE);  /* 使能DMA中I2C2_RX数据传输通道 */  DMA_Cmd(LM75_DMA_RX_CHANNEL, ENABLE);  /* 等待DMA数据传输结束 */  LM75_Timeout = LM75_LONG_TIMEOUT;  while (!DMA_GetFlagStatus(LM75_DMA_RX_TCFLAG))  {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }          /* 发送停止信号 */  I2C_GenerateSTOP(LM75_I2C, ENABLE);  /* 失能相应的DMA通道(失能DMA中I2C2_RX通道) */  DMA_Cmd(LM75_DMA_RX_CHANNEL, DISABLE);  /* 失能I2C2的DMA请求 */    I2C_DMACmd(LM75_I2C,DISABLE);  /* 清除DMA通道中I2C2_RX数据传输完成标志 */  DMA_ClearFlag(LM75_DMA_RX_TCFLAG);  /* 返回配置寄存器的低8位 */  return (uint8_t)LM75_BufferRX[0];  
}  

 

LM75A温度读取函数

 

uint16_t LM75_ReadTemp(void)  
{     uint8_t LM75_BufferRX[2] ={0,0};  // 一共两个字节因此数组维度为1*2uint16_t tmp = 0;  // 温度的有效位数为11位,如上图所示/* 不断轮询等待直到总线不被占用 */  LM75_Timeout = LM75_LONG_TIMEOUT;  while (I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BUSY))   {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 配置DMA,将I2C2的DR寄存器读取的数据传输至内存数组当中 */  LM75_DMA_Config(LM75_DMA_RX, (uint8_t*)LM75_BufferRX, 2);    /* 此次DMA传输完成后,主设备自动发送停止信号 */  I2C_DMALastTransferCmd(LM75_I2C, ENABLE);  /* 发送I2C传输的起始信号 */  I2C_GenerateSTART(LM75_I2C, ENABLE);  /* 不断轮询直至“达到最大等待时限”或者“起始信号成功发送完成” */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_SB))   {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 发送从设备寄存器地址为了下一步访问该寄存器 */  I2C_Send7bitAddress(LM75_I2C, LM75_ADDR, I2C_Direction_Transmitter);  /* 不断轮询直至“超过最大等待时限”或者“模式成功配置为‘主发从收’模式” */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while (!I2C_CheckEvent(LM75_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))   {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 发送从设备的寄存器地址 */  I2C_SendData(LM75_I2C, LM75_REG_TEMP);    /* 不断轮询直至“达到最大等待时限”或者“发送非空数据并且数据发送完成” */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while ((!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_TXE)) && (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BTF)))    {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 主设备第二次发送起始信号 */    I2C_GenerateSTART(LM75_I2C, ENABLE);  /* 不断轮询直至“达到最大等待时限”或者“主设备起始信号发送完毕” */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_SB))   {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 发送LM75A从设备地址且配置数据传输方向是“从设备->主设备” */  I2C_Send7bitAddress(LM75_I2C, LM75_ADDR, I2C_Direction_Receiver);  /* 不断轮询直至“超过最大等待时限”或者“模式配置正确” */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while (!I2C_CheckEvent(LM75_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))     {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 使能I2C2的DMA请求 */  I2C_DMACmd(LM75_I2C,ENABLE);  /* 使能I2C2_RX对应的DMA传输通道 */  DMA_Cmd(LM75_DMA_RX_CHANNEL, ENABLE);  /* 不断轮询等待直至“DMA传输完成”或者“超出最大等待时限” */  LM75_Timeout = LM75_LONG_TIMEOUT;  while (!DMA_GetFlagStatus(LM75_DMA_RX_TCFLAG))  {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }          /* 主设备发送停止信号 */  I2C_GenerateSTOP(LM75_I2C, ENABLE);  /* 失能I2C2_RX对应的DMA传输通道 */  DMA_Cmd(LM75_DMA_RX_CHANNEL, DISABLE);  /* 失能I2C2的DMA请求 */    I2C_DMACmd(LM75_I2C,DISABLE);  /* 清除DMA传输完成标志 */  DMA_ClearFlag(LM75_DMA_RX_TCFLAG);  /* 处理内存中接收到的数据 */  tmp = (uint16_t)(LM75_BufferRX[0] << 8);  tmp |= LM75_BufferRX[1];      /* 返回Temp寄存器中温度的高9位(16bits-7bits) */  return (uint16_t)(tmp >> 7);  
}  

数据读取的套路:

 

LM75A寄存器配置函数

// RegName:要访问的寄存器地址
// RegValue:要写入的寄存器值
uint8_t LM75_WriteReg(uint8_t RegName, uint16_t RegValue)  
{     uint8_t LM75_BufferTX[2] ={0,0};  // LM75A中寄存器一般都是2个字节的,因此需要一次写一个字节,共写两次LM75_BufferTX[0] = (uint8_t)(RegValue >> 8);  // LM75_BufferTX[0]-寄存器低8位LM75_BufferTX[1] = (uint8_t)(RegValue);  // LM75_BufferTX[1]-寄存器高8位/* 不断轮询直到“到达最大等待时限”或者“总线被释放” */  LM75_Timeout = LM75_LONG_TIMEOUT;  while (I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BUSY))   {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 配置I2C_TX数据发送引脚对应的DMA传输通道 */  LM75_DMA_Config(LM75_DMA_TX, (uint8_t*)LM75_BufferTX, 2);  /* 主设备发送起始信号 */  I2C_GenerateSTART(LM75_I2C, ENABLE);  /* 不断轮询直至“达到最大等待时限”或者“起始信号传输完成” */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while (I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_SB) == RESET)   {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 发送从设备地址,访问从设备并且配置数据传输方向为“主设备->从设备” */  I2C_Send7bitAddress(LM75_I2C, LM75_ADDR, I2C_Direction_Transmitter);  /* 不断轮询等待直至“数据传输方向为主发从收”或者“达到最大等待时限” */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while (!I2C_CheckEvent(LM75_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))  {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* Transmit the first address for r/w operations */  I2C_SendData(LM75_I2C, RegName);  /* 不断轮询等待直至“达到最大等待时限”或者“发送数据非空并且发送一个字节完成” */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while ((!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_TXE)) && (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BTF)))    {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 使能I2C的DMA传输请求 */  I2C_DMACmd(LM75_I2C,ENABLE);  /* 使能I2C2_TX数据传输通道 */  DMA_Cmd(LM75_DMA_TX_CHANNEL, ENABLE);  /* 不断轮询等待直至“DMA数据传输结束”或者“传输时间大于最大等待时限” */  LM75_Timeout = LM75_LONG_TIMEOUT;  while (!DMA_GetFlagStatus(LM75_DMA_TX_TCFLAG))  {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }    /* 等待最后一个字节传输完毕 */  LM75_Timeout = LM75_LONG_TIMEOUT;  while (I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BTF))    {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 主设备发送停止信号 */  I2C_GenerateSTOP(LM75_I2C, ENABLE);  /* 失能I2C2_TX的DMA数据传输通道 */  DMA_Cmd(LM75_DMA_TX_CHANNEL, DISABLE);  /* 使能I2C2的DMA传输通道 */    I2C_DMACmd(LM75_I2C,DISABLE);  /* 清除I2C2_TX对应的DMA传输完成标志 */  DMA_ClearFlag(LM75_DMA_TX_TCFLAG);  return LM75_OK;  
}  

 

函数返回值如下:

函数返回标志

说明

LM75_OK

寄存器配置成功

LM75_TIMEOUT_UserCallback()

寄存器配置失败

LM75A状态配置函数

uint8_t LM75_ShutDown(FunctionalState NewState)  
{     uint8_t LM75_BufferRX[2] ={0,0};  uint8_t LM75_BufferTX = 0;  __IO uint8_t RegValue = 0;      /* 不断轮询等待直至“超过最大等待时限”或者“总线被释放” */  LM75_Timeout = LM75_LONG_TIMEOUT;  while (I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BUSY))   {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 配置DMA中的I2C2_RX数据接收通道 */  LM75_DMA_Config(LM75_DMA_RX, (uint8_t*)LM75_BufferRX, 2);    /* 是下一次的DMA传输为最后一次DMA传输,即加上这次一共使用DMA传输两次数据 */  I2C_DMALastTransferCmd(LM75_I2C, ENABLE);  /* 主设备发送起始信号 */  I2C_GenerateSTART(LM75_I2C, ENABLE);  /* 等待起始信号发送完毕 */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_SB))   {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 发送从设备地址 */  I2C_Send7bitAddress(LM75_I2C, LM75_ADDR, I2C_Direction_Transmitter);  /* 不但轮询等待直至“从设备被顺利访问并且数据传输方向为‘主发从收’”或者“超过最大等待时限” */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while (!I2C_CheckEvent(LM75_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))   {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 发送从设备寄存器地址 */  I2C_SendData(LM75_I2C, LM75_REG_CONF);    /* 等待最后一个非空数据传输完成 */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while ((!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_TXE)) && (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BTF)))    {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 主设备第二次发送起始信号 */    I2C_GenerateSTART(LM75_I2C, ENABLE);  /* 检测是否发送完起始信号 */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_SB))   {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 发送LM75A的从设备地址 */  I2C_Send7bitAddress(LM75_I2C, LM75_ADDR, I2C_Direction_Receiver);  /* 检测从设备是否正常应答并且数据传输方向是否为“主收从发” */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while (!I2C_CheckEvent(LM75_I2C, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))     {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 失能I2C的DMA传输请求 */  I2C_DMACmd(LM75_I2C,ENABLE);  /* 使能对应的DMA传输通道 */  DMA_Cmd(LM75_DMA_RX_CHANNEL, ENABLE);  /* 等待DMA传输完成 */  LM75_Timeout = LM75_LONG_TIMEOUT;  while (!DMA_GetFlagStatus(LM75_DMA_RX_TCFLAG))  {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }          /* 主设备发送停止信号 */  I2C_GenerateSTOP(LM75_I2C, ENABLE);  /* 使能I2C2_RX数据发送通道 */  DMA_Cmd(LM75_DMA_RX_CHANNEL, DISABLE);  /* 使能I2C的DMA请求 */    I2C_DMACmd(LM75_I2C,DISABLE);  /* 清除DMA中I2C2_RX接收数据完成标志 */  DMA_ClearFlag(LM75_DMA_RX_TCFLAG);  /* 获取接收数据 */  RegValue = (uint8_t)LM75_BufferRX[0];  /*---------------------------- Transmission Phase ---------------------------*/  /*!< Enable or disable SD bit */  if (NewState != DISABLE)  {  /* 仅仅保留“配置寄存器”中的SD(shut down-关断)位不变 */  LM75_BufferTX = RegValue & LM75_SD_RESET;  }  else  {  /* 将LM75A置于关断状态 */  LM75_BufferTX = RegValue | LM75_SD_SET;  }    /* 等待总线处于空闲状态 */  LM75_Timeout = LM75_LONG_TIMEOUT;  while (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BUSY))   {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 配置DMA */  LM75_DMA_Config(LM75_DMA_TX, (uint8_t*)(&LM75_BufferTX), 1);  /* 主设备发送起始信号 */  I2C_GenerateSTART(LM75_I2C, ENABLE);  /* 起始位发送完毕(此时SB位会被置位) */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while (I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_SB) == RESET)   {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 发送从设备地址并设置数据传输方向“主设备->从设备” */  I2C_Send7bitAddress(LM75_I2C, LM75_ADDR, I2C_Direction_Transmitter);  /* 等待从设备应答成功并且确定数据传输方向正确 */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while (!I2C_CheckEvent(LM75_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))  {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 传输要操作的从设备的寄存器 */  I2C_SendData(LM75_I2C, LM75_REG_CONF);  /* 确保数据发送非空且最后一个字节的数据发送完成 */  LM75_Timeout = LM75_FLAG_TIMEOUT;  while ((!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_TXE)) && (!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BTF)))    {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 使能I2C的DMA请求 */  I2C_DMACmd(LM75_I2C,ENABLE);  /* Enable DMA TX Channel */  DMA_Cmd(LM75_DMA_TX_CHANNEL, ENABLE);  /* 等待DMA通道I2C2_TX数据发送完成 */  LM75_Timeout = LM75_LONG_TIMEOUT;  while (!DMA_GetFlagStatus(LM75_DMA_TX_TCFLAG))  {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }    /* 等待最后一个字节发送完成 */  LM75_Timeout = LM75_LONG_TIMEOUT;  while ((!I2C_GetFlagStatus(LM75_I2C,I2C_FLAG_BTF)))    {  if((LM75_Timeout--) == 0) return LM75_TIMEOUT_UserCallback();  }  /* 主设备发送停止信号 */  I2C_GenerateSTOP(LM75_I2C, ENABLE);  /* 失能DMA的I2C2_TX通道 */  DMA_Cmd(LM75_DMA_TX_CHANNEL, DISABLE);  /* 失能I2C2的DMA请求 */    I2C_DMACmd(LM75_I2C,DISABLE);  /* 清除DMA的I2C2_TX通道数据传输完成标志 */  DMA_ClearFlag(LM75_DMA_TX_TCFLAG);    return LM75_OK;  
}  

 

函数返回值:

函数返回值名称

说明

LM75_OK

使能/失能LM75A成功

LM75_TIMEOUT_UserCallback()

使能/失能LM75A失败

 


http://www.ppmy.cn/news/650924.html

相关文章

基于MDKA5D31-EK_T70开发板的QT示例-demo04:LM75A温度监测

By Mcuzone 硬件平台&#xff1a;MDKA5D31-EK_T70开发板 QT版本&#xff1a;4.8.5 简要说明&#xff1a;本示例主要演示QT下使用绘图设备绘制仪表盘并设置安全温度&#xff0c;采集底板LM75A的温度并显示&#xff0c;当温度超过安全温度时&#xff0c;报警灯报警。 如图所示…

基于MDKA5D31-EK_T70开发板的QT示例-demo09:LM75A温度曲线

By Mcuzone 硬件平台&#xff1a;MDKA5D31-EK_T70开发板 QT版本&#xff1a;4.8.5 简要说明&#xff1a;本示例主要演示应用程序采集开发板上的LM75A温度数据并绘制曲线。 应用程序运行效果&#xff1a; 采用7寸液晶屏&#xff0c;显示屏分辨率为800480&#xff1b; X轴为时间…

LM75AD温度传感器的应用(1)

LM75A是一种使用片上带隙温度传感器和Sigma-delta a-d转换技术的温度-数字转换器。该装置也是提供超温检测输出的热检测器。LM75A包含多个数据寄存器:配置寄存器(Conf)用于存储设备设置&#xff0c;如第7节“功能描述”中所述的设备操作模式、操作系统操作模式、操作系统极性和…

APT75DQ60BG ASEMI大功率快恢复二极管75A 600V

编辑&#xff1a;LL APT75DQ60BG ASEMI大功率快恢复二极管75A 600V 品牌&#xff1a;ASEMI 型号&#xff1a;APT75DQ60BG 封装&#xff1a;TO-247 电性参数&#xff1a;75A 600V 正向电流&#xff1a;75A 反向耐压&#xff1a;600V 引脚数量&#xff1a;2 芯片个数&am…

国鼎代理TP7512KTS1是75A,1200V高可靠性IGBT模块技术参数特征

主要特征 低VCE(sat) 低开关损耗 内置快恢复二极管 Tvj op150C VCE(sat)带正温度系数 极限参数 除非另有说明 , 否则TA 25C IGBT,逆变器 符号参数参数范围单位VCES集电极—发射极电压1200VVGES栅极-发射极电压20VIC连续集电极电流 (TC95℃ ),Tvj max175C75AICpulse集电极脉冲…

ca75a_c++_标准IO库-利用流对象把文件内容读取到向量-操作文件

/*ca75a_c_标准IO库习题练习 习题8.3,8.4,8.6 习题8.9、8.10 ifstream inFile(fileName.c_str()); 1>d:\users\txwtech\projects\ca75a\ca75a\ca75a.cpp(28): error C2079: “inFile”使用未定义的 class“std::basic_ifstream<char,std::char_traits<char>>”…

RK3288:linux系统中基于I2C的数字温度传感器TCN75A的驱动调试

CPU:RK3288 Kernel&#xff1a;4.4 Systerm:linux&#xff08;buidroot&#xff09; IC&#xff1a;TCN75A 下面我们来看这款芯片的介绍&#xff1a; 引脚介绍&#xff0c;一共八个引脚&#xff1a; 引脚描述&#xff1a; 我选择的是9位&#xff0c;0.5度的分辨率。 默认极限…

cyclone4驱动LM75A温湿度传感器学习

1. LM75A第一次使用&#xff0c;I2C接口&#xff0c;8脚 2. 打开quartus工程&#xff0c;下面只要是看看代码结构&#xff0c;问题在于多个always语句&#xff0c;逻辑上不太好分清楚&#xff0c;主要看状态机 1 module I2C_READ(2 clk,3 rst_n,4 scl,sda,data5 …