【STM32F103】STM32F103硬件IIC读取温度传感器EMC1314

STM32F103 硬件I2C读取温度传感器

上篇写了STM32F103使用硬件IIC读取经典外设EEPROM,只是设计到一个写数据与读数据的过程,这篇主要介绍来读写一个温度传感器EMC1314型号的案例。
读写传感器的数据有一个重要的步骤就是学会看懂它的手册(datasheet),从手册中我们需要获取几类关键信息,一是该传感器的物理地址(特别重要),因为同一个传感器可能因为容量或者型号细小的差别会导致物理地址也有很大的差别。二是该传感器的初始化配置的寄存器。三是储存数据的寄存器,这里存储着你要读取的传感器数据,有些是可以直接读取,而有些是需要换算与计算,这些都需要仔细读取寄存器部分才能弄明白。

1.温度传感器读取前的初始化

针对EMC温度传感器的初始化,主要是出了I2C2口引脚的一些初始化配置外,还有该传感器本身的一些寄存器配置,这些配置是与I2C2口的配置是在初始化的时候一起进行的。EMC寄存器初始化的配置主要包括是每次读取数据前的EMC重置和EMC开启读取这两个寄存器的操作。
用封装的EMC写一字节的接口对该两个寄存器的地址进行操作,例如

u16 EMC_Rst()
{
    printf("EMC_Rst\r\n");
    EMC_WriteByte(0x22, 0xF0);  //EMC重置
	delay_ms(50);
	return RET_SUCC;
}	

u16 EMC_Start()
{
	  printf("EMC_Start\r\n");
	  EMC_WriteByte(0x03,0x80);  //EMC开启读取
	  printf("EMC Start end");
	  return RET_SUCC;
}

u16 EMC_Initializes(void)
{
	  I2C2_GPIO_Configuration();
	  I2C2_Configuration();
	  delay_ms(50);
	  return RET_SUCC;
}```

u16 EMC_Init()
{
	EMC_Initializes();
	EMC_Rst();
	printf("EMC Init end");
	return RET_SUCC;
}
```c
//EMC写一字节
u16 EMC_WriteByte(uint16_t Addr, uint16_t Data)
{
    
	  I2C_AcknowledgeConfig(I2C2,ENABLE);
  
	  
	  while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY));
 
		/* 1.开始 */
		
		I2C_GenerateSTART(I2C2, ENABLE);
		while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));
		/* 2.设备地址/写 */
		I2C_Send7bitAddress(I2C2, EMC_DEV_ADDR, I2C_Direction_Transmitter);  //数据地址
			 
		while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
  
		/* 3.数据地址 */
		I2C_SendData(I2C2, Addr);                                 //寄存器数据地址(8位)
		while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    
		/* 4.写一字节数据 */
		I2C_SendData(I2C2, Data);                                            //发送数据
		while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    
		/* 5.停止 */
		I2C_GenerateSTOP(I2C2, ENABLE);
		return RET_SUCC;
		
}


//EMC读一字节
u16 EMC_ReadByte(uint16_t Addr, uint16_t *Data)
{

	  I2C_AcknowledgeConfig(I2C2,ENABLE);
  
	  while(I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY));
   
		/* 1.开始 */
		I2C_GenerateSTART(I2C2, ENABLE);
		while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));
   
		/* 2.设备地址/写 */
		I2C_Send7bitAddress(I2C2, EMC_DEV_ADDR, I2C_Direction_Transmitter);
	
		while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
		 
    
		/* 3.数据地址 */
	
		I2C_SendData(I2C2, Addr);                                 //数据地址(8位)
		while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
     
		/* 4.重新开始 */
		I2C_GenerateSTART(I2C2, ENABLE);
		while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT));
    
		/* 5.设备地址/读 */
		I2C_Send7bitAddress(I2C2, EMC_READ_ADDR, I2C_Direction_Receiver);
		while(!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));
    
		/* 6.读一字节数据 */
		I2C_AcknowledgeConfig(I2C2, DISABLE);                              //产生非应答
		while(I2C_GetFlagStatus(I2C2, I2C_FLAG_RXNE) == RESET);
		
		*Data = I2C_ReceiveData(I2C2);                                     //读取数据

		/* 7.停止 */
		I2C_GenerateSTOP(I2C2, ENABLE);	
		return RET_SUCC;
}

2.读取EMC寄存器的数据

这部分在读取温度数据之前,为了检测硬件I2C读取接口的准确性,我们可以先在EMC寄存器中找到存有固定值的寄存器读一读,将读出的数据与真实数据比较一下是否一致。比如存有该设备ID的寄存器,先读取该寄存器来检验一下接口的准确性。
读取的过程也很简单,传入对应的寄存器地址直接读取该值,比如

u16 EMC_ID_Get(u16 *ID)
{
	 EMC_Init();
	 EMC_Start();
     delay_ms(50);
	 EMC_ReadByte(0xFE, ID);
	 printf("EMC_ID = %d\r\n", *ID);
	 return RET_SUCC;
}

读取之后发现读取出来的数值为85与实际存储的值相同,说明读取的接口没有问题。
接下来就是直接去读取存有温度数据的寄存器了,EMC温度传感器跟其他的温度传感器又不一样。一是它读取出来的数据是由两部分组成,分别要读取整数位和小数位,其中整数部分是一个寄存器的八位数,小数部分则是另一个寄存器的三位数,且存在一字节的高三位,这里我们读取的该小数位寄存器的时候需要左移五位并上0x7才能正确取到小数位的值,然后将这两部分拼成一个11位的数才是正确的温度数据;二是该11位的数还不是最后的温度值,需要再进行换算,乘以一个换算系数,寄存器手册里面读取的温度表格清楚划分了11位数中每一位对应代表0.125,所以说明换算系数为0.125,因为还需要将二进制的11位数化为十进制后乘以0.125;三是该温度传感器中没有引入正负位,有的温度传感器特地留出高位用来表示数据的正负情况,这边该温度传感器是没有表现正负的需求。

//标准读取温度的接口
u16 EMC_Temp_Get(float *temperature)
{
	  u16 TL,TH;
	  u32 tem,tem1;
	  EMC_Init();
	  EMC_Start();
  	  delay_ms(50);
	  EMC_ReadByte(0x01, &TH);     //外部温度整数部分 
	  EMC_ReadByte(0x10, &TL);     //外部温度小数部分
	  tem = (TL>>5)&0x7;
	  printf("tem = %d\n", tem);
      tem1=(TH<<3)|tem;//获得低三位 共十一位
	  printf("tem1 = %d\n", tem1);  
     *temperature = tem1*0.125; // 十进制乘以0.125得到最终度数。
	  if(*temperature>=LIMIT_MAX)
	  {
			 *temperature = LIMIT_MAX;
	  }
     printf("temperature = %f\n", *temperature);
	 return RET_SUCC; 
}

这里还加上了一个判断就是温度传感器读取的阈值最大为127.875,如果超过那显示读取的数据只能是该值,当然一般用温度传感器来读取的数值不会超过,温度读取的量程完全够用。最后读取出来的数据打印出来,浮点数是三十多度,长期读下来也是正常的稳定变高,没有出现突变的形况。说明读取的数据准确可靠。

总结

读取这种需要数据换算的传感器,有两点比较重要,一是要看懂它的手册,手册里面包含比较终于的物理地址和相关操作的寄存器,二是该温度的换算机制一定得弄清楚,原始数据是什么,经过怎么样的处理然后得到最后的真实数据,这两点至关重要。欢迎大家留言讨论,有任何问题可以积极探讨。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
STM32F103C8T6是一款基于ARM Cortex-M3内核的微控制器,它具有丰富的外设资源,包括IICI2C)总线接口。HAL库是ST公司提供的一种高级硬件抽象层,可以简化硬件操作,方便用户进行开发。 在使用STM32F103C8T6和HAL库进行6050的IIC读取时,需要先初始化IIC总线,并配置6050的设备地址和寄存器地址。 首先,我们需要包含必要的头文件: ```c #include "stm32f1xx_hal.h" #include "i2c.h" ``` 然后,在主函数中进行IIC的初始化: ```c HAL_Init(); MX_I2C1_Init(); // 初始化IIC总线 ``` 接下来,我们需要定义6050的设备地址和寄存器地址: ```c #define MPU6050_ADDR 0xD0 // 6050的设备地址 #define ACCEL_XOUT_H 0x3B // 加速度计X轴高位寄存器地址 ``` 然后,我们可以编写读取6050的函数来实现具体的读取操作: ```c void MPU6050_ReadAccel(int16_t* accelData) { uint8_t buffer[6]; HAL_I2C_Mem_Read(&hi2c1, MPU6050_ADDR, ACCEL_XOUT_H, 1, buffer, 6, HAL_MAX_DELAY); accelData[0] = (buffer[0] << 8) | buffer[1]; accelData[1] = (buffer[2] << 8) | buffer[3]; accelData[2] = (buffer[4] << 8) | buffer[5]; } ``` 在函数中,我们首先定义一个缓冲区用于存储读取的数据,然后使用HAL库提供的函数`HAL_I2C_Mem_Read`来进行6050寄存器的读取操作。读取到的数据存储在缓冲区中。最后,我们通过移位运算和位或运算将高位和低位数据组合成16位的加速度数据。 最后,我们可以在主函数中调用`MPU6050_ReadAccel`函数来读取6050的加速度数据: ```c int16_t accelData[3]; MPU6050_ReadAccel(accelData); // 使用读取到的加速度数据进行后续处理 ``` 以上是使用STM32F103C8T6和HAL库进行6050的IIC读取的简要示例代码。具体的实现细节可能会根据具体的需求和引脚配置有所不同,需要根据实际情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值