|
|
|
@ -177,3 +177,144 @@ float resistance2Temperature(float R1) {
|
|
|
|
|
# 2. I2C
|
|
|
|
|
|
|
|
|
|
[I2C 温湿度传感器](https://www.bilibili.com/video/BV1QN411D7ak/?spm_id_from=333.788&vd_source=3c8e333d6657680a469ddf0238f01d6a)
|
|
|
|
|
|
|
|
|
|
## 2.1. 设置
|
|
|
|
|
|
|
|
|
|
1. 先新建一个工程,取名为 humidity;
|
|
|
|
|
2. 设置调试模式为 Serial Wire;
|
|
|
|
|
3. 打开串口2;
|
|
|
|
|
4. 查看开发板19号外设,使用PB6/PB7;
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
在引脚设置中点击PB6,看到使用的是I2C1;
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
5. 在Connectivity中找到I2C1,设置I2C模式为 I2C;
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
6. 在Project Manager中设置为每个外设使用独立的 c/.h 文件:
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
7. 按照上个例子设置printf使用浮点;
|
|
|
|
|
|
|
|
|
|
## 2.2. 编码
|
|
|
|
|
|
|
|
|
|
inc目录建立一个新文件aht20.h
|
|
|
|
|
|
|
|
|
|
```h
|
|
|
|
|
#ifndef __DHT20_H__
|
|
|
|
|
#define __DHT20_H__
|
|
|
|
|
|
|
|
|
|
#include "i2c.h"
|
|
|
|
|
|
|
|
|
|
// 初始化AHT20
|
|
|
|
|
void AHT20_Init(void);
|
|
|
|
|
|
|
|
|
|
// 获取温度和湿度
|
|
|
|
|
void AHT20_Read();
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
src 目录建立一个新文件 aht20.c
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
#include <aht20.h>
|
|
|
|
|
|
|
|
|
|
#define AHT20_ADDRESS 0x70
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 查看状态字是否校准
|
|
|
|
|
*/
|
|
|
|
|
void AHT20_Init(void) {
|
|
|
|
|
uint8_t read_buf = 0;
|
|
|
|
|
// 等待DHT20上电稳定
|
|
|
|
|
HAL_Delay(40);
|
|
|
|
|
HAL_I2C_Master_Receive(&hi2c1, AHT20_ADDRESS, &read_buf, 1, 10);
|
|
|
|
|
if ((read_buf & 0x08) != 0x08) {
|
|
|
|
|
// 状态字没有校准,发送出初始化命令
|
|
|
|
|
uint8_t send_buf[3] = { 0xBE, 0x08, 0x00 };
|
|
|
|
|
HAL_I2C_Master_Transmit_DMA(&hi2c1, AHT20_ADDRESS, send_buf, 3);
|
|
|
|
|
HAL_Delay(100);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
void AHT20_Read(float *temp, float *hum) {
|
|
|
|
|
uint8_t sendBuffer[3] = { 0xAC, 0x33, 0x00 };
|
|
|
|
|
uint8_t readBuffer[6];
|
|
|
|
|
HAL_I2C_Master_Transmit(&hi2c1, AHT20_ADDRESS, sendBuffer, 3, HAL_MAX_DELAY);
|
|
|
|
|
HAL_Delay(75);
|
|
|
|
|
HAL_I2C_Master_Receive(& hi2c1, AHT20_ADDRESS, readBuffer, 6, HAL_MAX_DELAY);
|
|
|
|
|
if ((readBuffer[0] & 0x80) == 0x00) {
|
|
|
|
|
uint32_t data = 0;
|
|
|
|
|
data = ((uint32_t) readBuffer[3] >> 4) + ((uint32_t) readBuffer[2] << 4) + ((uint32_t) readBuffer[1] << 12);
|
|
|
|
|
*hum = data * 100.0f / (1 << 20);
|
|
|
|
|
|
|
|
|
|
data = (((uint32_t) readBuffer[3] & 0x0F) << 16) + (((uint32_t) readBuffer[4]) << 8) + (uint32_t) readBuffer[5];
|
|
|
|
|
*temp = data * 200.0f / (1 << 20) - 50;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
main.c 文件的 USER CODE BEGIN Includes 区域添加头文件:
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
/* USER CODE BEGIN Includes */
|
|
|
|
|
#include "aht20.h"
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
/* USER CODE END Includes */
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
main函数的 USER CODE BEGIN 2 区域添加内容
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
/* USER CODE BEGIN 2 */
|
|
|
|
|
AHT20_Init();
|
|
|
|
|
float temp, hum;
|
|
|
|
|
char message[50];
|
|
|
|
|
/* USER CODE END 2 */
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
完善 main 函数的 while 循环:
|
|
|
|
|
|
|
|
|
|
```c
|
|
|
|
|
while (1) {
|
|
|
|
|
AHT20_Read(&temp, &hum);
|
|
|
|
|
sprintf(message, "温度:%.1f 湿度:%.1f \n", temp, hum);
|
|
|
|
|
HAL_UART_Transmit(&huart2, (uint8_t*) message, strlen(message), 100);
|
|
|
|
|
HAL_Delay(2000);
|
|
|
|
|
/* USER CODE END WHILE */
|
|
|
|
|
|
|
|
|
|
/* USER CODE BEGIN 3 */
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 2.3. 代码分析
|
|
|
|
|
|
|
|
|
|
### 2.3.1. I2C的地址
|
|
|
|
|
|
|
|
|
|
在启动传输后,随后传输的I2C首字节包括7位的I2C设备地址 0x38和一个SDA方向位 x(读R:‘1’,写W:‘0’)。
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
因此,如果是读:实际地址是 0x71;如果是写,实际地址是0x70;注意代码中关于I2C的读写命令;
|
|
|
|
|
|
|
|
|
|
HAL_I2C_Master_Transmit和HAL_I2C_Master_Receive 的地址都使用0x70,HAL_I2C_Master_Transmit会自动设置最后一位是0(仍然是0x70);HAL_I2C_Master_Receive会自动设置最后一位是1(就是0x71)
|
|
|
|
|
|
|
|
|
|
### 温湿度数据的重组
|
|
|
|
|
|
|
|
|
|
按照AHT20的说明(p8),返回六个字节的顺序:
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|

|