ESP8266與STM32串口資料互動(通過JSON)
- ESP8266部分
- JSON決議庫的安裝
- 串口接收的實作
- ArduinoJson庫實作資料決議
- ArduinoJson庫實作資料的打包發送
- STM32部分
- JSON決議庫的安裝
- 串口接收的實作
- JSON庫實作資料決議
- JSON資料的打包發送
- 程式分享
在這篇文章中我會通過介紹ESP8266和STM32兩部分的代碼來實作兩塊MCU串口資料的互動,互動的資料格式采用的是JSON格式,ESP8266的開發環境使用的是arduino,STM32使用的是KEIL5,
ESP8266部分
ESP8266我會從以下三部分介紹:①ArduinoJson決議庫的安裝②串口接收的實作③ArduinoJson庫實作資料決議④ArduinoJson庫實作資料的打包發送
JSON決議庫的安裝
本篇博客中使用的JSON庫為ArduinoJson,版本是V5版本,目前最新的是V6版本,大家可以選擇V6版本安裝,只需看下示例,修改下我分享的工程即可,

串口接收的實作
在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包,大家自動安裝即可,

串口接收的實作
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
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/247718.html
標籤:其他
上一篇:STM32學習筆記(三)
