STM32
直播中

李玉兰

7年用户 1475经验值
私信 关注
[问答]

如何去完成STM32串口的回环测试实验呢

STM32串口的回环测试是什么意思?
如何去完成STM32串口的回环测试实验呢?

回帖(1)

寇昕

2021-12-8 11:13:43
串口初始化代码就不分享了,大家都有的,我做的是回环测试,也就是用了两个串口,一个串口给ESP8266发送指令,另一个接收他发回来的数据,如果需要代码最后会给
先分享一下代码,大概讲解一下(从简)
建立连接

//Server:服务器类型        IP:服务器地址        PORT:端口号
void ESP_CIPSTART(const char* Server,const char* IP,const char* PORT)
{
        char temp[40] = {0};
        uint8_t k = 0;
        sprintf(temp,"AT+CIPSTART="%s","%s",%srn",Server,IP,PORT);
        while(temp[k]!='')
        {
                USART_SendByte(ESP_USARTx,temp[k]);
                while(USART_GetFlagStatus(ESP_USARTx,USART_FLAG_TXE) == RESET);
                k++;
        }
        while(USART_GetFlagStatus(ESP_USARTx,USART_FLAG_TC) ==RESET);
}
CIPSTART不懂,那就去先了解AT指令,附上别人的分享

检测响应


//rsp:你要检测的响应字符串,waitTimes_ms:超时退出
uint8_t ESP_Check_Respond(const char* rsp,u16 waitTimes_ms)
{
        while((strstr(ESP_Usart_RecBuf,rsp) == NULL)&&(--waitTimes_ms))
        {
                delay_ms(1);
        }
        if(waitTimes_ms) return SUCCESS;
        else return ERROR;
}
strstr是标准库string.h的,include
发送命令字符串


//Enter是否加入换行 1就加入
void ESP8266_SendATcmd(const char* AT_cmd,u8 Enter)
{
        char CMDBuf[20] = {0};
        uint8_t k = 0;
        strcat(CMDBuf,AT_cmd);
        if(Enter)
        {       
                strcat(CMDBuf,"rn");        //加入换行
        }
        while(*(CMDBuf+k)!='')
        {
                USART_SendByte(ESP_USARTx,*(CMDBuf+k));
                while(USART_GetFlagStatus(ESP_USARTx,USART_FLAG_TXE) == RESET);
                k++;
        }
        while(USART_GetFlagStatus(ESP_USARTx,USART_FLAG_TC) ==RESET);
}
void ESP_SendString(const char* str)
{
        uint8_t k = 0;
        do
        {
                USART_SendByte(ESP_USARTx,str[k]);
                while(USART_GetFlagStatus(ESP_USARTx,USART_FLAG_TXE) == RESET);
                k++;
        }while(*(str+k)!='');
        while(USART_GetFlagStatus(ESP_USARTx,USART_FLAG_TC) == RESET);
}
发送AT指令、发送字符串(向ESP8266)
基于上面两个函数,我定义了一些宏

#define        OPEN_PTMODE()                                ESP8266_SendATcmd("AT+CIPMODE=1",1)        //打开透传模式,要记得关
#define        CLOSE_PTMODE()                                ESP_SendString("+++")                                //退出透传模式(重要!不然会一直接收数据)
#define        CMD_CIPCLOSE()                                ESP_SendString("AT+CIPCLOSErn")        //退出IP
#define CMD_AT()                                        ESP8266_SendATcmd(AT,CMD_ENTER)
#define        CMD_RST()                                        ESP8266_SendATcmd(AT_RST,CMD_ENTER)


获取时间

NETWORK_TIME myTime;
//获取网络时间
uint8_t Get_NetWork_Time(void)
{
       
        uint8_t GetFlag = 0;
        ESP_CIPSTART("TCP","www.beijing-time.org","80");
        delay_ms(50);
        if(ESP_Check_Respond("CONNECT",400) == 0)
        {
                ESP_ERROR("ERROR0");
                return 0;
        }
        //delay_ms(1000);
        OPEN_PTMODE();                                                        //开透传
        delay_ms(50);
        if(ESP_Check_Respond("OK",400) == 0)
        {
                CLOSE_PTMODE();       
                ESP_ERROR("ERROR1");
                return 0;
        }
        ESP8266_SendATcmd("AT+CIPSEND",1);
        delay_ms(50);
        if(ESP_Check_Respond("OK",400) == 0)
        {
                CLOSE_PTMODE();       
                ESP_ERROR("ERROR1");
                return 0;
        }
        ESP_SendString("GET /time15.asp HTTP/1.1rnHost:www.beijing-time.orgrn");
        ESP_SendString("GET /time15.asp HTTP/1.1rnHost:www.beijing-time.orgrn");
        delay_ms(500);
        if(GetNET_Time(&myTime,ESP_Usart_RecBuf))        GetFlag = 1;
        //delay_ms(1000);
        CLOSE_PTMODE();                //关透传
        delay_ms(50);       
        CMD_CIPCLOSE();                //退出IP
        delay_ms(50);                                       
        return GetFlag;
}
先别急着看代码,我说一下这个函数的流程是,建立连接,开启透传(记得关).发送CIPSEND指令开始进入发送模式,然后发送两次获取时间的字符串(不知道为什么要发两次),然后通过一个函数(GetNET_Time)提取时间数据,成功提取返回1,失败为0,最后关闭透传,切记),退出连接.下面分享一下怎么提取数据。
提取时间数据

先给大家看一下格式

typedef struct
{
        char week[5];
        char date[3];
        char month[5];
        char year[6];
        char hours[4];
        char minute[4];
        char seconds[4];
} NETWORK_TIME;
1
2
3
4
5
6
7
8
9
10
上代码


uint8_t GetNET_Time(NETWORK_TIME* time,char *Timestr)
{
        char* pbuf = NULL;
        pbuf = strstr(Timestr,"Date:");
        if(pbuf)
        {
                if(sscanf(pbuf,"%*[^:]: %[^,], %[^ ] %[^ ] %[^ ] %[^:]:%[^:]:%[^ ]",
                time->week,time->date,time->month,time->year,time->hours,time->minute,time->seconds))
                {
                        return 1;
                }
        }
        return 0;
}


sscanf在stdio.h, include进去,sscanf用法自己查
说一下过程,传入数组缓冲区数据,然后用strstr函数查找”Date:“这个字符所在位置(指针),最后传入sscanf按格式提取出年月日。。。等时间数据(字符串)。
可能有些人不懂数组缓冲区,我以前发了一篇IDLE中断,需要的可以看看,同样可以定义一个ESP用到的串口的接收缓冲。
下面来测试一下结果,分享我的测试代码
extern NETWORK_TIME myTime;

int thour;
int tmin;
int tsec;
int main()
{
        /*Parameter Configuration*/
       
        /*Init*/
        delay_init(168);
        USART_Config();
        LED_GPIO_Config();
        ESP8266_USART_Config();        //初始化ESP的串口
        ESP_Idle_Receive_Config();        //初始化空闲接收中断
        /*Configuration Operation*/
        ESP8266_SendATcmd("AT+RST",1);        //一定要复位一下,并且连上WIFI,CWMODE=1或者3
        if(Get_NetWork_Time())
                {
                        sscanf(myTime.hours,"%d",&thour);
                        sscanf(myTime.minute,"%d",&tmin);
                        sscanf(myTime.seconds,"%d",&tsec);
                        printf("rn%s %d:%d:%d",myTime.year,thour+8,tmin,tsec);
                }
        /*LOOP*/
        while(1)
        {
                LED1_TOGGLE;
                delay_ms(500);
        }
}
我把字符串转化成整型了,其实也可以直接使用字符串,%s就行了,我转成整型是因为时间有时差,那是0度线的时间,我也不知道哪里,北京时间+8就对了(东8区?)
我的结果:



回环测试
#define        ESP_USE_IDLE_RECEIVE                //是否开启空闲接收中断
#define ESP_USART_REC_BUFSIZE                100
//头文件↑


static u16 ESP_Usart_Count = 0;                //接收计数,在中断函数调用
char ESP_Usart_RecBuf[ESP_USART_REC_BUFSIZE];
#ifdef ESP_USE_IDLE_RECEIVE
void ESP_USARTx_IRQHandle()
{
        u16 times;
        if(USART_GetITStatus(ESP_USARTx,USART_IT_RXNE) != RESET)
        {
                ESP_Usart_RecBuf[ESP_Usart_Count] = USART_ReceiveData(ESP_USARTx);
                ESP_Usart_Count++;
        }
        if(USART_GetITStatus(ESP_USARTx,USART_IT_IDLE) != RESET)
        {
                ESP_Usart_RecBuf[ESP_Usart_Count] = USART_ReceiveData(ESP_USARTx);
                //ESP_Usart_Count++;
                /*此处加入对接收缓冲区的操作*/
                for(times = 0;times < ESP_Usart_Count;times++)
                {
                        USART_SendByte(DEBUG_USART,ESP_Usart_RecBuf[times]);
                }
                ESP_Usart_Count = 0;
        }
}
#endif
举报

更多回帖

发帖
×
20
完善资料,
赚取积分