完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
电子发烧友论坛|
嗨,我想听一些经验丰富的程序员如何不用循环缓冲区解析长字符串(比如4kB+)的建议。我使用的是PIC18F47J53,我不能在main中使用循环缓冲区和解析,因为我的主循环可能长达350ms,这对于UART来说115200波特,对于任何缓冲区来说都太长了。状态机,根据刚刚收到的字符和状态从一个状态跳到另一个状态,像这样:但是很难添加对原始长字符串的新解析。那么有没有办法可以像我一样不用手动解析多个部分(温度、压力、湿度…)?也许把有趣的部分存储为const char[]并且只是递增位置,并将const char[pos]与刚收到的char进行比较,并在单个情况下解析数字?谢谢你
|
|
相关推荐
15个回答
|
|
|
取决于您想要提取多少主题以及存在多少部分歧义。至于歧义:“temp_c”和“temp_f”更难,“.*”。如果资源有限,没有歧义,我将做什么——非常粗略的概念:关于设置:1。列出“有趣”主题的关键词列表。在这个上下文中,没有歧义的是,这些关键字在第一个字符中是不同的。2。你可以考虑分组模糊关键字——尽快决定单个关键字。关于解析:1。从“重置”开始。2。决定接收哪个关键字/组的第一个字符。3。丢弃第一个错配与选择的关键字/组。否则检查匹配,直到变量部分(值)开始。4。解析变量部分并通过接收的字符转换字符。5。不要忘记只在诸如n、r或类似的终止符号的情况下才重置。整个过程必须由状态机的层次结构控制(除了顶部的SM,至少部分是“可重用的”)。我忘了:这可以在ISR中实现。除了最终的第一个字符(找到匹配的键盘或组)和“group/keyword分支”之外,每次只有一个字符串与-1字符进行比较。容易实现。
|
|
|
|
|
|
我会使用状态机,但不是每个字符!我将做如下操作:-I.E.将标识符字符串读入缓冲比较器中,以列出想要的标识符,这些标识符跳到行尾或读取值并分配给先前标识的变量。您只需要一个临时缓冲区,大小为标识符或值的最大长度。在一些状态下,有些检查,比如eol和缓冲区溢出,但是您应该了解一般概念。对于许多比较,您可以使用循环和标识符字符串数组。可能还有其他方法,例如二叉树,但是上述方法简单易懂,并且应该很快。除非标识符列表很长,并且由具有与名称相同的长初始部分的标识符组成。
|
|
|
|
|
|
谢谢你的想法,但我不知道你如何决定选择哪个词。如果我把所有可能的选项都作为二维数组,那么我需要为每行设置bool变量,它告诉我这个单词是否有效,是否应该进行比较。你能写一些你的想法的假例子吗?simong123:如果要解析多于1个部分,这是不可能的,因为如果保存以缓冲temp_c,并且主代码可以处理它之前,其他部分(._kph)会到达,这将覆盖您的第一次搜索。在ISR中调用STRNCMP和ATOI不是一个好主意,但是二叉树可以是很好的起点。
|
|
|
|
|
|
它需要相当多的程序内存,但是您的基于字符的状态机正是您想要做的。编写和维护都很困难。在这种情况下,我通常编写一个简单的程序,它运行在PC机上,并生成C代码的文本,然后在需要时将其包含在主程序中。
|
|
|
|
|
|
假设一个48 MHz的时钟(你没有说BTW),那就给你1000个+。您可以编写自己的strncmp&atoi版本用于内联(PIC18在函数调用中没有很多状态可以保存),它们可以非常简单。
|
|
|
|
|
|
http://zserge.com/jsmn.htmlThis声称是一个增量的、轻量级的JSON解析器,它可以完成您想要的操作,而不需要重新设计轮子。
|
|
|
|
|
|
诺斯盖伊:ROM没问题,我现在有一半PIC内存(64kB)空闲,但是只剩下600BRAM。也许是坏问题,但是你的软件不可用?我不认为我能自己写这样的短句。至少不是没有重复的箱子。也许我会继续使用我手工制作的状态机。微笑:Simong123:假设你是对的,PIC在48MHz下运行。别误会我的意思,但是我仍然认为你的建议有重大问题,因为它会尝试比较用引号分隔的每个字符串。这不是单次比较的问题,而是对部分匹配的项进行十倍的比较……jtemples:也许我看不到,但是JSMN需要整个JSON字符串才能从中获得特定的项。我没有。
|
|
|
|
|
|
对于这种特殊的情况,我没有,但我经常遇到生成代码比手动编写代码更容易的情况。这真的很容易。只需使用printf()输出C代码,然后将输出捕获到文件中。当然,您需要花费一些时间来编写程序,但是与花费时间复制和粘贴相比,它的工作量要小得多,并且不容易出错。
|
|
|
|
|
|
附件是一些我以前尝试过的修改版本。我用McC18和它在一个PICDEM FS USB上编译它。数据是通过粘贴您的示例发送到TeraTerm,115200 8N-1.由于某种原因,它不喜欢主FSM的切换(状态),所以我必须实现它,好像……如果,我不能找到原因!-(测试从测试数据中提取16个值)。注意,对于一些值(例如纬度),它读取数据多次和覆盖,因为我不费力去分析Curle括号。字符串比较已经被推广到一个数组中,它还保存了数据类型和读取数据的方法(没有引号的整数或带有引用的一般数据)。主要接收函数FSM在函数PARSEDATA()中,由高优先级中断例程调用。这样做所有的标识符匹配,然后将值数据接收到第二个RX缓冲区。当值数据已经被接收时,它会启动一个低优先级中断(我使用了It2,但是任何未使用的外围中断(除了It0!)可以调用ParseVal()来解析实际值数据。这允许主fsm立即重置&开始接收下一个标识符,并且您不必在覆盖数据之前依赖main()来解析数据,因此主中的任何其他任务可能需要花多长时间!编辑:顺便说一下,如果解析花括号,则可以分割字符串搜索以减少每个单独搜索的深度。E 4列表等)根据结果列表进行搜索。
|
|
|
|
|
|
奇怪的是关于开关(状态)……你得到了什么错误?
|
|
|
|
|
|
没有错误,它只是没有输入任何情况下的语句,只是跳过去。我确认了状态为枚举保存了正确的值(STATE_START==0),但是它仍然直接跳过<:-(其他开关语句工作正常吗?)??????也许与EnUM有关?非常奇特。以前从没见过这样的事!
|
|
|
|
|
|
我懂了。。。好笑!也许是关于EnUM的一些东西,肯定是被它的形状或大小弄糊涂了。?
|
|
|
|
|
|
simong123:哇,谢谢你给我举的这个超级例子。虽然我的解决方案只使用一个优先级中断,但我可能会重写它并使用你的解决方案。但是我在这里看到一个负值,因为下一个引用的数据可以在你处理旧的之前到达。因此,在解析旧数据或在解析第一个数据时创建第二个缓冲区时,必须先进行不可接受的接收。
|
|
|
|
|
|
在这种情况下,如果您真的认为处理一个字符串可能比处理另一个字符串的时间更长,那么我将使用两个缓冲区。
|
|
|
|
|
|
我实际上是这样做的,因为ATOFF()太长了,导致了超支。记住,直到接收到下一个标识符之后,它才处理该值,从您给出的示例中,该值是>=8个字符(包括引号,因为大多数行都缩进得不止这些),这对于atoi()、atof()或字符串副本来说已经足够了。进行标识符字符串比较的低优先级中断,但是认为它将不必要地因为很少的增益而使其复杂化(在值解析阶段必须对引用的和未引用的值进行选择)。
|
|
|
|
|
只有小组成员才能发言,加入小组>>
MPLAB X IDE V6.25版本怎么对bootloader和应用程序进行烧录
473 浏览 0 评论
5793 浏览 9 评论
2334 浏览 8 评论
2224 浏览 10 评论
请问是否能把一个ADC值转换成两个字节用来设置PWM占空比?
3530 浏览 3 评论
1124浏览 1评论
有偿咨询,关于MPLAB X IPE烧录PIC32MX所遇到的问题
1097浏览 1评论
我是Microchip 的代理商,有PIC16F1829T-I/SS 技术问题可以咨询我,微信:A-chip-Ti
873浏览 1评论
MPLAB X IDE V6.25版本怎么对bootloader和应用程序进行烧录
475浏览 0评论
/9
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-12-2 07:44 , Processed in 1.568332 second(s), Total 70, Slave 63 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191

淘帖
1316