Pav*_*Pav 4 c microcontroller interpreter command serial-port
我想解释一个命令字符串,由微控制器收到(PIC16f877A,如果这有什么不同)通过串口.
字符串有一个非常简单和直接的格式:$ AABBCCDDEE(2个字符的5个"块"+总共11个字符的'$')其中:$ AA =命令的实际名称(可以是字母,数字,两者;强制性的); BB-EE =参数(数字;可选);
我想用C/C++编写代码.
我想我可以通过串口抓取字符串,将其破解为块,切换(){case}和memcmp命令块($ AA).然后我可以使用二进制决策树来使用BB CC DD和EE块.
我想知道这是否是正确的做法(这对我来说有点难看,肯定必须有一个不那么乏味的方法来做到这一点!).
不要过度设计它!这并不意味着盲目编码,但是一旦你设计了一些看似可以完成工作的东西,你就可以开始实现它了.实施将为您提供有关您的架构的反馈.
例如,在编写switch case时,您可能会发现自己重写的代码与您刚才为前一种情况编写的代码非常相似.实际上写下一个算法会帮助你看到你没想到的一些问题,或者你没有看到的一些简化.
第一次尝试时不要瞄准最好的代码.瞄准
采取小步骤.你不必一次完成整个事情.
一旦你做得对,你就可以开始考虑更好的解决方案了.
ASCII 接口从定义上来说是丑陋的。理想情况下,你有某种框架结构,也许你有,$表示框架之间的划分,你说它们的长度是11个字符。如果总是 11 那很好,如果只是有时更难的话,希望开头有一个 $ ,结尾有 0x0A 和/或 0x0D/0x0A (CR/LF)。通常,我有一个代码模块,它只是从串行端口提取字节并将它们放入(循环)缓冲区中。缓冲可以追溯到串行端口板上几乎没有缓冲的时代,但即使在今天,尤其是微控制器,情况仍然如此。然后是另一个代码模块,用于监视缓冲区搜索帧。理想情况下,该缓冲区足够大,可以将帧留在那里并为下一帧留出空间,并且不需要另一个缓冲区来保存接收到的帧的副本。使用循环缓冲区,第二个模块可以将头指针移动(必要时丢弃)到帧标记的开头,并等待完整帧的数据。一旦出现完整的帧,它就会调用另一个处理该帧的函数。该功能可能就是您要问的功能。“只需编写代码”可能就是答案,您处于微控制器中,因此您无法在操作系统解决方案上使用惰性高级桌面应用程序。如果您自己创建或通过库可用,或者不取决于您的解决方案,您将需要某种 strcmp 函数。暴力 if(strncmp(&frame[1],"bob",3)==0) then, else if(strncmp(&frame[1],"ted",3) then, else if... 当然可以,但是你可能会用这种东西来消耗你的rom,也可能不会。这种方法所需的缓冲会消耗大量的ram。这种方法非常具有可读性和可维护性,但也可移植。可能不会很快(可维护)通常与可靠性和/或性能相冲突),但这可能不是一个问题,只要您可以在下一个出现之前处理这个数据,或者在未处理的数据掉出循环缓冲区之前。帧检查器例程可以简单地检查帧是否良好,我通常放置开始和结束标记、长度和某种算术校验和,如果它是坏帧,则将其丢弃,这节省了大量检查坏/损坏的代码当帧处理例程返回到搜索帧例程时,它会移动头指针以清除不再需要的帧,无论是好帧还是坏帧。帧检查器可能仅验证帧并将其交给另一个进行解析的函数。这种布置中的每个乐高积木都有一个非常简单的任务,并且假设其下方的乐高积木已正确执行其任务。模块化、面向对象,无论您想使用什么术语,都可以使设计、编码、维护、调试变得更加容易。(以性能和资源为代价)。
如果您的微控制器没有足够的资源,那么状态机方法也可以很好地工作。到达的每个字节都会使状态机进入一种状态。从idle开始等待第一个字节,第一个字节是$吗?不要丢弃它并返回空闲状态。如果第一个字节是 $ 则转到下一个状态。如果您正在寻找命令“and”、“add”、“or”和“xor”,那么第二个状态将与“a”、“o”和“x”进行比较,如果这些都不是进入空闲状态。如果是 a,则进入比较 n 和 d 的状态,如果是 o,则进入寻找 r 的状态。如果在或状态中查找 r 没有看到 r,则进入空闲状态,如果看到则处理命令,然后进入空闲状态。该代码是可读的,因为您可以查看状态机并看到单词 a,n,d, a,d,d, o,r, x,o,r 以及它们最终导致的位置,但通常不被视为可读代码。这种方法使用很少的 ram,更多地依赖 rom,但与其他解析方法相比,总体上可以使用最少的 rom。这里又是非常可移植的,超越了微控制器,但在微控制器之外,人们可能会认为你对这种代码很疯狂(当然,如果这是 verilog 或 vhdl,则不会)。这种方法更难维护、更难阅读,但非常快速、可靠,并且使用的资源最少。
无论命令被解释后采用什么方法,您都必须确保可以通过代码的确定性性能或中断或其他方式执行命令而不会丢失串行端口上的任何字节。
底线 ascii 接口总是丑陋的,它们的代码,无论您使用多少层库来使工作变得更容易,执行的结果指令都是丑陋的。从定义上来说,一种尺寸并不适合任何人。只需开始编码,尝试状态机并尝试 if-then-else-strncmp 以及其间的优化。您应该很快就能看出哪一个在您的编码风格、工具/处理器以及要解决的问题方面表现最好。