提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
一、串口显示温湿度数据
I2C简介
I²C(Inter-Integrated Circuit)总线是一种由Philips(现NXP Semiconductors)开发的简单的双向二线制串行总线协议。它允许微控制器和其他集成电路(ICs)进行短距离通信,主要用于连接低速的外围设备。I²C总线仅使用两条线路:一条串行数据线SDA(Serial Data Line)和一条串行时钟线SCL(Serial Clock Line)。这两条线通常通过上拉电阻连接到电源电压。
物理层特性
半双工通信:由于SDA线既是数据发送线也是数据接收线,I²C总线是半双工的,意味着数据传输在同一时间只能朝一个方向进行。
开漏输出:每个I²C设备的SDA和SCL引脚通常采用开漏输出结构,这使得多个设备可以共享总线而不相互干扰,因为它们不会试图主动将线拉至高电平,而是依赖上拉电阻来保持线处于高电平状态。
“线与”逻辑:由于使用了开漏输出,当多个设备尝试同时将线拉低时,总线电平可以被拉至低,从而实现逻辑“与”操作。
总线仲裁:如果多个主控设备试图控制总线,仲裁过程确保只有一个主控设备能够成功发送数据。这是通过检测SDA线上的数据是否与预期的一致来实现的,如果不一致,则说明有冲突,主控设备会停止传输并释放总线。
协议层特性
寻址:I²C设备通过一个7位或10位地址来识别,这取决于设备是否支持扩展地址。地址通常在设备的数据手册中指定,且部分设备允许通过硬件跳线或软件配置来改变地址。
启动和停止条件:通信开始时,必须有一个启动条件,即SCL为高时SDA从高到低的变化;而通信结束时,必须有一个停止条件,即SCL为高时SDA从低到高的变化。
应答位:每次传输字节后,接收方会发送一个应答位,表示数据已正确接收。如果发送方没有接收到应答位,则可能需要重传数据或者检查总线错误。
数据传输:数据以字节为单位传输,每个字节后跟随一个应答位。数据的传输是同步的,由SCL时钟信号的上升沿触发数据采样。
速度模式
I²C协议支持多种速度模式:
标准模式:最高100 kbps
快速模式:最高400 kbps
快速模式+:最高1 Mbps
高速模式:最高3.4 Mbps
模拟快速模式:最高10 Mbps(非官方)
I²C总线的简单性和效率使其成为许多嵌入式系统中的常见选择,用于连接如传感器、EEPROM、RTC(实时钟)、ADCs(模数转换器)、DACs(数模转换器)等低速设备。
1.工程项目配置
RCC配置
SYS配置
USART1配置,进行串口通信端口的配置
I2C1配置,连接温湿度传感器AHT20
时钟配置
项目工程配置
最后打开工程
2.代码修改
为实现温度采集,需要加入以下两个文件
aht20.c代码如下
#include "aht20.h"
#define AHT20_ADDRESS 0x70 // 从机地址
//AHT20 的驱动程序
void AHT20_Init () //AHT20初始化函数 记住要在"aht20.h"中声明
{
uint8_t readBuffer;//用于接收状态信息
HAL_Delay(40);
HAL_I2C_Master_Receive(&hi2c1, AHT20_ADDRESS, &readBuffer, 1, HAL_MAX_DELAY);//I2C读取函数,读数据函数 readBuffer此时获得了一个字节的状态字。
if((readBuffer & 0x08) == 0x00) //判断第三位是否为0 发送0xBE命令初始化
{
uint8_t sendBuffer [3] = {
0xBE , 0x08 , 0x00};
HAL_I2C_Master_Transmit(&hi2c1, AHT20_ADDRESS, sendBuffer, 3, HAL_MAX_DELAY);//I2C发送函数
}
}
void AHT20_Read(float *Temperature , float *Humidity) //AHT20读取温度湿度函数 记住要在"aht20.h"中声明
{
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 date = 0;//接收温湿度需要2个半字节 所以要32
date = ((uint32_t )readBuffer[3] >> 4) + ((uint32_t )readBuffer[2] << 4) + ((uint32_t )readBuffer[1] << 12);//对数据进行移位拼接.
*Humidity = date * 100.0f / (1 << 20);//(1 << 20) 意为2的20次方. 乘100.0可以表示为百分数
date = (((uint32_t )readBuffer[3] & 0x0F)<< 16) + ((uint32_t )readBuffer[4] << 8) + (uint32_t )readBuffer[5];//& 0x0F: 将这个无符号整数与十六进制数0x0F进行按位与操作。0x0F的二进制表示为00001111,这个操作会保留readBuffer[3]的低四位,即将高四位清零。
*Temperature = date * 200.0f / (1 << 20) - 50;
}
}
aht20.h代码如下
/*
* aht20.h
*
* Created on: Apr 25, 2024
* Author: lenovo
*/
#ifndef INC_AHT20_H_
#define INC_AHT20_H_
#include "i2c.h"
void AHT20_Init (void);
void AHT20_Read(float *Temperature , float *Humidity);
#endif /* INC_AHT20_H_ */
修改main文件,代码如下
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2024 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "i2c.h"
#include "usart.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "i2c.h"
#include <stdio.h>
#include "string.h"
#include "aht20.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
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_USART1_UART_Init();
/* USER CODE BEGIN 2 */
AHT20_Init ();//初始化AHT20
float temperature , humidity ;
char message [50];
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
AHT20_Read( &temperature , &humidity); //读取AHT20
sprintf(message ,"温度: %f℃ , 湿度: %f.\r\n",temperature , humidity);//拼接
HAL_UART_Transmit(&huart1, (uint8_t*)message,strlen(message) , HAL_MAX_DELAY);//串口发???函??
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {
0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {
0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct