接着之前的改一下,注意波特率改成9600了,开了串口干脆改成蓝牙吧顺手的事。
运行效果:
这篇运行成功的代码是开启NVIC,改成DMA只需要把接收和发送函数后面的 _IT 改成 _DMA 就行了,也就是 AHT20_Get();和AHT20_Measure();这两个函数里面需要改。
一、配置cubemx的I2C1+NVIC以及USART2
开了USART2,把下面波特率改成9600即可
二、写代码
由于中断和DMA都是是非阻塞模式(与上一篇轮询模式不同,轮询模式要等待所有数据发送、接受完才会向下执行,所有有个等待时间Time,之前设置的HAL_MAX_DELAY),它会将任务交给外设后向下执行,所以要设置状态机,以及使用回调函数。
设置状态机就是把上一篇里的void AHT20_Read(float *Temperature, float *Humidity)函数分解成多个函数,详情可见keysking的解析。
状态机:
0:初始状态,发送测量命令 AHT20_Measure();
1:正在发送 Tx回调函数
(在通过AHT20_Measure();的HAL_I2C_Master_Transmit_IT();发送命令数据全部到从机后,由I2C中断调用,此时状态机到达2)
2、完成发送,等待80ms后读取 AHT20_Get();
3、读取中 Rx回调函数
4、读取完成,数据解析并展示 AHT20_Analysis(&temperature, &humidity);
回调函数分别在5137和5154行
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c)
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c)
AHT20.c
#include "AHT20.h"
/***************手册第八面5.4****************/
#define AHT20_ADDRESS 0x70
uint8_t readBuffer[6] = {0};
void AHT20_Init()
{
uint8_t readBuffer;
HAL_Delay(40); //上电后要等待40ms
HAL_I2C_Master_Receive(&hi2c1, AHT20_ADDRESS, &readBuffer, 1, HAL_MAX_DELAY); //读取温湿度值
if ((readBuffer & 0x08) == 0x00) //判断校准使能位Bit[3]是否为0
{
uint8_t sendBuffer[3] = {0xBE, 0x08, 0x00};
HAL_I2C_Master_Transmit(&hi2c1, AHT20_ADDRESS, sendBuffer, 3, HAL_MAX_DELAY); //发送数组
}
}
void AHT20_Read(float *Temperature, float *Humidity)
{
uint8_t sendBuffer[3] = {0xAC, 0x33, 0x00};
uint8_t readBuffer[6] = {0};
HAL_I2C_Master_Transmit_IT(&hi2c1, AHT20_ADDRESS, sendBuffer, 3); //直接发送触发测量命令
HAL_Delay(80); //等待80ms待测量完成
HAL_I2C_Master_Receive_IT(&hi2c1, AHT20_ADDRESS, readBuffer, 6); //读取
if ((readBuffer[0] & 0x80) == 0x00) //判断读取状态字Bit[7]是否为0
{
uint32_t data = 0;
data = ((uint32_t)readBuffer[3] >> 4) + ((uint32_t)readBuffer[2] << 4) + ((uint32_t)readBuffer[1] << 12); //拼接数据
*Humidity = data * 100.0f / (1 << 20); //注意%以及float型
data = (((uint32_t)readBuffer[3] & 0x0F) << 16) + ((uint32_t)readBuffer[4] << 8) + (uint32_t)readBuffer[5];
*Temperature = data * 200.0f / (1 << 20) - 50;
}
}
/*************发送命令,等待测量***************/
void AHT20_Measure(){
static uint8_t sendBuffer[3] = {0xAC, 0x33, 0x00};
HAL_I2C_Master_Transmit_IT(&hi2c1, AHT20_ADDRESS, sendBuffer, 3);
}
/******************读取********************/
void AHT20_Get(){
HAL_I2C_Master_Receive_IT(&hi2c1, AHT20_ADDRESS, readBuffer, 6);
}
/******解析数据函数,要有两个向外传递数据的float指针入参**********/
void AHT20_Analysis(float *Temperature, float *Humidity){
if ((readBuffer[0] & 0x80) == 0x00) //判断读取状态字Bit[7]是否为0
{
uint32_t data = 0;
data = ((uint32_t)readBuffer[3] >> 4) + ((uint32_t)readBuffer[2] << 4) + ((uint32_t)readBuffer[1] << 12); //拼接数据
*Humidity = data * 100.0f / (1 << 20); //注意%以及float型
data = (((uint32_t)readBuffer[3] & 0x0F) << 16) + ((uint32_t)readBuffer[4] << 8) + (uint32_t)readBuffer[5];
*Temperature = data * 200.0f / (1 << 20) - 50;
}
}
AHT20.h
#ifndef __AHT20_H
#define __AHT20_H
#include "I2C.h"
#include "main.h"
void AHT20_Init();
void AHT20_Read(float *Temperature, float *Humidity);
void AHT20_Measure();
void AHT20_Get();
void AHT20_Analysis(float *Temperature, float *Humidity);
#endif
I2C.c(加入了回调函数)
/* USER CODE BEGIN 0 */
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c){
if(hi2c == &hi2c1)
aht20State = 2;
}
void HAL_I2C_MasterRxCpltCallback(I2C_HandleTypeDef *hi2c){
if(hi2c == &hi2c1)
aht20State = 4;
}
/* USER CODE END 0 */
main.h(加了全局变量申明)
/* USER CODE BEGIN ET */
extern uint8_t aht20State;
/* USER CODE END ET */
main.c
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C1_Init();
MX_USART2_UART_Init();
/* USER CODE BEGIN 2 */
AHT20_Init();
float temperature, humidity;
char message[50];
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(aht20State == 0){
AHT20_Measure();
aht20State = 1;
}else if(aht20State == 2){
HAL_Delay(80);
AHT20_Get();
aht20State = 3;
}else if(aht20State == 4){
AHT20_Analysis(&temperature, &humidity);
sprintf(message, "Temperature: %.1f,Humidity: %.1f %%\r\n", temperature, humidity);
HAL_UART_Transmit(&huart2, (uint8_t *)message, strlen(message), HAL_MAX_DELAY);
HAL_Delay(1000);
aht20State = 0;
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}