stm32通过wifi模块实现手机远程控制灯与舵机

由于对wifi模块的控制需要,在网上找了许多资料,发现wifi模块通过单片机进行通讯的代码不多,也有一些存在着错误,于是便自己写了一个wifi控制舵机和灯的程序,记录下来

stm32通过wifi模块实现手机远程控制灯与舵机内容包括:

  • 所需要的元器件
    • 整体思路
    • 连线图
    • 完成效果
    • 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外设(灯和舵机)的控制

stm32通过wifi模块实现手机远程控制灯与舵机_第1张图片

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而崩溃。

你可能感兴趣的:(stm32)