基于STM32的ESP8266连接Onenet(HAL库)

若该文为原创文章,转载请注明原文出处。

一直使用标准库开发STM32及其他单片机,刚好有个项目要求使用HAL库,以前有用过其他的,没有记录,趁此机会,记录下移植HAL库的全过程

简单的一个DEMO,使用的是STM32F103C8T6单片机,采用ESP-01SWIFI模块,连接Onenet通讯。

一、接口

OLED:

SCL -> PB5

SDA -> PB4

WIFI模块:

RX -> PA2

TX -> PA3

RST -> PA1

二、程序移植

没有采用CubeMX配置,在正点原子的例程上下载了个DEMO程序,直接修改

1、串口移植

串口移植主要是串口2配置,还有数据处理,这里直接附代码

复制代码
#include "sys.h"
#include "usart.h"	
#include "esp8266.h"

//C库
#include <stdarg.h>
#include <string.h>
#include <stdio.h>

////////////////////////////////////////////////////////////////////////////////// 	 
//如果使用ucos,则包括下面的头文件即可.
#if SYSTEM_SUPPORT_OS
#include "includes.h"					//ucos 使用	  
#endif
 
uint8_t rx_data; // 接收缓冲区
//////////////////////////////////////////////////////////////////
//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 

}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
    USART1->DR = (u8) ch;      
	return ch;
}
#endif 


#if EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误   	
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART_RX_STA=0;       //接收状态标记	  

u8 aRxBuffer[RXBUFFERSIZE];//HAL库使用的串口接收缓冲
UART_HandleTypeDef UART1_Handler; //UART句柄
UART_HandleTypeDef UART2_Handler; //UART句柄

//初始化IO 串口1 
//bound:波特率
void uart_init(u32 bound)
{	
	//UART 初始化设置
	UART1_Handler.Instance=USART1;					    //USART1
	UART1_Handler.Init.BaudRate=bound;				    //波特率
	UART1_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //字长为8位数据格式
	UART1_Handler.Init.StopBits=UART_STOPBITS_1;	    //一个停止位
	UART1_Handler.Init.Parity=UART_PARITY_NONE;		    //无奇偶校验位
	UART1_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //无硬件流控
	UART1_Handler.Init.Mode=UART_MODE_TX_RX;		    //收发模式
	HAL_UART_Init(&UART1_Handler);					    //HAL_UART_Init()会使能UART1
	
	HAL_UART_Receive_IT(&UART1_Handler, (u8 *)aRxBuffer, RXBUFFERSIZE);//该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量
  
}

//UART底层初始化,时钟使能,引脚配置,中断配置
//此函数会被HAL_UART_Init()调用
//huart:串口句柄

void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
    //GPIO端口设置
	GPIO_InitTypeDef GPIO_Initure;
	
	if(huart->Instance==USART1)//如果是串口1,进行串口1 MSP初始化
	{
		__HAL_RCC_GPIOA_CLK_ENABLE();			//使能GPIOA时钟
		__HAL_RCC_USART1_CLK_ENABLE();			//使能USART1时钟

	
		GPIO_Initure.Pin=GPIO_PIN_9;			//PA9
		GPIO_Initure.Mode=GPIO_MODE_AF_PP;		//复用推挽输出
		GPIO_Initure.Pull=GPIO_PULLUP;			//上拉
		GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA9

		GPIO_Initure.Pin=GPIO_PIN_10;			//PA10
		GPIO_Initure.Mode=GPIO_MODE_AF_INPUT;	//模式要设置为复用输入模式!	
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA10
		
#if EN_USART1_RX
		HAL_NVIC_DisableIRQ(USART1_IRQn);				//使能USART1中断通道
		HAL_NVIC_SetPriority(USART1_IRQn,3,3);			//抢占优先级3,子优先级3
#endif	
	}
	else if(huart->Instance==USART2)//如果是串口1,进行串口1 MSP初始化
	{
		__HAL_RCC_GPIOA_CLK_ENABLE();			//使能GPIOA时钟
		__HAL_RCC_USART2_CLK_ENABLE();			//使能USART1时钟
		__HAL_RCC_AFIO_CLK_ENABLE();
	
		GPIO_Initure.Pin=GPIO_PIN_2;			//PA9
		GPIO_Initure.Mode=GPIO_MODE_AF_PP;		//复用推挽输出
		GPIO_Initure.Pull=GPIO_PULLUP;			//上拉
		GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;//高速
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA9

		GPIO_Initure.Pin=GPIO_PIN_3;			//PA10
		GPIO_Initure.Mode=GPIO_MODE_AF_INPUT;	//模式要设置为复用输入模式!	
		HAL_GPIO_Init(GPIOA,&GPIO_Initure);	   	//初始化PA10
		
		HAL_NVIC_EnableIRQ(USART2_IRQn);				//使能USART1中断通道
		HAL_NVIC_SetPriority(USART2_IRQn,3,3);			//抢占优先级3,子优先级3
	}
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart->Instance==USART1)//如果是串口1
	{
		  rx_data = (uint8_t)(huart->Instance->DR);
    
    
    HAL_UART_Receive_IT(&UART1_Handler, &rx_data, 1); // 再次开启中断接收
	}
	else if(huart->Instance==USART2)//如果是串口1
	{
  		//HAL_UART_Transmit(&huart1, &rx_data, 1, HAL_MAX_DELAY); // 回传接收到的数据
    rx_data = (uint8_t)(huart->Instance->DR);
    Esp8266_Rx_IRQHandle(rx_data);
    
    HAL_UART_Receive_IT(&UART2_Handler, &rx_data, 1); // 再次开启中断接收
	}
}
 
//串口1中断服务程序
void USART1_IRQHandler(void)                	
{ 
	HAL_UART_IRQHandler(&UART1_Handler);	//调用HAL库中断处理公用函数
} 
#endif	


 
//初始化IO 串口1 
//bound:波特率
void Usart2_Init(u32 bound)
{	
	//UART 初始化设置
	UART2_Handler.Instance=USART2;					    //USART1
	UART2_Handler.Init.BaudRate=bound;				    //波特率
	UART2_Handler.Init.WordLength=UART_WORDLENGTH_8B;   //字长为8位数据格式
	UART2_Handler.Init.StopBits=UART_STOPBITS_1;	    //一个停止位
	UART2_Handler.Init.Parity=UART_PARITY_NONE;		    //无奇偶校验位
	UART2_Handler.Init.HwFlowCtl=UART_HWCONTROL_NONE;   //无硬件流控
	UART2_Handler.Init.Mode=UART_MODE_TX_RX;		    //收发模式
	HAL_UART_Init(&UART2_Handler);					    //HAL_UART_Init()会使能UART1
		
	HAL_UART_Receive_IT(&UART2_Handler, (u8 *)aRxBuffer, 1);//该函数会开启接收中断:标志位UART_IT_RXNE,并且设置接收缓冲以及接收缓冲接收最大数据量
}


void Usart_SendString(USART_TypeDef *USARTx, unsigned char *str, unsigned short len)
{
  HAL_UART_Transmit(&UART2_Handler, (uint8_t*)str, len,1000);	//发送接收到的数据
  while(__HAL_UART_GET_FLAG(&UART2_Handler,UART_FLAG_TC)!=SET);		//等待发送结束
}


//串口1中断服务程序
void USART2_IRQHandler(void)                	
{ 
	HAL_UART_IRQHandler(&UART2_Handler);	//调用HAL库中断处理公用函数
} 


void UsartPrintf(USART_TypeDef *USARTx, char *fmt,...)
{

	unsigned char UsartPrintfBuf[296];
	va_list ap;
	unsigned char *pStr = UsartPrintfBuf;
	
	va_start(ap, fmt);
	vsnprintf((char *)UsartPrintfBuf, sizeof(UsartPrintfBuf), fmt, ap);							//格式化
	va_end(ap);
	

		HAL_UART_Transmit(&UART1_Handler, (uint8_t*)pStr, strlen(pStr),1000);	//发送接收到的数据
  while(__HAL_UART_GET_FLAG(&UART1_Handler,UART_FLAG_TC)!=SET);		//等待发送结束


}

代码是在例程上直接添加,增加了初始化及传输和接收数据处理。

2、ESP8266接收处理

复制代码
void Esp8266_Rx_IRQHandle(char data)
{
    if(esp8266_cnt >= sizeof(esp8266_buf)) esp8266_cnt = 0; //防止串口被刷爆
      esp8266_buf[esp8266_cnt++] = data;
}

替换原来的串口2中断函数

3、配置

OLED使有的是PB4和PB5没有关闭JTAT会不能显示

复制代码
	__HAL_RCC_AFIO_CLK_ENABLE();
	__HAL_AFIO_REMAP_SWJ_NOJTAG();  // 禁用JTAG,保留SWD

4、堆栈

注意需要调节堆栈

5、程序架构

增加了Onenet底层,这个网上有,基本不用修改,修改的是串口部分,已经修改了

6、主程序

复制代码
int main(void)
{ 
	unsigned char *dataPtr = NULL;	
	
 HAL_Init();                    	 	//初始化HAL库    
 Stm32_Clock_Init(RCC_PLL_MUL9);   	//设置时钟,72M
	
	__HAL_RCC_AFIO_CLK_ENABLE();
	__HAL_AFIO_REMAP_SWJ_NOJTAG();  // 禁用JTAG,保留SWD
	
	delay_init(72);               		//初始化延时函数
	uart_init(115200);					 //初始化串口
	LED_Init();					     	 	//初始化LED	
	KEY_Init();							      //初始化按键
	
	OLED_Init();            // OLED初始化
	
	ESP8266_Init();         // ESP8266初始化
	TIM3_Init(9999, 7199);
	
	OLED_Clear();
	OLED_ShowString(0,0,"Init Ok.",16, 1);
	
 while(1)
 {	
			 /* 数据发送 */
    if(time3scnt >= 20 || senflg == 1)
    {      
      senflg = 0;
      time3scnt = 0;
					
					 OneNet_SendData();	//发送数据到云平台
      ESP8266_Clear();    //情况串口接收区缓存
        

    }
    dataPtr = ESP8266_GetIPD(0);//获取云平台下发的数据
		  if(dataPtr != NULL)//如果不为空,解析
    {
      OneNet_RevPro(dataPtr);	//平台返回数据检测
    }
    
  }
}

测试是正常的,后续会增加传感器的HAL库使用。

如有侵权,或需要完整代码,请及时联系博主。

相关推荐
Sophia么么2 小时前
嵌入式知识---如何配置定时器的时基单元,如何配置输出通道
单片机·嵌入式硬件
Katecat996632 小时前
尿液样本中细胞与非细胞成分检测分类系统实现
单片机·分类·数据挖掘
2401_863318633 小时前
基于单片机的恒温箱设计
单片机·嵌入式硬件
ベadvance courageouslyミ3 小时前
嵌入式硬件基础
嵌入式硬件·51单片机·嵌入式·数码管·二极管
范纹杉想快点毕业4 小时前
欧几里得算法与扩展欧几里得算法,C语言编程实现(零基础全解析)
运维·c语言·单片机·嵌入式硬件·算法
2301_773730314 小时前
嵌入式—51单片机day1
单片机·嵌入式硬件·51单片机
PegasusYu4 小时前
STM32校准读取激光测距传感器VL53L0X距离数据
stm32·测距·stm32cubeide·激光测距·vl53l0x·飞行时间·stm32g031f8
代码游侠4 小时前
学习笔记——嵌入式与51单片机学习
单片机·嵌入式硬件·学习·51单片机
zy135380675734 小时前
12V输入5V/2A输出升降压芯片AH4002
科技·单片机·物联网·fpga开发·硬件工程·智能电视