CSDN,记录美好生活,打卡第一天;
最近做的GD32f10x项目用到了esp8266_12s模块开发,主要集中在与QT或者其他图形上位机之间的通信,可以说是测试功能,但是体系建立后,可以延伸做很多物联网功能,相信这WiFi大家也老熟了,话不多说,直接上代码;
App_Esp8266.h
#ifndef _APPESP8266_H_
#define _APPESP8266_H_
#include "usart.h"
#include "stdio.h"
#include "stdarg.h"
#include "stdlib.h"
#include "string.h"
#include "Drv_Systick.h" // 这个根据自己的延时接口包含即可,楼主这是正常的系统定时器
// #include "App_Device.h" // 后续有空发自定义通信协议模块接口,对于操控物联网这些会很轻松
#define MAX_PWD 50
//ESP自身热点信息
#define ESP8266_SSID "ESP_WiFi"
#define ESP8266_PWD "12345678"
#define ESP8266_CH 5
#define ESP8266_ENC 3
#define ESP8266_CLIENT 1
#define ESP8266_DEFULT 0
//目标热点信息
#define SSID "huiyishi"
#define PWD "66668888"
// TCP连接相关
#define TCP "TCP"
#define UDP "UDP"
#define PORT 8080
//设置静态参数(这个与自定义通信协议有关,QT发送热点信息包就需要先连接esp,后续转STA就能通过分配的动态IP通信)
#define STATIC_IP "192.168.4.2"
#define STATIC_GW "192.168.4.1"
#define STATIC_MK "255.255.255.0"
extern volatile uint8_t Uart1RecvBuf[512];
extern volatile uint8_t Uart1RecvLen;
extern volatile bool isInitMode;//全局信号,区分开指令部分和通信部分接收
extern bool esp8266_initialized;
// U08 = uint8_t U16 = uint16_t .....
extern void ESP8266_Init();//初始化功能函数封装(对esp8266_init的封装,可能比较多余吧)
extern void ESP8266_Reset(void);//重置ESP8266回初始状态
extern void ESP8266_Restore(void);//恢复出厂设置
extern bool esp8266_init(void); //初始化,步骤:1、模式选择(AP+STA)2、连接热点3、上电自动连接4、设置自身热点信息5、多路连接6、设置服务器模式7、查询连接热点分配的IP地址;
extern void esp8266_config(void); //GPIO和串口配置(最好是自己单独验证下自己的串口能否收发,这里强烈推荐使用安信可的串口调试工具!)
extern U08 ESP8266_SendStaIP_At(char *cmd,int waittime,char *ack);//独属发送CIFSR指令,获取到STA_IP保存到缓存区,方便后续发送给上位机
extern U08 esp8266_send_at(char *cmd,int waittime,char *ack); //发送指令
extern void ESP8266_USART_Send(U08 *str, U16 len);//ESP串口发送,封装串口1写入数据
//常用指令集
extern void ESP8266_RST(void);//重启ESP8266
extern void ESP8266_Test(void);//发送AT测试指令
extern void ESP8266_GMR(void);//测试AT固件版本
extern void ESP8266_Baud(U32 baud_rate);//调整ESP8266串口波特率
extern U08 ESP8266_WorkModeSet(U08 mode);//设置ESP工作模式
extern U08 ESP8266_ModeRefer(void);//查询ESP当前工作模式
extern U08 ESP8266_ConnectAP(char *ssid, char *pwd);//加入AP,也就是连接热点
extern U08 ESP8266_SetStaticIP(char *ip,char *gateway,char *netmask);//在AP模式下设置静态IP信息
extern U08 ESP8266_CIPAP(void);//查询AP模式下的IP地址信息,_DEF后缀是保存到ESP的flash中
extern U08 ESP8266_ApInfo(void);//查询当前WIFi信息
extern U08 ESP8266_SetAP(char *ssid,char *pwd,U08 ch,U08 ecn,U08 sta,U08 defult);//设置WiFi热点
extern U08 ESP8266_QuitConect(void);//退出与AP的连接
extern bool ESP8266_CwjapStatus(void);//查看连接热点是否成功
extern U08 ESP8266_Cipstatus(void);//查看连接状态
extern U08 ESP8266_CIPSTA(void);//查看ESP连接热点后分配到的IP地址、网关、掩码
extern U08 ESP8266_CIFSR_IP(void);//查看本地IP地址
extern U08 ESP8266_DisconnectAP(void);//退出与AP的连接
extern U08 ESP8266_AP_List(void);//列出当前可用AP列表
extern U08 ESP8266_IP_addr(void);//查看已接入设备的IP地址
extern U08 ESP8266_Cwautoconn(void);//上电自动连接AP
/************TCP/IP指令*****************/
extern U08 ESP8266_TCPorUDP_ConnectStatus(U08 id,U08 *type,U08 *addr,U16 port,U08 tetype);//获得连接TCP/UDP状态
extern U08 ESP8266_TCPorUDP_Connect(char *type,char *addr,U16 port);//建立TCP/UDP连接
extern U08 ESP8266_TcpServer(U08 mode);//ESP8266打开关闭服务器端
extern U08 ESP8266_TransParent(U08 mode);//0-1透传模式
extern U08 ESP8266_LinkMode(U08 mode);//ESP8266设置单路连接或者多路连接
extern void ESP8266_Send(U08 *str,U16 ID,U16 len);//发送字符串数据,这个是服务器模式下使用
extern void ESP8266_ExitUnvarnishSend(void);//ESP8266退出透传模式
extern void ESP8266_SendStatus(void);//查看esp发送数据是否成功
extern U08 ESP8266_ServerTimeOut(U16 time);//设置服务器超时时间
#endif
App_Esp8266.c
#include "App_Esp8266.h"
volatile uint8_t Uart1RecvBuf[512] = {0};
volatile uint8_t Uart1RecvLen = 0;
bool esp8266_initialized = FALSE;
//全局信号,区分开指令部分和通信部分接收
volatile bool isInitMode = TRUE;
//串口1初始化配置(看你使用哪个串口来设置ESP所使用)
void esp8266_config(void)
{
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_AF);//使能复用时钟
rcu_periph_clock_enable(RCU_USART1);
//USART1端口配置-用于调试,库函数中串口1对应数据手册中的串口2,
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);//TX
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_3);//RX
usart_deinit(USART1);
usart_baudrate_set(USART1, 115200U);
usart_word_length_set(USART1, USART_WL_8BIT);
usart_stop_bit_set(USART1, USART_STB_1BIT);
usart_parity_config(USART1, USART_PM_NONE);
usart_hardware_flow_rts_config(USART1, USART_RTS_DISABLE);
usart_hardware_flow_cts_config(USART1, USART_CTS_DISABLE);
usart_receive_config(USART1, USART_RECEIVE_ENABLE);
usart_transmit_config(USART1, USART_TRANSMIT_ENABLE);
/* enable USART receive interrupt */
//nvic_irq_enable(USART1_IRQn,0,0);
usart_interrupt_enable(USART1, USART_INT_RBNE);
usart_enable(USART1);
}
/****************************ESP8266 Function***************************************/
void ESP8266_USART_Send(U08 *str, U16 len)
{
UART1WriteData(str, len);
}
//独属发送CIFSR指令,获取到STA_IP保存到缓存区,方便后续发送给上位机
U08 ESP8266_SendStaIP_At(char *cmd,int waittime,char *ack)
{
int timeout = 0;
int waitAckTime = waittime * 100;
int len = strlen(cmd);
// 清空数据长度
Uart1RecvLen = 0;
// 清空缓冲区
memset((U08 *)Uart1RecvBuf,0,sizeof(Uart1RecvBuf));
//发送指令
ESP8266_USART((U08 *)cmd, len);
while(timeout < waitAckTime)
{
if(Uart1RecvLen > 0)
{
if(strstr((char*)Uart1RecvBuf, ack) != NULL)
{
memset(WiFi_CIFSR_Buff,0,sizeof(WiFi_CIFSR_Buff));
strncpy((char *)WiFi_CIFSR_Buff,(char *)Uart1RecvBuf,strlen((char *)Uart1RecvBuf));
printf("%s\r\n",Uart1RecvBuf);
}
return 0; // 成功接收到应答
}
DelayMS(10);
timeout += 1;
}
printf("119 time out \r\n");
return -1; // 超时
}
//esp8266发送指令
U08 esp8266_send_at(char *cmd,int waittime,char *ack)
{
int timeout = 0;
int waitAckTime = waittime * 100;
int len = strlen(cmd);
// 清空数据长度
Uart1RecvLen = 0;
// 清空缓冲区
memset((U08 *)Uart1RecvBuf,0,sizeof(Uart1RecvBuf));
//发送指令
ESP8266_USART_Send((U08 *)cmd, len);
while(timeout < waitAckTime)
{
if(Uart1RecvLen > 0)
{
// 检查是否接收到完整的应答(其实就是esp返回的信息截取部分判断)
if (strstr((char*)Uart1RecvBuf, ack) != NULL)
{
//查看响应是否OK(调试用)
printf("%s\r\n", Uart1RecvBuf);
return 0; // 成功接收到应答
}
}
DelayMS(4);
timeout += 1;
printf("time: %d\n",timeout);
}
printf("time out \r\n");
return -1; // 超时
}
//发送AT测试指令
void ESP8266_Test(void)
{
esp8266_send_at("AT\r\n",2,"OK");
DelayMS(20);
}
//重启ESP8266
void ESP8266_RST(void)
{
esp8266_send_at("AT+RST\r\n",2,"OK");
DelayMS(20);
}
//恢复出厂设置
void ESP8266_Restore(void)
{
esp8266_send_at("AT+RESTORE\r\n",2,"OK");
DelayMS(20);
}
//测试AT固件版本
void ESP8266_GMR(void)
{
esp8266_send_at("AT+GMR\r\n",2,"OK");
DelayMS(20);
}
//调整ESP8266串口波特率
void ESP8266_Baud(U32 baud_rate)
{
switch(baud_rate)
{
case 9600:
esp8266_send_at("AT+UART_CUR=9600,8,1,0,0\r\n", 2,"OK");
break;
case 38400:
esp8266_send_at("AT+UART_CUR=38400,8,1,0,0\r\n", 2,"OK");
break;
case 74880:
esp8266_send_at("AT+UART_CUR=74880,8,1,0,0\r\n", 2,"OK");
break;
case 115200:
esp8266_send_at("AT+UART_CUR=115200,8,1,0,0\r\n", 2,"OK");
break;
default:break;
}
DelayMS(20);
}
/*
*设置ESP工作模式
*param:1-STA模式 2-AP模式 3-STA+AP模式
*return:0-连接成功 1-连接失败
*/
U08 ESP8266_WorkModeSet(U08 mode)
{
char cmd[20] = {0};
sprintf(cmd, "AT+CWMODE_DEF=%d\r\n", mode); //_DEF是保存到esp8266的flash中
return esp8266_send_at(cmd, 3,"OK");
}
//查询ESP当前工作模式
U08 ESP8266_ModeRefer(void)
{
return esp8266_send_at("AT+CWMODE?\r\n",2,"OK");
}
/*
*brief:加入AP,也就是连接热点
*<ssid>字符串参数,接入点名称
*<pwd>字符串参数,密码最长 64 字节 ASCII
*如果连接过一次那么上电会自动连接,需要手动断开或者连接其他AP
*/
U08 ESP8266_ConnectAP(char *ssid, char *pwd)
{
char CMD[MAX_PWD]= {0};
sprintf(CMD,"AT+CWJAP_DEF=\"%s\",\"%s\"\r\n",ssid,pwd);
return esp8266_send_at(CMD,2,"OK");
}
//查看连接热点是否成功
bool ESP8266_CwjapStatus(void)
{
//_DEF后缀是保存到esp8266的flash中
if(esp8266_send_at("AT+CWJAP_DEF?\r\n",2,"+CWJAP_DEF:") == 0) //一般连接过则会自动连接,那么返回连接状态就行
{
return TRUE;
}
return FALSE;
}
//退出与AP的连接
U08 ESP8266_QuitConect(void)
{
return esp8266_send_at("AT+CWQAP\r\n",2,"OK");
}
//查询当前WIFi信息
U08 ESP8266_ApInfo(void)
{
return esp8266_send_at("AT+CWSAP_DEF?\r\n",2,"OK");
}
//查询AP模式下的IP地址信息,_DEF后缀是保存到ESP的flash中
U08 ESP8266_CIPAP(void)
{
return esp8266_send_at("AT+CIPAP_DEF?\r\n",2,"OK");
}
//在AP模式下设置静态IP信息
U08 ESP8266_SetStaticIP(char *ip,char *gateway,char *netmask)
{
char str[50] = {0};
sprintf(str,"AT+CIPAP_DEF=\"%s\",\"%s\",\"%s\"\r\n",ip,gateway,netmask);
return esp8266_send_at(str,2,"OK");
}
/*
*brief:设置ESP8266热点信息
*param 1: 账号
*param 2: 密码
*param 3: 通道
*param 4: 加密
<ecn>加密方式
0 OPEN
1 WEP
2 WPA_PSK
3 WPA2_PSK
4 WPA_WPA2_PSK
*/
U08 ESP8266_SetAP(char *ssid,char *pwd,U08 ch,U08 ecn,U08 sta,U08 defult)
{
char str[50] = {0};
sprintf(str,"AT+CWSAP_DEF=\"%s\",\"%s\",%d,%d,%d,%d\r\n",ssid,pwd,ch,ecn,sta,defult);
return esp8266_send_at(str,2,"OK");
}
//查看连接状态
U08 ESP8266_Cipstatus(void)
{
return esp8266_send_at("AT+CIPSTATUS\r\n",2,"OK");//查看IP状态码
}
//查看STA模式IP地址等信息
U08 ESP8266_CIPSTA(void)
{
return esp8266_send_at("AT+CIPSTA_DEF?\r\n",2,"OK");//查看ESP连接热点后分配到的IP地址、网关、掩码
}
//查看本地IP地址
U08 ESP8266_CIFSR_IP(void)
{
return ESP8266_SendStaIP_At("AT+CIFSR\r\n",2,"STAIP");
}
//查看本地IP地址
U08 ESP8266_CIFSR_IP(void)
{
return ESP8266_SendStaIP_At("AT+CIFSR\r\n",2,"STAIP");
}
//列出当前可用AP列表
U08 ESP8266_AP_List(void)
{
return esp8266_send_at("AT+CWLAP\r\n",2,"OK");
}
//查看已接入设备的IP地址
U08 ESP8266_IP_addr(void)
{
return esp8266_send_at("AT+CWLIF\r\n",2,"OK");
}
//上电自动连接AP
U08 ESP8266_Cwautoconn(void)
{
//0:上电不自动连接AP;1:上电自动连接AP;本设置保存到flash
return esp8266_send_at("AT+CWAUTOCONN=1\r\n",2,"OK");
}
/************TCP/IP指令*****************/
/*
*<id>连接的 id 号 0-4
*<type>字符串参数,类型 TCP 或 UDP
*<addr>字符串参数,IP 地址
*<port>端口号
*<tetype>
* 0:本模块做 client 的连接
* 1:本模块做 server 的连接
*返回当前模块的连接状态和连接参数。
STATUS:<stat>+ CIPSTATUS:<id>,<type>,<addr>,<port>,<tetype>
*
*/
U08 ESP8266_TCPorUDP_ConnectStatus(U08 id,U08 *type,U08 *addr,U16 port,U08 tetype)
{
//使用时按照参数发送即可
return 0;
}
//建立TCP/UDP连接
U08 ESP8266_TCPorUDP_Connect(char *type,char *addr,U16 port)
{
char CMD[MAX_PWD] = {0};
sprintf(CMD,"AT+CIPSTART=\"%s\",\"%s\",%d\r\n",type,addr,port);
return esp8266_send_at(CMD,2,"OK");
}
//ESP8266打开服务器端
U08 ESP8266_TcpServer(U08 mode)
{
//0-关闭 1-打开
char cmd[MAX_PWD]={0};
sprintf(cmd, "AT+CIPSERVER=%d,8080\r\n", mode);
return esp8266_send_at(cmd, 2,"OK");
}
//ESP8266设置单路连接或者多路连接
U08 ESP8266_LinkMode(U08 mode)
{
//0-单路 1-多路
char cmd[20];
sprintf(cmd, "AT+CIPMUX=%d\r\n", mode);
return esp8266_send_at(cmd, 2,"OK");
}
/*
*透传模式
*0 – 非透传模式
*1 – 透传模式
*响应 OK
*/
U08 ESP8266_TransParent(U08 mode)
{
char cmd[20];
sprintf(cmd, "AT+CIPMODE=%d\r\n", mode);
return esp8266_send_at(cmd, 2,"OK");
}
//ESP8266退出透传模式
void ESP8266_ExitUnvarnishSend(void)
{
U08 cmd[] = {"+++"};
ESP8266_USART(cmd,3);
DelayMS(1000);
esp8266_send_at("AT",2,"OK");
}
/*
*-发送数据:
*1、作为client发送,设置为单路连接,开启透传
*2、作为server发送,设置为多路连接,开启非透传(不支持透传)
*
*/
void ESP8266_Send(U08 *str,U16 ID,U16 len)
{
char pstr[50]={0};
sprintf(pstr,"AT+CIPSEND=%d,%d\r\n",ID,len);
//esp8266_send_at(pstr,3,">");
ESP8266_USART((U08 *)pstr,strlen(pstr));
DelayMS(500);
//发送数据,此时esp8266接收到的定长数据会直接发送给上位机
ESP8266_USART_Send(str,len);
}
//查看esp发送数据是否成功
void ESP8266_SendStatus(void)
{
esp8266_send_at("AT+CIPSEND?\r\n",2,"OK");
}
//设置服务器超时时间
U08 ESP8266_ServerTimeOut(U16 time)
{
char str[20]={0};
sprintf(str,"AT+CIPSTO=%d\r\n",time);
return esp8266_send_at(str,2,"OK");
}
bool esp8266_init(void)
{
//保证新的esp8266只初始化一次功能,如果配置过则不在配置
if(!esp8266_initialized)
{
ESP8266_WorkModeSet(3);//设置AP+STA模式 ESP8266_ApStatus()
if(ESP8266_CwjapStatus() == TRUE) // 判断连接是否成功
{
//如果连接成功则让指示灯闪烁2次
//WiFi_LedCtl();//可以自己写个LED控制接口调用
}
else //如果未连接则连接,连接过会保存在ESP flash中
{
ESP8266_ConnectAP(gSSID, PASSWD);
}
ESP8266_Cwautoconn();//上电自动连接AP
ESP8266_SetStaticIP(STATIC_IP,STATIC_GW,STATIC_MK);//设置AP模式下静态参数
ESP8266_SetAP(ESP8266_SSID,ESP8266_PWD,ESP8266_CH,ESP8266_ENC,ESP8266_CLIENT,ESP8266_DEFULT);//设置ESP WiFi热点,自身打开热点
ESP8266_LinkMode(1);//设置多路连接模式,客户端接入,这里说明一下收到的格式:+IPD,N,X,:(DATA) N:客户端编号,X:接收字节数
ESP8266_TcpServer(1);//设置服务器模式
//查询IP、状态码信息
//ESP8266_Cipstatus();//esp8266连接热点状态码
ESP8266_CIFSR_IP();
isInitMode = FALSE;// 指令初始化完成后切换通信接收模式
esp8266_initialized = TRUE;
}
return esp8266_initialized;
}
//重置ESP8266回初始状态
void ESP8266_Reset(void)
{
esp8266_initialized = FALSE;
esp8266_init();
}
//初始化功能函数
void ESP8266_Init()
{
esp8266_init();
}
然后是串口的编写,其基本是按照官方案例来写的接口,串口中断接收数据分为指令处理和通信处理(采用环形缓冲区处理),如果不处理的话信息处理就比较乱,对于喜欢串口看log的来说简直灾难,继续;
uart.h
#ifndef __USART_H__
#define __USART_H__
extern void USART_Configuration(uint32_t com);
extern U16 UART1GetRxDataLen(void);
extern U16 UART2GetRxDataLen(void);
extern U16 UART1ReadData(U08 *pBuff, U16 buffLen);
extern U16 UART2ReadData(U08 *pBuff, U16 buffLen);
extern U16 UART1WriteData(U08 *pBuff, U16 len);
extern U16 UART2WriteData(U08 *pBuff, U16 len);
#endif
usart.c
#include "usart.h"
#include <string.h>
#include "stdio.h"
#include "App_Esp8266.h"
#if 1
/* retarget the C library printf function to the USART */
int fputc(int ch, FILE *f)
{
usart_data_transmit(USART2, (uint8_t)ch);
while(RESET == usart_flag_get(USART2, USART_FLAG_TBE));
return ch;
}
#endif
//esp8266+IPD数据处理
static enum {WAIT_IPD, READ_LENGTH, READ_DATA} state = WAIT_IPD;
// 串口1数据接收buff大小
#define UART1_RX_BUFF_SIZE (1024)
// 串口2数据接收buff大小
#define UART2_RX_BUFF_SIZE (256)
// 串口接收数据队列结构体定义
#pragma pack(1)
typedef struct
{
U16 head;
U16 tail;
U08 buff[UART1_RX_BUFF_SIZE];
} UartRxData_t;
#pragma pack()
// 串口1接收到的数据长度
#define UART1_RX_DATA_LEN ((gUart1RxData.tail + UART1_RX_BUFF_SIZE - gUart1RxData.head) % UART1_RX_BUFF_SIZE)
// 删除串口1已读取的数据,len为删除数据的长度
#define UART1_RX_DATA_DELETE(len) (gUart1RxData.head = (gUart1RxData.head + (len)) % UART1_RX_BUFF_SIZE)
// 判断串口1接收buff是否已满
#define UART1_RX_BUFF_IS_FULL() (((gUart1RxData.tail + 1) % UART1_RX_BUFF_SIZE == gUart1RxData.head) ? TRUE : FALSE)
// 串口2接收到的数据长度
#define UART2_RX_DATA_LEN ((gUart2RxData.tail + UART2_RX_BUFF_SIZE - gUart2RxData.head) % UART2_RX_BUFF_SIZE)
// 删除串口2已读取的数据,len为删除数据的长度
#define UART2_RX_DATA_DELETE(len) (gUart2RxData.head = (gUart2RxData.head + (len)) % UART2_RX_BUFF_SIZE)
// 判断串口2接收buff是否已满
#define UART2_RX_BUFF_IS_FULL() (((gUart2RxData.tail + 1) % UART2_RX_BUFF_SIZE == gUart2RxData.head) ? TRUE : FALSE)
// 串口1接收数据队列
UartRxData_t gUart1RxData = {0, 0, {0}};
// 串口2接收数据队列
static UartRxData_t gUart2RxData = {0, 0, {0}};
/********************************串口2的重定向函数定义-END****************************************/
//需要初始化配置的串口,com,可选参数USART0,USART1,USART2
void USART_Configuration(uint32_t com)
{
/* USART configure */
switch(com)//打开对应串口时钟,gpio口初始化在gpio中
{
case USART0: rcu_periph_clock_enable(RCU_USART0);
break;
case USART1: rcu_periph_clock_enable(RCU_USART1);
break;
case USART2: rcu_periph_clock_enable(RCU_USART2);
break;
default:break;
}
usart_deinit(com);
usart_baudrate_set(com, 115200U);
usart_word_length_set(com, USART_WL_8BIT);
usart_stop_bit_set(com, USART_STB_1BIT);
usart_parity_config(com, USART_PM_NONE);
usart_hardware_flow_rts_config(com, USART_RTS_DISABLE);
usart_hardware_flow_cts_config(com, USART_CTS_DISABLE);
usart_receive_config(com, USART_RECEIVE_ENABLE);
usart_transmit_config(com, USART_TRANSMIT_ENABLE);
/* enable USART receive interrupt */
usart_interrupt_enable(com, USART_INT_RBNE);
usart_enable(com);
}
/*
* Description : 获取串口1接收到的数据长度
* Paramter : None
* Return : 串口1接收到的数据长度
*/
U16 UART1GetRxDataLen(void)
{
return UART1_RX_DATA_LEN;
}
/*
* Description : 获取串口2接收到的数据长度
* Paramter : None
* Return : 串口2接收到的数据长度
*/
U16 UART2GetRxDataLen(void)
{
return UART2_RX_DATA_LEN;
}
/*
* Description : 串口1数据读取(USART1)
* Parameter - pBuff : 数据读取buffer指针
* Parameter - buffLen: 数据读取buffer长度
* Return : 返回读取到的数据长度
*/
U16 UART1ReadData(U08 *pBuff, U16 buffLen)
{
if (pBuff == NULL || buffLen == 0)
{
return 0;
}
U16 len = (UART1_RX_DATA_LEN < buffLen) ? UART1_RX_DATA_LEN : buffLen;
printf("Extracted packet: ");
for(int i = 0; i < UART1_RX_DATA_LEN; i++)
{
printf("%02X ", gUart1RxData.buff[i]);
}
printf("\n");
if (len > 0)
{
if (gUart1RxData.head < gUart1RxData.tail)
{
memcpy(pBuff, (U08*)(gUart1RxData.buff + gUart1RxData.head), len);
}
else if (gUart1RxData.head + len <= UART1_RX_BUFF_SIZE)
{
memcpy(pBuff, (U08*)(gUart1RxData.buff + gUart1RxData.head), len);
}
else
{
U16 temp_len = UART1_RX_BUFF_SIZE - gUart1RxData.head;
memcpy(pBuff, (U08*)(gUart1RxData.buff + gUart1RxData.head), temp_len);
memcpy(pBuff + temp_len, (U08*)(gUart1RxData.buff), len - temp_len);
}
UART1_RX_DATA_DELETE(len);
}
return len;
}
/*
* Description : 串口2数据读取(USART2)
* Parameter - pBuff : 数据读取buffer指针
* Parameter - buffLen: 数据读取buffer长度
* Return : 返回读取到的数据长度
*/
U16 UART2ReadData(U08 *pBuff, U16 buffLen)
{
if (pBuff == NULL || buffLen == 0)
{
return 0;
}
U16 len = (UART2_RX_DATA_LEN < buffLen) ? UART2_RX_DATA_LEN : buffLen;
if (len > 0)
{
if (gUart2RxData.head < gUart2RxData.tail)
{
memcpy(pBuff, (U08*)(gUart2RxData.buff + gUart2RxData.head), len);
}
else if (gUart2RxData.head + len <= UART2_RX_BUFF_SIZE)
{
memcpy(pBuff, (U08*)(gUart2RxData.buff + gUart2RxData.head), len);
}
else
{
U16 temp_len = UART2_RX_BUFF_SIZE - gUart2RxData.head;
memcpy(pBuff, (U08*)(gUart2RxData.buff + gUart2RxData.head), temp_len);
memcpy(pBuff + temp_len, (U08*)(gUart2RxData.buff), len - temp_len);
}
UART2_RX_DATA_DELETE(len);
}
return len;
}
/*
* Description : 串口1数据写入(USART1)
* Parameter - pBuff : 数据写入buffer指针
* Parameter - buffLen: 数据写入buffer长度
* Return : 返回写入的数据长度
*/
U16 UART1WriteData(U08 *pBuff, U16 len)
{
if (pBuff == NULL || len == 0)
{
return 0;
}
for (U16 i = 0; i < len; i++)
{
usart_data_transmit(USART1, pBuff[i]);
while (RESET == usart_flag_get(USART1, USART_FLAG_TBE));
}
return len;
}
/*
* Description : 串口2数据写入(USART2)
* Parameter - pBuff : 数据写入buffer指针
* Parameter - buffLen: 数据写入buffer长度
* Return : 返回写入的数据长度
*/
U16 UART2WriteData(U08 *pBuff, U16 len)
{
if (pBuff == NULL || len == 0)
{
return 0;
}
for (U16 i = 0; i < len; i++)
{
usart_data_transmit(USART2, pBuff[i]);
while (RESET == usart_flag_get(USART2, USART_FLAG_TBE));
}
return len;
}
#if 1
//串口1接收数据
void USART1_IRQHandler(void)
{
static uint16_t dataLength = 0;
static uint16_t dataCount = 0;
uint8_t val = 0;
if(RESET != usart_interrupt_flag_get(USART1, USART_INT_FLAG_RBNE))
{
val = (uint8_t)usart_data_receive(USART1);
if(isInitMode)
{
// 在初始化阶段,使用Uart1RecvBuf
if ((int)Uart1RecvLen < sizeof(Uart1RecvBuf))
{
Uart1RecvBuf[Uart1RecvLen++] = val;
}
}
else
{
// 判断串口1接收缓冲区是否未满
switch(state)
{
case WAIT_IPD:
if(val == '+') state = READ_LENGTH;
break;
case READ_LENGTH:
if(val == ':') {
state = READ_DATA;
dataCount = 0;
}
else if(val >= '0' && val <= '9') {
dataLength = dataLength * 10 + (val - '0');
}
break;
case READ_DATA:
if(((gUart1RxData.tail + 1) % UART1_RX_BUFF_SIZE) !=
gUart1RxData.head)
{
gUart1RxData.buff[gUart1RxData.tail] = val;
gUart1RxData.tail = (gUart1RxData.tail + 1) % UART1_RX_BUFF_SIZE;
dataCount++;
if(dataCount >= dataLength) {
state = WAIT_IPD;
dataLength = 0;
}
}
else
{
//用memset清空一下,或者使用上面的接口删除缓存区
}
break;
}
}
//清除接收标志位
usart_interrupt_flag_clear(USART1, USART_INT_FLAG_RBNE);
}
}
#endif
//串口2接收数据
void USART2_IRQHandler(void)
{
uint8_t val;
if(RESET != usart_interrupt_flag_get(USART2, USART_INT_FLAG_RBNE))
{
val= (uint8_t)usart_data_receive(USART2);
// 如果接收队列未满,则把接收到的数据存入队列
if (((gUart2RxData.tail + 1) % UART2_RX_BUFF_SIZE) != gUart2RxData.head)
{
gUart2RxData.buff[gUart2RxData.tail] = val;
gUart2RxData.tail = (gUart2RxData.tail + 1) % UART2_RX_BUFF_SIZE;
}
else
{
// 数据队列已满,丢弃数据
}
//清除接收标志位
usart_interrupt_flag_clear(USART2, USART_INT_FLAG_RBNE);
}
}