stm32通過wifi模塊實現手機遠程控制燈與舵機

由於對wifi模塊的控制需要,在網上找了許多資料,發現wifi模塊通過單片機進行通訊的代碼不多,也有一些存在着錯誤,於是便自己寫了一個wifi控制舵機和燈的程序,記錄下來

stm32通過wifi模塊實現手機遠程控制燈與舵機內容包括:

所需要的元器件

  • stm32單片機
  • usb-ttl模塊
  • stlink
  • wifi模塊8066
  • 舵機

整體思路

1.stm32先進行wifi模塊初始化,發送AT指令使得wifi模塊進入sta模式,自動發送wifi名稱與密碼連接至手機的熱點,接入TCP,並開啓通透傳遞模式。
2.通過手機發送led信號讓wifi模塊接收到信息,並返回單片機,在串口2上顯示,並翻轉單片機上的led燈,返回連接成功信息到手機上。
3.通過手機發送舵機信號讓wifi模塊接收到信息,返回單片機,在串口2上顯示,並控制連接在單片機上的舵機轉動,返回連接成功信息到手機上。

連線圖

stm32通過uart1與wifi連接,
stlink連接stm32,
usb-ttl連接stm32的uart2,
舵機連接tim4來實現用脈衝控制舵機轉動角度。

完成效果

使程序能夠自行連接給定的WIFI熱點和服務器並實現雙向通信,通過wifi模塊完成手機對stm32外設(燈和舵機)的控制

wifi模塊

wifi模塊初始化

wifi模塊的初始化中,有幾個指令是不可缺少的:

  • AT測試
  • AT+CWMODE=1設置工作模式
  • AT+CWJAP=“熱點名稱”,“熱點密碼”
  • AT+CIPSTART=“TCP”,“服務器地址”,端口號

代碼解析

  • wifi模塊初始化代碼
int wifi_init()
{
	uint8_t ret=0;
	ret = Send_AT_commend("AT", "OK", 100);
	if(!ret)
		return -1;
	ret = Send_AT_commend("AT+CWMODE=1", "OK", 100);
	if(!ret)
		return -2;
	wifi_str();
	ret = Send_AT_commend(temp, "OK", 9000); 			
	if(!ret)
		return -3;
	server_str();
	ret = Send_AT_commend(temp, "OK", 3000);			
	if(!ret)
		return -4;	
	ret = Send_AT_commend("AT+CIPMODE=1", "OK", 100);
	if(!ret)
		return -5;
	return 1;
}

uint8_t wifi_str()
{
	int i=0;
	while(temp[i])temp[i++]=0x00;
	strcat(temp,"AT+CWJAP=");
	strcat(temp,"\"");
	strcat(temp,NAME);
	strcat(temp,"\",\"");
	strcat(temp,PWD);
	strcat(temp,"\"");
}
uint8_t server_str()
{
	int i=0;
	while(temp[i])temp[i++]=0x00;
	strcat(temp,"AT+CIPSTART=\"TCP\",\"");
	strcat(temp,ADDR);
	strcat(temp,"\",");
	strcat(temp,PORT);
}

  • 發送AT指令部分代碼
uint8_t Send_AT_commend(char *at_commend, char *re_commend, uint16_t time_out)
{
	uint8_t i=0;
	for(i=0;i<3;i++)
	{
		clear_buf();
		HAL_UART_Transmit(&huart1, (uint8_t *)at_commend, strlen(at_commend), 0xFFFF);
		HAL_UART_Transmit(&huart1, (uint8_t *)"\r\n", 2, 0xFFFF);					HAL_Delay(time_out);
    	if(find_str(re_commend))
			return 1;
		i++;
	}
	return 0;
}
void clear_buf()
{
	uint16_t i;
	for(i=0;i<2000;i++)
		my_re_buf1[i]=0x00;
	HAL_UART_Receive_IT(&huart1,my_re_buf1,1);
}


  • 舵機控制代碼
void MG996R_Set_Angle(int16_t angle)
{
	if ((-90 <= angle) && (angle <= 90))
	{
		CCR_value = (10. / 9) * angle + 150;	
	}
	__HAL_TIM_SET_COMPARE(&htim11, TIM_CHANNEL_1, CCR_value);
}
  • 串口接收中斷信息
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(huart==&huart1)
	{	
		HAL_UART_Receive_IT(&huart1,&my_re_buf1[++pt_w1],1);			
	}	
	

}
  • 定時器中斷
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	int i=0,len=0;
	if(htim==&htim4)
	{

			while(pt_r1<pt_w1 )
		{
			while(pt_r1<pt_w1)
				HAL_UART_Transmit(&huart2,&my_re_buf1[pt_r1++],1,1000);				
			HAL_UART_Transmit(&huart2,(uint8_t *)"\r\n",2,1000);						
			
			
			if(find_str("LED")){
			
			HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);    //LED
        	HAL_UART_Transmit(&huart1, (uint8_t *)"success", 7, 0xFFFF);   //return 	
			}
			if(find_str("SERVO")){
        	if(m==0){
			MG996R_Set_Angle(-40); 	//SERVO
			m++;	
			}		
			
			HAL_UART_Transmit(&huart1, (uint8_t *)"success", 7, 0xFFFF);   //return 
			
			}			
		}
		
		if(pt_r1>=pt_w1)
		{
			pt_w1=pt_r1=0;
			HAL_UART_AbortReceive_IT(&huart1);
			HAL_UART_Receive_IT(&huart1,my_re_buf1,1);
		}
		
		
		while(send_buf[i])send_buf[i++]=0x00;			
		while(pt_r2<pt_w2 )
		{
	
			HAL_UART_Transmit(&huart1,&my_re_buf2[pt_r2++],1,1000);								
			HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_13);    //LED
		
		}
		if(pt_r2>=pt_w2)
		{
			pt_w2=pt_r2=0;
			HAL_UART_AbortReceive_IT(&huart2);	
			HAL_UART_Receive_IT(&huart2,my_re_buf2,1);
		}
		
	}
	
	
}


遇到的問題

  1. 剛開始wifi模塊初始化自動加載的時候會出問題,之後發現是初始化代碼裏缺少了通透模式的設定,使得無法通過wifi連續傳遞信息
  2. 寫代碼的時候容易把函數寫在主程序後,有時候keil會報錯,解決方法是創建一個新的c程序,在主函數裏include這個程序的頭文件,之後引用就不會出現這樣的問題了
  3. 串口發送與接收十分重要,有時候可以用來檢測wifi模塊是否能連接上stm32

總結

希望自己以後可以碼代碼的時候更加細緻,這樣能讓工程不會因爲一些很小的bug而崩潰。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章