您当前的位置:五五电子网电子知识单片机-工控设备综合-其它单片机C51编程几个有用的模块 正文
单片机C51编程几个有用的模块

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

点击数:7294 次   录入时间:03-04 11:39:27   整理:http://www.55dianzi.com   综合-其它

异步发送接收服务函数:
在一个简单的系统或多机通讯系统中的从机上,一般情况下不需要复杂的停等的工作模式,而且往往单片机需要对硬件进行控制和检测,不允许长时间的停下来检测通讯,但又要求当需要通讯时需要尽快的反应速度,这时就需要使用异步发送和接收服务函数。
使用异步发送和接收服务函数需要在Config.h文件中定义SCOMM_AsyncInterface宏。
同样提供两个服务函数:
void SendPackage(BYTE* pbyData, BYTE byLen);
发送数据包,参数pbyData为将要改善的数据包的缓冲区指针,byLen为将要发送的数据包的长度。
这里的函数的接口与同步发送和接收的服务函数相同。关于这里的细节,见后面对同步和异步服务函数的说明。 void AsyncRecePackage(BYTE byParam);
接收数据包,参数byParam的意义见后面的描述。
使用异步通讯需要用户定义一个回调函数,原型如下:
void OnRecePackage(BYTE* pbyData, BYTE byBufLen);
当异步接收服务函数接收到数据包之后,调用OnRecePackage回调函数,在pbyData指定的缓冲区中存放数据包,byBufLen为数据包的长度。
在Config.h文件中定义宏SCOMM_TIMEOUT可以设定异步接收的超时值,当开始接收数据包,但没有收完数据而发生了SCOMM_TIMEOUT次时钟中断后,认为接收超时,将已接收到的数据删除。

同步和异步通讯服务函数:
有些情况下,比如一个通讯系统中,由一台计算机通过串口控制主机,主机通过串口连接很多从机,主机的串口采用分时复用,在这样的模型中,主机和控制计算机之间的通讯可以使用,异步通讯方式,而主机与从机可以使用同步通讯方式。而同步和异步的发送函数接口是相同的,在这样的情况下,发送都是同步的。在这样的模型中,当使用不同的接收函数之前,需要注意清除接收缓冲区中的内容,通讯模块提供函数:ClearReceBuffer来做到这一点,此函数原型如下:
void ClearReceBuffer();

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

另一种办法需要在Config.h文件中定义宏SCOMM_ComplexPackageFormat。(需要注意的是,不能够同时定义 SCOMM_SimplePackageFormat和SCOMM_ComplexPackageFormat宏,否则会造成严重的不可预见性错误。
这时需要提供回调函数QueryPackageFormat,原形如下:
BYTE QueryPackageFormat(BYTE byData, BYTE byCount, BYTE byParam);
函数中三个参数的含义与使用简单数据包格式时判断数据包尾的宏的参数相同。
函数通过返回值来通知作为调用者的接收函数对接收到的数据如何处理,但目前这种方法仅为需要处理复杂数据包格式时的一种可选方法,但不推荐。用户如果想使用这种方法可以自己更改接收函数中相应的
#ifdef SCOM_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, 如下:
#define KBVALUE      WORD
这样, 就可以使用16位的键盘扫描码, 如果此时还达不到要求, 可以将键盘扫描码定义成一个结构, 但这样做将会增加代码量及消耗更多的RAM资源, 故不推荐。
  扫描模块调用OnKBScan取得扫描码, 并调用用户可以重定义的宏IsNoKeyPressed来判断是否有键按下, 缺省的IsNoKeyPressed实现如下:
#define IsNoKeyPressed(x)      ((x) == 0x00)  
即认为OnKBScan返回0扫描码时为没有键按下, 如果扫描函数返回其它非零扫描码做为无键按下的扫描码时, 可以在Config.h文件中重定义IsNoKeyPressed宏的实现。
  8位键盘扫描码(缺省值)时, 相应的扫描函数为:
BYTE OnKBScan()
  当扫描模块经过软件消抖动之后, 发现有键按下, 就会调用另一个回调函数onKeysPressed。 函数的声明应该如下:
void onKeyPressed(BYTE byKBValue, BYTE byState)
其中中的参数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] 


本文关键字:单片机  综合-其它单片机-工控设备 - 综合-其它