1. 问题的提出,及状态机简介
ZHUMAO整了个门禁用的读卡器,比以前那种更好,不需要发指令就能读,只要刷卡,读卡器就向串口上写数据。仍然是串口的,还是韦根协议。"刷卡就向上写"避免了轮询读卡器,效率更高,代码也容易了。不过,也造成一个问题。下发命令,然后轮询读的模式下,如果在串口线上只有一个读卡器,不需要对输入的数据特别检验和处理,接收到的数据一定是对的,按协议读入多少个字符,然后按偏移量取有效的部分就行了。"刷卡就向上写"的模式,需要保证对齐,必须从刷卡后产生的第一字符开始读,读到最后一个,要避免从中间读起。如果中间出现了噪音之类的干扰,由于不能下发指令要求对齐 (或者开始读),就再也找不到开始位置,数据全乱。
解决这个问题的方案是状态机。
状态机是个著名的数学模型,在数字电路、编译原理、面向对象系统分析与设计、形式语言与状态机中都有提及。状态机效率很不错,刘典同学曾经用状态机模型写程序参加过CSDN上的比赛,检验IP地址是否合法,获得过第二名。状态机描述问题清晰,邦哥和亮哥曾经用状态机重写安卓程序的界面部分,把原来"朴素"方法可能出现的BUG都去除了。
正确的思考方法是有效的工具,在解决问题中非常重要。人类通常不懈于在猛兽面前炫耀速度和力量,而是使用弩箭和陷阱。所以,工具对于成为人类多么重要。所以,不用状态机,而依靠单纯的智力是多么愚蠢。
2. 问题描述
该型号读卡器上传的数据看起来是这样的,以十六进制表示,"02 XX XX XX XX 0d 0a 03"。其中的4个 XX 表示卡号,是我们感兴趣的部分。其余的部分必须匹配,才能说明读卡器正常工作,卡号有效。
主程序准备写成这样:
1 if __name__ == '__main__':
2 s = state_machine()
3 t = serial.Serial('COM3')
4 while True:
5 str = s.go(t)
6 print str.upper()
其中第2行初始化一个 state_machine 类的实例。在第4行开始的循环中,每次迭代都调用 s.go(t),把串口传给状态机。在状态机的go中,读很多次串口,直到遇到一次完整有效的卡号,作为返回值,在第6行中打印出来。这个串口t如果改为在 state_machine 的构造函数中,会更好一些。不过我对python语法不熟,大部分时间都消
ZHUMAO整了个门禁用的读卡器,比以前那种更好,不需要发指令就能读,只要刷卡,读卡器就向串口上写数据。仍然是串口的,还是韦根协议。"刷卡就向上写"避免了轮询读卡器,效率更高,代码也容易了。不过,也造成一个问题。下发命令,然后轮询读的模式下,如果在串口线上只有一个读卡器,不需要对输入的数据特别检验和处理,接收到的数据一定是对的,按协议读入多少个字符,然后按偏移量取有效的部分就行了。"刷卡就向上写"的模式,需要保证对齐,必须从刷卡后产生的第一字符开始读,读到最后一个,要避免从中间读起。如果中间出现了噪音之类的干扰,由于不能下发指令要求对齐 (或者开始读),就再也找不到开始位置,数据全乱。
解决这个问题的方案是状态机。
状态机是个著名的数学模型,在数字电路、编译原理、面向对象系统分析与设计、形式语言与状态机中都有提及。状态机效率很不错,刘典同学曾经用状态机模型写程序参加过CSDN上的比赛,检验IP地址是否合法,获得过第二名。状态机描述问题清晰,邦哥和亮哥曾经用状态机重写安卓程序的界面部分,把原来"朴素"方法可能出现的BUG都去除了。
正确的思考方法是有效的工具,在解决问题中非常重要。人类通常不懈于在猛兽面前炫耀速度和力量,而是使用弩箭和陷阱。所以,工具对于成为人类多么重要。所以,不用状态机,而依靠单纯的智力是多么愚蠢。
2. 问题描述
该型号读卡器上传的数据看起来是这样的,以十六进制表示,"02 XX XX XX XX 0d 0a 03"。其中的4个 XX 表示卡号,是我们感兴趣的部分。其余的部分必须匹配,才能说明读卡器正常工作,卡号有效。
主程序准备写成这样:
1 if __name__ == '__main__':
2 s = state_machine()
3 t = serial.Serial('COM3')
4 while True:
5 str = s.go(t)
6 print str.upper()
其中第2行初始化一个 state_machine 类的实例。在第4行开始的循环中,每次迭代都调用 s.go(t),把串口传给状态机。在状态机的go中,读很多次串口,直到遇到一次完整有效的卡号,作为返回值,在第6行中打印出来。这个串口t如果改为在 state_machine 的构造函数中,会更好一些。不过我对python语法不熟,大部分时间都消