STM32F4系列IIC读取HDC1080 温湿度传感器HAL库
1.STM32F4系列IIC接口初始化
(1)通过STM32Cube创建工程

本项目采用的是STM32F427,IO 接口采用的是PC9和PA8;如下图:
if(i2cHandle->Instance==I2C3)
{
/* USER CODE BEGIN I2C3_MspInit 0 */
/* USER CODE END I2C3_MspInit 0 */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**I2C3 GPIO Configuration
PC9 ------> I2C3_SDA 用于板载的温湿度传感器通讯
PA8 ------> I2C3_SCL
*/
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C3;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF4_I2C3;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* I2C3 clock enable */
__HAL_RCC_I2C3_CLK_ENABLE();
/* USER CODE BEGIN I2C3_MspInit 1 */
/* USER CODE END I2C3_MspInit 1 */
}

STM32Cube的IIC配置直接用默认信息就行。中断也无须使能,IO端口设置为高速。
(2)IIC接口初始化
void MX_I2C3_Init(void)//用于板载的温湿度传感器通讯
{
/* USER CODE BEGIN I2C3_Init 0 */
/* USER CODE END I2C3_Init 0 */
/* USER CODE BEGIN I2C3_Init 1 */
/* USER CODE END I2C3_Init 1 */
hi2c3.Instance = I2C3;
hi2c3.Init.ClockSpeed = 100000;
hi2c3.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c3.Init.OwnAddress1 = 0;
hi2c3.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c3.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c3.Init.OwnAddress2 = 0;
hi2c3.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c3.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c3) != HAL_OK)
{
Error_Handler();
}
/** Configure Analogue filter
*/
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c3, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
{
Error_Handler();
}
/** Configure Digital filter
*/
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c3, 0) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN I2C3_Init 2 */
/* USER CODE END I2C3_Init 2 */
}
2.HDC1080数据采集部分
(1)头文件里宏定义寄存器地址和函数声明
#define ADDR_HDC1080 0x80 //1000 000RW
#define HDC1080_TempAddress 0x00 //读取温度的地址
#define HDC1080_HumiAddress 0x01 //读取湿度的地址
#define HDC1080_Configuration 0x02 //写配置信息的寄存器地址
#define HDC1080_ManufactID 0xFE
void HDC1080Setresolition(void);
void Get_HDC1080Value(float *rt,float *rh);
(2)重点寄存器与手册对照关系
(3)测试STM32硬件IIC与HDC芯片的接口是否通讯正常
void HDC1080Setresolition(void)
{
uint8_t Manu_Id[2];
HAL_I2C_Mem_Read(&hi2c3,ADDR_HDC1080,(uint8_t)HDC1080_ManufactID, I2C_MEMADD_SIZE_8BIT, (uint8_t *)Manu_Id, 2,1000); //0x5449 是正确的
Usart8_SendData(Manu_Id,2);
uint8_t buf[4];
buf[0]=0x10; //bit12 =1 温度湿度都采集
buf[1]=0x00; //0001 0000 0000 0000 bit10=0 温度14bit,bit8,9=00,湿度=14bit
HAL_I2C_Mem_Write(&hi2c3, ADDR_HDC1080, (uint8_t)HDC1080_Configuration, I2C_MEMADD_SIZE_8BIT, buf, 2, 100);
// HAL_I2C_Mem_Read(&hi2c3,ADDR_HDC1080,(uint8_t)0x02, I2C_MEMADD_SIZE_8BIT, (uint8_t *)Manu_Id, 2,1000); //0x5449 是正确的
// Usart8_SendData(Manu_Id,2);
}
(4)STM32的HAL库IIC设置注意事项
A: 在HAL_I2C_Mem_Read函数中的I2C_MEMADD_SIZE_8BIT一定要设置为I2C_MEMADD_SIZE_8BIT模式,因为器件手册中要求必须是I2C_MEMADD_SIZE_8BIT模式;
B:可以先读取器件的ID,通过串口显示一下,如果读取的ID是正确的,那说明IIC接口的HAL库与芯片通讯之间是正常的。
(5)STM32的HAL库 一个函数读取温度和湿度代码
void Get_HDC1080Value(float *rt,float *rh)
{
uint16_t temp,humi;
uint8_t buf[4];//读取数据的缓存
HAL_I2C_Mem_Read(&hi2c3,ADDR_HDC1080,(uint8_t)HDC1080_TempAddress, I2C_MEMADD_SIZE_8BIT, (uint8_t *)buf, 4,1000); //读取4个,前两个是温度,后两个是湿度
temp = buf[0] << 8;
temp |= buf[1];
humi = buf[2] << 8;
humi |= buf[3];
//ut 和 uh 为从HDC1080中读取出的原始温湿度值,这里根据芯片手册中的公式进行转换。
*rt = temp / pow(2.0, 16.0) * 165.0 - 40.0; //'C
*rh = humi / pow(2.0, 16.0) * 100.0; //%RH
}
3.HDC1080数据采集核心技术点

编程手册里面数了要等待数据转换完成,但是直接使用STM32的hal库HAL_I2C_Mem_Read(&hi2c3,ADDR_HDC1080,(uint8_t)HDC1080_TempAddress, I2C_MEMADD_SIZE_8BIT, (uint8_t *)buf, 4,1000);
是没有等待的时间的,
需要在Stm32f4xx_hal_i2C.c里面修改
static HAL_StatusTypeDef I2C_RequestMemoryRead(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint32_t Timeout, uint32_t Tickstart)
{
/* Enable Acknowledge */
SET_BIT(hi2c->Instance->CR1, I2C_CR1_ACK);
/* Generate Start */
SET_BIT(hi2c->Instance->CR1, I2C_CR1_START);
/* Wait until SB flag is set */
if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK)
{
if (READ_BIT(hi2c->Instance->CR1, I2C_CR1_START) == I2C_CR1_START)
{
hi2c->ErrorCode = HAL_I2C_WRONG_START;
}
return HAL_TIMEOUT;
}
/* Send slave address */
hi2c->Instance->DR = I2C_7BIT_ADD_WRITE(DevAddress);
/* Wait until ADDR flag is set */
if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK)
{
return HAL_ERROR;
}
/* Clear ADDR flag */
__HAL_I2C_CLEAR_ADDRFLAG(hi2c);
/* Wait until TXE flag is set */
if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
{
if (hi2c->ErrorCode == HAL_I2C_ERROR_AF)
{
/* Generate Stop */
SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP);
}
return HAL_ERROR;
}
/* If Memory address size is 8Bit */
if (MemAddSize == I2C_MEMADD_SIZE_8BIT)
{
/* Send Memory Address */
hi2c->Instance->DR = I2C_MEM_ADD_LSB(MemAddress);
}
/* If Memory address size is 16Bit */
else
{
/* Send MSB of Memory Address */
hi2c->Instance->DR = I2C_MEM_ADD_MSB(MemAddress);
/* Wait until TXE flag is set */
if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
{
if (hi2c->ErrorCode == HAL_I2C_ERROR_AF)
{
/* Generate Stop */
SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP);
}
return HAL_ERROR;
}
/* Send LSB of Memory Address */
hi2c->Instance->DR = I2C_MEM_ADD_LSB(MemAddress);
}
/* Wait until TXE flag is set */
if (I2C_WaitOnTXEFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)
{
if (hi2c->ErrorCode == HAL_I2C_ERROR_AF)
{
/* Generate Stop */
SET_BIT(hi2c->Instance->CR1, I2C_CR1_STOP);
}
return HAL_ERROR;
}
if(hi2c ==&hi2c3) //温湿度传感器 需要一个延时
HAL_Delay(20);
/* Generate Restart */
SET_BIT(hi2c->Instance->CR1, I2C_CR1_START);
/* Wait until SB flag is set */
if (I2C_WaitOnFlagUntilTimeout(hi2c, I2C_FLAG_SB, RESET, Timeout, Tickstart) != HAL_OK)
{
if (READ_BIT(hi2c->Instance->CR1, I2C_CR1_START) == I2C_CR1_START)
{
hi2c->ErrorCode = HAL_I2C_WRONG_START;
}
return HAL_TIMEOUT;
}
/* Send slave address */
hi2c->Instance->DR = I2C_7BIT_ADD_READ(DevAddress);
/* Wait until ADDR flag is set */
if (I2C_WaitOnMasterAddressFlagUntilTimeout(hi2c, I2C_FLAG_ADDR, Timeout, Tickstart) != HAL_OK)
{
return HAL_ERROR;
}
return HAL_OK;
}
3. 到此,所有问题都解决了。
更多推荐

所有评论(0)