1. 程式人生 > >esp8266 TCP Client STA模式

esp8266 TCP Client STA模式

    因為嵌入式課程做的東西想用esp8266 將開發板上使用攝像頭獲取的影象傳送到電腦。所以參考正點原子上的示例學習做了一下。雖然有原始碼可以參考,不過在根據自己的需要修改的過程中還是遇到不少問題的。

    esp8266的初始化過程為:

        1. 首先需要初始化串列埠的波特率。在初次嘗試傳輸影象的時候,由於傳輸的速度太慢(1s僅能傳送2000位元組),我以為是串列埠設定的波特率問題,所以用了一個USB轉TTL 使用 AT+UART指令修改串列埠的波特率為921600(程式碼中以及串列埠除錯助手都要調整為對應的值)。不過再次嘗試並沒有顯著的提高傳輸速度(這是因為程式碼中其他地方的原因,下面會解釋)。

        2. 接著用一個迴圈傳送AT 指令,是否可以連線模組。在測試傳送資料的時候,由於我是移值的UCOSIII 系統,OV7670 將圖象資料儲存在SRAM 中,此時傳送資料的任務等待,所以連續傳送兩次資料之間有時間間隔。在這個間隔中有時候會出現模組連線不上的情況(就是傳送AT 指令無法連線到模組)。之前我以為重新把連線的過程執行一遍就沒有問題了,但是依然沒有解決這個問題。後來改為如果連線中斷不重新連線,而是直接退出當前傳送。一般情況下,在中斷10s後會重新識別到模組的。

        3. 測試之後,傳送ATE0 關閉回顯。該步驟感覺可選,不過沒有測試。

        4. 使用AT+CWMODE=1 設定模式為STA。

        5. 在設定模式之後使用AT+RST 重啟模組,延時4s等待重啟完成

        6. 使用AT+CWJAP 連線WIFI ,需要用到WIFI 的SSID 與密碼,在該步驟後,開發板將會獲得一個IP 地址

        7. 使用AT+CIPMUX =0指令設定為單連線,=1 為多連線

        8. 使用AT+CIPSTART 指令啟動TCP 連線,引數為TCP 、目標主機的IP 、目標主機的埠

        9. 使用AT+CIPMODE=1 退出透傳模式。如果要傳送指令,需要退出透傳模式,在傳送資料的時候,需要開啟透傳

        10.之後就可以使用AT+CIPSEND 指令傳輸資料了

    在以上步驟中,需要經常使用atk_8266_at_response(1) 檢查接收到的資料。該函式是例程中封裝好的函式,如果直接操作到暫存器的話,可以參考如下的步驟:

	if(USART3_RX_STA&0X8000)		//接收到一次資料了
	{ 
		USART3_RX_BUF[USART3_RX_STA&0X7FFF]=0;//新增結束符
		printf("%s",USART3_RX_BUF);	//傳送到串列埠
		if(mode)USART3_RX_STA=0;
	} 

    在傳輸的過程中,可以使用如下的步驟檢查模組的連線狀態:

u8 atk_8266_consta_check(void)
{
	u8 *p;
	u8 res;
	if(atk_8266_quit_trans())return 0;			//退出透傳 
	atk_8266_send_cmd("AT+CIPSTATUS",":",50);	//傳送AT+CIPSTATUS指令,查詢連線狀態
	p=atk_8266_check_cmd("+CIPSTATUS:"); 
	res=*p;									//得到連線狀態	
	return res;
}

    下面是傳送資料任務部分的程式碼,傳送資料的部分,每次傳送512個位元組(因為傳送的緩衝限制為不超過600個位元組)。傳送位元組數大約為10KB,大約用時1-2s。相比較於之前的程式碼,主要是修改的傳送資料的迴圈。之前在迴圈中,每一次傳送都使用quit_trans 於AT+CIPSEND 指令。在將這兩步刪除之後,傳送速度提高很快。具體速度最快可以達到多少還沒有測試。

檔案 send_msg.c

#include "send_img_task.h"
#include <stdio.h>
#include "camera_main.h"
#include "usart.h"	

/*******************

	用於向電腦傳送資料

*********************/

void send_img()
{
	uart_init(921600);	 		//串列埠初始化為 921600
	printf("wifi 任務\r\n");
	while(!hasimg)//等待srma 中有影象,同時也用於在camera_main 中的初始化函式完成之後再執行當前接下來的任務
	{
		printf("in wifi task      hasimg=%d    hassend = %d\r\n",hasimg,hassend);
	}		
	printf("傳送影象幀的任務開始\r\n");
	printf("準備與電腦建立連線..........\r\n");
	connect_to_computer();		//首先建立連線
	
	while(1)
	{
		if(!hasimg)
		{
			printf("等待SRAM 中的資料\r\n");
			delay_ms(30);
			if(atk_8266_consta_check() == '+')
				printf("連線正常....\r\n");
			else
				printf("連線中斷......\r\n");
			atk_8266_at_response(1);
			continue;
		}
		printf("準備傳送一幀影象\r\n");
		//wifi_send_data("DA",2);
		wifi_send_data((char *)imgarray,4800*2);		//76800 為總的畫素點數,每個16位,傳送80*60
		printf("一幀影象傳送完畢\r\n");
		if(atk_8266_consta_check() == '+')
			printf("連線正常\r\n");
		else
			printf("連線中斷\r\n");
		atk_8266_at_response(1);
		delay_ms(30);
		hassend=1;
		hasimg=0;
	}

}

檔案 wifi_conn.c

#include "wifi_conn.h"
#include "usart.h"
#include <stdio.h>
#include <stdlib.h>
#include "common.h"
#include <string.h>
#include "os.h"

/***********************
	連線電腦的方法

**************************/
void connect_to_computer()
{
	char *p =NULL;
	printf("開始初始化WIFI 模組\r\n");
	while(atk_8266_send_cmd("AT","OK",20))		//檢查WIFI 模組是否線上
	{
		atk_8266_quit_trans();	//退出透傳
		atk_8266_send_cmd("AT+CIPMODE=0","OK",200);	//關閉透傳模式
		printf("嘗試連線到模組\r\n");
		delay_ms(800);
	}
	printf("模組連線成功\r\n");
	while(atk_8266_send_cmd("ATE0","OK",20));	//關閉回顯
	printf("開始設定WIFI STA 模式\r\n");
	delay_ms(10);
	atk_8266_at_response(1);	//檢查模組傳送的資料
	atk_8266_send_cmd("AT+CWMODE=1","OK",50);	//設定WIFI STA 模式
	atk_8266_send_cmd("AT+RST","OK",20);
	delay_ms(4000);
	p = (char *)malloc(sizeof(char)*128);
	sprintf(p,"AT+CWJAP=\"%s\",\"%s\"",wifista_ssid,wifista_password);
	atk_8266_at_response(1);
	while(atk_8266_send_cmd((u8*)p,"WIFI GOT IP",300));	//連線目標路由
	atk_8266_at_response(1);
	printf("連線到電腦wifi \r\n");
	delay_ms(100);
	atk_8266_send_cmd("AT+CIPMUX=0","OK",40);		//單連線
	printf("設定連線的IP 地址\r\n");
	sprintf(p,"AT+CIPSTART=\"TCP\",\"192.168.137.1\",8086");
	while(atk_8266_send_cmd((u8*)p,"OK",200))
	{
		printf("TCP 連線失敗!\r\n");
	}
	printf("TCP 連線成功!\r\n");
	atk_8266_send_cmd("AT+CIPMODE=1","OK",200);
	//atk_8266_at_response(1);
	USART3_RX_STA=0;
	free(p);
	
}

/****************************

	使用WIFI 傳送資料
	由於影象畫素每個畫素點是16位的資料,所以每次傳送一個16位的資料
len :	以位元組為單位計算的長度
	使用8266傳送緩衝的大小為600個位元組,在該函式中採用每次傳送512個位元組

*****************************/

void wifi_send_data(char *data,int len)
{	
	char *p = data;
	
	p = (char*)malloc(sizeof(char)*128);

	if(atk_8266_consta_check() == '+')
	{
		printf("連線正常\r\n");
	}
	else
	{
		printf("連線中斷\r\n");
		return;
	}
	atk_8266_at_response(1);
	delay_ms(10);
	
	free(p);
	
	p=data;
	//首先發送起始資訊
	atk_8266_quit_trans();
	atk_8266_send_cmd("AT+CIPSEND","OK",20);
	u3_printf("start of msg");
	atk_8266_at_response(1);
	delay_ms(30);
	
	while(len > 0)
	{		
		if(len >= 512)
		{
			len -= 512;
			u3_printf("%512.512s",p);
			p+=512;
		}
		else
		{
			u3_printf("%s",p);
			len=0;
		}
		atk_8266_at_response(1);
		delay_ms(10);
	}
	//傳送標識一幀影象結束的訊息
	atk_8266_quit_trans();
	atk_8266_send_cmd("AT+CIPSEND","OK",20);
	u3_printf("end of msg");
	atk_8266_at_response(1);
	delay_ms(10);
	atk_8266_at_response(1);
	
	printf("傳送結束==========================================\r\n");
//	char *p = data;
//	char *send_content = (char*)malloc(sizeof(char)*2);
//	while(len > 0)
//	{
//		atk_8266_quit_trans();
//		atk_8266_send_cmd("AT+CIPSEND","OK",20);
//		sprintf(send_content,"%02x%02x",*p,*(p+1));
//		u3_printf(send_content);		//傳送資料
//		p +=2;
//		len -= 2;
//		atk_8266_at_response(1);
//	}
//	free(send_content);
}