ESP8266與STM32串口數據交互


在這篇文章中我會通過介紹ESP8266和STM32兩部分的代碼來實現兩塊MCU串口數據的交互,交互的數據格式採用的是JSON格式,ESP8266的開發環境使用的是arduino,STM32使用的是KEIL5。


ESP8266部分

ESP8266我會從以下三部分介紹:①ArduinoJson解析庫的安裝②串口接收的實現③ArduinoJson庫實現數據解析④ArduinoJson庫實現數據的打包發送

JSON解析庫的安裝

本篇博客中使用的JSON庫爲ArduinoJson,版本是V5版本,目前最新的是V6版本,大家可以選擇V6版本安裝,只需看下示例,修改下我分享的工程即可。
安裝ArduinoJson

串口接收的實現

在ESP8266程序中需要將usartEvent();函數放到loop()函數中。

/*串口數據接收*/
void usartEvent(){
   
     
  comdata = "";
  while (Serial.available())//時刻讀取硬件串口數據
  {
   
     
    comdata = Serial.readStringUntil('\n');//從串口緩存區讀取字符到一個字符串型變量,直至讀完或遇到某終止字符。
    UserData(comdata);//進行JOSN數據解析
  }
  while (Serial.read() >= 0){
   
     }//清除串口緩存
}

ArduinoJson庫實現數據解析

/*數據解析{status:true}*/ 
void UserData(String content){
   
     
  StaticJsonDocument<200> doc;//申請JSON解析空間
  DeserializationError error = deserializeJson(doc,content);
  if (error) {
   
     //解析錯誤
    Serial.print(F("deserializeJson() failed: "));
    return;
  }
  status=  doc["status"];
}

ArduinoJson庫實現數據的打包發送

參照ArduinoJson庫的JsonGeneratorExample工程即可得到以下代碼,當然也可採用serial.println()函數進行格式化輸出。

  StaticJsonDocument<200> doc;
  doc["sensor"] = "gps";
  doc["time"] = 1351824120;
  serializeJsonPretty(doc, Serial);

STM32部分

STM32同ESP8266一樣,我會從以下四部分介紹:①JSON解析庫的安裝②串口接收的實現③JSON庫實現數據解析④JSON數據的打包發送

JSON解析庫的安裝

STM32上我採用的JSON解析庫是Jansson,我會給大家提供這個庫的pack包,大家自動安裝即可。
JSON解析庫的安裝

串口接收的實現

STM32的串口中斷我才用的是串口空閒中斷,空閒中斷是接受數據後出現一個byte的高電平(空閒)狀態,就會觸發空閒中斷。
代碼實現如下:
需要定義的全局變量:u8 buf1_size = 0;//串口數據接收數量標記 bool data_change = 0;//串口接收完成/變化標誌位

void USART1_printf (char *fmt, ...){
   
       
	char buffer[USART1_REC_LEN+1];  // 數據長度
	u8 i = 0;	
	va_list arg_ptr;
	va_start(arg_ptr, fmt);  
	vsnprintf(buffer, USART1_REC_LEN+1, fmt, arg_ptr);
	while ((i < USART1_REC_LEN) && (i < strlen(buffer))){
   
      
        USART_SendData(USART1, (u8) buffer[i++]);
        while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET); 
	}
	va_end(arg_ptr);
}

void USART1_Init(u32 bound){
   
       //串口1初始化
    //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);//開啓ENABLE/關閉DISABLE串口接收中斷
	USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//開啓串口空閒中斷
	USART_Cmd(USART1, ENABLE);                    //使能串口 
}

void USART1_IRQHandler(void){
   
       //串口1中斷服務程序(固定的函數名不能修改)	
	u8 clear = clear;
	USART_ClearFlag(USART1,USART_FLAG_TC);
 
	if(USART_GetITStatus(USART1,USART_IT_RXNE)!=Bit_RESET)//串口中斷髮生        
	{
   
      
		if(data_change == 0)//重新接收
		{
   
      
			memset(USART1_RX_BUF,0,sizeof(USART1_RX_BUF));//清空整個接收數組
			data_change = 1;//標誌位拉高
		}
		USART1_RX_BUF[buf1_size++]=USART1->DR;
	}
		 
	else if(USART_GetFlagStatus(USART1,USART_FLAG_IDLE)!=Bit_RESET)//空閒中斷髮生
	{
   
      			
		buf1_size = 0;
		data_change = 0;//標誌位拉低,下次數據改變進入
		data_sys = 1;//允許解析
		
		clear = USART1->SR;//空閒中斷要讀這兩個寄存器
		clear = USART1->DR;
		USART_ClearITPendingBit(USART1,USART_IT_IDLE);//清除空閒中斷標誌位	
	}
} 

JSON庫實現數據解析

JSON庫解析需要調用頭文件#include <jansson.h>,bool類型變量使用需要#include "stdbool.h"頭文件。
並且非常重要的是,在對大量數據進行解析的時候,需要將startup_stm32f10x_md.s33的Stack_Size EQU 0x00000200修改爲Stack_Size EQU 0x00000C00,這一步驟是將STM32的堆棧增加,防止在解析的時候出現堆棧不夠用的情況。

#include <jansson.h>
bool led_status;
//開關燈JSON函數{"status":true}
//存在問題!!使用本函數解析後串口printf無法使用,建議使用USART1_printf函數實現發送
/** 
* @brief  Json解析函數
* @param none
* @return 
* - 0 轉換成功
* - 1 轉換失敗
* @details   
*/ 
uint8_t Jansson_Analysis(char *text)
{
   
      
	json_error_t error;
	json_t *root;
	
	root = json_loads((const char*)text, 0, &error); 
	if(json_is_object(root))
	{
   
      
		status = json_object_get(root, "status");
		if(json_is_true(status))
			led_status = 1;
		else if(json_is_false(status))
			led_status = 0;
	}
	else
	{
   
      
		USART1_printf("root format error:%d-%s\r\n", error.line, error.text);
		return 1;
	}
	json_decref(root);//釋放JSON空間
	return 0;
}
/*
// string 類型的解析
name = (char *)json_string_value(json_object_get(root, "name"));
// int 類型的解析
age = json_integer_value(json_object_get(root, "age"));
// double 類型的解析
score = json_real_value(json_object_get(root, "score"));
// bool 類型的解析
status = json_object_get(root, "status");
if(json_is_true(status))
else if(json_is_false(status))
*/

JSON數據的打包發送

Jansson包提供了一個json數據打包的函數,但此函數在打包過程中會佔用極大的片內空間,因此在這裏僅介紹給大家,不推薦大家使用,推薦大家使用的方法還是使用printf函數進行格式化輸出。

/** 
* @brief  將數據打包爲Json格式
* @param [in] status 
* @return none
* @details   
*/ 
void jansson_pack(bool state)
{
   
      
	json_t *root;
	char *out;
	/* Build the JSON object */
	root = json_pack("{sb}","status",status);
	out = json_dumps(root, JSON_ENCODE_ANY);
	printf("%s",out);
	json_decref(root);//釋放JSON空間
	free(out);//釋放JSON空間
}
/*
s 代表string類型
b 代表bool類型
d 代表int類型
f 代表float、double類型
*/

使用printf格式化輸出只需要:

printf("{\"status\":%d}",status);

需要注意的是在使用格式化輸出函數輸出JSON數據時需要自己進行JSON格式的校驗和轉義。
推薦大家使用JSON在線視圖查看器.進行格式查驗和轉義。


程序分享

ESP8266
STM32


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