基于cubemx的硬件iic SHT30的iic调试

1 篇文章 0 订阅
1 篇文章 0 订阅

一直对stm32的硬件iic敬而远之,好像说是有问题的,就一直用的模拟iic实现,今天用sht30试了一下,发现基于cubemx来配置iic还挺方便的。现做如下记录

首先是硬件平台:stm32f103vet6指南者

先总结一下步骤

cubemx配置->SHT30_Init(选择模式)->reset->利用Init的返回值判断是否成功->读取->数据拼接

涉及到的自己写的函数有

Init,reset,read,Dat_To_Float

先说配置cubemx:

基础的时钟配置略

 

 单纯打开iic

下面的参数顺便讲解一下

1.speedmode可以选择标准和快速

时钟速度可调,快速的话可以到40000,还要调占空比

2.clock stretching

clock stretching通过将SCL线拉低来暂停一个传输.直到释放SCL线为高电平,传输才继续进行.clock stretching是可选的,很多没有,像sht30是有的,我看有个博主发的单词读取的代码里面就用到了这个,但我这里没有用

3.地址长度

7位10位可选,这里因为后面要加读取或者写入后面相当于要加一位,就是8位或者11位

后面的不经常用(可能单纯我不常用)不说了

keil代码部分:

我是基于https://blog.csdn.net/BearPi/article/details/104311539这个代码写的,我来说说我的理解

  /* USER CODE BEGIN 2 */
		SHT30_Init();
		SHT30_reset();
    if(SHT30_Init() == HAL_OK)
        printf("sht30 init ok.\n");
    else
        printf("sht30 init fail.\n");
  /* USER CODE END 2 */

我们来剖析一下

首先是SHT30_Init

/*****/

这里要说一下题外话,基于iic发送的函数比如在dma模式中有两种

一个是用于存储设备的比如eeprom,还有一个就是一般的传感器呀这种

传感器用transmit,存储器的话是mem_write

 /****/

 好,继续,这里传的cmd:MEDIUM_2_CMD我们打开来看看

初始化相当于选择模式,

 

 对应的是中等重复性(和精度有关)的每秒两次测量

好,我们再来说说这个的函数构造,还是比较常见

uint8_t	SHT30_Send_Cmd(SHT30_CMD cmd)
{
    uint8_t cmd_buffer[2];
    cmd_buffer[0] = cmd >> 8;
    cmd_buffer[1] = cmd;
    return HAL_I2C_Master_Transmit(&hi2c1, SHT30_ADDR_WRITE, (uint8_t*) cmd_buffer, 2, 0xFFFF);
}

 每次只能发8位,总共是16位的指令(16进制有四位,那就是16位的指令了),所以要分为两次发送,cmd>>8这个指令就是在提取高位cmd[0],然后iic是高位先行,那个transmit的函数里面要放入cmd的地址,所以这个cmd[0]放高位

另外这个函数除了初始化之外还有返回值

/---------reset-------------------------/

同理只是加了一个延迟

/---------while循环------------/

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
		HAL_Delay(1000);
		if(SHT30_Read_Dat(recv_dat) == HAL_OK)
		{
			if(SHT30_Dat_To_Float(recv_dat, &temperature, &humidity)==0)
			{
				printf("temperature = %.2f*c, humidity = %.2f%%\n", temperature, humidity);
			}
			else
			{
				printf("crc check fail.\n");
			}
		}
		else
		{
			printf("read data from sht30 fail.\n");
		}
	
  }

 来细看SHT_Read_Dat

/**
 * @brief	从SHT30读取一次数据
 * @param	dat —— 存储读取数据的地址(6个字节数组)
 * @retval	成功 —— 返回HAL_OK
*/
uint8_t SHT30_Read_Dat(uint8_t* dat)
{
	SHT30_Send_Cmd(READOUT_FOR_PERIODIC_MODE);
	return HAL_I2C_Master_Receive(&hi2c1, SHT30_ADDR_READ, dat, 6, 0xFFFF);
}

其中

对应手册的周期模式读取

 recv_dat这个是存储的数组地址

其中

HAL_I2C_Master_Receive(&hi2c1, SHT30_ADDR_READ, dat, 6, 0xFFFF);

 SHT30_ADDR_READ是七位地址加一个1,dat是存的位置,6表示存多少个

6个的原因是

温度两个,湿度两个,还有两个CRC

0xFFFF表示一个Timeout

/--------------------数据拼接

			if(SHT30_Dat_To_Float(recv_dat, &temperature, &humidity)==0)
			{
				printf("temperature = %.2f*c, humidity = %.2f%%\n", temperature, humidity);
			}

-------------------/

接收完过后就是数据的拼接

/**
 * @brief	将SHT30接收的6个字节数据进行CRC校验,并转换为温度值和湿度值
 * @param	dat  —— 存储接收数据的地址(6个字节数组)
 * @retval	校验成功  —— 返回0
 * 			校验失败  —— 返回1,并设置温度值和湿度值为0
*/
uint8_t SHT30_Dat_To_Float(uint8_t* const dat, float* temperature, float* humidity)
{
	uint16_t recv_temperature = 0;
	uint16_t recv_humidity = 0;
	
	/* 校验温度数据和湿度数据是否接收正确 */
	if(CheckCrc8(dat, 0xFF) != dat[2] || CheckCrc8(&dat[3], 0xFF) != dat[5])
		return 1;
	
	/* 转换温度数据 */
	recv_temperature = ((uint16_t)dat[0]<<8)|dat[1];
	*temperature = -45 + 175*((float)recv_temperature/65535);
	
	/* 转换湿度数据 */
	recv_humidity = ((uint16_t)dat[3]<<8)|dat[4];
	*humidity = 100 * ((float)recv_humidity / 65535);
	
	return 0;
}

先是CRC校验,然后是 

分析完成,成功输出!

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值