cubeIDE开发, stm32的WIFI通信设计(基于AT指令)

news2024/10/7 12:26:04

一、stm32的WIFI配置

        通常WIFI模块就是一个独立的单片机,只是内置了WFIF通信软件的单片机,并该通信软件提供了AT通信指令集给开发人员,基于这些指令集我们就可以针对项目需要进行二次集成开发出所需的业务应用软件。

        本文本文采用的开发板是stm32L496VGT3,该开发板的MCU及WIFI模块(MW31)硬件电路图如下:

        MCU采用PC4、PC5连接WIFI实现通信,PB0、PB1作为辅助控制。

 WIFI模块给出了两个通信接口,一个用来连接MCU(电路板已经连接好了,本文就采用该接口实现MCP串口通信控制WIFI模块),一个用来给外置使用。

 与WIFI通信关联的MCU的IO端口设置要求,开发板给出如下:

         以及各个IO口具体参数要求

         打开CubeMX配置页面,按上述要求设置WIFI配置通信接口USART3:

         开启USART3外部中断功能:

         设置PC4、PC5的IO接口参数

         同时芯片图形化配置页面设置PB0、PB1为GPIO_OutPut模式,并进入GPIO配置页面,设置PB0、PB1的IO接口参数:

          完成配置点击保存按钮或代码生产按钮生成代码:

二、代码设计

        本文基于前一篇博文的串口通信能力基础上来实现的,即已经完成了printf函数映射到lpusart进行串口通信:cubeIDE开发, stm32调试信息串口通信输出显示_py_free的博客-CSDN博客

         我们先实现串口USART3的接收回调实现,在改写ICore目录下的usart.h、usart.c代码文件:

        usart.h内容如下,类似lpusart串口添加了串口USART3的接收辅助变量:

/*
 * usart.h
 *
 *  Created on: Oct 20, 2022
 *      Author: Administrator
 */

#ifndef INC_USART_H_
#define INC_USART_H_

#include "stm32l4xx_hal.h" //HAL库文件声明
#include <string.h>//用于字符串处理的库
#include "print.h"//用于printf函数串口重映射

extern UART_HandleTypeDef hlpuart1;//声明LPUSART的HAL库结构体
extern UART_HandleTypeDef huart3;//声明USART3的HAL库结构体

#define HLPUSART_REC_LEN  256//定义LPUSART最大接收字节数
#define USART3_REC_LEN  256//定义USART3最大接收字节数

extern uint8_t  HLPUSART_RX_BUF[HLPUSART_REC_LEN];//接收缓冲,最大HLPUSART_REC_LEN个字节.末字节为换行符
extern uint16_t HLPUSART_RX_STA;//接收状态标记
extern uint8_t HLPUSART_NewData;//当前串口中断接收的1个字节数据的缓存

extern uint8_t USART3_RX_BUF[USART3_REC_LEN];	//接收缓冲,最大USART_REC_LEN个字节.
extern uint16_t USART3_RX_STA;				//接收状态标记,bit15:接收完成标志,bit14:接收到0x0d,bit11~0:接收到的有效字节数目
extern uint8_t USART3_NewData;					//当前串口中断接收的1个字节数据的缓存

void  HAL_UART_RxCpltCallback(UART_HandleTypeDef  *huart);//串口中断回调函数声明

#endif /* INC_USART_H_ */

        usart.c内容如下,添加了USART3的回调处理,实现接收来自WIFI模块的数据,lpusart和USART3的回调处理几乎一样的,主要就是接收到一个数据,就缓存起来,并再次开启中断接收;在接收到回车字段或缓存溢出是,进行标记(HLPUSART_RX_STA和USART3_RX_STA的前四位可以标记,后12位为数据长度记录)改写,该标记留给外部调用来处理,不再回调函数中进行接收标记复位:

/*
 * usart.c
 *
 *  Created on: Oct 20, 2022
 *      Author: Administrator
 */

#include "usart.h"
#include "wifi.h"

uint8_t  HLPUSART_RX_BUF[HLPUSART_REC_LEN];//接收缓冲,最大HLPUSART_REC_LEN个字节.末字节为换行符
/*
 * bit15:接收到回车(0x0d)时设置HLPUSART_RX_STA|=0x8000;
 * bit14:接收溢出标志,数据超出缓存长度时,设置HLPUSART_RX_STA|=0x4000;
 * bit13:预留
 * bit12:预留
 * bit11~0:接收到的有效字节数目(0~4095)
 */
uint16_t HLPUSART_RX_STA=0;接收状态标记//bit15:接收完成标志,bit14:接收到回车(0x0d),bit13~0:接收到的有效字节数目
uint8_t HLPUSART_NewData;//当前串口中断接收的1个字节数据的缓存

uint8_t USART3_RX_BUF[USART3_REC_LEN];	//接收缓冲,最大USART_REC_LEN个字节.
uint16_t USART3_RX_STA=0;				//接收状态标记,bit15:接收完成标志,bit14:接收到0x0d,bit11~0:接收到的有效字节数目
uint8_t USART3_NewData;					//当前串口中断接收的1个字节数据的缓存

void  HAL_UART_RxCpltCallback(UART_HandleTypeDef  *huart)//串口中断回调函数
{
	if(huart ==&hlpuart1)//判断中断来源(串口1:USB转串口)
    {
		if(HLPUSART_NewData==0x0d){//回车标记
     	  HLPUSART_RX_STA|=0x8000;//标记接到回车
		}else{
			if((HLPUSART_RX_STA&0X0FFF)<HLPUSART_REC_LEN){
				HLPUSART_RX_BUF[HLPUSART_RX_STA&0X0FFF]=HLPUSART_NewData; //将收到的数据放入数组
				HLPUSART_RX_STA++;  //数据长度计数加1
			}else{
				HLPUSART_RX_STA|=0x4000;//数据超出缓存长度,标记溢出
			}
        }
       HAL_UART_Receive_IT(&hlpuart1,(uint8_t *)&HLPUSART_NewData,1); //再开启接收中断
    }
	if(huart ==&huart3)//判断中断来源(串口3:WIFI模块)
	{
		if(USART3_NewData==0x0d){//回车标记
			USART3_RX_STA|=0x8000;//标记接到回车
		}else{
			if((USART3_RX_STA&0X0FFF)<USART3_REC_LEN){
				USART3_RX_BUF[USART3_RX_STA&0X0FFF]=USART3_NewData; //将收到的数据放入数组
				USART3_RX_STA++;  //数据长度计数加1
			}else{
				USART3_RX_STA|=0x4000;//数据超出缓存长度,标记溢出
			}
        }
		HAL_UART_Receive_IT(&huart3,(uint8_t *)&USART3_NewData,1); //再开启接收中断
	}
}

        在ICore目录下创建wifi.h和wifi.c源码文件实现WIFI驱动:

        wifi.h内容如下:

/*
 * wifi.h
 *
 *  Created on:
 *      Author: Administrator
 */

#ifndef WIFI_WIFI_H_
#define WIFI_WIFI_H_

#include "stm32l4xx_hal.h" //HAL库文件声明
#include "usart.h"
#include "main.h"
#include <string.h>//用于字符串处理的库
#include <stdarg.h>
#include <stdlib.h>
#include "stdio.h"

extern UART_HandleTypeDef huart3;//声明UART2的HAL库结构体

void WIFI_printf (char *fmt, ...); //WIFI模块发送
void WIFI_TCP_SEND (char *fmt, ...);//在TCP模式下的发送数据(不处理返回状态的盲发)

#endif /* WIFI_WIFI_H_ */

        wifi.c内容如下,本质上就是调用HAL_UART_Transmit函数对huart3句柄进行写入数据操作,实现发送数据到WIFI模块:

/*
 * wifi.c
 *
 *  Created on:
 *      Author: Administrator
 */

#include "wifi.h"

//WIFI模块通信,使用UART3,这是专用的printf函数
//调用方法:WIFI_printf("123"); //向USART2发送字符123
void WIFI_printf (char *fmt, ...)
{
	char buff[USART3_REC_LEN+1];  //用于存放转换后的数据 [长度]
	uint16_t i=0;
	va_list arg_ptr;
	va_start(arg_ptr, fmt);
	vsnprintf(buff, USART3_REC_LEN+1, fmt, arg_ptr);//数据转换
	i=strlen(buff);//得出数据长度
	if(strlen(buff)>USART3_REC_LEN)i=USART3_REC_LEN;//如果长度大于最大值,则长度等于最大值(多出部分忽略)
	/*HAL_StatusTypeDef ret =*/ HAL_UART_Transmit(&huart3,(uint8_t *)buff,i,0xffff);//串口发送函数(串口号,内容,数量,溢出时间)
    //printf("WIFI_printf Len:%02d\r\n",ret);
    va_end(arg_ptr);
}
//WIFI模块在TCP模式下的数据发送:TCP发送的规定是先发AT+CIPSEND=数量,等待返回“>“后再发送数据内容。
//调用方法:WIFI_TCP_SEND("123\r\n"); //TCP方式发送字符123和回车换行
void WIFI_TCP_SEND (char *fmt, ...)
{
	char buff[USART3_REC_LEN+1];  //用于存放转换后的数据 [长度]
	uint16_t i=0;
	va_list arg_ptr;
	va_start(arg_ptr, fmt);
	vsnprintf(buff, USART3_REC_LEN+1, fmt, arg_ptr);//数据转换
	i=strlen(buff);//得出数据长度
	if(strlen(buff)>USART3_REC_LEN)i=USART3_REC_LEN;//如果长度大于最大值,则长度等于最大值(多出部分忽略)
	WIFI_printf("AT+CIPSEND=%d\r\n",i);//先发送AT指令和数据数量
	HAL_Delay(100);//等待WIFI模块返回">",此处没做返回是不是">"的判断。稳定性要求高的项目要另加判断。
    HAL_UART_Transmit(&huart3,(uint8_t *)buff,i,0xffff);//发送数据内容(串口号,内容,数量,溢出时间)
    va_end(arg_ptr);
}

//所有USART串口的中断回调函数HAL_UART_RxCpltCallback,统一存放在【usart.C】文件中。

        在main.c文件添加WIFI通信实现代码,main.c部分内容如下:

/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
//用户编写1
#include "../../ICore/key.h"
#include "../../ICore/led.h"
#include "../../ICore/print.h"
#include "../../ICore/usart.h"   //添加串口usart3接收回调实现的头文件
#include "../../ICore/wifi.h"    //添加串口usart3写入数据实现的头文件
/* 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_LPUART1_UART_Init();
  MX_USART3_UART_Init();
  /* USER CODE BEGIN 2 */
  //用户编写2
  ResetPrintInit(&hlpuart1);
  HAL_UART_Receive_IT(&hlpuart1,(uint8_t *)&HLPUSART_NewData, 1); //再开启接收中断
  HLPUSART_RX_STA = 0;
  HAL_UART_Receive_IT(&huart3,(uint8_t *)&USART3_NewData, 1); //usart3开启接收中断
  USART3_RX_STA = 0;
  set_led0_val(0);
  set_led1_val(get_key0_val());
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    //用户编写3
        //接收到电脑发送给(lpusart)数据,转身将其发送到给usart3,进而实现送数据给WIFI模块
		if(HLPUSART_RX_STA&0xC000){//溢出或换行,重新开始
			WIFI_printf("%.*s\r\n",HLPUSART_RX_STA&0X0FFF, HLPUSART_RX_BUF);
			HLPUSART_RX_STA=0;//接收错误,重新开始
			HAL_Delay(100);//等待
		}
        //接收到WIFI模块发送给(usart3)数据,转身将其发送到给lpusart,进而实现送数据给电脑终端
		if(USART3_RX_STA&0xC000){//溢出或换行,重新开始
			printf("%.*s\r\n", USART3_RX_STA&0X0FFF, USART3_RX_BUF);
			USART3_RX_STA=0;//接收错误,重新开始
			HAL_Delay(100);//等待
		}
    /*
	  if(KEY_0())//按下KEY0判断
	  {
		  printf("KEY0被按下\r\n");
		  WIFI_printf("AT+UARTE?\r\n");//发送AT指令
		  HAL_Delay(100);//等待
	  }
    */

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

三、编译及测试

        点击编译及运行按钮,

         如果编译及下载无异常,采用串口助手连接开发板,本文将开发板作为Station 模式连接家里的路由,设置账号密码及查询是否成功:

 测试运行结果如下:

         访问家里的路由控制界面查看如下:

四、关于WIFI模块的串口应用

        通过上面的实现,市面上大部分WIFI模块都能适用。只要AT指令能直达WIFI模块,无论是从MCU还是从电脑端,对于WIFI模块的操作就是看AT指令支持的情况及我们对AT指令的组合应用,可以实现项目开发中各种对WIFI使用的要求。当然在具体项目中,对于WIFI模块的选型就是看他们WIFI模块给的AT指令能否直接或间接组合满足项目要求。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/13896.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一、什么是计算机网络

1.1 概述 信件的要素&#xff1a; 打电话时包括连接和接通过程&#xff0c;要关注包括拨打者的状态和接听者的状态&#xff0c;称为TCP连接。发短信时只要发送者将短信发送出去即可&#xff0c;是否被接收或者发送的过程中是否有丢失这些都不关注&#xff0c;称之为UDP连接。计…

CentOS7安装jdk

文章目录前言准备工作一、将jdk的压缩文件传递到虚拟机里面二、解压缩三、配置环境变量前言 在大数据的技术中&#xff0c;Linux的环境是基础&#xff0c;jdk则是这些大数据工具的基础&#xff0c;在这篇博文中&#xff0c;我们主要介绍如何在Linux环境里安装jdk&#xff0c;以…

MySQL8.0优化 - 索引的数据结构

文章目录学习资料索引的数据结构B树常见索引概念聚簇索引特点优点缺点限制二级索引&#xff08;辅助索引、非聚簇索引&#xff09;回表联合索引Innodb的B树索引注意事项1、根页面位置万年不动2、内节点中目录项记录的唯一性3、一个页面最少存储2条记录索引的代价学习资料 【My…

Python可视化必备,在Matplotlib/Seaborn中轻松玩转图形拼接!

数据展示时&#xff0c;在同一页面上混合排版多个图形是一种常见的用法。 本次分享一个Python轮子patchworklib&#xff1a; 通过|、/轻松实现图形排列&#xff1b;比matplotlib、seaborn等自带子图功能更加灵活&#xff1b;灵感源于R中的patchwork。目录 在Matplotlib中使用…

【Java学习笔记】第四章 面向对象编程三部曲(中)

【Java学习笔记】第四章 面向对象编程三部曲&#xff08;上&#xff09; 【Java学习笔记】第四章 面向对象编程三部曲&#xff08;中&#xff09; 【Java学习笔记】第四章 面向对象编程三部曲&#xff08;下&#xff09; 文章目录5. 面向对象编程&#xff08;中&#xff09;5…

gdb调试 入门

程序的调试过程主要有&#xff1a;单步执行&#xff0c;跳入函数&#xff0c;跳出函数&#xff0c;设置断点&#xff0c;设置观察点&#xff0c;查看变量。 You can run "gdb" with no arguments or options; but the most usualway to start GDB is with one argume…

ANDROID ROOT FIDDLER HTTPS 抓包

参考 adb 修改手机代理方式_userwyh的博客-CSDN博客_adb shell settings put global http_proxy 手机模拟器安装证书并抓包_虚无-缥缈的博客-CSDN博客_模拟器安装证书 安卓手机使用adb添加系统证书方法 - 知乎 设置设备代理&#xff08;需要ROOT 设置代理&#xff1a; adb…

【重新安装Anaconda心得】

文章目录&#xff08;一&#xff09;环境变量设置&#xff08;二&#xff09;Anaconda添加镜像源【可以使用境外流量不用添加】&#xff08;三&#xff09;创建虚拟环境的细节&#xff08;四&#xff09;补充&#xff1a;conda的常用命令&#xff08;一&#xff09;环境变量设置…

算法篇------贪心1

文章目录贪心的概念题目1------经典的选择排序&#xff08;简单&#xff09;题目2----平衡字符串&#xff08;简单&#xff09;题目3---买卖股票的最佳时间(中等)题目4------跳跃游戏(中等)题目5-------钱币找零题目6------多机调度的问题贪心的概念 什么是贪心算法&#xff1…

ATF源码篇(九):docs文件夹-Components组件(8)固件升级

固件更新&#xff08;FWU&#xff09; 本文档描述了TF-A中可用的各种固件更新&#xff08;FWU&#xff09;机制的设计。 1、PSA固件更新&#xff08;PSA FWU&#xff09;-平台安全架构2、TBBR固件更新&#xff08;TBBR FWU&#xff09;-可信板引导要求 PSA固件更新实施了同名…

[附源码]java毕业设计课程作业管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

vtk拾取器-vtkAbstractPicker/vtkCellPicker

创建了VTK社区&#xff0c;欢迎大家加入雪易社区-CSDN社区云 简介&#xff1a;此文主要介绍vtk中的拾取器的用法&#xff0c;若能为各位小伙伴解决一些困扰就更好了。非常欢迎各位小伙伴指正并补充。 1. vtkAbstractPicker vtkAbstractPicker是vtk拾取器的基类&#xff0c;为…

2022下半年《软考-系统架构设计师》备考经验分享

前言 我参加了2022年11月份的《软考-系统架构设计师》考试&#xff0c;在一个多月的备考之中我总结了一些学习经验和答题技巧&#xff0c;现毫无保留的分享给大家&#xff0c;希望对报考的同学们有所帮助。彩蛋&#xff1a;关注我的公众号【劼哥舍】&#xff0c;回复“软考”即…

dubbo:docker安装dubbo-admin

0.引言 我们在搭建dubbo框架时&#xff0c;需要安装一个dubbo-admin来管理服务已经配置文件&#xff0c;今天我们来看看如何通过docker快速搭建一个dobbo-admin 1. 安装 1、首先到dockerhub上搜索dubbo-admin的镜像源 2、可以看到两个引用较高的镜像源&#xff0c;第一个是a…

SpringCloud和SpringBoot在调Feign传文件时的异常汇总及解决办法

主要记录SpringCloud在调Feign传文件时的问题&#xff1a; 1.&#xff08;按注意点2改正即可&#xff09; Current request is not a multipart request&#xff08;按注意点2改正即可&#xff09; 2.&#xff08;按注意点3处理即可&#xff09; The field files exceeds it…

Pytorch框架基础

目录 1-02张量的简介与创建 pytorch中的Tensor 张量的创建 1-03张量的操作 1. 拼接 2.张量的拼接与切分 3.张量索引 4.张量变换 1-02张量的简介与创建 张量是一个 &#xff0c;它是标量&#xff0c;向量&#xff0c;矩阵的高维拓展 pytorch中的Tensor 在pytorch中的属…

【C++】C++基础知识(七)---指针

C基础知识&#xff08;七&#xff09;1. 指针的定义与使用2. 指针的内存3. 空指针和野指针4. const修饰指针5. 指针与数组6. 指针与函数7. 指针用于数组和函数的案例1. 指针的定义与使用 指针的作用&#xff1a; ------通过指针可以直接的访问变量的内存&#xff0c;内存编号一…

企业在线培训场景下讲师+ppt课件直播应用效果

阿酷TONY / 原创 / 2022-11-17 / 长沙 企业在线培训场景下讲师ppt课件直播应用效果 &#xff1a; 图 / 直播示意图 设备需求&#xff1a; 1. 现场布摄像头&#xff0c;用于采集讲师摄像头视频和音频数据&#xff1b; 2. PC电脑或笔记本电脑一台&#xff08; 安装直播客户端&…

学会Python开发的第一步:写一个桌面小程序

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 又到了学Python时刻~ 当使用桌面应用程序的时候&#xff0c;有没有那么一瞬间&#xff0c; 想学习一下桌面应用程序开发&#xff1f; 建议此次课程大家稍作了解不要浪费太多时间&#xff0c; 因为没有哪家公司会招聘…

科普系列:AUTOSAR与OSEK网络管理比较(下)

在上篇中我们分别在状态机和报文格式方面对OSEK和AUTOSAR网络管理进行了简单介绍&#xff0c;感兴趣的小伙伴请移步至文章《科普系列&#xff1a;AUTOSAR与OSEK网络管理比较&#xff08;上&#xff09;》。 三、OSEK与AUTOSAR网络管理特点对比 本篇就是本文的重点了&#xff…