STM32与阿里云连接实践指南

STM32F103C8T6连接到阿里云IoT平台

目录

1. 准备工作

2. 阿里云IoT平台设置

3. 硬件连接

4. ESP8266配置

5. STM32F103C8T6编程

6. 测试与调试

7. 注意事项

8. 总结


在物联网(IoT)项目中,将微控制器连接到云端平台以实现远程监控和控制是一个常见的需求。本文将介绍如何使用STM32F103C8T6微控制器通过ESP8266 Wi-Fi模块连接到阿里云IoT平台,实现数据的上传和接收。

1. 准备工作

在开始之前,确保你拥有以下硬件和软件:

  • STM32F103C8T6开发板
  • ESP8266 Wi-Fi模块(如ESP-01S)
  • 串口调试工具(如USB转TTL模块)
  • 阿里云IoT平台账号
  • STM32开发环境(如STM32CubeIDE、Keil等)
  • ESP8266 AT指令集和MQTT协议的相关知识
  • 2. 阿里云IoT平台设置

    1. 创建产品:在阿里云IoT平台上创建一个新的产品,并选择对应的设备类型(如自定义设备)。
    2. 添加设备:在产品下添加一个新的设备,并获取该设备的三元组信息(ProductKey、DeviceName、DeviceSecret)。
    3. 配置Topic:根据业务需求配置MQTT的Topic,用于数据的上传和接收。

    3. 硬件连接

    将ESP8266 Wi-Fi模块通过UART接口连接到STM32F103C8T6的TX和RX引脚。同时,确保ESP8266模块的电源和地线也正确连接。

    4. ESP8266配置

    1. 烧录AT固件:使用串口调试工具将ESP8266的AT固件烧录到模块中。
    2. 配置Wi-Fi:通过AT指令配置ESP8266连接到你的Wi-Fi网络。
    3. 设置MQTT参数:使用AT指令设置MQTT的服务器地址、端口、ClientID、用户名、密码等信息。这些信息将用于ESP8266与阿里云IoT平台的连接。

    5. STM32F103C8T6编程

    1. 初始化UART:在STM32F103C8T6上初始化UART接口,以便与ESP8266通信。                   
      #include "sys.h"
      #include "usart.h"
      #include "wechatcmd.h"
      // 	 
      //如果使用ucos,则包括下面的头文件即可.
      #if SYSTEM_SUPPORT_UCOS
      #include "includes.h"					//ucos 使用	  
      #endif	  
      
      //
      //加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
      #if 1
      #pragma import(__use_no_semihosting)             
      //标准库需要的支持函数                 
      struct __FILE 
      { 
      	int handle; 
      
      }; 
      
      FILE __stdout;       
      //定义_sys_exit()以避免使用半主机模式    
      void _sys_exit(int x) 
      { 
      	x = x; 
      } 
      //重定义fputc函数 
      int fputc(int ch, FILE *f)
      {      
      	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
          USART1->DR = (u8) ch;      
      	return ch;
      }
      #endif 
      
      /*使用microLib的方法*/
       /* 
      int fputc(int ch, FILE *f)
      {
      	USART_SendData(USART1, (uint8_t) ch);
      
      	while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) {}	
         
          return ch;
      }
      int GetKey (void)  { 
      
          while (!(USART1->SR & USART_FLAG_RXNE));
      
          return ((int)(USART1->DR & 0x1FF));
      }
      */
       
      #if EN_USART1_RX   //如果使能了接收
      //串口1中断服务程序
      //注意,读取USARTx->SR能避免莫名其妙的错误   	
      u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
      //接收状态
      //bit15,	接收完成标志
      //bit14,	接收到0x0d
      //bit13~0,	接收到的有效字节数目
      u16 USART_RX_STA=0;       //接收状态标记	  
        
      void uart_init(u32 bound){
          //GPIO端口设置
          GPIO_InitTypeDef GPIO_InitStructure;
      	USART_InitTypeDef USART_InitStructure;
      	NVIC_InitTypeDef NVIC_InitStructure;
      	 
      	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能USART1,GPIOA时钟
           //USART1_TX   PA.9
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
          GPIO_Init(GPIOA, &GPIO_InitStructure);
         
          //USART1_RX	  PA.10
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
          GPIO_Init(GPIOA, &GPIO_InitStructure);  
      
         //Usart1 NVIC 配置
      
          NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
      	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
      	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
      	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
      	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
        
         //USART 初始化设置
      
      	USART_InitStructure.USART_BaudRate = bound;//一般设置为9600;
      	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
      	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
      	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
      	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
      	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
      
          USART_Init(USART1, &USART_InitStructure); //初始化串口
          USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断
          USART_Cmd(USART1, ENABLE);                    //使能串口 
      
      }
      
      void USART1_IRQHandler(void)                	//串口1中断服务程序
      	{
      	u8 Res;
      #ifdef OS_TICKS_PER_SEC	 	//如果时钟节拍数定义了,说明要使用ucosII了.
      	OSIntEnter();    
      #endif
      	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
      		{
      		Res =USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到的数据
      			
      			
      		//判断接收的数据				
      		WeChatCMD(USART_RX_BUF);
      		//判断接收到的数据END
      		
      		if((USART_RX_STA&0x8000)==0)//接收未完成
      			{
      			if(USART_RX_STA&0x4000)//接收到了0x0d
      				{
      				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
      				else USART_RX_STA|=0x8000;	//接收完成了 
      				}
      			else //还没收到0X0D
      				{	
      				if(Res==0x0d)USART_RX_STA|=0x4000;
      				else
      					{
      					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
      					USART_RX_STA++;
      					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
      					}		 
      				}
      			}   		 
           } 
      #ifdef OS_TICKS_PER_SEC	 	//如果时钟节拍数定义了,说明要使用ucosII了.
      	OSIntExit();  											 
      #endif
      } 
      #endif	
      
      

    2. 发送AT指令:编写代码以发送AT指令到ESP8266,控制其连接到Wi-Fi和阿里云IoT平台。      
      void Connect_Aliyun(void)
      {
      		printf("AT\r\n");
      		Delay_ms(2000);
      		printf("AT+RST\r\n");
      		Delay_ms(2000);
      		printf("AT+RESTORE\r\n");
      		Delay_ms(2000);
      		printf("AT+CWMODE=1\r\n");
      		Delay_ms(2000);
      		printf("AT+CIPSNTPCFG=1,8,\"ntp1.aliyun.com\"\r\n");
      		Delay_ms(2000);
      		printf("AT+CWJAP=\"NiuZi\",\"09202001\"\r\n");
      		Delay_ms(4000);
      		printf("AT+MQTTUSERCFG=0,1,\"NULL\",\"8266&k0ujzEBGvfR\",\"e81f0abf0c05a62ff1f586fab525dace2a89abf37f2e044c57e353cf82f15a36\",0,0,\"\"\r\n");
      		Delay_ms(4000);
      		printf("AT+MQTTCLIENTID=0,\"k0ujzEBGvfR.8266|securemode=2\\,signmethod=hmacsha256\\,timestamp=1709111842031|\"\r\n");
      		Delay_ms(2000);
      		printf("AT+MQTTCONN=0,\"iot-06z00j0k17u1su8.mqtt.iothub.aliyuncs.com\",1883,1\r\n");
      		Delay_ms(10000);
      		printf("AT+MQTTSUB=0,\"/k0ujzEBGvfR/8266/user/get\",1\r\n");
      		Delay_ms(2000);
      }

    3. 数据上传:根据业务需求,将STM32F103C8T6上采集的数据封装成MQTT消息,并通过UART发送到ESP8266,再由ESP8266上传到阿里云IoT平台。
    4. 接收指令:编写代码以接收来自阿里云IoT平台的MQTT消息,并根据消息内容执行相应的操作。
      uint8_t Rx_data = 0;
      	#define BUFFER_SIZE 256
      	#define END_CHAR '\n'
      	
      	uint8_t rx_buffer[BUFFER_SIZE];
      	uint8_t rx_index=0;
        uint8_t i=0;
      
      	void process_data(uint8_t *data,uint16_t length)
      {
      	if(strstr((char*)data,"\"LED\":1"))
      	{
      		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_RESET);
      	//printf("LED1 ON\r\n");
      		//printf("send \"on\" ok\r\n");
      		memset(rx_buffer,0,BUFFER_SIZE);
      		
      	}
      	else if(strstr((char*)data,"\"LED\":0"))
      	{
      		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_14,GPIO_PIN_SET);
      	//	printf("LED1 OFF\r\n");
      		//printf("send \"off\" ok\r\n");
      		memset(rx_buffer,0,BUFFER_SIZE);
      	}
      	if(strstr((char*)data,"\"LED\":2"))
      	{
      		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);
      		
      	//	__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,1500);
      		//printf("send \"on\" ok\r\n");
      		//printf("LED1 ON\r\n");
      		memset(rx_buffer,0,BUFFER_SIZE);
      		
      	}
      	else if(strstr((char*)data,"\"LED\":3"))
      	{
      		
      		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_SET);
      		
      	//	__HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,500);
      		//printf("send \"off\" ok\r\n");
      		memset(rx_buffer,0,BUFFER_SIZE);
      	}
      	
      	
      }
      
      void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
      {
      	if(huart->Instance == USART2)//仅处理中断1
      	{
      		if(rx_index < BUFFER_SIZE - 1)//缓冲区还有空间
      		{
      			if(rx_buffer[rx_index-1] != END_CHAR)//如果上一符号不是结束字符
      			{
      				rx_buffer[rx_index++]=(uint8_t)(huart->Instance->DR &0X00FF);
      				
      			}
      			if(rx_buffer[rx_index-1] == END_CHAR)//如果上一符号是结束字符
      			{
      				process_data(rx_buffer ,rx_index-1);
      				rx_index=0;
      				
      			}
      		}
      		else
      		{
      			rx_index = 0;
      			memset(rx_buffer,0,BUFFER_SIZE);
      		}
      		HAL_UART_Receive_IT(&huart2,&Rx_data,1);
      	}
      	
      	
      }

    6. 测试与调试

    1. 测试Wi-Fi连接:确保ESP8266能够成功连接到Wi-Fi网络。
    2. 测试MQTT连接:使用MQTT客户端工具(如MQTT.fx)测试ESP8266与阿里云IoT平台的MQTT连接是否正常。
    3. 测试数据上传与接收:在STM32F103C8T6上运行程序,测试数据的上传和接收功能是否正常。

    7. 注意事项

  • 确保STM32F103C8T6的UART波特率与ESP8266的波特率一致。
  • 在发送AT指令时,注意指令的格式和参数的正确性。
  • 在处理MQTT消息时,注意消息的解析和格式的正确性。
  • 在实际应用中,可以考虑使用中断或DMA方式来提高UART通信的效率。
  • 8. 总结

    通过本文的介绍,你应该已经了解了如何使用STM32F103C8T6和ESP8266 Wi-Fi模块连接到阿里云IoT平台,并实现数据的上传和接收。在实际项目中,你可以根据具体需求进行相应的修改和扩展。希望本文对你有所帮助!

    作者:胡剑烨

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32与阿里云连接实践指南

    发表回复