GD32F10x单片机+ESP8266_12S+IPD数据解析

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);  
    }  
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值