amobbs.com 阿莫电子技术论坛

标题: 有没有谁在stm32上使用过cJSON库?? [打印本页]

作者: xuanwozhe    时间: 2015-4-29 11:15
标题: 有没有谁在stm32上使用过cJSON库??
最近用wifi转串口做网络通信的应用,接口是json格式的,也就是说,单片机要对接收到的json数据进行解析,同样也要将数据封装成json格式发送出去。
我现在用的是cJSON库,在VS环境上测试的时候,一点问题也没有。但同样的程序移植到stm32上时,总是发生各种莫名其妙的错误,稍不注意就会出来Hardfault,有时候是数据转换成字符串输出根本不对。
传输的字符串比较长的话,根本就解析不出来数据了。
我认为应该是stm32 64Kb的内存有点不够,因为看到有些同样用json接口的产品,它们用的是512KB的RAM。
而且,我现在做的东西有时候传输的数据量比较大,基本上有近1000个字节。

暂时想到两个解决方法,一个是使用外置的RAM,利用FSMC扩展1M的SRAM,但之前没这方面的经验,手上也没有带有相关功能的学习板,学习加制板测试会花费较长的时间,而且还不一定管用。
另一个就是自己写个简单的库完成json的解析和封装,好在暂时用不到json格式的嵌套,应该不会太难。但依旧担心内存不够的问题。

只剩下不到一个月的时间就得出成果了,所以想问下大家有没有做过类似工作的,能给指个明路??先谢谢了。
作者: a312835782    时间: 2015-4-29 11:37
我只有一些简单的包发,    直接就当字符串来处理,  把包头放好,数据填进去
作者: binaimei2007    时间: 2015-4-29 11:49
我在STM32上用过,只用他的解析功能,用在获取豆瓣电台歌曲的信息,没发现什么问题
作者: xuanwozhe    时间: 2015-4-29 12:35
binaimei2007 发表于 2015-4-29 11:49
我在STM32上用过,只用他的解析功能,用在获取豆瓣电台歌曲的信息,没发现什么问题 ...

数据量大吗??我刚写了一个简单程序测试了一下,只进行解析
while(1)
        {
                if(USART_RX_STA&0x8000)
                {

                        json = cJSON_Parse(USART_RX_BUF);
                        if(!json)
                                printf("Error before: [%s]\n", cJSON_GetErrorPtr());
                        else
                        {
                                data = cJSON_GetObjectItem(json, "data")->valuestring;
                                printf("%s\n", data);
                                free(data);
                        }
                       
                        cJSON_Delete(json);
                }       
        }
测试的json数据中只有data一个键值对,当data的字符串长度达到大概四五百时,就直接输出 Error before: [?]
作者: xuanwozhe    时间: 2015-4-29 13:01
binaimei2007 发表于 2015-4-29 11:49
我在STM32上用过,只用他的解析功能,用在获取豆瓣电台歌曲的信息,没发现什么问题 ...

你用的是哪个库??json网站http://www.json.org/ 下面C语言哪一个有好几个库,我之前用的其中的cJSON
作者: binaimei2007    时间: 2015-4-29 13:10
xuanwozhe 发表于 2015-4-29 13:01
你用的是哪个库??json网站http://www.json.org/ 下面C语言哪一个有好几个库,我之前用的其中的cJSON ...

[attach]268384[/attach]

上面就是我当时用的,我的数据量不大,没有什么好的经验可以分享
作者: xuanwozhe    时间: 2015-4-29 13:59
binaimei2007 发表于 2015-4-29 13:10
上面就是我当时用的,我的数据量不大,没有什么好的经验可以分享

我用的和这个一样。

我只添加了三个键值对
                cJSON_AddStringToObject(json, "data0", "fkdjajkjs");
                cJSON_AddStringToObject(json, "data1", "fkdzj5d48k");
                cJSON_AddNumberToObject(json, "data2", 12345);
这样还可以正常输出,只要我在data0或者data1的字符串内多加一个字符,立马就出问题了,只输出一个问号,多增加一个键值对也是一样的问题
这是那里出了问题,我看你发给我的程序, 可以添加很多个键值对的啊。
作者: xuanwozhe    时间: 2015-4-29 14:01
a312835782 发表于 2015-4-29 11:37
我只有一些简单的包发,    直接就当字符串来处理,  把包头放好,数据填进去 ...

主要是接口已经定好了,我这边改的话,上面也得改。

不过还是想参考一下,麻烦给个事例,谢谢
作者: 728196    时间: 2015-4-29 14:24
如果 协议不太复杂的话  自己解析吧  64KB 的ram 有点太少了!
作者: linjunxiong    时间: 2015-4-30 11:47
看下有没用,之前用过是可以使用的,
作者: chxaitz    时间: 2015-4-30 18:10
感觉移植完内存就差不多了,64K的内存确实太少了。
作者: sddp001    时间: 2015-4-30 18:20
单片机,通信数据又不大,用JASON自寻短见啊
作者: gwnpeter    时间: 2015-5-1 17:53
keil 5.14 有 json 的pack呀,没有用过,可以试试
作者: xuanwozhe    时间: 2015-5-4 09:47
gwnpeter 发表于 2015-5-1 17:53
keil 5.14 有 json 的pack呀,没有用过,可以试试

好吧 我的版本好像是4.7的  有空试试
作者: xuanwozhe    时间: 2015-5-4 09:48
sddp001 发表于 2015-4-30 18:20
单片机,通信数据又不大,用JASON自寻短见啊

通信量还是蛮大的  而且上面已经定好了要使用json
作者: xuanwozhe    时间: 2015-5-4 09:51
chxaitz 发表于 2015-4-30 18:10
感觉移植完内存就差不多了,64K的内存确实太少了。

感觉64K的内存还是蛮多的啊   使用默认的堆栈大小   的确会出现各种bug  我吧堆栈的大小改大了很多  暂时没出现比较严重的bug
作者: xuanwozhe    时间: 2015-5-4 09:51
linjunxiong 发表于 2015-4-30 11:47
看下有没用,之前用过是可以使用的,

我看一下  谢谢分享
作者: windancerhxw    时间: 2015-5-6 14:14
帮顶一下
作者: wt19891114    时间: 2015-5-6 14:23
帮顶了,希望楼主能解决。
作者: redroof    时间: 2015-5-6 14:53
如果电脑发来的格式是固定的,那就直接当字符串来自己处理吧,这样最简单。你不需要完整的解析所有JSON内容。
你发给电脑的东西永远可以是字符串,反正格式你自己一定知道。只需要sprintf搞定一切,不必用JSON库
作者: jzb8736    时间: 2015-5-6 14:55
M3与512K的RAM?                               我记得最大256呢  
作者: xuanwozhe    时间: 2015-5-6 15:47
wt19891114 发表于 2015-5-6 14:23
帮顶了,希望楼主能解决。

算是已经解决了把 ,我把堆栈空间扩大了很多,暂时没出什么严重的问题
作者: xuanwozhe    时间: 2015-5-6 15:49
jzb8736 发表于 2015-5-6 14:55
M3与512K的RAM?                               我记得最大256呢

Marvell的88mc200这款微控制器,介绍上是这么说的
The Marvell 88MC200 microcontroller enables high-performance computing for a variety of smart devices at a cost-efficient price. An integral component of Marvell’s Smart Energy Platform, the 88MC200 provides a 55nm process with CPU speeds of 200 MHz and 512kB SRAM, and offers a rich I/O capability with on chip DC/DC converter, which significantly lowers bill of materials (BOM) cost.
作者: jzb8736    时间: 2015-5-6 16:12
xuanwozhe 发表于 2015-5-6 15:49
Marvell的88mc200这款微控制器,介绍上是这么说的
The Marvell 88MC200 microcontroller enables high-pe ...

sorry
我以为是st公司的芯片              
作者: shaw.wang    时间: 2015-5-6 17:47
jzb8736 发表于 2015-5-6 16:12
sorry
我以为是st公司的芯片

88MC200 marvell用在自己的wifi模组上比较多
作者: 好运来了    时间: 2015-5-7 10:58
楼主现在有没有解决这个json问题
作者: 好运来了    时间: 2015-5-7 11:09
binaimei2007 发表于 2015-4-29 11:49
我在STM32上用过,只用他的解析功能,用在获取豆瓣电台歌曲的信息,没发现什么问题 ...

你好,请问当时,是如何接受json字符串的
作者: xuanwozhe    时间: 2015-5-7 11:09
好运来了 发表于 2015-5-7 10:58
楼主现在有没有解决这个json问题

我把堆栈空间变大之后就解决了,这几天测试暂时没发现什么问题。
在startup_stm32f10x_hd.s启动文件中,默认的堆栈大小是:
Stack_Size      EQU     0x00000400;  1kB
Heap_Size       EQU     0x00000200; 0.5kB
因为cJSON要用到很多的指针,意味着要malloc很多的内存空间,这些都是在堆上申请的,所有就直接把堆栈改大了很多
Stack_Size      EQU     0x00002000; 8kB
Heap_Size       EQU     0x00004000;16kB
之后就没出现什么严重的问题了
作者: 好运来了    时间: 2015-5-7 11:14
xuanwozhe 发表于 2015-5-7 11:09
我把堆栈空间变大之后就解决了,这几天测试暂时没发现什么问题。
在startup_stm32f10x_hd.s启动文件中, ...

你们是怎么接收的,可以发个历程给我吗,不知道为什么我的只有text[]里面的东西可以解析,串口接的不行
作者: xuanwozhe    时间: 2015-5-7 11:56
好运来了 发表于 2015-5-7 11:14
你们是怎么接收的,可以发个历程给我吗,不知道为什么我的只有text[]里面的东西可以解析,串口接的不行 ...

[attach]269545[/attach]
作者: 好运来了    时间: 2015-5-7 12:14
xuanwozhe 发表于 2015-5-7 11:56

                                         if((USART_RX_STA&0x8000)==0)//接收未完成
                           {
                        if(USART_RX_STA&0x4000)//接收到了0x0d
                                {
                                if(RxData!=0x0a)USART_RX_STA=0;//接收错误,重新开始
                                else USART_RX_STA|=0x8000;        //接收完成了
                                }
                        else //还没收到0X0D
                                {       
                                if(RxData==0x0d)USART_RX_STA|=0x4000;
                                else
                                        {
                                        USART_RX_BUF[USART_RX_STA&0X3FFF]=RxData ;
                                        USART_RX_STA++;
                                        if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收          
                                        }                 
                                }
                          }
这是我串口中断里面的东西,应该没有问题吧
作者: xuanwozhe    时间: 2015-5-7 12:45
好运来了 发表于 2015-5-7 12:14
if((USART_RX_STA&0x8000)==0)//接收未完成
                           {
                        if(USART_RX_STA&0x4000)//接收到了0x0d

我觉的没有问题,你现在是无法解析数据吗??
发送的数据要符合json的标准,像这样:
{
"api_id":102,
"message_id":555,
"command":"rm1_study",
"mac":"AC:CF:23:48:BC:C7"
}
作者: 好运来了    时间: 2015-5-7 13:01
xuanwozhe 发表于 2015-5-7 12:45
我觉的没有问题,你现在是无法解析数据吗??
发送的数据要符合json的标准,像这样:
{

对啊,可是就是没有反应,我发进去的json,重新把它打印出来,就是不行void json_test()
{       
        char *out;
        cJSON *json;
       
                        if(USART_RX_STA&0x8000)
                                {
                                   json = cJSON_Parse(USART_RX_BUF);
                                                                        if(!json)
                                                                                printf("Error before: [%s]\n", cJSON_GetErrorPtr());
                                                                                        else
                                                                                                {
                                                                                                        out=cJSON_Print(json);
                                        cJSON_Delete(json);
                              printf("%s\n",out);
                                myfree(out);//free(out)有问题
                                                                                                }
                                                                                                       
                                                                                cJSON_Delete(json);
                                        }  
               
}
作者: xuanwozhe    时间: 2015-5-7 13:52
好运来了 发表于 2015-5-7 13:01
对啊,可是就是没有反应,我发进去的json,重新把它打印出来,就是不行void json_test()
{       
        char *out;

我这样写的,测试了下,没有问题
int main()
{
        char *out = NULL;
    cJSON *json = NULL;

        init();//串口初始化

        while(1)
        {      
       if(USART_RX_STA&0x8000)
       {
                   json = cJSON_Parse(USART_RX_BUF);
                    if(!json)
                        printf("Error before: [%s]\n", cJSON_GetErrorPtr());
                       else
                          {
                               out=cJSON_Print(json);
                              printf("%s\n",out);
                        
                                                          free(out);//free(out)???
                                                          cJSON_Delete(json);
                        }
                                               
          USART_RX_STA = 0;                                                   
         }  
               
        }
}
作者: 好运来了    时间: 2015-5-7 14:01
xuanwozhe 发表于 2015-5-7 13:52
我这样写的,测试了下,没有问题
int main()
{

这个好像一样,多了一个标志位清零,对了,你串口是怎么配置的,我USART_RX_BUF里面有数,但是就是没有成功
作者: xuanwozhe    时间: 2015-5-7 16:48
好运来了 发表于 2015-5-7 14:01
这个好像一样,多了一个标志位清零,对了,你串口是怎么配置的,我USART_RX_BUF里面有数,但是就是没有成 ...

void usart1_config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
               
        /* onfig USART1 clock */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
               
        /* USART1 GPIO config */
        /* Configure USART1 Tx (PA.09) as alternate function push-pull */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
       
        /* Configure USART1 Rx (PA.10) as input floating */
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
                       
                /* USART1 mode config */
        USART_InitStructure.USART_BaudRate = 9600;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        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_ClearFlag(USART1, USART_IT_RXNE);
        USART_ClearFlag(USART1, USART_FLAG_TC);
        USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
        USART_Cmd(USART1, ENABLE);
       
}

void usart1_nvic_init(void)
{
        NVIC_InitTypeDef NVIC_InitStructure;
       
        NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
       
        NVIC_Init(&NVIC_InitStructure);
}

void usart1_init(void)
{
        usart1_config();
        usart1_nvic_init();
}
作者: 好运来了    时间: 2015-5-7 17:53
xuanwozhe 发表于 2015-5-7 16:48
void usart1_config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;

嗯,这个配置根你一样,对啦,你中断你们怎么接收数据??我好像发现我是中断里接收数据有问题。
作者: 好运来了    时间: 2015-5-7 17:55
xuanwozhe 发表于 2015-5-7 16:48
void usart1_config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;

我这么接收
if(USART_GetITStatus(USART1, USART_IT_RXNE )==SET)//接收中断
     {
             USART_ClearITPendingBit(USART1,USART_IT_RXNE);//清除中断标志
             RxData = USART_ReceiveData(USART1); //接收数据(USART1->DR);        //读取接收到的数据

                                         if((USART_RX_STA&0x8000)==0)//接收未完成
                           {
                             if(USART_RX_STA&0x4000)//接收到了0x0d
                                     {
                                    if(RxData!=0x0a)USART_RX_STA=0;//接收错误,重新开始
                                     else USART_RX_STA|=0x8000;        //接收完成了
                                      }
                           else //还没收到0X0D
                                  {       
                                   if(RxData==0x0d)USART_RX_STA|=0x4000;
                                     else
                                           {
                                             USART_RX_BUF[USART_RX_STA&0X3FFF]=RxData ;
                                             USART_RX_STA++;
                                            if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收          
                                           }                 
                                   }
                            }
     }
会有问题吗?
作者: xuanwozhe    时间: 2015-5-7 18:50
好运来了 发表于 2015-5-7 17:55
我这么接收
if(USART_GetITStatus(USART1, USART_IT_RXNE )==SET)//接收中断
     {

json数据是以大括号开始和结尾的  所以我就直接以大括号进行判断的
变量match可以不用管它
void USART1_IRQHandler(void)
{
        u8 res;
       
        if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)//end with '}'
        {
                res = USART_ReceiveData(USART1);
                if(res == '}')
                {
                        USART_RX_BUF[USART_RX_STA++] = res;
                        match--;   
                        if(match == 0)
                                USART_RX_STA |= 0x8000;
                }
                else
                {
                        USART_RX_BUF[USART_RX_STA++] = res;
                        if(res == '{')  
                                match++;
                }
                       
        }
}
作者: outt60777    时间: 2015-5-7 19:00
这么多人用,我还以为就我呢
作者: 好运来了    时间: 2015-5-7 19:22
outt60777 发表于 2015-5-7 19:00
这么多人用,我还以为就我呢

呵呵,我也是刚刚才使用的。
作者: 好运来了    时间: 2015-5-7 19:26
xuanwozhe 发表于 2015-5-7 18:50
json数据是以大括号开始和结尾的  所以我就直接以大括号进行判断的
变量match可以不用管它
void USART1_I ...

哦,看来是接收数据时的方式不同。
作者: 好运来了    时间: 2015-5-7 19:31
xuanwozhe 发表于 2015-5-7 18:50
json数据是以大括号开始和结尾的  所以我就直接以大括号进行判断的
变量match可以不用管它
void USART1_I ...

这样使用不就只能使用于只有一对大括号的json了吗???
作者: xuanwozhe    时间: 2015-5-7 20:04
好运来了 发表于 2015-5-7 19:31
这样使用不就只能使用于只有一对大括号的json了吗???

加match就是为了简单实现大括号的匹配啊
作者: xuanwozhe    时间: 2015-5-7 20:05
outt60777 发表于 2015-5-7 19:00
这么多人用,我还以为就我呢

那你有没有用过与数据压缩相关的库啊,我找了好久没找到比较简单的
作者: outt60777    时间: 2015-5-7 21:09
xuanwozhe 发表于 2015-5-7 20:05
那你有没有用过与数据压缩相关的库啊,我找了好久没找到比较简单的

miniz  

miniz.c is a lossless, high performance data compression library in a single source file that implements the zlib (RFC 1950) and Deflate (RFC 1951) compressed data format specification standards. It supports the most commonly used functions exported by the zlib library, but is a completely independent implementation so zlib's licensing requirements do not apply. miniz.c also contains simple to use functions for writing .PNG format image files and reading/writing/appending .ZIP format archives. miniz's compression speed has been tuned to be comparable to zlib's, and it also has a specialized real-time compressor function designed to compare well against fastlz/minilzo.

Here's a blog update on miniz bug fixes/enhancements, and the current status of zip64 support. The source to the zip64 variant of miniz was released as part of Valve's vogl codebase: http://richg42.blogspot.com/2014 ... brary-released.html

Whenever I get the chance I'll be extracting it and releasing it separately.


https://code.google.com/p/miniz/
作者: 好运来了    时间: 2015-5-8 19:19
xuanwozhe 发表于 2015-5-7 20:04
加match就是为了简单实现大括号的匹配啊

这样,好像只能搞小数据,大的,多重对象的,就比较复杂,貌似实现不了。
作者: xuanwozhe    时间: 2015-5-8 20:05
好运来了 发表于 2015-5-8 19:19
这样,好像只能搞小数据,大的,多重对象的,就比较复杂,貌似实现不了。 ...

暂时没有多重数据,所以就这样简单写了
作者: xuanwozhe    时间: 2015-5-9 11:32
outt60777 发表于 2015-5-7 21:09
miniz  

miniz.c is a lossless, high performance data compression library in a single source file  ...

我试了下,这个是不是只能对字符串进行压缩啊。我想直接对十六进制的数组进行压缩,像这样的数据
u8 buf[]={0x77,0x66,x0x56,0x00, 0x0a, 0x3a....} 其中每个数都小于127
压缩完之后我还要把它变成字符串之后,放进json中传出去

作者: styleno1    时间: 2015-5-9 14:11
cJSON的Footprint是多少?Keil里的叫Jansson
作者: styleno1    时间: 2015-5-9 17:39
楼主使用她来做什么呢,我比较好奇在单片机它能用来做什么?
作者: xuanwozhe    时间: 2015-5-9 18:02
styleno1 发表于 2015-5-9 17:39
楼主使用她来做什么呢,我比较好奇在单片机它能用来做什么?

网络通信啊,主要是为了单片机端和服务器端解析更加方便
作者: 好运来了    时间: 2015-5-10 11:29
xuanwozhe 发表于 2015-5-8 20:05
暂时没有多重数据,所以就这样简单写了

好吧,看来只能暂时不使用多重数据了。
作者: outt60777    时间: 2015-5-12 21:28
xuanwozhe 发表于 2015-5-9 11:32
我试了下,这个是不是只能对字符串进行压缩啊。我想直接对十六进制的数组进行压缩,像这样的数据
u8 buf[ ...

16进制变字符串,只是数据量增大1/3。 base64
作者: zhiyuanzhitian    时间: 2016-11-15 18:09
刚好需要。。。看看
作者: lwj199302    时间: 2016-11-27 21:13
我也遇到过类似的问题,还没找出问题
作者: liujingwei    时间: 2016-11-28 09:44
cJSON要从堆里分配内存,堆设置小了肯定容易Hardwarefault了
作者: mpuhome    时间: 2016-11-28 09:50
学习了,最近刚好需要用这个,收藏




欢迎光临 amobbs.com 阿莫电子技术论坛 (https://www.amobbs.com/) Powered by Discuz! X3.4