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

上传人:z****2 文档编号:199348778 上传时间:2023-04-10 格式:DOCX 页数:11 大小:27.21KB
收藏 版权申诉 举报 下载
单片机C51编程几个有用的模块_第1页
第1页 / 共11页
单片机C51编程几个有用的模块_第2页
第2页 / 共11页
单片机C51编程几个有用的模块_第3页
第3页 / 共11页
资源描述:

《单片机C51编程几个有用的模块》由会员分享,可在线阅读,更多相关《单片机C51编程几个有用的模块(11页珍藏版)》请在装配图网上搜索。

1、单片机C51编程几个有用的模块狗glory 发表于 2005114 10:08:39要包含一个单片机硬件的资源头文件。各模块使用了定义在Common.h中的一些数据类型。如:BIT(bit) BYTE(unsigned char)等,具体请参见 源程序。时钟模块在单片机软件设计中,时钟是重要资源,为了充分利用时钟资源,故设计本时钟模块。本模块使用 定时器0,在完成用户指定功能的同时,还能够自动处理一些其它模块中与时钟相关的信息。时钟模块由声明文件Timer.h以及实现文件Timer.c组成。用户应该在Config.h中定义宏TIMER_RELOAD来设定定时器0的重装载初值。推荐的定时器0的中

2、 断时间大于1毫秒。在程序的初始化阶段调用时钟模块的初始化函数InitTimerModule()之后,就可以使用时钟模块所 以支持的各种功能。具体描述如下:延时:当用户需要进行一定时间的延时时,可以通过调用Delay ()来进行,参数为时钟中断的次数。如 时钟中断周期为1ms,想进行100ms的延时,则可以调用Delay(100)。注意:如果延时的绝对时间小于时钟中断的周期,则不能够用本方法做到延时。定时:当程序中需要使用定时功能时,如等待某外部事件,如果在一定时间内发生则继续执行,如果在 这段时间内发生,则认为出现错误,转向错误处理机制。在此推荐一种编程模式,但用户可以用自己认为更合理的方式

3、处理此类问题。这里简单说明一下关于阻塞式函数及非阻塞式函数。简单说,阻塞式函数就是当检测完成条件,如果不 能够完成则等待,如:void CheckSomething()/ gbitSuccessFlag is a global variable while(gbitSuccessFlag = FALSE)/ do nothing but waiting可以看到,当bitSuccessFlag没有被设置为TRUE时,函数保持等待状态不返回,这样就是阻塞式的函 数。另外一种情况:BIT CheckSomethingOif(gbitSuccessFlag = TRUE)/ .return TRUE;

4、return FALSE;在这里,如果所检测的事件有没有完成,函数进行检测之后,立刻返回,通过返回值报告完成情况,如 果没有完成,则等待调用者分配再次执行的机会。这样的函数就是非阻塞函数。在应用定时功能时,首先要将检测函数定义成非阻塞函数。如上面的第二个版本的CheckSomething。然后下面模式:BIT bitDone = FALSE;ResetClock(); / clear timer interrupt times counterwhile(GetClock() MAX_WAITINGTIME)if(CheckSomething() = TRUE)bitDone = TRUE;br

5、eak;if(bitDone = FALSE)/ process time out或者简单写成:BIT bitDone = FALSE;ResetClock();while(GetClock() = (z)当然,用户也可以将IsPackageHeader和IsPackageTailer定义成为函数,通过BIT类型的返回值来向 调用者提供与相应宏相同的信息。另一种办法需要在Config.h文件中定义宏SCOMM_ComplexPackageFormat。(需要注意的是,不能够同时 定义 SCOMM_SimplePackageFormat 和 SCOMM_ComplexPackageFormat

6、宏,否则会造成严重的不可预见性 错误。这时需要提供回调函数QueryPackageFormat,原形如下:BYTE QueryPackageFormat(BYTE byData, BYTE byCount, BYTE byParam);函数中三个参数的含义与使用简单数据包格式时判断数据包尾的宏的参数相同。函数通过返回值来通知作为调用者的接收函数对接收到的数据如何处理,但目前这种方法仅为需要处理 复杂数据包格式时的一种可选方法,但不推荐。用户如果想使用这种方法可以自己更改接收函数中相应 的#ifdef SCOM_ComplexPackageFormat#endif / SCOMM_Complex

7、PackageFormat 预编译指令之间的内容。例如指定QueryPackageFormat的返回值的含义:0:继续找数据包头或继续找数据包尾。1:找到数据包头。2:找到数据包尾。3:数据包出错,需要抛弃。然后更改源代码来实现上面的协议。注意:当用户需要使用字符串的时候,可以利用简单的包装函数将字符串转换为字节数组。所以没有必 要提供专用的字符串处理函数。键盘扫描模块键盘扫描模块有两种工作方式,一种为自动的由时钟模块调用,另一种是由程序员自行调用。1) 由时钟模块自动调用的方式将时钟模块实现文件(Timer.h)及键盘扫描模块的实现文件(KBScan。c)包含进工程,在Config.h文件

8、中添加TIMER_KBSCANDELAY宏。时钟模块自动对时钟中断进行计数,当达到TIMER_KBSCANDELAY宏所定 义的值后,自动调用键盘扫描模块中的函数KBScanProcess()进行键盘扫描,也就是说,这个宏的值可 以决定按键消抖动的时间。用户应该提供两个回调函数OnKBScan()及onKeysPressed()。在函数OnKBScan中进行键盘扫描,并返 回扫描码。扫描码的类型缺省为BYTE,当键盘规模较大时,BYTE不能够完全包含键盘信息时,可在Config.h文件中重定义宏KBVALUE,如下:#define KBVALUEWORD这样,就可以使用16位的键盘扫描码,如果

9、此时还达不到要求,可以将键盘扫描码定义成一个结构, 但这样做将会增加代码量及消耗更多的RAM资源,故不推荐。扫描模块调用OnKBScan取得扫描码,并调用用户可以重定义的宏IsNoKeyPressed来判断是否有键 按下,缺省的IsNoKeyPressed实现如下:#define IsNoKeyPressed(x)(x) = 0x00)即认为OnKBScan返回0扫描码时为没有键按下,如果扫描函数返回其它非零扫描码做为无键按下的扫 描码时,可以在Config.h文件中重定义IsNoKeyPressed宏的实现。8位键盘扫描码(缺省值)时,相应的扫描函数为:BYTE OnKBScan()当扫描模

10、块经过软件消抖动之后,发现有键按下,就会调用另一个回调函数onKeysPressed。函数 的声明应该如下:void onKeyPressed(BYTE byKBValue, BYTE byState)其中中的参数byKBValue的类型为BYTE,此为缺省值,如果使用其它类型的扫描码,就将此参数变为相 应类型。这个值由OnKBScan返回。另一个参数byState在通常情况下为零。但当用户在Config.h中定 义宏KBSCAN_BRUSTCOUNT,同时键盘上的某键被按住不放时,扫描模块对它自己的调用(注意这里和 TIMER_KBSCANDELAY宏不同,TIMER_KBSCANDELAY

11、是时钟中断足够的次数后调用扫描模块,而 KBSCAN_BRUSHCOUNT为扫描模块自身的被调用次数)进行计数,当达到KBSCAN_BRUSTCOUNT时,扫描模块 调用onKeysPressed,此时第一个参数的含义不变,而byState变成1,同时计数器复位,又经过一段 时间后,用值为3的byState调用onKeysPressed。这样就可以很方便的实现多功能键或者检测某键的 长时间被按下。2)由用户自行调用由用户自行在程序中调用扫描模块,而不是由时钟中断自行调用。其它与方式1相同。注意:1)函数KBScanProcess为非阻塞函数,它将在很快的时间内返回,等待再次分配给它执行的机会。

12、2)函数KBScanProcess是在时钟中断外部运行的,它的过程可以被任何中断打断,但不影响系统运行。3)byState的最大值为250,之后被复位为零。应用举例现在来举例说明上述几个模块的使用方法。硬件环境描述:为了控制一盏灯,需要单片机提供一个做控制功能的开关量,这里不描述外部接口电路,只说明当 单片机的P10脚为高电平时,灯灭,当P10脚为低电平时,灯亮。可以通过计算机由串口发送命令来控制,或通过一个按键(push button不是自锁式的按键)来手动控制 (按键接在P11脚上,当键没有按下时,P11电平为高,键按下时,引脚电平被接低),当使用按键手动 控制的时候,需要给计算机发送通知

13、。设定串口通讯指令如下:数据包由0xff做包头,4个字节长,第二个字节为命令代码,第三个字节为数据,最后一个字节为校验 位。命令和数据代码有如下组合:(计算机发给单片机)0x10 0x01:计算机控制灯亮。(数据位是非零值即可)0x10 0x00:计算机控制灯灭。(单片机发给计算机)0x11 0x01 :单片机正常执行控制指令,返回。(数据位是非零值即可)0x11 0x00:单片机不能够正常执行控制指令,或控制指令错(不明含义的数据包或校验错等)。 0x12 0x01 :手动控制灯亮。(数据位是非零值即可)0x12 0x00:手动控制灯灭。建立工程:在硬盘上建立文件夹Projects,在Pro

14、jects下建立Common文件夹及Example文件夹。将各模块的 头文件及实现文件拷贝到Common文件夹下(推荐使用这样的文件组织结构,其它工程也可以建立在 Projects下,各工程共享Common文件夹中的代码)。启动KeilC的IDE,在Example下建立新工程,将各模块的实现文件包含进工程。在Example文件夹下建立Output文件夹,更改工程设置,将Output作为输出文件和List文件的输 出文件夹(推荐使用这样的结构,当保存工程文件时,可以简单的删除Output文件夹中的内容而不会误 删有用的工程文件)。建立工程配置头文件Config.h及工程主文件Example.c,

15、并将Exmaple.c文件加入工程。输入代码:代码的具体编写过程略。下面是最后的Config.h文件及Example.c文件。/ file: Config.h/#ifndef _C0NFIG_H_#define CONFIG H#i nclude Atmel/At89x52.h# i nclude “./Common/Common.h#defineTIMER RELOAD922#defineTIMER KBSCANDELAY40#define#define#defineSC0MM_AsyncInterfaceIsPackageHeader(x)IsPackageTailer(x, y, z)/

16、使用AT89C52做控制/使用自定义的数据类型/ 11.0592MHz晶振,1ms中断周期/ 40ms重检测按键状态,即40ms消抖/使用异步通讯服务=0xff)(x)(y) = (z)/判断包头是不是0xff/判断包的长度是不是足够#endif / _CONFIG_H_ / file: Example.c/#i nclude # i nclude “./Common/Common.h# i nclude “./Common/Timer.h# i nclude “./Common/Scomm.h# i nclude “./Common/KBScan.hstatic void Initializ

17、e。InitTimerModule();InitSCommModule(Oxfd, TRUE);EA = 1;void main()Initialize。;while(TRUE)ImpTimerService();AsyncRecePackage(4);/在中断外部响应时钟中断事件void OnTimerEvent()/ do nothing/控制外部灯static void TriggerLamp(BIT bEnable)PIO = bEnable;/键扫描回调函数BYTE KBScan()BIT b;P11 = 1;b = P11;return b;/计算校验和static BYTE Ca

18、lcCheckSum(BYTE* pbyBuf,BYTE by, bySum = 0;for(by = 0; by byLen; by+)/初始化时钟模块/初始化通讯模块,11.0592MHz晶振,/波特率为19200/开中断/初始化/主循环/实现时钟中断服务,如键盘扫描/接收4个字节长的数据包/需要反相控制/读之前拉高引脚电平/读入引脚状态/数据反相做扫描码BYTE byLen)bySum += pbyBufby;return 0 - bySum;/接收到键盘消息回调函数void onKeyPressed(BYTE byValue, BYTE byState)BYTE by4;if(bySt

19、ate = 0)switch(byValue)case 0x01:gbitLampState = g bitLampState; / 灯状态取反 TriggerLamp(gbitLampState); / 执行控制 by0 = 0xff;/构造数据包by1 = 0x12;by2 = (BYTE)gbitLampState;by3 = CalcCheckSum(by, 3);/ 求校验和SendPackage(by, 4);/ 发送数据包break;/处理其它扫描码default:break;/接收到数据包回调函数void OnRecePackage(BYTE* pbyBuf, BYTE byB

20、ufLen)BYTE by4;by0 = 0xff;by1 = 0x11;if(byBufLen != 4 | pbyBuf3 != CalcCheckSum(pbyBuf, 3)by2 = 0;by3 = CalcCheckSum(by, 3);SendPackage(by, 4);/处理长度或校验和不正确switch(pbyBuf1)case 0x10:gbitLampState = (BIT)pbyBuf2;TriggerLamp(gbitLampState);by2 = 1;by3 = CalcCheckSum(by,SendPackage(by, 4); break;3);/发送成功执行通知default:/不知道的命令by2 = 0;by3 = CalcCheckSum(by, SendPackage(by, 4);3);/发送没有成功执行通知break;

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!