【HAL库】HAL库STM32cubemx快速使用

文章目录

  • 整体框图
  • 一、基础工程
  • 1 新建工程
  • 2 配置RCC
  • 3 配置SYS
  • 4 工程设置
  • 5 生成代码
  • 6 keil设置下载&复位
  • 二、必备外设
  • 1 目录规范
  • 2 LED
  • 2 RTC
  • 3 USART
  • 4 KEY
  • 三、其他外设
  • 1 OLED(模拟IIC、模拟SPI)
  • 2 BH1750光强检测
  • 3 MQ2烟雾检测
  • 3 MQ4甲醛检测
  • 4 DHT11温湿度
  • 5 SIM900A GSM模块
  • 6 BMP180气压传感器
  • 7 ESP8266+Onenet+HTTP
  • 8 ESP8266+Onenet+MQTT
  • 整体框图

    image-20230409094054766

    软件:keil5、STM32Cubemx
    硬件:淘宝的STM32F103C8T6最小系统

    一、基础工程

    1 新建工程

    image-20230403143250580

    image-20230403143526045

    2 配置RCC

    选择外部时钟源。

    image-20230403144245550

    设置外部晶振输入值,我这块板子是8M。
    然后手动输入最大时钟频率,然后回车让他自动配置时钟树。我这块板子是72M。

    image-20230403144558704

    3 配置SYS

    我的下载器是SWD两根线的,所以我选这个。(一定配置完下载模式再进行程序下载,不然单片机变砖,需要从串口下载进行恢复)

    image-20230403144726224

    4 工程设置

    image-20230403145108357

    img

    5 生成代码

    点击生成代码

    img

    打开keil工程

    image-20230403145259140

    6 keil设置下载&复位

    选择下载器类型,我用的是DAP。点击后面的Setting。

    image-20230403145424797

    进入后勾选自动复位,表现为每次下载程序后单片机自动复位运行程序。
    设置完点击OK。

    image-20230403145616759

    二、必备外设

    1 目录规范

    在工程目录下,新建一个ICODE文件夹,用于存放自己写的各种外设文件。

    image-20230403145833040

    2 LED

    1 导入.c.h文件(就是将.c.h文件导入keil工程,后面不再叙述此环节)

    将之前写好的 LED文件夹复制到本工程的ICODE目录下。
    里边有led.c led.h文件夹。

    image-20230403150423937

    在工程中,创建ICODE文件夹,添加led.c文件。

    image-20230403150845428

    在工程中,添加led.h文件。

    image-20230403151117553

    image-20230403151200248

    2 Cubemx配置

    配置板子LED引脚,推挽输出模式。我这块板子是 PC13。
    重新生成代码。

    image-20230403151836114

    3 修改 .h 文件

    更改为其他引脚,只需更改LED端口号和引脚PIN。我这块板子是PC13。

    image-20230403152111448

    4 测试

    在main.c中添加 #include “led.h”
    在while里添加下面代码。LED灯闪烁。

    LED_Contrary();
    HAL_Delay(500);//500ms
    

    2 RTC

    1 导入.c.h文件(不再赘述,详细见LED部分)

    2 Cubemx配置

    和PC13冲突,核心板PC13是LED,所以禁用RTC OUT。

    3 修改 .c 文件

    在中断.c里,填加led头文件,在RTC中断函数里,加入500ms,LED电平反转函数。

    #include "led.h"
    
    static uint16_t rtccnt=0;
    rtccnt++;
    if(rtccnt>500) rtccnt=0,LED_Contrary();
    

    image-20230404190141584

    4 测试

    LED闪烁。

    3 USART

    1 导入.c.h文件(不再赘述,详细见LED部分)

    在keil工程中导入之前写好的.c.h文件。

    image-20230404190406936

    勾选使用

    image-20230408220340280

    2 Cubemx配置

    使用串口1,波特率默认,异步通信。

    image-20230404185429185
    开启中断
    image-20230404093133924

    3 修改 .h 文件

    代码默认使用串口1。添加其他串口可以在.h里,复制,改名。

    image-20230404183337374

    4 测试

    串口发送/接收函数:

    HAL_UART_Transmit();串口发送数据,使用超时管理机制 
    HAL_UART_Receive();串口接收数据,使用超时管理机制
    HAL_UART_Transmit_IT();串口中断模式发送  
    HAL_UART_Receive_IT();串口中断模式接收
    HAL_UART_Transmit_DMA();串口DMA模式发送
    HAL_UART_Transmit_DMA();串口DMA模式接收
    

    串口中断函数:

    HAL_UART_IRQHandler(UART_HandleTypeDef *huart);  //串口中断处理函数
    HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);  //串口发送中断回调函数
    HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart);  //串口发送一半中断回调函数(用的较少)
    HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);  //串口接收中断回调函数
    HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart);//串口接收一半回调函数(用的较少)
    HAL_UART_ErrorCallback();串口接收错误函数
    

    常用的发送函数为:HAL_UART_Transmit();

    常用的接收函数为:HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart);

    HAL库串口中断调用流程:

    image-20230404105922320

    发送:

    1 printf重映射:

    /* printf重映射 */
    #include <stdio.h>
    #ifdef __GNUC__
    #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
    #else
    #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
    #endif
    PUTCHAR_PROTOTYPE
    {
        //具体哪个串口可以更改huart1为其它串口
        HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1 , 0xffff);
        return ch;
    }
    

    2 printf发送:

    printf("hello \r\n"); //发送字符串
    
    float Data=1.11;
    printf("Data=%.2f \r\n",Data);	//发送变量
    

    3 Hal库自带发送函数:

    #include <stdio.h>
    
    HAL_UART_Transmit(&huart1,"hello\r\n",sizeof("hello\r\n"),0xffff);//发送字符串
    
    uint8_t Data1[]={"hello\r\n"};
    HAL_UART_Transmit(&huart1,Data1,sizeof(Data1),0xffff);//发送字符串
    
    uint8_t Databuffer[20]={0};
    float Data=1.11;
    sprintf(Databuffer,"Data=%.2f \r\n",Data);
    HAL_UART_Transmit(&huart1,Databuffer,strlen(Databuffer),0xffff);//发送变量 用strlen
    

    中断接收:

    1 定长

     /*	
    		串口接收中断
    		定长接收	
    */
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
    		if(huart == &huart1)
    		{
    			HAL_UART_Transmit(&huart1,(uint8_t *)&Uart1_RxData,1,0xffff);//原样返回
    			while(HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX);//检测UART发送结束
    			HAL_UART_Receive_IT(&huart1,(uint8_t *)&Uart1_RxData, 1); //&取地址
    		}
    }
    

    2 不定长

    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
      /* Prevent unused argument(s) compilation warning */
      UNUSED(huart);
    	
    	if(huart == &huart1)
    	{
    		if(Uart1_Rx_Cnt >= 255)  //溢出判断
    		{
    			Uart1_Rx_Cnt = 0;
    			memset(Uart1_RxBuffer,0x00,sizeof(Uart1_RxBuffer));
    			HAL_UART_Transmit(&huart1, (uint8_t *)"数据溢出", 10,0xFFFF); 	
    		}
    		else
    		{
    			Uart1_RxBuffer[Uart1_Rx_Cnt++] = Uart1_RxData;   //接收数据转存
    		
    			if((Uart1_RxBuffer[Uart1_Rx_Cnt-1] == 0x0A)&&(Uart1_RxBuffer[Uart1_Rx_Cnt-2] == 0x0D)) //判断结束位\r\n。0x0D是\r,0x0A是\n
    			{
    				/*	此处添加用户代码	*/
    
    				HAL_UART_Transmit(&huart1, (uint8_t *)&Uart1_RxBuffer, Uart1_Rx_Cnt,0xFFFF); //将收到的信息发送出去
    				while(HAL_UART_GetState(&huart1) == HAL_UART_STATE_BUSY_TX);//检测UART发送结束
    
    				/*	此处添加用户代码	*/
    				Uart1_Rx_Cnt = 0;
    				memset(Uart1_RxBuffer,0x00,sizeof(Uart1_RxBuffer)); //清空数组
    			}
    		}
    		HAL_UART_Receive_IT(&huart1, (uint8_t *)&Uart1_RxData, 1);   //再开启接收中断
    	}
    }
    

    4 KEY

    1 导入.c.h文件(不再赘述,详细见LED部分)

    在keil工程中导入之前写好的.c.h文件。

    2 Cubemx配置

    3 修改 .h 文件

    4 测试

    三、其他外设

    1 OLED(模拟IIC、模拟SPI)

    1 导入.c.h文件(不再赘述,详细见LED部分)

    在keil工程中导入之前写好的.c.h文件。选择IIC的或者SPI的。(模拟IIC和模拟SPI)

    image-20230404190842999

    image-20230404191104861

    2 Cubemx配置

    任选对应OLED引脚个数的GPIO,设置成推挽输出。设置为高速。

    image-20230404192656241

    3 修改 .h 文件

    更改为其他引脚,只需更改OLED端口号和引脚PIN

    image-20230404191352126

    4 测试

    OLED 显示字体大小 16*16 最合适。能放4行:0 16 32 48。

    添加头文件

    #include "oled.h"
    

    添加初始化

    OLED_Init();
    OLED_ColorTurn(0);			//0正常显示,1 反色显示
    OLED_DisplayTurn(0);		//0正常显示 1 屏幕翻转显示
    

    1 显示字符:

    OLED_ShowString(0,0,"hello",16,1); 
    OLED_Refresh();//更新0
    

    2 显示变量:

    uint8_t Databuffer[20]={0};
    float Data=1.11;
    sprintf(Databuffer,"Data=%.2f \r\n",Data);//sprintf
    OLED_ShowString(0,16,Databuffer,16,1);  
    OLED_Refresh();
    

    3 显示中文:

    
    

    1

    2 BH1750光强检测

    1 导入.c.h文件(不再赘述,详细见LED部分)

    在keil工程中导入之前写好的.c.h文件。

    2 Cubemx配置

    3 修改 .h 文件

    4 测试

    添加头文件

    添加初始化

    3 MQ2烟雾检测

    1 导入.c.h文件(不再赘述,详细见LED部分)

    在keil工程中导入之前写好的.c.h文件。

    image-20230404202319711

    2 Cubemx配置

    随意选一个ADC引脚。初始化ADC引脚。

    3 修改 .h 文件

    4 测试

    添加头文件

    #include "mq2.h"
    

    采集

    uint16_t MQ2_DATA=0;
    MQ2_DATA = GetMQ4Value();
    

    3 MQ4甲醛检测

    同MQ2,AD读取。

    浓度转化函数:

    uint16_t GetMQ4Value(void)
    {
    			uint16_t ADCVal;
    			float Voltage;
    			uint16_t ppm;
    			HAL_ADC_Start(&hadc1);//开始ADC采集
    			HAL_ADC_PollForConversion(&hadc1,500);//等待采集结束
    			if(HAL_IS_BIT_SET(HAL_ADC_GetState(&hadc1), HAL_ADC_STATE_REG_EOC))//读取ADC完成标志位
    			{
    				ADCVal =  HAL_ADC_GetValue(&hadc1);//读出ADC数值
    			}
    			Voltage = ADCVal * 3.3 / 4096;
    	//无天然气的环境下,实测AOUT端的电压为0.5V,当检测到天然气时,电压每升高0.1V,实际被测气体浓度增加200ppm
    			ppm = (Voltage - 0.5) / 0.1 * 200;
    			return ppm;
    			//return ADCVal;
    }
    

    4 DHT11温湿度

    1 导入.c.h文件(不再赘述,详细见LED部分)

    在keil工程中导入之前写好的.c.h文件。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4kFUCvSv-1681004471418)(null)]

    2 Cubemx配置

    任选一个IO口,配置为高速,推挽输出。

    1 导入.c.h文件(不再赘述,详细见LED部分)

    在keil工程中导入之前写好的.c.h文件。

    image-20230404202744976

    2 Cubemx配置

    随意选择一个IO口。配置为推挽输出,高速。

    3 修改 .h 文件

    定义DHT11总线连接的GPIO端口, 只需要修改下面2行代码即可任意改变DATA的引脚

    image-20230404194855017

    4 测试

    添加头文件

    #include "dht11.h"
    

    添加初始化

    DHT11_Init();						//DHT11温湿模块初始化
    

    读取温湿度

    uint8_t DHT11_DATA[2]={0};		//用于存放DHT11温湿度数据
    DHT11_ReadData(DHT11_BUF);		//读出DHT11传感器数据(参数是存放数据的数组指针)
    printf("湿度:%2d% 温度:%2d℃\r\n",DHT11_BUF[0],DHT11_BUF[1]);//串口打印湿度温度
    

    5 SIM900A GSM模块

    1 导入.c.h文件(不再赘述,详细见LED部分)

    在keil工程中导入之前写好的.c.h文件。

    2 Cubemx配置

    3 修改 .h 文件

    4 测试

    添加头文件

    添加初始化

    6 BMP180气压传感器

    1 导入.c.h文件(不再赘述,详细见LED部分)

    在keil工程中导入之前写好的.c.h文件。

    image-20230409090534520

    2 Cubemx配置

    采用模拟IIC,任意选两个io口设置为推挽输出模式。我这边选B7 B6。

    配置串口1,重映射printf。

    cubemx基本工程和配置看:【HAL库】HAL库STM32cubemx快速使用

    3 修改 .h 文件

    只需要修改下面2行代码即可任意改变引脚

    image-20230409090442577

    4 测试

    添加头文件

    #include "bmp1801.h"
    

    添加初始化

    BMP_Init();				  //BMP180初始化
    BMP_ReadCalibrationData();//BMP180初始化
    

    读取

    uint8_t ID = 0;		//BMP180器件号
    ID = BMP_ReadOneByte(0xd0);	//读取设备ID
    BMP_UncompemstatedToTrue();	//读取气压值
    printf("ID = %d\t  temp = %d.%dC\t   Pressure = %.2fkPa\t   Altitude = %.5fm\r\n",ID,bmp180.Temp/10,bmp180.Temp%10,(float)bmp180.p/1000.0,bmp180.altitude);
    HAL_Delay(500);
    

    image-20230409092351354

    7 ESP8266+Onenet+HTTP

    1 导入.c.h文件(不再赘述,详细见LED部分)

    在keil工程中导入之前写好的.c.h文件。

    2 Cubemx配置

    3 修改 .h 文件

    4 测试

    添加头文件

    添加初始化

    8 ESP8266+Onenet+MQTT

    1 导入.c.h文件(不再赘述,详细见LED部分)

    在keil工程中导入之前写好的.c.h文件。

    image-20230408211617282

    2 Cubemx配置

    串口1用于调试,串口3用于ESP8266通信,打开中断。

    基础的我就不配置了,可以看前面的详细讲解。

    3 修改 .c.h 文件

    移植时要修改的地方:

    1 改所用串口

    发送部分:在esp8266.c里,将huart3全部替换为要修改的串口号,比如串口2。

    image-20230408212731847

    接收部分:用串口中断接收esp8266发来的消息。随便在哪个文件夹填加串口回调函数,我个人是之前专门建了个uart.c文件放串口相关的所有代码。

    加入下面的代码(串口号根据个人情况修改)

    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    {
        if(huart == &huart3)//esp8266接收云平台数据
    		{
    			if(esp8266_cnt >= sizeof(esp8266_buf))
    			{            
    				esp8266_cnt = 0; //防止串口被刷爆
    			}
    			esp8266_buf[esp8266_cnt++] = Uart3_RxData;
    
    			HAL_UART_Receive_IT(&huart3,(uint8_t *)&Uart3_RxData, 1); //&取地址
    		}
    }
    

    2 改wifi名字和密码

    image-20230408211926168

    3 改产品ID、设备ID、鉴权信息。

    image-20230408212601399

    4 测试

    添加头文件

    #include "onenet.h"
    #include "esp8266.h"
    

    添加初始化

    别忘了开串口中断。

    HAL_UART_Receive_IT(&huart3,(uint8_t *)&Uart3_RxData, 1);//开启串口中断
    /* esp8266连接wifi+连接Onenet */
    HAL_Delay(2000);
    ESP8266_Init();					//初始化ESP8266,连接wifi
    HAL_Delay(2000);
    while(OneNet_DevLink())			//连接OneNET
    HAL_Delay(2000);
    

    连接成功的话,onenet会显示设备在线。串口也会打印成功。

    image-20230408213614618

    image-20230408220823254

    发送数据

    OneNet_SendData();	//发送数据
    ESP8266_Clear();	//清空数据缓存区
    HAL_Delay(3000);	//3s发送一次
    

    image-20230408220926312

    要发什么数据,在这里改:

    image-20230408214852054

    接收数据

    dataPtr = ESP8266_GetIPD(0);//获取平台返回的数据
    if(dataPtr != NULL)//如果返回数据不为空
    	OneNet_RevPro(dataPtr);//平台返回数据检测
    
    物联沃分享整理
    物联沃-IOTWORD物联网 » 【HAL库】HAL库STM32cubemx快速使用

    发表回复