1. 程式人生 > >stm32-esp8266驅動程式

stm32-esp8266驅動程式

esp8266模組是串列埠通訊,通訊的協議是AT指令,要正確的配置對應的AT指令模組才可以工作,這裡就需要知道AT指令有沒有配置成功,這個比較容易實現,一般傳送AT指令配置成功的話,晶片都會返回至少一個OK,當然還有其它資料,我們只需要去解析有沒有接收到OK就知道指令傳送是否成功了。我這裡是作為TCP客服端,所以只需要以下一些指令即可:

1>>	傳送		AT\r\n			返回 	"OK"
	以上操作確保晶片連線正常,工作正常

2>>	傳送 		ATE0\r\n		返回	"OK"
	關閉回顯

3>>	傳送 	AT+CWMODE=1\r\n		返回	"OK"
	設定成客服端模式


4>>	傳送   	AT+CIPSTATUS		返回	"2 3 4 5"	2 3為連線
	確保連線到路由器

5>>	傳送 	AT+CWJAP="HES_WIFI","wifi_pass"	返回 	"OK"
													返回	"FAIL"
	連線到路由器

6>>		傳送 	AT+CWAUTOCONN=1		返回	"OK"
	開機自動連線

7>>		傳送 	AT+CIPSTART="TCP","192.168.0.105",8888		返回	"OK"
	連線到伺服器

8>>		傳送 	AT+CIPCLOSE		返回	"OK"
	關閉伺服器連線

8>>		傳送    AT+CIPMODE=1 	返回	"OK"
	設定透傳模式1
9>>		傳送    AT+CIPSEND		返回	">"
	進入透傳
10>>	傳送 	+++				返回	無

程式驅動也會按照這個流程來實現;

大概框架如下

esp8266wifi.c檔案主要是AT指令配置

serial_config.c檔案主要用於解析返回的資料,例如OK,>等

uart.c是串列埠的應用協議

1-先看看esp8266wifi的內容

#define FANHUI_V		"OK"		//普通指令返回值

extern u8 wifi_name[20];		//路由器名字
extern u8 wifi_pass[20];		//路由器密碼

extern u8 wifi_ip[32];			//伺服器ip
extern u8 wifi_port[6];		//伺服器埠

static u8 wifi_work_mode;		//wifi模組的工作模式,1為配置模式,2為透傳模式

#define _WIFI_TRAN_MODE 		2
#define _WIFI_CONFIG_MODE 	1
	
/*模組初始化
	
	1.測試AT命令,保證晶片工作正常
	2.關閉回顯
	3.設定成客服端模式
	4.連線到路由器
	5.連線到伺服器
	6.設定透傳模式1
	7.開始透傳
	
	8.關閉透傳


*/
u8 esp8266_init(void);

//測試AT指令,確保連線和晶片正常
u8 test_at(void);

//關閉回顯
u8 close_huixian(void);

//設定成客戶端
u8 set_client(void);

//判斷是否連線路由器
u8 is_connect_ap(void);

//連線到路由器
u8 connect_ap(void);

//設定自動連線路由器
u8 aotu_connect_ap(void);

//連線到伺服器
u8 connect_server(void);

//斷開伺服器
u8 disconnect_server(void);

//設定透傳模式
u8 set_mode1(void);

//開始透傳
u8 start_tran(void);

//關閉透傳
u8 close_tran(void);

//設定為透傳模式
void set_tran_mode(void);

//設定成配置模式
void set_config_mode(void);

//獲取工作模式
u8 get_work_mode(void);


//傳送命令和等待時間
u8 send_cmd_wait(u8 *str,u8 len,u32 d_ms);



#endif

這裡主要介紹一下

//傳送命令和等待時間 u8 send_cmd_wait(u8 *str,u8 len,u32 d_ms);

這個函式比較重要,主要功能還是發生一個AT指令,等待nms後檢測是否收到OK,下面是實現

//傳送命令和等待時間
u8 send_cmd_wait(u8 *str,u8 len,u32 d_ms)
{

	serial2_sned_buff(str,len);
	
	delay_ms(d_ms);

	if(find_quq_del(OK))	//查詢串列埠資料快取是否OK
	{
		
		return 1;
	}
	return 0;
}

關閉透傳也比較特殊,實現如下

//關閉透傳
u8 close_tran()
{
	serial2_sned_buff((u8*)"+++",3);
	delay_ms(20);
	serial2_sned_buff((u8*)"+++",3);
	delay_ms(20);
	serial2_sned_buff((u8*)"\r\n",2);
	delay_ms(20);
	
	return 1;
}

所有函式太多,只介紹幾個關鍵的,其它的可以在後面下載原始碼。

接下來是serial_config檔案

這個檔案主要實現1-串列埠緩衝區新增資料(資料要在串列埠中斷新增),2-解析是否存在相應指令

#define MES_LEN 200


//command
#define OK	(char*)"OK"
#define AP2	(char*)"2\r\n"
#define AP3	(char*)"3\r\n"
#define OFF (char*)"off"
#define ON (char*)"on"
#define STATE (char*)"state"

//Log Switch
#define ERIAL_CONFIG_LOG 0


static	int num;
static	char mes_buf[MES_LEN];		//串列埠佇列長度


	//尋找子並移除子串

int find_str_del(char *mes,char *str);
	//尋找命令
	//引數:命令
	//查詢到命令返回1,否則0
int find_quq_del(char *str);
	//新增資料到佇列
void add_mes_buf(char ch);
	

#endif

uart.c應用協議是自己定義的,和模組沒有關係,其實以上2個檔案已經看正常的初始化esp8266了。

初始化函式:

u8 esp8266_init()
{
	
	//設定成配置模式
	set_config_mode();
	
	//測試AT
	if(test_at())
	{
		#if ESP8266_LOG
		printf("esp8266硬體 正常\r\n");
		#endif
	}
	else
	{
		#if ESP8266_LOG
		printf("esp8266硬體 異常\r\n");
		printf("嘗試關閉透傳...\r\n");
		#endif
		
		close_tran();
		
	}
	//關回顯
	if(close_huixian())
	{
		#if ESP8266_LOG
		printf("關閉esp8266回顯 正常\r\n");
		#endif
	}
	else
	{
		#if ESP8266_LOG
		printf("關閉esp8266回顯 異常\r\n");
		#endif
	}
	//設定成客戶端
	if(set_client())
	{
		#if ESP8266_LOG
		printf("設定成客戶端 正常\r\n");
		#endif
	}
	else
	{
		#if ESP8266_LOG
		printf("設定成客戶端 異常\r\n");
		#endif
	}
	//判斷是否連線到路由器	is_connect_ap
	if(is_connect_ap())
	{
		#if ESP8266_LOG
		printf("連線路由器 正常\r\n");
		#endif
	}
	else	//如果沒有連線路由器,則去連線
	{
		#if ESP8266_LOG
		printf("連線路由器 異常\r\n");
		printf("嘗試連線路由器...\r\n");
		#endif
		
		if(connect_ap())
		{
			#if ESP8266_LOG
			printf("連線路由器 正常\r\n");
			#endif
			aotu_connect_ap();
		}
		else
		{
			#if ESP8266_LOG
			printf("連線路由器 異常\r\n");
			#endif
		}
		
	}
	
	
	
	//連線到伺服器
	if(connect_server())
	{
		#if ESP8266_LOG
		printf("連線伺服器 正常\r\n");
		#endif
	}
	else
	{
		#if ESP8266_LOG
		printf("連線伺服器 異常\r\n");
		printf("嘗試關閉連線伺服器,重新連線...\r\n");
		#endif
		
		if(disconnect_server())
		{
			#if ESP8266_LOG
			printf("關閉連線伺服器 正常\r\n");
			#endif
				//連線到伺服器
			if(connect_server())
			{
				#if ESP8266_LOG
				printf("重新連線伺服器 正常\r\n");
				#endif
			}
			else
			{
				#if ESP8266_LOG
				printf("連線伺服器 異常\r\n");
				#endif
			}
		}
		else
		{
			#if ESP8266_LOG
			printf("關閉連線伺服器 異常\r\n");
			#endif
		}
		
		
	}
	//設定透傳模式1
	if(set_mode1())
	{
		#if ESP8266_LOG
		printf("設定透傳模式1 正常\r\n");
		#endif
	}
	else
	{
		#if ESP8266_LOG
		printf("設定透傳模式1 異常\r\n");
		#endif
	}		
	//開始透傳
	if(start_tran())
	{
		#if ESP8266_LOG
		printf("開始透傳 正常\r\n");
		#endif
		
		//設定成配置模式
		set_tran_mode();
		
	}
	else
	{
		#if ESP8266_LOG
		printf("開始透傳 異常\r\n");
		#endif
		
		return 0;
		
	}	
	
	return 1;
}

整體使用的過程。

1,主函式必須初始化串列埠,esp8266_init()

2,while(1)裡面實現如下,

//任務2函式
void task2_func(void *param)
{

	u8 data_count_time=0;	
	int j=1;
	
	while(1)
	{
		
		if(get_work_mode()==_WIFI_TRAN_MODE)	//判斷是否是透傳模式
		{
			
			//檢查wifi資料
			check_wifi_data();
			
			if(wifi_mes.recv_len>0)
			{
				printf("%dwifi:%s\r\n",j++,wifi_mes.recv_data);
			}
			else
			{
				data_count_time++;
				if(data_count_time==5)		//如果很久沒有接到資料
				{
					clear_wifi_buf();		//清空快取
				}
			}
			
			//serial2_sned_buff((u8*)"hello world\r\n",13);
		}
		task_delay(1);

	}
	
}

串列埠中斷實現如下:如果是配置模式,把資料放到命令解析的快取裡,如果是透傳模式,把資料放到應用協議的快取裡

void USART2_IRQHandler(void)
{

	   USART_ClearFlag(USART2,USART_FLAG_TC);  
    if(USART_GetITStatus(USART2,USART_IT_RXNE)!=Bit_RESET)//檢查指定的USART中斷髮生與否  
    {  
   
			u8  k=USART_ReceiveData(USART2);  
				
			if(get_work_mode()==_WIFI_CONFIG_MODE)	//如果是配置模式
			{
				add_mes_buf(k);
			
			}else
			{
				
				wifi_buf_add(k);
				//printf("%x ",k);
				
			}
 
      
    }  

	
}

整體測試下來,效果還是很不錯的,一晚上通訊沒有宕機掉線。用的是TCP工具,沒有自己寫socket

程式碼量還是比較多的,不能一一講解,可以下載原始碼學習,看部分程式碼可以知道註釋是很足的。