KeilC51常用功能模块使用说明

发布者:Yuexiang666最新更新时间:2016-12-16 来源: eefocus关键字:Keil  C51  功能模块 手机看文章 扫描二维码
随时随地手机看文章

本文档包括单片机系统中常用到的时钟中断、通讯及键盘扫描等模块(见所附源程序)的说明。这些模块使用前后台系统模型。为达到最大的灵活性, 需要在用户工程中定义config.h文件, 在其中定义各模块可选参数的设置,而不是直接更改源代码。

这些可选内容大部分为宏定义,如果不定义宏相应的功能在编译时被屏蔽,不会增加代码长度。 具体可选内容见各模块中的说明。

在Config.h文件中还要包含一个单片机硬件的资源头文件。

各模块使用了定义在Common.h中的一些数据类型。如:BIT(bit) BYTE(unsigned char)等,具体请参见源程序。

 

时钟模块

  在单片机软件设计中, 时钟是重要资源, 为了充分利用时钟资源, 故设计本时钟模块。 本模块使用定时器0,在完成用户指定功能的同时, 还能够自动处理一些其它模块中与时钟相关的信息。

  时钟模块由声明文件Timer.h以及实现文件Timer.c组成。

  用户应该在Config.h中定义宏TIMER_RELOAD来设定定时器0的重装载初值。推荐的定时器0的中断时间大于1毫秒。

 

  在程序的初始化阶段调用时钟模块的初始化函数InitTimerModule()之后,就可以使用时钟模块所以支持的各种功能。具体描述如下:

延时:当用户需要进行一定时间的延时时,可以通过调用Delay()来进行,参数为时钟中断的次数。如时钟中断周期为1ms, 想进行100ms的延时, 则可以调用Delay(100)。

注意:

如果延时的绝对时间小于时钟中断的周期,则不能够用本方法做到延时。

 

定时:当程序中需要使用定时功能时,如等待某外部事件,如果在一定时间内发生则继续执行,如果在这段时间内发生,则认为出现错误,转向错误处理机制。

在此推荐一种编程模式,但用户可以用自己认为更合理的方式处理此类问题。

这里简单说明一下关于阻塞式函数及非阻塞式函数。简单说,阻塞式函数就是当检测完成条件,如果不能够完成则等待,如:

void CheckSomething()

{

  // gbitSuccessFlag is a global variable

  while(gbitSuccessFlag == FALSE)

  {

    // do nothing but waiting

  }

}

可以看到,当bitSuccessFlag没有被设置为TRUE时,函数保持等待状态不返回,这样就是阻塞式的函数。

另外一种情况:

BIT CheckSomething()

{

  if(gbitSuccessFlag == TRUE)

  {

    // …

    return TRUE;

  }

  return FALSE;

}

在这里,如果所检测的事件有没有完成,函数进行检测之后,立刻返回,通过返回值报告完成情况,如果没有完成,则等待调用者分配再次执行的机会。这样的函数就是非阻塞函数。

在应用定时功能时,首先要将检测函数定义成非阻塞函数。如上面的第二个版本的CheckSomething。

然后下面模式:

BIT bitDone = FALSE;

ResetClock(); // clear timer interrupt times counter

while(GetClock() < MAX_WAITINGTIME)

{

  if(CheckSomething() == TRUE)

  {

    bitDone = TRUE;

    break;

  }

}

if(bitDone == FALSE)

{

  // process time out

}

 

或者简单写成:

BIT bitDone = FALSE;

ResetClock();

while(GetClock() < MAX_WAITINGTIME && (bitDone = CheckSomething));

if(bitDone == FLASE)

{

  // …

}

 

软件看门狗:实现具有局限性的看门狗功能。在程序中合适的地方加入对软件看门狗的复位函数ResetWatchDog(),在Config.h中加入宏TIMER_WATCHDOGTIMEOUT。当程序运行时,如果在发生TIMER_WATCHDOGTIMEOUT次时钟中断之内没有复位软件看门狗, 则系统复位。

注意:

如果没有加入TIMER_WATCHDOGTIMEOUT宏,程序中的ResetWatchDog没有任何用处,不用删除。

如果系统不能实现时钟中断,则软件看门狗也同时失去功能。

目前版本的的时钟模块的复位功能并不是完全复位,主要表现在当复位之后,系统将不再响应任何中断。所以软件看门狗只是一个程序的调试功能,不应该将它用于正式工作的程序,此时应该使用硬件看门狗。

 

用户自定义任务:如果想在时钟中断内执行一些耗时较短的任务,可以定义回调函数OnTimerInterrupt。函数原形为:void OnTimerInterrupt();

如果想在发生时钟中断时执行一些功能,而这些功能又耗时相对较长,不合适放在中断响应函数内部,则可以在程序中的主循环中的任意地方添加: ImpTimerService(),同时提供原形为void OnTimerEvent()的回调函数。具体的程序如下所示:

void main()

{

  Initialize();

  while(TRUE)

  {

    // … working

    ImpTimerService();

    // … working

  }

}

 

void OnTimerEvent()

{

  // do some task

}

 

对通讯模块提供支持:如通讯中的各种超时等,见通讯模块中的详细说明。

对键盘扫描模块提供支持:可以自动调用键盘扫描模块,见键盘扫描模块中的详细说明。

对程序调试提供支持:在程序开发过程中,有时为了判断程序是不是在工作,常用利用单片机系统的某一空闲引脚通过一个限流电阻接一个发光二极管,在程序中间隔固定时间交替控制发光管的明暗。实现这个功能只要在Config.h文件中定义TIMER_FLASHLED宏,如:

#define TIMER_FLASHLED        P1_0

则当时钟中断发生256次之后,改变发光管的状态。

 

通讯模块

  串口资源做为单片机与外界通信的常用手段,通讯模块提供了完全缓冲的串口通讯底层机制,适用于长度不大的数据包的发送及接收。如果处理关键数据,需要用户自己提供纠错协议。

  通讯模块由声明文件SComm.h及实现文件SComm.c组成。

  初始化:调用函数InitSCommModule()来初始化通讯模块:

  void InitSCommModule(BYTE byTimerReload, BIT bitTurbo)

  参数说明:

byTimerReload: 定时器1的重装载初始值。

bitTurob: 当此参数为TRUE时,串行通讯在定时器1的溢出速率基础上加倍。为FALSE时,串行通讯速率为定时器1的溢出速率。

 

  缓冲区:模块使用了由宏SCOMM_SENDBUFSIZE、SCOMM_RECEBUFSIZE及SCOMM_PKGBUFSIZE所指定长度的三个缓冲区,分别为发送、接收及数据包(用于处理接收到的数据)缓冲区(如果没有使用异步接收功能,则不需要使用数据包缓冲区)。

  在缺省时,这三个宏都被定义为10,但用户可以自已按照系统的RAM资源占用情况在Config.h中重定义缓冲区的大小。需要注意的是,如果缓冲的长度不够,当发送或接收长数据包的时候可能会发生问题,关于数据缓冲区的最小值的设置可以参考下面的说明。

  注意:需要尽快取出接收缓冲区中的数据,否则当缓冲区满之后,新的数据将被简单的丢掉。

 

  字节级服务函数: 在Config.h文件中定义了宏SCOMM_DriverInterface(如:#define SCOMM_DriverInterface),则可以使用字节级服务函数,即通讯模块的底层函数。

  共有两个函数可以使用:

  void SendByte(BYTE byData);

  发送一个字节,如果当前缓冲区满,则等待。参数byData为要发送的数据。

BYTE ReceByte();

接收一个字节,如果当前缓冲区中没有数据,则此函数阻塞,直到接收到数据为止。接收到数据通过返回值返回。

可以通过调用IsSendBufEmpty() IsSendBufFull() IsReceBufEmpty() IsReceBufFull()  宏来判断缓冲区的空或满,以防系统阻塞。

不推荐直接使用这一级的服务函数,应该使用高层次上的服务函数或者在这一级服务函数的基础上构造自己的通讯函数。

  

  数据包级服务函数:在Config.h文件中定义宏SCOMM_PackageInterface(如: #define SCOMM_PackageInterface)则可以使用数据包级服务函数。

  共有两个函数可以使用:

void SendPackage(BYTE* pbyData, BYTE byLen);

发送数据包,参数pbyData为将要发送的数据包缓冲区(数组)的指针,byLen为将要发送的数据包的长度。

当没有定义SCOMM_DriverInterface时,数据被完全缓冲。即不能够发送长度超过发送缓冲区长度的数据包。当定义了SCOMM_DriverInterface时,采用单字节发送,这时不限制需要发送的数据的长度。

 

BYTE RecePackage(BYTE* pbyData, BYTE byLen);

接收数据包,参数pbyData为存放将要接收的数据的缓冲区,byLen为缓冲区长度。返回值为接收到的字节数,当模块的接收缓冲区为空时,函数非阻塞,立即返回,返回值为零。

 

同步发送接收服务函数:

比如在一个串行总线多机通讯系统中,主机需要定时循检各从机的状态,往往是发一个包含从机地址及指令的数据包给从机,之后等待一定的时间,从机需要在这段时间之内给主机一个应答,如果没有这个应答,则认为从机工作状态出错,转去进行相应的处理。在这个模型里,主机不能够不进行等待而给另一台从机发送指令,也不能够不管从机在很久没有应答的情况下继续等待。还有一种情况,比如当使用485总线进行通信时,如果是两条通讯线则系统只能工作在半双工模式下,总线在同一时间内只能工作在发送或接收, 为了防止发送和接收相互干扰,这时的通讯常常需要使用同步发送和接收。

当在Config.h文件中定义宏SCOMM_SyncInterface后,则可以使用通讯模块提供同步发送接收函数:

void SendPackage(BYTE* pbyData, BYTE byLen);

发送数据包,参数pbyData为将要改善的数据包的缓冲区指针,byLen为将要发送的数据包的长度。

这个函数可以保证等待一个完整的数据包完全发送出去之后,它才返回,在这段时间内,它会阻塞运行。

 

BYTE SyncRecePackage(BYTE* pbyBuf, BYTE byBufLen, WORD wTimeout, BYTE byParam);

接收数据包。返回值为接收到的数据包长度。参数pbyBuf为将要接收数据包的缓冲区的指针,byBufLen为提供的缓冲区的长度,wTimeout为通信超时值,如果在发生了由wTimeout所指定次数的时钟中断而还没有接收到或没有接收到完整的数据包时,函数返回零,最后一个参数byParam的含义见后面的解释。

 

异步发送接收服务函数:

在一个简单的系统或多机通讯系统中的从机上,一般情况下不需要复杂的停等的工作模式,而且往往单片机需要对硬件进行控制和检测,不允许长时间的停下来检测通讯,但又要求当需要通讯时需要尽快的反应速度,这时就需要使用异步发送和接收服务函数。

使用异步发送和接收服务函数需要在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();


关键字:Keil  C51  功能模块 引用地址:KeilC51常用功能模块使用说明

上一篇:8051指令周期表
下一篇:单片机中断的应用

推荐阅读最新更新时间:2024-03-16 15:25

编程点滴:AVR UART I/O 功能模块
本程序实现AVR设备UART端口 输入/回显/格式化输出 功能,由此可以通过PC机终端软件与设备直接交互。 程序有参考Samsung S3C2440库文件。 程序组成:测试程序 main.c ,功能模块 uart.c 及其头文件 uart.h 。 main.c /* ****************************************************** * File Name: main.c * Function: AVR UART I/O 功能模块 * Description: 实现UART输入/回显/格式化输出功能, 方便程序调试 * Authon & Date: Joshua Chan, 2
[单片机]
单片机 keil流水灯实验
做流水灯实验以前,必须先弄清楚各个发光二极管是怎么控制的,其次,在了解了keil的内部左移右移函数,就可以写出比较简短的流水灯的实验代码。 在写的过程中遇到过一些问题,怎么控制灯的走向,应该用一个怎么样的变量来实现传递,这个很重要。 解决的方法是定义一个unsigned char型变量。 此外还要写一个延时函数,可以是带参数的,也可以不带。 在while大循环里,不能忘了点亮一盏灯,就要把它关上。 #include reg52.h #include intrins.h //包含有左右循环移位子函数的库 #define uint unsigned int void delay() //延时函数,
[单片机]
Proteus与keil的联机仿真设置问题
KeilC与Proteus连接调试 1、假若KeilC与Proteus均已正确安装在C:\Program Files的目录里,把C:\Program Files\Labcenter Electronics\Proteus 6 Professional\MODELS\VDM51.dll复制到C:\Program Files\keilC\C51\BIN目录中。如果没有可以去网上下载; 2、用记事本打开C:\Program Files\keilC\C51\TOOLS.INI文件,在 栏目下加入: TDRV8=BIN\VDM51.DLL ( Proteus VSM Monitor-51 Driver ) 其中 TDRV8 中的 8 要
[单片机]
Proteus与<font color='red'>keil</font>的联机仿真设置问题
C51中关于指针的种种用法
#i nclude reg51.H f(){} f1(){} f2(){} main() { { int x; int *px; //下面这些表示虽然很烦,但是生成的代码却及其简洁:(黑体部分实际使用过) //将 xdata 型指针 0x4000 赋给 px px=(int xdata *)0x4000; //表示从 xdata 0x4000处取一个 char 给x x=*((char xdata *)0x4000); (可以将0X4000处,改成一个整形变量,方便进行操作。) 或者*((char xdata *)0x4000)=X;//表示给存在xda
[单片机]
C51的XTAL1,XTAL2的外接电源经验
C51的XTAL1,XTAL2的外接电源经验: 1.XTAL1 XTAL2 外接由两个电容与晶振的并联谐振时钟电路 C1,C2 选30pF,晶振选1.2-12MHz,设计时,当使晶振各电容尽可能的与C51单片机靠近,以保证稳定可靠 2.或用外部振荡器接至XTAL2,XTAL1接地,注意:XTAL1如果不接地的话,Electrical Rule Check会给出错误如下下: ELECTRICAL RULES CHECK REPORT ============================= Design: D:\proteus-design\yx-design\IO-1.DSN Doc. no.: NONE Revi
[单片机]
用于手机SoC设计的部件级多媒体功能模块
  尽管视频编解码是一个复杂的过程,但Tensilica的Diamond系列标准音、视频引擎却能简化SoC设计团队的设计任务。Diamond标准音视频引擎就像一个低功耗黑盒,SoC设计师无需精通H.264/AVC、MPEG-4和数字音频就可以将其整合到便携式多媒体和手机芯片中。   视频编码过程如图1所示。首先,SoC主处理器通过指令配置Diamond视频引擎,然后将未编码的视频帧发送给该引擎,由它对视频帧进行编码,并将编码后的图像数据(VDE)送回主处理器。进行视频解码时,主处理器首先通过指令配置Diamond视频引擎,然后将VDE发送给它,由它进行图像解码,最后将已解码的帧传回主处理器。音频解码过程,主处理器将压缩的音频流发送
[嵌入式]
C51的基础 9 《 指针、结构、联合和枚举 》
指针、结构、联合和枚举 本节专门对第二节曾讲述过的指针作一详述。并介绍Turbo C新的数据类型: 结构、联合和枚举, 其中结构和联合是以前讲过的 五种基本数据类型(整型、浮点型、字符型、指针型和无值型)的组合。枚举是一个被命名为整型常数的集合。最后对类型说明 (typedef)和预处理指令作一阐述。 指 针(point) 学习Turbo C语言, 如果你不能用指针编写有效、正确和灵活的程序, 可以认为你没有学好C语言。指针、地址、数组及其相互 关系是C语言中最有特色的部分。规范地使用指针,可以使程序达到简单明了, 因此, 我们不但要学会如何正确地使
[单片机]
利用全局及外部变量实现C51无能数化调用A51函数
摘要: 利用C51全局及外部变量,可实现无参数化调用A51函数,不但避免开了传统C51调用C51时繁琐的接口约定,而且把在A51中所用到的变量全部放至C51程序中而不必考虑变量在内存中的位置,使编程更加简洁。用实例验证了该方法的优越性和有效性。 关键词: C51 A51 汇编语言 无参数化调用 电子技术应用 2001年第7期发表苟帅的文章“ASM51无参数化调用C51函数的实现”,阐述了ASM51无参数化调用C51函数的实现原理并给出实例来验证该方法的优越性和可行性。作者在文章中
[传感技术]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved