新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > 单片机C51编程几个有用的模块

单片机C51编程几个有用的模块

作者:时间:2012-07-04来源:网络收藏

为了能够使用用SyncRecePackage或AsyncRecePackage函数从接收到的数据中识别出如上格式的数据包,有两种方法:
第一种办法是在Config.h文件中定义宏SCOMM_SimplePackageFormat,说明数据包为一种简单格式,比如上面的协议。
之后还要定义两个宏分别用来识别数据包头和数据包尾,两个宏分别是:
IsPackageHeader(x)和IsPackageTailer(x,y,z)
接收函数(SyncRecePackage和AsyncRecePackage)在没有开始接收数据包(准确的说是还没有从接收到的数据包中找到包头的时候),会对接收到的每一个字节的数据调用IsPackageHeader宏,将相应的数据作为参数,如果IsPackageHeader宏的结果为TRUE,则认为找到了数据包头,否则继续对下一个字节进行判断。
上面的协议对应的IsPackageHeader宏可以写为:
#defineIsPackageHeader(x)((x)==0xff)
当接收到包头之后,接收函数会对接下来的每一个字节数据调用IsPackagTailer宏来判断是不是已经接收完数据包,三个参数分别为:
x:当前判断的数据。
y:从包头开始到当前被判断的数据止的计数值,即当前已经接收到的字节数。
z:用户在调用SyncRecePackage或AsyncRecePackage时指定的byParam参数。
与IsPackageHeader相似,如果宏IsPackageTailer的运算结果为TRUE,则认为接收到完整的数据包,则调用相应的回调函数(对于异步接收函数)或返回(对于接收函数)。如果运算结果为FALSE则继续判断下一个字节的数据。
上面的协议对应的IsPackageTailer宏可以写为:
#defineIsPackageTailer(x,y,z)((y)>=(z))
当然,用户也可以将IsPackageHeader和IsPackageTailer定义成为函数,通过BIT类型的返回值来向调用者提供与相应宏相同的信息。

另一种办法需要在Config.h文件中定义宏SCOMM_ComplexPackageFormat。(需要注意的是,不能够同时定义SCOMM_SimplePackageFormat和SCOMM_ComplexPackageFormat宏,否则会造成严重的不可预见性错误。
这时需要提供回调函数QueryPackageFormat,原形如下:
BYTEQueryPackageFormat(BYTEbyData,BYTEbyCount,BYTEbyParam);
函数中三个参数的含义与使用简单数据包格式时判断数据包尾的宏的参数相同。
函数通过返回值来通知作为调用者的接收函数对接收到的数据如何处理,但目前这种方法仅为需要处理复杂数据包格式时的一种可选方法,但不推荐。用户如果想使用这种方法可以自己更改接收函数中相应的
#ifdefSCOM_ComplexPackageFormat
#endif//SCOMM_ComplexPackageFormat
预编译指令之间的内容。
例如指定QueryPackageFormat的返回值的含义:
0:继续找数据包头或继续找数据包尾。
1:找到数据包头。
2:找到数据包尾。
3:数据包出错,需要抛弃。
然后更改源代码来实现上面的协议。

注意:当用户需要使用字符串的时候,可以利用简单的包装函数将字符串转换为字节数组。所以没有必要提供专用的字符串处理函数。

键盘扫描模块
键盘扫描模块有两种工作方式,一种为自动的由时钟模块调用,另一种是由程序员自行调用。
1)由时钟模块自动调用的方式
将时钟模块实现文件(Timer.h)及键盘扫描模块的实现文件(KBScan。c)包含进工程,在Config.h文件中添加TIMER_KBSCANDELAY宏。时钟模块自动对时钟中断进行计数,当达到TIMER_KBSCANDELAY宏所定义的值后,自动调用键盘扫描模块中的函数KBScanProcess()进行键盘扫描,也就是说,这个宏的值可以决定按键消抖动的时间。
用户应该提供两个回调函数OnKBScan()及OnKeysPressed()。在函数OnKBScan中进行键盘扫描,并返回扫描码。扫描码的类型缺省为BYTE,当键盘规模较大时,BYTE不能够完全包含键盘信息时,可在Config.h文件中重定义宏KBVALUE,如下:
#defineKBVALUEWORD
这样,就可以使用16位的键盘扫描码,如果此时还达不到要求,可以将键盘扫描码定义成一个结构,但这样做将会增加代码量及消耗更多的RAM资源,故不推荐。
扫描模块调用OnKBScan取得扫描码,并调用用户可以重定义的宏IsNoKeyPressed来判断是否有键按下,缺省的IsNoKeyPressed实现如下:
#defineIsNoKeyPressed(x)((x)==0x00)
即认为OnKBScan返回0扫描码时为没有键按下,如果扫描函数返回其它非零扫描码做为无键按下的扫描码时,可以在Config.h文件中重定义IsNoKeyPressed宏的实现。
8位键盘扫描码(缺省值)时,相应的扫描函数为:
BYTEOnKBScan()
当扫描模块经过软件消抖动之后,发现有键按下,就会调用另一个回调函数OnKeysPressed。函数的声明应该如下:
voidOnKeyPressed(BYTEbyKBValue,BYTEbyState)
其中中的参数byKBValue的类型为BYTE,此为缺省值,如果使用其它类型的扫描码,就将此参数变为相应类型。这个值由OnKBScan返回。另一个参数byState在通常情况下为零。但当用户在Config.h中定义宏KBSCAN_BRUSTCOUNT,同时键盘上的某键被按住不放时,扫描模块对它自己的调用(注意这里和TIMER_KBSCANDELAY宏不同,TIMER_KBSCANDELAY是时钟中断足够的次数后调用扫描模块,而KBSCAN_BRUSHCOUNT为扫描模块自身的被调用次数)进行计数,当达到KBSCAN_BRUSTCOUNT时,扫描模块调用OnKeysPressed,此时第一个参数的含义不变,而byState变成1,同时计数器复位,又经过一段时间后,用值为3的byState调用OnKeysPressed。这样就可以很方便的实现多功能键或者检测某键的长时间被按下。
2)由用户自行调用
由用户自行在程序中调用扫描模块,而不是由时钟中断自行调用。其它与方式1相同。

注意:
1)函数KBScanProcess为非阻塞函数,它将在很快的时间内返回,等待再次分配给它执行的机会。
2)函数KBScanProcess是在时钟中断外部运行的,它的过程可以被任何中断打断,但不影响系统运行。
3)byState的最大值为250,之后被复位为零。


上一页 1 2 3 下一页

评论


相关推荐

技术专区

关闭