Oliver 发表于 2008-5-8 20:35:09

请教大侠,单片机解复杂的通讯协议(UART)用什么写法比较好,直观,高效?

比如接收命令有100条,对应不同的处理.命令格式相同,但长度不一样,内容也是多变.要是用100个if或者switch的话估计头都大了.

好象有种写法是用结构或者数组的,大侠指点啊.

weixichao 发表于 2008-5-8 22:56:24

我觉得用switch比较直观!
关键在于你有100条命令,对应100种处理,只要这些处理不能合并,就没办法简单!

luan3703 发表于 2008-5-8 23:09:14

用函数指针数组,对应的命令做数组下标。

Oliver 发表于 2008-5-8 23:09:41

基本格式是:
msg_start + msg_sn + data_size + msg_key + cmd + msg_id + data1 to data n + check + msg_end

cmd是命令,决定要干什么等(27条),然后msg_id决定是什么具体内容(几乎每条cmd都对应好几个分支),最后才能是协议内容.

可不可以做一个数组,用它来扫描分析协议的具体内容.?

Oliver 发表于 2008-5-8 23:13:57

有点懂"【2楼】 luan3703"的意思.

是不是协议分析时先从1个cmd结构中找到对应的cmd,然后取出结构的另一成员

(因为cmd的排列不是连续的,这样可以得到一个连续编号).

用这个成员做涵数指针的偏移量转到相应涵数?

Oliver 发表于 2008-5-8 23:14:40

2楼能给个简单列子吗?或者哪里有相关资料可参考,谢谢

mljda 发表于 2008-5-8 23:56:51

void(*fun)(void)=
{{00,00,f02,00,},
{f10,00,00,00,},
{00,00,00,f23,}
};

//cmd=0,id=2
void f02(void)
{}
...
//cmd=1,id=0
void f10(void)
{}
...
//cmd=2,id=3
void f23(void)
{}

main

......
void(*fun)(void);
.....


就分开了。
注意如果cmd和id不连续,则要注意对齐数组中程序指针的地址。
--------------------更新结构体-----------------
需要接收数据长度是固定的。

union {
struct {
unsigned char head;
unsigned char xfel;
unsigned intdfa;
unsigned char cmd;
unsigned char id;
unsigned char buf;
.....
}struct;
unsigned char array;
}uart_data;



接收的时候顺序接收到uart_data.array中。
取的时候
void(*fun)(void);



如果不是固定的,就只能挨个判断取cmd,id了

Oliver 发表于 2008-5-9 00:05:46

谢谢 【6楼】 mljda 技术是人性 的指点,看来用这个方法解协议也不错,如果这样100条协议就要100个涵数了.也挺恐怖

jklooo 发表于 2012-7-12 17:07:24

weixichao 发表于 2008-5-8 22:56 static/image/common/back.gif
我觉得用switch比较直观!
关键在于你有100条命令,对应100种处理,只要这些处理不能合并,就没办法简单! ...

最简单的就这个switch了,其他的都脱了裤子放屁,还不是要写一大堆

jazsmile 发表于 2012-7-13 09:37:43

写一个流程图,按照你的协议接受和解析数据。
我用switch已可满足了。

mljda 定义的更好,高人。

orzorzorzorz 发表于 2012-7-13 16:08:43

既然你的帧是有一定格式的
那么你就把你的帧格式要解析出来即可
解析出来符合你帧格式的帧,然后再处理不同命令的功能
用switch case也是在你解析完整了帧格式才用的

我看你格式有帧头和帧尾,那就不存在解析不了的问题了
但是有一点,如果你是全双工工作的话,你得考虑帧头帧尾的转义处理

Excellence 发表于 2012-7-13 16:17:17

函数指针那个思路不错,可以试试,学习。

develop 发表于 2012-7-13 17:44:48

非線性==>線性==>非線性

skyxjh 发表于 2012-9-7 09:25:38

用函数指针数组的解决办法不错。

unsigned int checkPad0(void)
{
...
}
unsigned int checkPad1(void)
{
...
}
...
unsigned int checkPad19(void)
{
...
}

unsigned int(*const checkPad[])(void) = {
checkPad0,checkPad1,checkPad2,checkPad3,checkPad4,
checkPad5,checkPad6,checkPad7,checkPad8,checkPad9,
checkPad10,checkPad11,checkPad12,checkPad13,checkPad14,
checkPad15,checkPad16,checkPad17,checkPad18,checkPad19
};

void main(void)
{
unsigned char i;
for(i=0;i<20;i++) checkPad();
}

richards 发表于 2012-9-7 09:44:49

这个 有意思。   这么多命令。

jz701209李 发表于 2012-9-7 10:44:40

路过学习一下!!!!!!

kisscontrol 发表于 2019-10-11 17:01:53

正在找高效率的极简应答方法,有启发

xintao 发表于 2019-10-12 13:30:27

习惯了switch

nongxiaoming 发表于 2019-10-12 16:58:08

switch最直观,其他搞什么数组函数指针的耗内存调试又不直观,完全没必要

ruxz@263.net 发表于 2019-10-14 00:22:04

nongxiaoming 发表于 2019-10-12 16:58
switch最直观,其他搞什么数组函数指针的耗内存调试又不直观,完全没必要

同意你的说法,而且看看命令的重复频率,高的放前面!

leiyitan 发表于 2019-10-14 08:46:16

楼主还是搞少了,几百个函数有什么的呢,没问题的
页: [1]
查看完整版本: 请教大侠,单片机解复杂的通讯协议(UART)用什么写法比较好,直观,高效?