您的位置:首页 > 文旅 > 旅游 > 移动开发平台_吉林品牌网站建设商家_营销策划推广公司_销售平台

移动开发平台_吉林品牌网站建设商家_营销策划推广公司_销售平台

2025/4/18 23:22:04 来源:https://blog.csdn.net/nanxl1/article/details/147161775  浏览:    关键词:移动开发平台_吉林品牌网站建设商家_营销策划推广公司_销售平台
移动开发平台_吉林品牌网站建设商家_营销策划推广公司_销售平台

08_Z-Stack中使用ESP8266

前言

​ 本章讲解Zigbee协调器使用ESP8266模块,与上位机实现TCP/IP通信。将介绍Mcu串口配置、AT指令集,并提供一份基于AT指令集ESP驱动代码。ESP相关代码在AT.cAT.h文件中,将其添加到App组下。

Mcu串口配置

​ 在之前的章节中,讲解了CC2530UART0配置,借助于Z-Stack提供的HAL接口,能很方便的将其移植到Z-Stack的框架上。但由于Z-Stack的一些缺陷,其默认是不支持同时使用两个串口的,因此对于与ESP通信的UART1,我们采用操作寄存器的方式进行配置和使用

  • CC2530 UART1配置
/**
* @brief 初始化与ESP通信所用的MCU串口 UART1 Rx: P0_5   Tx: P0_4
*/
void AT_McuUart_Init(void)
{// 端口配置PERCFG = 0x00;  // 外设采用默认位置P2DIR |= 0x40;  // 当端口0引脚冲突时,优先使用UART1P2DIR &= 0x7F;P0SEL |= 0x30;  // P0端口 4、5引脚设置为外设功能// UART 配置U1CSR |= 0x80;  // 选择UART模式U1UCR |= 0x02;  // 8bit 无校验 1bit停止位// 波特率设置 Baud = (256 + BAUD_M)*2^(BAUD_E) / 2^28 * F    F为系统时钟频率 32MHz// 若波特兰要设置成115200 则BAUD_M = 194   BAUD_E = 11U1BAUD |= 0xC2;  // 194U1GCR |= 0x0B;  // 11// 配置接收中断URX1IF = 0;   // 清除接收中断标志URX1IE = 1;   // 使能接受中断EA = 1;   // 开启全局中断U1CSR |= 0x40;  // 接收器使能 需要先配置完USART所有参数
}
  • 定义接收缓存区和接收状态
unsigned char AT_RxBuf;   // 接收缓存
unsigned char AT_RxData[AT_UART_BUF_LEN];  // 数据保存
unsigned char AT_RxState = 0;  // 接收状态  0
  • 中断函数接收消息
/**
* @brief AT UART1 接收中断函数
*/
#pragma vector = URX1_VECTOR
__interrupt void USAT1_ISR(void)
{static unsigned int idx = 0;if(U1CSR&0x04 != 0)   // 接收到数据{if(AT_RxState == 1){memset(&AT_RxData, 0, sizeof(AT_RxData));  // 清空缓存AT_RxState = 0;}AT_RxBuf = U1DBUF;   // 读取数据if(idx < AT_UART_BUF_LEN && AT_RxState==0)  // 接收数据{AT_RxData[idx++] = AT_RxBuf;if(AT_RxBuf == '\n'){AT_RxState = 1;  // 接收完成idx = 0;}}else    // 数据超过限制{AT_RxState = 1;  // 接收完成idx = 0;}  }URX1IF = 0;  // 清除中断标志
}
  • 重写putchar()函数
/**
* @brief 重写 putchar函数 UART0
*/
__near_func int putchar(int c)
{UTX1IF = 0;   // 清除发送标志位U1DBUF = (char)c;while(UTX1IF == 0);  // 等待发送成功  发送成功时 发送标志位复位return(c);
}

AT指令集

AT指令集是从终端设备(Terminal Equipment,TE)或数据终端设备(Data Terminal Equipment,DTE)向终端适配器(Terminal Adapter,TA)或数据电路终端设备(Data Circuit Terminal Equipment,DCE)发送的指令集。

​ 其指令结构为: 每条AT指令都以AT作为开头,并以特定的字符或字符串结尾。指令的响应数据包中包含执行结果,如果指令执行成功,通常会返回OK字符串;如果执行失败,则返回ERROR字符串或其他错误代码。

ESP8266就能通过AT指令集进行配置与操作,而实际上官方提供了一套SDK接口,但由于我们的需求比较简单,因此直接使用AT指令集,从而避免繁多的文档查找和学习

​ 下面以TCP单连接为例:

  • 配置WIFI模式:
AT+CWMODE=3
  • 连接路由器
AT+CWJAP="SSID","password"
  • 查询ESP8266设备的IP地址
AT+CIFSR
  • 用网络调试助手创建一个TCP服务器,假设创建服务器地址为"192.168.1.101": 8080
AT+CIPSTART="TCP","192.168.1.101",8080
  • 发送数据
AT+CIPSEND=4  // 设置数据长度
test  // 发送的数据

ESP驱动代码

​ 根据AT指令集,实现ESPTCP单连接的驱动代码

AT.h

AT.h中,可配置需要连接的路由器主机IP/端口。也可配置ESPSoftAP模式下的名称和密码

#ifndef __AT_H
#define __AT_H
#include "hal_types.h"
/*==============MCU Parameters============*/
#define AT_UART_BUF_LEN            128                          
#define AT_UART_BR                 HAL_UART_BR_115200
#define AT_UART_PORT               HAL_UART_PORT_1
/*==============ESP Parameters===============*/
#define SSID                       "\"Nanxl\""   // 路由器WIFI名称
#define PASSWORD                   "\"1805110506@qq.com\""  // 路由器WIFI密码
#define DSTADDR                    "\"192.168.1.101\""  // 目标主机IP
#define DSTPORT                    "8080"                 // 目标主机端口
#define DEVICE_ID                  "\"ESP-NANXL\""          // ESP WIFI名称
#define DEVICE_PASS                "\"ESP-2025\""           // ESP WIFI密码
#define AT_UART_BR_NUM             "115200"
#define AT_UART_DATA_BIT           "8"     
#define AT_UART_STOP_BIT           "1"
#define AT_UART_PARITY             "0"
#define AT_UART_FLOW_CTR           "1"
#define AT_MAX_WAIT_TIME           32000     
/*==============AT Command===============*/
/*==============Basic Command=========*/
#define AT                         "AT"     // 测试指令    
#define AT_RESET                   "AT+RST" // 重启       
#define AT_CLOSE_ECHO              "ATE0"   // 关闭回显
#define AT_OPEN_ECHO               "ATE1"   // 打开回显
#define AT_RESTORE                 "AT+RESTORE"  // 恢复出厂设置
#define AT_VERSION_INFO            "AT+GMR"      // 查询版本信息
#define AT_GET_MODE                "AT+CWMODE?"  // 查询ESP8266工作模式
#define AT_SET_DVEAP_INFO          "AT+CWSAP=" DEVICE_ID "," DEVICE_PASS ",5,3" // 配置ESP SOFT AP参数
#define AT_SET_DEV_UART            "AT+UART=" AT_UART_BR_NUM ","\AT_UART_DATA_BIT "," \AT_UART_STOP_BIT "," \AT_UART_PARITY "," \AT_UART_FLOW_CTR/*==============TCP/IP================*/
#define AT_SET_APS_MODE           "AT+CWMODE=3"  // 配置WIFI模式(softAP+station mode) 并保存到FLASH
#define AT_CONNECT_ROUTER          "AT+CWJAP=" SSID "," PASSWORD  // 连接路由器
#define AT_ACK_IP                  "AT+CIFSR"      // 获取ESP8266 设备的IP地址
#define AT_CONNECT_SERVER          "AT+CIPSTART=" "\"TCP\"" "," DSTADDR "," DSTPORT  // 连接服务器
#define AT_GET_AP_INFO             "AT+CWJAP?"     // 查询已接入的AP
#define AT_SEND_DATA               "AT+CIPSEND="
/*===============functions=============*/
extern void AT_ESP_Init(void);
extern bool AT_Test(void);
extern bool AT_Send_Data(char * data);
extern void AT_McuUart_Init(void);
static void AT_UartCB(uint8 port, uint8 event);
static void AT_Dev_Uart_Config(void);
static void AT_SendCmd(char * cmd);
static void AT_Connect_TCP_Server(void);
static void AT_Basic_Config(void);
static bool AT_Wait_Cmd(uint16 time);
static bool AT_Wait_SendData(void);
static void AT_Delay_Ms(uint16 time);
/*===============variable==============*/
extern unsigned char AT_RxBuf;   // 接收缓存
extern unsigned char AT_RxData[AT_UART_BUF_LEN];  // 数据保存
extern unsigned char AT_RxState;  // 接收状态  0
#endif

AT.c

#include "ioCC2530.h"
#include "AT.h"
#include "hal_uart.h"
#include "OnBoard.h"
#include <stdio.h>
#include <string.h>
unsigned char AT_RxBuf;   // 接收缓存
unsigned char AT_RxData[AT_UART_BUF_LEN];  // 数据保存
unsigned char AT_RxState = 0;  // 接收状态  0
/**
* @brief 重写 putchar函数 UART0
*/
__near_func int putchar(int c)
{UTX1IF = 0;   // 清除发送标志位U1DBUF = (char)c;while(UTX1IF == 0);  // 等待发送成功  发送成功时 发送标志位复位return(c);
}/**
* @brief 初始化ESP8266
*/
void AT_ESP_Init(void)
{// ESP Basic ConfigAT_Basic_Config();// ESP Uart ConfigAT_Dev_Uart_Config();// Connect to TCP ServerAT_Connect_TCP_Server();
}/**
* @brief 测试ESP能否正常工作
*/
bool AT_Test(void)
{AT_SendCmd(AT_CLOSE_ECHO); // 关闭回显AT_Wait_Cmd(2000);AT_SendCmd(AT);  // 测试指令return AT_Wait_Cmd(2000);
}/**
* @brief 发送数据
*/
bool AT_Send_Data(char * data)
{char cmd[AT_UART_BUF_LEN];sprintf(cmd, "%s%c", AT_SEND_DATA, strlen(data)+'0');AT_SendCmd(cmd);AT_Wait_Cmd(5);AT_SendCmd(data);AT_Wait_Cmd(5);return AT_Wait_SendData();  // 等待发送数据完成
}
/**
* @brief 初始化与ESP通信所用的MCU串口 UART1 Rx: P0_5   Tx: P0_4
*/
void AT_McuUart_Init(void)
{// 端口配置PERCFG = 0x00;  // 外设采用默认位置P2DIR |= 0x40;  // 当端口0引脚冲突时,优先使用UART1P2DIR &= 0x7F;P0SEL |= 0x30;  // P0端口 4、5引脚设置为外设功能// UART 配置U1CSR |= 0x80;  // 选择UART模式U1UCR |= 0x02;  // 8bit 无校验 1bit停止位// 波特率设置 Baud = (256 + BAUD_M)*2^(BAUD_E) / 2^28 * F    F为系统时钟频率 32MHz// 若波特兰要设置成115200 则BAUD_M = 194   BAUD_E = 11U1BAUD |= 0xC2;  // 194U1GCR |= 0x0B;  // 11// 配置接收中断URX1IF = 0;   // 清除接收中断标志URX1IE = 1;   // 使能接受中断EA = 1;   // 开启全局中断U1CSR |= 0x40;  // 接收器使能 需要先配置完USART所有参数
}/**
* @brief AT UART1 接收中断函数
*/
#pragma vector = URX1_VECTOR
__interrupt void USAT1_ISR(void)
{static unsigned int idx = 0;if(U1CSR&0x04 != 0)   // 接收到数据{if(AT_RxState == 1){memset(&AT_RxData, 0, sizeof(AT_RxData));  // 清空缓存AT_RxState = 0;}AT_RxBuf = U1DBUF;   // 读取数据if(idx < AT_UART_BUF_LEN && AT_RxState==0)  // 接收数据{AT_RxData[idx++] = AT_RxBuf;if(AT_RxBuf == '\n'){AT_RxState = 1;  // 接收完成idx = 0;}}else    // 数据超过限制{AT_RxState = 1;  // 接收完成idx = 0;}  }URX1IF = 0;  // 清除中断标志
}/**
* @brief 向ESP发送命令
*/
static void AT_SendCmd(char * cmd)
{printf("%s\r\n", cmd);
}/**
* @brief
*/
static void AT_Basic_Config(void)
{AT_SendCmd(AT_CLOSE_ECHO); // 关闭回显AT_Wait_Cmd(2000);AT_SendCmd(AT_SET_DVEAP_INFO); // 设置SoftAP参数AT_Wait_Cmd(2000);
}/**
* @brief ESP 串口配置
*/
static void AT_Dev_Uart_Config(void)
{AT_SendCmd(AT_SET_DEV_UART);AT_Wait_Cmd(2000);
}/**
* @brief 设置ESP为TCP模式 并连接到TCP服务器
*/
static void AT_Connect_TCP_Server(void)
{AT_SendCmd(AT_SET_APS_MODE);  // 设置ESP为 SoftAP+Station 模式AT_Wait_Cmd(2000);                // 等待指令完成AT_SendCmd(AT_CONNECT_ROUTER); // 连接路由器WIFIAT_Wait_Cmd(2000);AT_SendCmd(AT_CONNECT_SERVER); // 连接服务器AT_Wait_Cmd(2000);AT_Send_Data("hello TCP"); // 发送初始数据AT_Send_Data("hello TCP"); // 发送初始数据AT_Send_Data("hello TCP"); // 发送初始数据AT_Send_Data("hello TCP"); // 发送初始数据AT_Send_Data("hello TCP"); // 发送初始数据AT_Send_Data("hello TCP"); // 发送初始数据AT_Send_Data("hello TCP"); // 发送初始数据AT_Send_Data("hello TCP"); // 发送初始数据AT_Send_Data("hello TCP"); // 发送初始数据
}/**
* @brief 等待指令完成
*/
static bool AT_Wait_Cmd(uint16 time)
{AT_Delay_Ms(time);if(strncmp(AT_RxData, "OK", 2)==0)return TRUE;return FALSE;
}/**
* @brief AT 延时函数 
*/
void AT_Delay_Ms(uint16 time)
{while(time--){Onboard_wait(1000);  // OnBorad_wait 提供us级延时,但并不完全准确}
}/**
* @brief 等待发送数据完成
*/
static bool AT_Wait_SendData(void)
{AT_Wait_Cmd(10); // 等待接收消息 延时时间应根据发送数据的长度进行调整if(strncmp((char *)AT_RxData, "Send OK", 7) == 0)return TRUE;return FALSE;
}
  • Note: 发送数据指令后的延时时间,应根据发送数据的长度进行调整。
  • AT_RxData在接受数据时存在丢包情况暂未解决

应用层

​ 在zcl_samplesw.c中编写以下代码

/*==================ESP8266=================*/
#ifdef ZDO_COORDINATOR/*** @brief ESP8266初始化*/static void zclSampleSw_ESP_Init(void){AT_McuUart_Init();  // 初始化与ESP8266通讯的串口AT_ESP_Init();  // ESP8266初始化}/*** @brief 通过ESP8266发送数据*/static bool zclSampleSw_Send_Data(char * data){return AT_Send_Data(data);}
#endif

​ 在zclSampleSw_Init中调用zclSampleSw_ESP_Init

#ifdef ZDO_COORDINATOR// Init UartzclSampleSw_InitUart();// Init ESPzclSampleSw_ESP_Init();ZDO_RegisterForZDOMsg ( zclSampleSw_TaskID, Device_annce );  // 注册 Device_annce 簇ID...

实验现象

  • 查看PC端的IP地址
    在这里插入图片描述

  • AT.h中,修改对应参数

在这里插入图片描述

  • 打开网络调试助手,创建一个TCP服务器

在这里插入图片描述

  • 将程序下载进开发板中,运行(这九条消息是连接到服务器后自动发送的, 代码在AT_Connect_TCP_Server中)

在这里插入图片描述

参考资料

ESP8266 Non-OS SDK API 参考.pdf

ESP8266 Non-OS AT 指令使用示例_V1.3.pdf

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com