概述
文章目录
- 1- JSON介绍
- 2- 配置添加代码
- (1)配置
- (2)usart.c(串口初始化保存获取数据)
- (2)gpio.c(建立映射关系)
- (3)main.c(串口接收数据并解析)
- 3- 调试结果
- 4- 涉及到的函数理解及分析
- (1)HAL_UART_Transmit()
- (2)HAL_UART_Receive_IT()
- (3)JSON_Validate()
- (4)JSON_Search()
- (5)strncasecmp()
1- JSON介绍
JSON(JavaScript Object Notation),即 JS对象简谱,是一种轻量级的数据格式。
它采用完全独立于编程语言的文本格式来存储和表示数据,语法简洁、层次结构清晰,易于人阅读和编写,同时也易于机器解析和生成,有效的提升了网络传输效率。
JSON 可以将 JavaScript 对象中表示的一组数据转换为字符串,然后就可以在网络或者程序之间轻松地传递这个字符串,并在需要的时候将它还原为各编程语言所支持的数据格式。
JSON是一种语法,用来序列化对象、数组、数值、字符串、布尔值和NULL值。JSON数据的本质就是一段字符串而已,只不过有不同意义的分隔符将其分割开来而已。
我们看上面的符号,里面有[],{}等符号,其中:
- ()表示一个对象,它是一个无序的键值对(属性值)集合,里面的不同键值对用逗号隔开
- 冒号:表示一个键值对(key:value),冒号前面是属性的名称(key),后面是属性的值(value)。值可以是双引号括起来的字符串(string)、数值(number)、true,false, null、对象(object)或者数组(array),这些结构可以嵌套。
- []表示的是一个数组,它是值的有序集合,值之间使用逗号分隔。
我们使用串口接收PC端下发的JSON格式的LED控制指令报文,解析并实现LED灯的控制:
JSON格式控制数据报文定义:
{“RedLed”:“on”,“GreenLed”:“on”,“BlueLed”:“on”}
{“RedLed”:“off”,“GreenLed”:“off”,“BlueLed”:“off”}
JSON作为广泛使用的数据通信格式吗,每种编程语言都会有很多解析库,而C语言中经常用到的JSON解析库有cJSON,但因为嵌入式单片机中的Flash、RAM有限,这里我们就使用单片机中常用的免费开源操作系统FreeRTOS里自带的coreJSON库:
json文件链接:coreJSON库
提取码:5253
2- 配置添加代码
(1)配置
配置使能串口USART1的中断,使用中断来接收串口上收到的数据。
(2)usart.c(串口初始化保存获取数据)
/* USER CODE BEGIN 0 */
static uint8_t s_uart1_rxch;//获取到的一个字节的数据保存在这里,相当于中转站
char g_uart1_rxbuf[256];//将s_uart1_rxch获取到的每个字节保存在g_uart1_rxbuf中
uint8_t g_uart1_bytes;//一次累加,最大256
/* USER CODE END 0 */
/*MX_USART1_UART_Init()串口初始化函数中添加HAL_UART_Receive_IT()函数*/
/*使能usart1的中断接收,中断接收到的每个字节的数据保存在s_uart1_rxch中*/
void MX_USART1_UART_Init(void)
{
HAL_UART_Receive_IT(&huart1, &s_uart1_rxch, 1);
}
/* USER CODE BEGIN 1 */
/*printf()函数的定义,可以不用管*/
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)/*char类型是以int类型存储的,所以可以用int*/
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/*在这里添加串口中断接收的回调函数,还要g_uart1_rxbuf没有满,就将中断接收到的1字节数据s_uart1_rxch存储到g_uart1_rxbuf中,并将g_uart1_bytes 自加。*/
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart -> Instance == USART1 )
{
if( g_uart1_bytes < sizeof(g_uart1_rxbuf) )
{
g_uart1_rxbuf[g_uart1_bytes++] = s_uart1_rxch;
}
HAL_UART_Receive_IT(&huart1, &s_uart1_rxch, 1);
}
}
/* USER CODE END 1 */
usart.h
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <string.h>
/* USER CODE END Includes */
/* USER CODE BEGIN Private defines */
/*在这里添加uart1接收buffer 相关变量声明,并添加一个宏clear_uart1_rxbuf()用来清除接收buffer里的数据*/
extern char g_uart1_rxbuf[256];
extern uint8_t g_uart1_bytes;
#define clear_uart1_rxbuf() do { memset(g_uart1_rxbuf, 0, sizeof(g_uart1_rxbuf) ); g_uart1_bytes = 0;}while(0)
/* USER CODE END Private defines */
(2)gpio.c(建立映射关系)
/* USER CODE BEGIN 2 */
gpio_t leds[LedMax] =
{
{"SysLed", SysLed_GPIO_Port, SysLed_Pin},
{"BlueLed", BlueLed_GPIO_Port, BlueLed_Pin},
{"RedLed", RedLed_GPIO_Port, RedLed_Pin},
{"GreenLed", GreenLed_GPIO_Port, GreenLed_Pin},
};
void turn_led(int which, int status)
{
GPIO_PinState level;
if( which<0 || which>=LedMax)
{
return ;
}
level = status == OFF ? GPIO_PIN_SET : GPIO_PIN_RESET;
HAL_GPIO_WritePin(leds[which].group, leds[which].pin, level);
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (Key1_Pin == GPIO_Pin)
{
blink_led(BlueLed, 500);
}
else if(Key2_Pin == GPIO_Pin)
{
blink_led(RedLed, 500);
}
}
/* USER CODE END 2 */
gpio.h
/* USER CODE BEGIN Prototypes */
enum
{
SysLed,
BlueLed,
RedLed,
GreenLed,
LedMax,
};
#define OFF 0
#define ON 1
/*将gpio.c中定义的gpio_t结构体定义移到头文件中来,并在它里面添加一个char *name的字段,其它C文件会用到这个结构体。*/
typedef struct gpio_s
{
const char *name;
GPIO_TypeDef *group;
uint16_t pin;
} gpio_t;
extern gpio_t leds[LedMax];
extern void turn_led(int which, int status);
extern void blink_led(int which, uint32_t interval);
void sysled_hearbeat(void);
/* USER CODE END Prototypes */
(3)main.c(串口接收数据并解析)
需要包含core_json.h这个头文件,.h和.c文件网盘有,下载之后在相关路径放进去然后刷新,会看见加载到STM32IDE中了。
/* USER CODE BEGIN Includes */
#include "core_json.h"
/* USER CODE END Includes */
/* USER CODE BEGIN 0 */
static int parser_led_json(char *json_string, int bytes);
static void proc_uart1_recv(void);
/* USER CODE END 0 */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
proc_uart1_recv();
}
/* USER CODE BEGIN 4 */
int parser_led_json(char *json_string, int bytes)
{
JSONStatus_t result;
char save;
char *value;
size_t valen;
int i;
printf("BDUG: Start parser JSON string:%srn", json_string);
result = JSON_Validate(json_string, bytes);
if(JSONPartial == result)
{
printf("WARN: JSON document is valid so far but incomplete!rn");
return 0;
}
if(JSONSuccess != result )
{
printf("ERROR: JSON doument is not valid JSON!rn");
return -1;
}
for(i=0; i<LedMax; i++)
{
result = JSON_Search( json_string, bytes, leds[i].name, strlen(leds[i].name), &value, &valen);
if(JSONSuccess == result)
{
save = value[valen];
value[valen] = '