文档库 最新最全的文档下载
当前位置:文档库 › STM32L0单片机 定时中断编程参考知识点

STM32L0单片机 定时中断编程参考知识点

STM32L0单片机  定时中断编程参考知识点
STM32L0单片机  定时中断编程参考知识点

A

嵌入式项目代码结构的分层——HAL(硬件抽象层)、FML(功能模块层)、APL(应用程序层)

一、遇到的问题

在“Zigbee之旅”系列博文中,每写一篇笔者都会编写一个小实验来展开讲解。通过这一段时间的实践,我积累了一些编码经验,但也体会到了之前的代码结构的缺陷:

(1)开发效率低:每次使用片内的某一资源(例如定时器等),笔者都要去查询CC2430中文手册,比较eggache~

(2)代码重复较多:每个实验源码中,诸如xtal_init,led_init等初始化函数每次都要编写

(3)不易修改:代码中的业务逻辑与SFR的操作混在一起,可读性较差,修改起来也费力

正是由于以上问题,笔者决定暂停了该系列博文的续写,抽出时间来思考一下解决办法。

笔者在学习嵌入式编程之前,曾有过https://www.wendangku.net/doc/ce7890641.html, 网站开发经验,对其分层理论也有所实践,下面简单提一下:

一般的有一定复杂度的网站可分为以下三层:

(1)数据接入层(DAL):负责与数据库的交互,供业务逻辑层调用

(2)业务逻辑层(BLL):调用数据接入层以获取数据,并为具体的业务需求提供支持

(3)用户界面层(UIL):负责呈现最终的用户界面

相信博客园中很大一部分朋友都对此非常熟悉,在此不再赘述。总之,分层以后,大大提高了代码的复用性与扩展性。

那么在嵌入式开发中,能否也利用分层的思想,来提高开发效率,增强其可维护性与可扩展性呢?下面,是一些笔者思考后的浅见。

当然不能照搬https://www.wendangku.net/doc/ce7890641.html, 的具体分层思想,具体问题得具体分析嘛~

首先,嵌入式开发的核心就是芯片,它提供固定的片内资源共开发者使用。而且它具有一个很重要的特点就是,不随项目的需求变动而变动。所以应将其作为最底层,为上层提供基础支持。我们将其命名为硬件抽象层(Hardware Abstract Layer)。

芯片有了当然还不够,通常我们会在片外扩展一些功能模块来满足具体的项目需求,例如:传感器、键盘、LCD屏等。这一层的特点是,随项目的变动而以模块为单位动态增减。这一层的运作需要芯片内部资源的支持,所以应处于硬件抽象层之上,并为上层调用。我们将其命名为功能模块层(Functional Module Layer)。

OK,现在原材料都准备齐了:芯片+扩展模块,接下来就要开始真正的加工了:我们需要灵活调用之前两层所提供的接口,实现具体的项目需求。我们将其命名为应用程序层(Application Layer)。

图文:

(1)硬件抽象层(HAL)

实现对片内资源(如定时器、ADC、中断、I/O等) 的通用配置,隐藏具体的SFR操作细节,为上层提供简单清晰的调用接口。

(2)功能模块层(FML)

通过调用HAL,实现项目中所涉及到的各片外功能模块,隐藏具体的模块操作细节,并为上层提供简单清晰的调用接口。

(3)应用程序层(APL)

通过调用HAL与FML,实现最终的应用功能。

四、小试牛刀

OK,我们举一个具体的例子,来说明分层思想的运用。

在写作“Zigbee之旅”系列的某一篇博文时,笔者需要完成一个略带综合性的小实验“温度监测系统”,需求分析大概如下:

? CC2430节点实现对温度的定时采集,并可通过LED灯指示其采样频率

?节点将数据传送至PC端

?节点可以接收来自PC的控制指令,以调整采样速率和电源模式

?具备停机自动复位能力

?可进入睡眠状态,并可由按键唤醒

从上面的需求中我们可以看出,本实验的核心芯片为CC2430,需要的片外扩展模块为LED灯与按键,预期要达到具体项目需求即以上五点。

接下来,我们利用上面提到的分层理论小试牛刀,对“温度监测系统”这一实验的代码结构进行规划:

(1)应用程序层(APL)

[main.c] 引用 hal.h、ioCC2430.h 与 module.h,实现温度采集、与PC互通信、停机复位等具体的应用需求

(2)功能模块层(FML)

[module.h] 定义了一系列片外功能模块(LED、按键),以及一系列的相关函数的声明

[module.c] 引用hal.h,实现各片外模块(LED、按键)的功能

(3)硬件抽象层(HAL)

[ioCC2430.h](系统自带):定义了CC2430的所有SFR 、中断向量

[hal.h] 包括常用类型定义、常用赋值宏、以及CC2430片上资源的配置(I/O、串口通讯、ADC、定时器、电源管理等)

(注:由于本实验所涉及的片外模块——LED与按键——的使用极其简单,所以笔者将其合并入了单个源文件。若遇到较复杂的模块,可以单独新建 .h 与 .c 文件来实现,如LCD.h、LCD.c)经此设计,其优点逐渐浮出水面:

? 高效的开发速率:编完HAL 层中的hal.h之后,我们就可以很方便地调用,而不必反复地去查询SFR的具体设置细则

? 快速扩展:若需要加强系统功能,只需在FML 层添加相应功能模块(即 .c 文件),并在 main.c 中

调用即可

? 较高的代码重用性:HAL 层所提供的SFR操作可供通用,而且该层几乎不用修改就可直接用于新的CC2430项目中

? 较好的可维护性:项目代码结构清晰,HAL 与FML 几乎不需要修改,只需修改APL 即可

五、结语

可能对于嵌入式编程高手来说,上述理论可能完全算不得什么,甚至还存在着很大的错误。不过在一个初学者从入门走向精通的途中,像这种发现问题→投入思考→提出方案的学习模式,我相信是值得而且很有必要的。就像很多人说的那样:过程比结论更重要。

接下来,笔者将会把大部分精力投入到“Zigbee之旅”的第一阶段的收尾工作中。希望在学习了C51编码规范,以及对代码分层的思考之后,我能够编写出一个虽然小但五脏俱全的项目代码。

敬请期待:Zigbee之旅(十):探索型综合小实验——基于CC2430的温度监测系统(未完成)

分类: 嵌入式开发

B

整理: MilerShao

近日,某工程师用STM32F103C8开发产品,用到TIM3的PWM输出功能。他发现TIM3_CH2可以实现PWM【此通道对应的GPIO脚是PB5】;而TIM3_CH1却不能实现PWM【此通道对应的GPIO脚是PB4】。该工程师在基于ST官方之前提供的标准外设固件库做应用软件设计。

从客户的描述来看,基本可以肯定TIM3的时钟、GPIOB的时钟都已正确使能了。关于TIM3_CH1的PWM 初始化代码应该不会有啥问题,除非偶尔的笔误没发现。后来一起查看了相关PWM初始化代码也的确没发现问题。

PB5脚对应的TIM3_CH2可以实现PWM,而PB4对应的TIM3_CH1却无法实现PWM。怀疑该脚是否还有其它的复用了。客户说,PB4他只用来做PWM输出,并无其它功能安排,硬件线路上也无其它连接。

打开芯片数据手册,查看PB4的管脚说明如下:

从这里可以看出,PB4脚的复位后的主功能是个特定功能脚,是JTAG口的一个复位脚。如果要用做TIM3_CH1的话得先做REMAP操作才可以。

经与客户工程师沟通,他的确也做了相关REMAP操作,而且REMAP是没问题的。因为PB5也是经过同一REMAP操作后才能成为TIM3_CH2通道的。

既然REMAP没问题,那应该是别的原因。询问该工程师是否使用JTAG调试口,答曰用SWD口,只涉及PBA13/PA14,根本没用到PB4。

查看STM32F1参考手册可以发现PB4及PA13\PA14\PA15\PB3等5个脚在芯片复位后默认的就是专用的调试口,非通用GPIO。现在客户工程师虽然用SWD接口,只用到PA13\PA14两根线,但PB4及PA15、PB3三根线的属性没变,还是专用调试口。如果要把不用的PB4等三根线作为GPIO,还得额外做些相关寄存器配置,即操作AFIO_MAPR寄存器中的SWJ_CFG【2:0】三个位。

让客户工程师在程序代码里添加有关AFIO_MAPR寄存器的配置代码后,测试基于PB4脚的TIM3_CH1的PWM输出功能,一切正常。看来,问题就出在跟调试口复用的GPIO脚释放问题上。即对于复位后呈现专用调试口的功能脚,欲部分或全部用在GPIO,得额外通过相关软件代码配置来修改其属性,将相关管脚释放为GPIO。

STM32 MCU芯片管脚复用之灵活而复杂是其一特色,增强了管脚使用与安排的灵活性。也正因为这个灵活,经常有人会因为管脚复用的安排遇到些小麻烦。像类似问题,在数据手册里各个管脚的复用功能都一一列出了,然后逐一核对有无多重使用问题也不难找到原因。

不过,如果使用ST公司的STM32CubeMx图形化配置工具来做管脚安排及时钟初始化等就可以避免很多类似上面谈到的繁琐或麻烦。利用STM32CubeMx配置工具,很多初始化的东西都可以依据你的管脚和时钟安排、外设功能的使能等而生成出相应的配置代码,不必手动二次添加配置,让你去专注你的用户应用代码设计与调试。

比方是以上面事例来谈,关于TIM3的功能脚的REMAP、JTAG脚的配置以及项目中用到的各外设的时钟使能、相关GPIO的配置等都可自动生成,不会出现配置代码方面丢这个少那个的问题,使用起来给开发者带来了不少方便,节省了不少时间。

C

由于板子上没有焊外部晶振,所以选择HSI(16MHZ)为时钟源通过PLL倍频。在第一帖中

https://www.wendangku.net/doc/ce7890641.html,/thread/277383/1写了一个简易的代码体验了一下工程的建立。其中没有配置时钟,程序在2MHZ的时钟频率下运行。程序效果是LED灯闪烁,程序中有一段延时是这么写的:

view plaincopy to clipboardprint?

1.void delay_test()

2.{

3. uint32_t ui_delay = 0xffff;

4. while(ui_delay--);

5.}

现在配置时钟为32MHZ,仍然使用这个延时函数,理论上是应该闪的更快。

打开STM32CUBEMX,选择新建工程,选择型号后配置外设资源:

板子上LED2接在PA5引脚上,所以配置PA5为输出模式

再配置时钟:

生成项目:

打开项目文件夹后,进入工程文件夹,打开MDK的工程:

在main.c中添加上面提到的延时函数,在添加如下代码作为测试:

view plaincopy to clipboardprint?

1.int main(void)

2.{

3.

4. /* USER CODE BEGIN 1 */

5.

6. /* USER CODE END 1 */

7.

8. /* MCU Configuration----------------------------------------------------------*/

9.

10. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

11. HAL_Init();

12.

13. /* Configure the system clock */

14. SystemClock_Config();

15.

16. /* System interrupt init*/

17. HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);

18.

19. /* Initialize all configured peripherals */

20. MX_GPIO_Init();

21.

22. /* USER CODE BEGIN 2 */

23.

24. /* USER CODE END 2 */

25.

26. /* USER CODE BEGIN 3 */

27. /* Infinite loop */

28. while (1)

29. {

30. HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);

31. delay_test();

32. HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);

33. delay_test();

34. }

35. /* USER CODE END 3 */

36.

37.}

编译之后,配置好DEBUG选项,下载程序,可以看到的效果是,LED灯闪烁的肉眼看不清,几乎是一直亮着。将延时函数中ui_delay = 0xffff;修改为ui_delay = 0xfffff;才可以看到LED闪烁起来。从效果上看,

时钟配置应该是有效果的

D

第一优先规则:

First Object = InPolygon,Second Object = All

第二优先规则:

First Object = All,Second Object = All

进入Design -> Rules -> Clearance 项目。选择第一个对象的匹配条件。现有的条件均没有Polygon 一项,于是进入

Query Builder。发现匹配条件中有Object Kind is 一项,而右侧列表中有Poly。依此设置点击OK 之后生成Full Query

内容为IsPolygon。那么满足IsPolygon 的对象与所有对象之间的间距肯定就是敷铜与所有对象之间的间距了,点击Apply

后报错“Some rules have incorrect definitions. Would you like to correct them?”说明此路不通:

设置Query

报错

心生好奇,上Google 搜索关键字“Altium (IsPolygon)”,返回第一个结果是Altium 官方的wiki 结果:https://www.wendangku.net/doc/ce7890641.html,/pages/viewpage.action?pageId=6848757

原来如彼,Polygon 本身作为对象是非法的,因为这里隐含的对象是导线之类的物体,不可能IsPolygon。必须用

InPolygon属性。而InPolygon 属性在Query Builder 里是找不到的。好奇尝试了一下用IsPolygon 做条件关键字,没有报

错,说明可行。

在Clearance 中右键添加新规则,并对新旧两个规则进行命名以便区分。而且我注意到两个规则有优先级之分:

我决定拿优先级为1的规则做通用规则,用于规范手动布线时属于不同网络的各种对象最小间距。而次优先的规则专门用

于限制敷铜与其它对象的最小间距。但我忽略了这是个逻辑问题,第一个规则里面的匹配条件必须彻底排除掉第二个规则所限

制的对象。如果没有排除,则优先级为1的规则会“覆盖”另一个规则。也就是说,如果第一个规则里的First Object 或者

Second Object 中任意一个可以包含InPolygon 这个属性,则第二个规则就形同虚设了。我想要的15mil间距不会出现,所有

的敷铜仍然按照8mil间距铺设。所以应该这样编辑第一个规则:

第二个规则:

打勾使这两组规则均生效,然后点OK。可以看到原先按照8mil间距铺设的敷铜已经被绿色高亮,明显已经无法通过规则检查。

重建敷铜,发现敷铜已经可以按照期望中的方式铺设。

单片机定时器习题

单片机定时器/计数器、中断和串行口习题 一、填空题 1、若要启动定时器T0开始计数,则应将TR0的值设置为 1 。 2、定时器T1工作在方式0时,其定时时间为(8192-定时器初值)*2us 。方式1时定时时间又为(65536-定时器初值)*2us 。 3、串行通信有异步通信和同步通信两种基本通讯方式。 4、波特率是指每秒钟传递信息的位数。 5、如果要将现有的波特率加倍,可使用指令MOV PCON,#80H 。 6、当串行口工作在方式1时,一帧信息共有10位,即起始位、8个数据位、停止位。 7、串行口工作在方式2时的波特率为fosc/32或fosc/64 。 8、外部中断1的程序入口地址是0013H 。 二、选择题 1、若要采用定时器0,方式1,如何设置TMOD__B__ A.00H B.01H C.10H D. 11H 2、单片机采用方式0时是13位计数器,它的最大定时时间是多少?_B__ A.81.92ms B.8.192ms C.65.536ms D.6.5536ms 3、以下哪项不是中断的特点? C A.分时操作 B.实时处理 C.在线编程 D.故障处理 4、外部中断响应时间至少需要__A个机器周期。 A.3 B.2 C.4 D.8 5、通过串口发送和接受数据时,在程序中使用__A___指令。 A.MOV BMOVX C.MOVC D.SW AP 6、以下哪个是中断优先级寄存器?__B A.IE B.IP C.TCON D.SCON 7、串行口中断的程序入口地址是 C 。 A 0003H B 001BH C 0023H D 000BH 三、判断题 1、8051的两个定时器T0和T1都是16位的计数器。(对) 2、单片机的计数器最高检测频率为振荡频率的1/12。(错) 3、定时/计数器的方式2具有自动装入初值的功能。(对) 4、引起中断的原因或发出中断申请的来源称为中断源。(对) 5、中断可使CPU和外设同时工作。(对) 6、定时器的特殊功能寄存器TMOD是用作中断溢出标志,并控制定时计数器的启动和停止。(错) 7、定时器控制寄存器TCON可以位寻址。(对) 8、MCS-51系列单片机的5个中断源都是可屏蔽中断。(对) 四、综合题

单片机中断程序大全

单片机中断程序大全公司内部编号:(GOOD-TMMT-MMUT-UUPTY-UUYY-DTTI-

//实例42:用定时器T0查询方式P2口8位控制L E D闪烁#include // 包含51单片机寄存器定义的头文件void main(void) { // EA=1; //开总中断 // ET0=1; //定时器T0中断允许 TMOD=0x01; //使用定时器T0的模式1 TH0=(65536-46083)/256; //定时器T0的高8位赋初值 TL0=(65536-46083)%256; //定时器T0的高8位赋初值 TR0=1; //启动定时器T0 TF0=0; P2=0xff; while(1)//无限循环等待查询 { while(TF0==0) ; TF0=0; P2=~P2; TH0=(65536-46083)/256; //定时器T0的高8位赋初值 TL0=(65536-46083)%256; //定时器T0的高8位赋初值 //实例43:用定时器T1查询方式控制单片机发出1KHz音频

#include // 包含51单片机寄存器定义的头文件sbit sound=P3^7; //将sound位定义为P3.7引脚 void main(void) {// EA=1; //开总中断 // ET0=1; //定时器T0中断允许 TMOD=0x10; //使用定时器T1的模式1 TH1=(65536-921)/256; //定时器T1的高8位赋初值 TL1=(65536-921)%256; //定时器T1的高8位赋初值 TR1=1; //启动定时器T1 TF1=0; while(1)//无限循环等待查询 { while(TF1==0); TF1=0; sound=~sound; //将P3.7引脚输出电平取反 TH1=(65536-921)/256; //定时器T0的高8位赋初值 TL1=(65536-921)%256; //定时器T0的高8位赋初值 } } //实例44:将计数器T0计数的结果送P1口8位LED显示 #include // 包含51单片机寄存器定义的头文件sbit S=P3^4; //将S位定义为P3.4引脚

51单片机中断定时器浅谈

51单片机中断定时器浅谈 中断处理函数原型 void timer1() interrupt0 using 0 timer1() 函数名 interrupt 表示是中断处理函数 0 表示是第几个中断源的处理函数 using 0 表示是使用第几组工作寄存器一般在C语言里面编译器屏蔽了会自动分配程序员一般不用关心。 注意:如果在中断处理函数中进行处理数据不能处理的数据量太大,因为定时器时间已到它就会又进入下一个中断处理函数,也就是这个中断处理函数还没有处理完下一个中断又来了。这样会造成结果错误或异常。 定时器: 定时器又2个寄存器控制,一个是TMOD 用于选择定时器、计数器 T0,T1的工作模式和工作方式。另一个是TCON 用于控制TO,T1的启动和停止,同时包含了T0,T1的状态,这2个寄存器在单片机复位时候所有位都被清0. TMOD 是不能位寻址的,因为它的地址是89H不能被8

整除。只能赋值或者进行与或运算进行赋值,其中有位是C/T 是把它配置成定时器还是计数器 0 表示是 定时器 M0,M1 这2位进行是定时器的模式几共4种模式其中方式1为16 高8位 TH0,低8位在 TL0 (65536-50000)/256 这就是高8位(65536-50000)%6 放入低8位是大约50毫秒前提是晶振为12兆赫。凡是用11.0592 的晶振是因为单片机要进行串口通讯因为 实现标准的波特率 4800 2400 115200 好计算。才选用11.0592的晶振。单片机的晶振可以选12兆一下的晶振都可以。12兆算是最快的速度了。当然不排除其他高速的单片级,可能达到更高运算速度。定时器最高一次定时为65535的数字,也就是大概65毫秒,因为是16位高8位低8位。所以如果用定时器长时间定时可以设置多次定时然后在main里面判断。实现长时间定时。定时器是一个加1的寄存器。初值最小为0 。最大65535 ,单片机做延时不占用MCU的资源比用 while 或 for循环好,能提高效率,当时浪费一个I/O口,所以用时综合考虑。 在一般情况下都是定时器与中断一起使用的,如:定时器时间到发生中断,一般都是IE TMOD TCON 三个寄存器联合使用 TCON 控制TR0 TR1 运行与停止 TMOD 控制工作模式 IE 控制总中断与对应的那个中断的开关

51单片机独立按键程序查询法和外部中断两种

//以下程序都是在VC++6.0 上调试运行过的程序,没有错误,没有警告。 //单片机是STC89C52RC,但是在所有的51 52单片机上都是通用的。51只是一个学习的基础平台,你懂得。 //程序在关键的位置添加了注释。 //用//11111111111111111代表第一个程序。//2222222222222222222222222代表第二个程序,以此类推 //1111111111111111111111111111111111111111111111111111111111111111111 //1111111111111111111111111111111111111111111111111111111111111111111 /****************************************************************************** * * 实验名: 左右流水灯实验 * 使用的IO : LED使用P2,键盘使用P3.1 * 实验效果: 按下K1键, * 注意: ******************************************************************************* / #include #include #define GPIO_LED P2 sbit K1=P3^1; void Delay10ms( ); //延时10ms /****************************************************************************** * * 函数名: main * 函数功能: 主函数 * 输入: 无 * 输出: 无 ******************************************************************************* / void main(void) { unsigned int i,j; j=0xfe; //1111_1110 while(1) { GPIO_LED=j; if(K1==0) //检测按键K1是否按下 { Delay10ms(); //消除抖动 if(K1==0) {

单片机中断实验报告

人的一生要疯狂一次,无论是为一个人,一段情,一段旅途,或一个梦想 ------- 屠呦呦 实验三定时器中断实验 一、实验目的 1、掌握51单片机定时器基本知识; 2、掌握定时器的基本编程方法; 3、学会使用定时器中断。 二、实验内容 1、利用定时器设计一个秒表,计数范围为0—59,并在数码管实时显示。 三、实验设备 PC 机一台、单片机实验箱 主要器件:AT89C52、7SEG-BCD、 四、实验步骤 1、使用Proteus设计仿真原理图; 2、使用Keil设计程序; 3、联合调试仿真。 五、实验流程图 六、实验程序与结果 #include #define uint unsigned int #define uchar unsigned char sbit F=P2^1;

void timer1_init() { TMOD=0x10;//将定时器1设置为工作方式1 TH1=(65536-6000)/256;//定时器每加一时间为1/fsoc,定时时间为1/500 //(1/500)s/(1/3000000)s=6000 TL1=(65536-6000)%256;//fsoc=3000000,所以装入16位定时器中值为65536-6000 EA=1; ET1=1; TR1=1; } void main() { timer1_init(); while(1); } void timer1() interrupt 3 { TH1=(65536-6000)/256;//每次进入中断,重装初值TL1=(65536-6000)%256; F=~F;//每次进入中断P1.1口取反 } #include #define uint unsigned int #define uchar unsigned char sbit F=P2^1; void timer0_init() {TMOD=0x01;//将定时器0设置为工作方式1 TH0=(65536-83)/256;//定时器每加一时间为1/fsoc,定时时间为2Khz,既500us //500us/6us=83.3333 TL0=(65536-83)%256;//fsoc=6000000,所以装入16位定时器中值为65536-83 EA=1; ET0=1; TR0=1; }void main() { timer0_init(); while(1); } void timer0() interrupt 1 { TH0=(65536-83)/256;//每次进入中断,重装初值 TL0=(65536-83)%256; F=~F;//每次进入中断P1.1口取反,表示定时时间到 } #include // 包含51单片机寄存器定义的头文件 #define seg_data P1 #define seg_data2 P3 #define uint unsigned int sbit D1=P2^0; //将D1位定义为P2.0引脚 uint counter=0; unsigned int unit=0,decade=0,avs=0;//time=0;

定时器中断程序设计实验

实验一定时器/中断程序设计实验 一、实验目的 1、掌握定时器/中断的工作原理。 2、学习单片机定时器/中断的应用设计和调试 二、实验仪器和设备 1、普中科技单片机开发板; 2、Keil uVision4 程序开发平台; 3、PZ-ISP 普中自动下载软件。 三、实验原理 805l 单片机内部有两个 16 位可编程定时/计数器,记为 T0 和 Tl。8052 单片机内除了 T0 和 T1 之外,还有第三个 16 位的定时器/计数器,记为 T2。它们的工作方式可以由指令编程来设定,或作定时器用,或作外部脉冲计数器用。定时器 T0 由特殊功能寄存器 TL0 和 TH0 组成,定时器 Tl 由特殊功能寄存器 TLl 和 TH1 组成。定时器的工作方式由特殊功能寄存器 TMOD 编程决定,定时器的运行控制由特殊功能寄存器 TCON 编程控制。T0、T1 在作为定时器时,规定的定时时间到达,即产生一个定时器中断,CPU 转向中断处理程序,从而完成某种定时控制功能。T0、T1 用作计数器使用时也可以申请中断。作定时器使用时,时钟由单片机内部系统时钟提供;作计数器使用时,外部计数脉冲由 P3 口的 P3.4(或 P3.5)即 T0(或 T1)引脚输入。 方式控制寄存器 TMOD 的控制字格式如下: 低 4 位为 T0 的控制字,高 4 位为 T1 的控制字。GATE 为门控位,对定时器/计数器的启动起辅助控制作用。GATE=l 时,定时器/计数器的计数受外部引脚输入电平的控制。由由运行控制位 TRX (X=0,1)=1 和外中断引脚(0INT 或 1INT)上的高电平共同来启动定时器/计数器运行;GATE=0时。定时器/计数器的运行不受外部输入引脚的控制,仅由 TRX(X=0,1)=1 来启动定时器/计数器运行。 C/-T 为方式选择位。C/-T=0 为定时器方式,采用单片机内部振荡脉冲的 12 分频信号作为时钟计时脉冲,若采用 12MHz 的振荡器,则定时器的计数频率为 1MHZ,从定时器的计数值便可求得定时的时间。 C/-T=1 为计数器方式。采用外部引脚(T0 为 P3.4,Tl 为 P3.5)的输入脉冲作为计数脉冲,当 T0(或 T1)输入信号发生从高到低的负跳变时,计数器加 1。最高计数频率为单片机时钟频率的 1/24。 M1、M0 二位的状态确定了定时器的工作方式,详见表。

51单片机定时中断C语言的写法步骤

51单片机定时中断C语言的写法步骤 程序说明:51单片机定时器0工作于方式一,定时50ms中断一次 晶振为12M #include void main { TOMD = 0X01;//配置定时器0工作于方式一 TH1 = (65536-50000)/256; //高八位装入初值 TL1 = (65536-50000)%256; //低八位装入初值 ET0 = 1; //开定时器0中断 EA = 1; //开总中断 TR0 = 1; //启动定时器0 while(1) { ; } } void Timer0_int() interrupt 1 { //重新装初值 TH1 = (65536-50000)/256; //高八位装入初值 TL1 = (65536-50000)%256; //低八位装入初值 } /****************************************************************************** *********************************/ 上面是比较好理解的。如果实在要求简洁的话,看下面的,跟上面功能一样 #include void main { TOMD = 0X01;//配置定时器0工作于方式一 TH1 = 0x3c; //高八位装入初值 TL1 = 0xb0; //低八位装入初值 IE = 0x82;//开总中断并开定时器0中断 TR0 = 1; //启动定时器0 while(1) { ; } }

void Timer0_int() interrupt 1 { //重新装初值 TH1 = 0x3c; //高八位装入初值TL1 = 0xb0; //低八位装入初值}

单片机的中断与定时

第五章单片机的中断与定时 重点及难点: 单片机中断与定时的基本概念、单片机的中断系统、单片机的定时器/计数器、单片机外部中断源的扩展。 教学基本要求: 1、掌握单片机中断与定时的基本概念; 2、掌握单片机的中断源、中断控制、中断响应过程的基本概念及单片机中断系统的功 能和使用方法; 3、掌握单片机的定时器/计数器的初值计算、工作方式控制寄存器的初始化、程序的设 计方法和步骤; 4、了解单片机外部中断源扩展的常用方法和步骤。 教学内容 §5.1 中断的基本知识 一、一般微机的输入/输出方式 1.条件传送方式 2.查询传送方式 3.直接存储器存取(DMA—Direct Memory Access)方式 4.中断传送方式 二、中断概述 (一)中断的概念 所谓“中断”,是指计算机在执行某一段程序的过程中,由于计算机系统内、外的某种原因,有必要中止原程序的执行,而去执行相应的处理程序,待处理结束后,再返回来继续执行本中断的原程序的过程。 (二)中断源 引起中断的原因,或是能发出中断申请的来源,称为中断源。 (三)中断的分类 (1)屏蔽中断 (2)非屏蔽中断。 (3)软件中断。 (四)中断的开放与关闭 中断的开放与关闭,亦称为开中断和关中断。这是指CPU中断系统的状态,只有当CPU 处于开中断状态时,才能接受外部的中断申请。反之,当CPU处于关中断状态时,则不能接

受外部的中断申请。 (五)中断的优先级 (六)中断处理过程 一个完整的中断处理的基本过程应包括:中断请求、中断响应、中断处理和中断返回。 §5.2 MCS-51单片机的中断系统 一、中断源 (一)外中断 (二)定时中断 (三)串行中断 MCS-51中断系统结构框图 二、中断控制 (一)定时器控制寄存器(TCON) 1.IE0和IE1—外中断请求标志位 2.IT0和IT1—外中断请求触发方式控制位 IT0(IT1)= 1 脉冲触发方式,后沿负跳有效。 IT0(IT1)= 0 电平触发方式,低电平有效。 此位由软件置“1”或清“0”。 3.TF0和TF1—计数溢出标志位 (二)串行口控制寄存器(SCON) 1.TI —串行口发送中断请求标志位 2.RI —串行口接收中断请求标志位 (三)中断允许控制寄存器(IE)

单片机实验 中断、定时器

大连理工大学实验报告(模板) 实验时间:年月日星期时间::~ : 实验室(房间号):实验台号码:班级:姓名: 指导教师签字:成绩: 实验三外部中断/INT0实验 一、实验目的和要求 学习、掌握单片机的中断原理。正确理解中断矢量入口、中断调用和中断返回的概念及物理过程。学习编写“软件防抖”程序,了解“软件防抖”原理。 对/int0、/int1两个外部中断进行编程,其中: ●主程序的功能:LDE灯“全亮”、“全灭”交替进行 --------(状态2); ●Int0中断服务程序功能:2个相邻的LED灯被点亮且循环左移(状态0); ●Int1中断服务程序功能:1个LED灯被点亮且循环右移 ---(状态1);【注意】:实验仪上的LED灯物理位置最左侧为d0;最右侧为d7。 二、实验算法 1 在主程序中利用CPL P3.3的指令驱动其电平不断地转换(由逻辑笔电路做程序状态监视)。 2 在中断服务程序中将P3.3置位(P3.3=1),实现对计数器“加1”并(通过P1口)显示的功能。 3 中断结束后回到主程序,程序继续对P3.3的电平不断取反。 三、实验电路图

四、实验流程图 主程序入口INT0入口 设置中断允许P3.2置1 设置中断优先级调用延时子程序 设TCON 计数器加一并显示 CLR A开中断 (P0)—(A) P3.2=0? 调用延时子程序调用延时子程序 (A)—(A) RETI INT1同理 五、程序清单 ORG 0000H LJMP START ORG 0003H LJMP INT_0 ORG 0013H LJMP INT_1 ORG 0100H ;主程序 START: MOV SP,#60H MOV IE,#85H

51单片机实验——单片机定时与外部中断

实验题目:单片机定时与外部中断的作用1 一、实验目的 1)熟悉单片机定时功能的使用 2)熟悉外部中断的使用 3)熟悉一些常用的C语言编程语句 4)熟练单片机的一些使用及操作方法 二、实验原理 工作原理框图 7_SEG_LED:

8_BI Ts_LED: 三、参考程序 #include #define FOSC 11059200L #define BAUD 9600 #define TRUE 1 #define FALSE 0 int CmpCnt; int T0IntCnt; bit FlagTimerOk; unsigned char LedVal; sbit HC373_CLK = P3^6;sbit Int0=P3^2; sbit P1_4=P1^4;sbit P1_5=P1^5;sbit P1_6=P1^6;sbit P1_7=P1^7; unsigned char code a[10]={0x03,0x9f,0x25,0x0d,0x99,0x49,0x41,0x1f,0x01,0x19};

void Init_T0(void) { TMOD = 0x01; //T0 方式1 TH0 = (65536-(FOSC)/1200)/256; TL0 = (65536-(FOSC)/1200)&0xff; ET0 = 1; TR0 = 1; } void Init_Uart(void) { SCON = 0x50; //UART设置 PCON = 0x80; TMOD = 0x21; TH1=0xfa; //定时器1设置 TL1=0xfa; TR1=1; ES=1; EA=1; } void Init_INT0(void) interrupt 0 { int s; s=0; while(Int0==0) s++; //防抖设置if(s>100) { if(CmpCnt>1) CmpCnt=CmpCnt-1; else CmpCnt=50; s=0;

51单片机C语言中断程序定时计数器

51单片机C语言中断程序定时/计数器 程序一 利用定时/计数器T0从P1.0输出周期为1s 的方波,让发光二极管以1HZ闪烁, #include //52单片机头文件 #include //包含有左右循环移位子函数的库#define uint unsigned int //宏定义 #define uchar unsigned char //宏定义 sbit P1_0=P1^0; uchar tt; void main() //主函数 { TMOD=0x01;//设置定时器0为工作方式1 TH0=(65536-50000)/256; TL0=(65536-50000)%256; EA=1;//开总中断 ET0=1;//开定时器0中断 TR0=1;//启动定时器0 while(1);//等待中断产生 }

void timer0() interrupt 1 { TH0=(65536-50000)/256; TL0=(65536-50000)%256; tt++; if(tt==20) { tt=0; P1_0=~P1_0; } } 程序二 利用定时/计数器T1产生定时时钟, 由P1口控制8个发光二极管, 使8个指示灯依次一个一个闪动, 闪动频率为10次/秒(8个灯依次亮一遍为一个周期),循环。#include //52单片机头文件 #include //包含有左右循环移位子函数的库 #define uint unsigned int //宏定义 #define uchar unsigned char //宏定义

单片机定时器详解

一、MCS-51单片机的定时器/计数器概念 单片机中的定时器和计数器其实是同一个物理的电子元件,只不过计数器记录的是单片机外部发生的事情(接受的是外部脉冲),而定时器则是由单片机自身提供的一个非常稳定的计数器,这个稳定的计数器就是单片机上连接的晶振部件;MCS-51单片机的晶振经过12分频之后提供给单片机的只有1MHZ的稳定脉冲;晶振的频率是非常准确的,所以单片机的计数脉冲之间的时间间隔也是非常准确的,这个准确的时间间隔是1微秒; MCS-51单片机外接的是12MHZ的晶振(实际上是11.0592MHZ),所以,MCS-51单片机内部的工作频率(时钟脉冲频率)是12MHZ/12=1MHZ=1000000次/秒=1000000条指令/秒=1000000次/1000000微秒=1次/微秒=1条指令/微秒;也就是说,晶振振荡一次,就会给单片机提供一个时钟脉冲,花费的时间是1微秒,此时,CPU会执行一条指令,经历一个机器周期;即:1个时钟脉冲=1个机器周期=1微秒=1条指令; 注:个人PC机上的CPU主频是晶振经过倍频之后的频率,这一点恰好与MCS-51单片机的相反,MCS-51单片机的主频是晶振经过分频之后的频率; 总之:MCS-51单片机中的时间概念就是通过计数脉冲的个数来测量出来的;1个脉冲=1微秒=1条指令=1个机器周期; MCS-51单片机定时器/计数器的简单结构图: 8051系列单片机有两个定时器:T0和T1,分别称为定时器和定时器T1,这两个定时器都是16位的定时器/计数器;8052系列单片机增加了第三个定时器/计数器T2;它们都有定时或事件计数功能,常用于时间控制、延时、对外部时间计数和检测等场合; 二、定时器/计数器的结构 8051单片机的两个定时器T0和T1分别都由两个特殊功能寄存器组成;T0由特殊功能寄存器

51单片机外部中断与定时器的实用

中断使能寄存器 通过设置中断使能寄存器 IE 的 EA 位 使能所有中断 每个中断源都有单独的使能位 可通过软件设置 IE 中相应的使能位在任何时候使能或禁能中断 中断使能寄存器 IE 的各 位如下所示 中断使能寄存器IE 位地址 0AFH 0AEH 0ADH 0ACH 0ABH 0AAH 0A9H 0A8H 位符号 EA / ET2 ES ET1 EX1 ET0 EX0 EA 使能标志位 置位则所有中断使能 复位则禁止所有中断保留 ET2 定时器2 中断使能 ES 串行通信中断使能 ET1 定时器 1 中断使能 EX1 外部中断 1 使能 ET0 定时器0 中断使能 EX0 外部中断 0使能 8051 支持两个中断优先级 有标准的中断机制, 低优先级的中断只能被高优先级的中断所中断 ,而高优先级的中断不能被中断。 中断优先级寄存器 每个中断源都可通过设置中断优先级寄存器IP 来单独设置中断优先级 如果每个中断源的相应位被置位 则该中断源的优先级为高,如果相应的位被复位, 则该中断源的优先级为低, 如果你觉得两个中断源不够用 ,别急以后我会教你如何增加中断优先级 表 A-5 示出了 IP 寄存器的各位 此寄存器可位寻址 IP 寄存器 位地址 0BFH 0BEH 0BDH 0BCH 0BBH 0BAH 0B9H 0B8H 位符号 / / / PS PT1 PX1 PT0 PX0 编号 中断源 中断向量 上电复位 0000H 0 外部中断0 0003H 1 定时器0溢出 000BH 2 外部中断1 0013H 3 定时器1溢出 001BH 4 串行口中断 0023H 5 定时器2溢出 002BH PT2 定时器 2中断优先级 PS 串行通信中断优先级 PT1 定时器 1中断优先级 PX1 外部中断1 优先级 PT0 定时器0中断优先级 PX0 外部中断0 优先级

实验五 8051单片机定时中断实验

实验五8051单片机定时中断实验 一实验目的: 了解8051系列单片机的定时中断基本工作原理。掌握8051系列单片机定时中断的用法。 二实验原理: 在上一个实验里我们介绍了8051单片机的外中断应用,本实验要介绍的是定时器中断的应用。 8051系列单片机至少有两个16位的内部定时器/计数器,既可以编程为定时器使用,也可以作为计数器使用。如果是计数内部晶振驱动时钟,它是定时器,如果是计数8051的输入管脚的信号,就是计数器。 MCS-51单片机内部的定时/计数器的结构如图5-1所示,定时器T0特性功能寄存器TL0(低8位)和TH0(高8位)构成,定时器T1由特性功能寄存器TL1(低8位)和TH1(高8位)构成。特殊功能寄存器TMOD控制定时寄存器的工作方式,TCON则用于控制定时器T0和T1的启动和停止计数,同时管理定时器T0和T1的溢出标志等。程序开始时需对TL0、TH0、TL1和TH1进行初始化编程,以定义它们的工作方式和控制T0和T1的计数。 图5-1 TMOD特殊功能寄存器的格式参见下表(表5-1): 表5-1 高4位为定时器/计数器1的控制字,低4位为定时器/计数器0的控制字。其中GATE 为门控信号,C/T为定时器或计数器的选择,而M1,M0是工作方式选择位。 当M1M0=00时,T/C工作在方式0。方式0为13位的T/C,其计数器由TH的8位和TL的5

位构成,计数器的计数值范围是: 1—8192(213),但是启动前可以预置计数初值。当C/T为 0时,T/C为定时器,计数脉冲为振荡源12分频的信号;当C/T为1时,T/C为计数器,对输入端T0或T1输入的脉冲进行计数。计数脉冲加到计数器上与否决定于启动信号。当GATE=0时,TR=1时T/C便启动,当GATE=1时,启动受到TR与INT的双重控制,即二者同时为高 时才启动。当计数满时,TH向高位进位,这时中断溢出标志TF置1,即产生中断请求。而当CPU转向中断服务程序时,TF自动清零。 当M1M0=01时,T/C工作在方式1。方式1和方式0的区别仅在于方式0的计数器位数为13位,而方式1的为16位。 当M1M0=10时,T/C工作在方式2。区别于前面的两种工作方式的是,方式2具有自动重装载的功能。TH和TL作为两个8位的计数器,TH中的8位初值始终保持不变,由TL进行8位计数。在计数溢出时不但会产生中断请求,而且自动将TH中的值加载至TL 中,即自动重装载。 当M1M0=11时,T/C工作在方式3。但是这种工作方式只存在于T/C0中,这时TH0与TL0成为两个独立的计数器。只有在T/C1作为串行口的波特率发生器使用,而造成定时器不够用时,T/C0才能工作在方式3。 下面是定时器时间常数计算公式,这个公式在方式1,即16 位定时或计数模式可用。 THX=(65536-定时时长[μS]/(机器周期数/时钟频率[MHz])/256; TLX=(65536-定时时长[μS]/(机器周期数/时钟频率[MHz])%256; 在定时器重装载过程中因为TL1=0可以不写。 三实验内容: 利用中断方式在LED上输出10HZ方波,系统晶体频率11.059MHz。 四实验电路图:

单片机外部中断详解及程序

单片机外部中断详解及程序 单片机在自主运行的时候一般是在执行一个死循环程序,在没有外界干扰(输入信号)的时候它基本处于一个封闭状态。比如一个电子时钟,它会按时、分、秒的规律来自主运行并通过输出设备(如液晶显示屏)把时间显示出来。在不需要对它进行调校的时候它不需要外部干预,自主封闭地运行。如果这个时钟足够准确而又不掉电的话,它可能一直处于这种封闭运行状态。但事情往往不会如此简单,在时钟刚刚上电、或时钟需要重新校准、甚至时钟被带到了不同的时区的时候,就需要重新调校时钟,这时就要求时钟就必须具有调校功能。因此单片机系统往往又不会是一个单纯的封闭系统,它有些时候恰恰需要外部的干预,这也就是外部中断产生的根本原由。 实际上在第二个示例演示中,就已经举过有按键输入的例子了,只不过当时使用的方法并不是外部中断,而是用程序查询的方式。下面就用外部中断的方法来改写一下第二个示例中,通过按键来更改闪烁速度的例子(第二个例子)。电路结构和接线不变,仅把程序改为下面的形式。 #include ;

unsigned int t=500; //定义一个全局变量t,并设定初始值为500次 //===========延时子函数,在8MHz晶振时约 1ms============= void delay_ms(unsigned int k) { unsigned int i,j; for(i=0;i

单片机定时器中断时间误差的解决方案

单片机定时器中断时间误差的解决方案 时间:2012-06-12 14:04:04 来源:作者: 1 前言 单片机内部一般有若干个定时器。如8051单片机内部有定时器0和定时器1。在定时器计数溢出时,便向CPU发出中断请求。当CPU正在执行某指令或某中断服务程序时,它响应定时器溢出中断往往延迟一段时间。这种延时虽对单片机低频控制系统影响甚微,但对单片机高频控制系统的实时控制精度却有较大的影响,有时还可能造成控制事故。为扩大单片机的应用范围,本文介绍它的定时器溢出中断与CPU响应中断的时间误差、补偿误差的方法和实例。 2 误差原因、大小及特点 产生单片机定时器溢出中断与CPU响应中断的时间误差有两个原因。一是定时器溢出中断信号时,CPU正在执行某指令;二是定时器溢出中断信号时,CPU正在执行某中断服务程序。 2.1. CPU正在执行某指令时的误差及大小 由于CPU正在执行某指令,因此它不能及时响应定时器的溢出中断。当CPU执行此指令后再响应中断所延迟的最长时间为该指令的指令周期,即误差的最大值为执行该指令所需的时间。由于各指令都有对应的指令周期,因此这种误差将因CPU正在执行指令的不同而不同。如定时器溢出中断时,CPU正在执行指令MOV A, Rn,其最大误差为1个机器周期。而执行指令MOV Rn, direct时,其最大误差为2个机器周期。当CPU正在执行乘法或除法指令时,最大时间误差可达4个机器周期。在8051单片机指令系统中,多数指令的指令周期为1~2个机器周期,因此最大时间误差一般为1~2个机器周期。若振荡器振荡频率为fosc,CPU正在执行指令的机器周期数为Ci,则最大时间误差为Δtmax1=12/fosc× Ci(us)。例如fosc=12MHZ,CPU正在执行乘法指令(Ci=4),此时的最大时间误差为: Δtmax1=12/fosc×Ci=12/(12×106)×4=4×10-6(s)=4(μs)

51单片机定时器与中断

例1:查询方式 ORG 0000H AJMP START ORG 30H START: MOV P1,#0FFH ;关所灯 MOV TMOD,#00000001B ;定时/计数器0工作于方式1 MOV TH0,#15H MOV TL0,#0A0H ;即数5536 SETB TR0 ;定时/计数器0开始运行 LOOP:JBC TF0,NEXT ;如果TF0等于1,则清TF0并转NEXT处 AJMP LOOP ;不然跳转到LOOP处运行 NEXT:CPL P1.0 MOV TH0,#15H MOV TL0,#9FH;重置定时/计数器的初值 AJMP LOOP END AJMP LOOP END 键入程序,看到了什么?灯在闪烁了,这可是用定时器做的,不再是主程序的循环了。简单地分析一下程序,为什么用JBC呢?TF0是定时/计数器0的溢出标记位,当定时器产生溢出后,该位由0变1,所以查询该位就可知宇时时间是否已到。该位为1后,要用软件将标记位清0,以便下一次定时是间到时该位由0变1,所以用了JBC指令,该指位在判1转移的同时,还将该位清0。 以上程序是能实现灯的闪烁了,可是主程序除了让灯闪烁外,还是不能做其他的事啊!不,不对,我们能在LOOP:……和AJMP LOOP指令之间插入一些指令来做其他的事情,只要保证执行这些指令的时间少于定时时间就行了。那我们在用软件延时程序的时候不是也能用一些指令来替代DJNZ吗?是的,但是那就要求你精确计算所用指令的时间,然后再减去对应的DJNZ循环次数,很不方便,而现在只要求所用指令的时间少于定时时间就行,显然要求低了。当然,这样的办法还是不好,所以我们常用以下的办法来实现。 程序2:用中断实现 ORG 0000H ,https://www.wendangku.net/doc/ce7890641.html, AJMP START ORG 000BH ;定时器0的中断向量地址 AJMP TIME0 ;跳转到真正的定时器程序处 ORG 30H START: MOV P1,#0FFH ;关所灯 MOV TMOD,#00000001B ;定时/计数器0工作于方式1 MOV TH0,#15H MOV TL0,#0A0H ;即数5536 SETB EA ;开总中断允许 SETB ET0 ;开定时/计数器0允许 SETB TR0 ;定时/计数器0开始运行 LOOP: AJMP LOOP ;真正工作时,这里可写任意程序 TIME0: ;定时器0的中断处理程序

单片机定时器实验

实验三单片机内部定时器应用 实验目的 1、理解单片机内部定时器的工作原理及使用方法 2、了解单片机定时中断程序的编写和调试方法 3、掌握定时器的基本使用方法 实验仪器 单片机开发板、万利仿真机、稳压电源、计算机 实验原理 1、单片机定时器的工原理 MCS-51 单片机内部有两个16 位可编程的定时器/计数器T0 和T1。它们即可用作定时器方式,又可用作计数器方式。其中T0 由TH0 和TL0 计数器构成;T1 由TH1 和TL1 计数器构成。 工作于定时器方式时,通过对机器周期(新型51单片机可以对振荡周期计数)的计数,即每一个机器周期定时器加1,来实现定时。故系统晶振频率直接影响定时时间。如果晶振频率为12MHZ,则定时器每隔(1/12MHZ)×12=1us 加1。 工作于计数器方式时,对P3.4 或P3.5 管脚的负跳变(1→0)计数。它在每个机器周期的S5P2 时采样外部输入,当采样值在这个机器周期为高,在下一个机器周期为低时,计数器加1。因此需要两个机器周期来识别一个有效跳变,故最高计数频率为晶振频率的1/24。 特殊功能寄存器TMOD 用于定时器/计数器的方式控制。高4 位用于设置T1,低4 位用于设置T0。如图4-7所示。 图4-7 定时器模式控制字格式 TCON 寄存器用于定时器的计数控制和中断标志。如图4-8所示。 图4-8 定时控制寄存器数据格式 编写程序控制这两个寄存器就可以控制定时器的运行方式。 单片机内部定时器/计数器的使用,简而概之:(1)如需用中断,则将EA和相关中断控制位置1;(2)根据需要设置工作方式,即对TMOD设置;(3)然后启动计数,即对TR0或TR1置1。(4)如使用中断,则计数溢出后硬件会自动转入中断入口地址;如使用查询,则必须对溢出中断标志位TF0或TF1进行判断。

单片机定时器中断时间误差的分析及补偿

单片机定时器中断时间误差的分析及补偿 admin3 发表于 2006-02-19 14:43:24 阅读全文 | 回复(0) | 引用通告 | 编辑 摘要:本文分析了单片机定时器溢出中断与CPU响应中断的时间误差,并给出了补偿误差的方法和实例。 关键词:单片机; 定时器; 中断; 误差 1前言 单片机内部一般有若干个定时器。如8051单片机内部有定时器0和定时器1。在定时器计数溢出时,便向CPU发出中断请求。当CPU正在执行某指令或某中断服务程序时,它响应定时器溢出中断往往延迟一段时间。这种延时虽对单片机低频控制系统影响甚微,但对单片机高频控制系统的实时控制精度却有较大的影响,有时还可能造成控制事故。为扩大单片机的应用范围,本文介绍它的定时器溢出中断与CPU响应中断的时间误差、补偿误差的方法和实例。 2误差原因、大小及特点 产生单片机定时器溢出中断与CPU响应中断的时间误差有两个原因。一是定时器溢出中断信号时,CPU正在执行某指令;二是定时器溢出中断信号时,CPU正在执行某中断服务程序。 2.1.CPU正在执行某指令时的误差及大小 由于CPU正在执行某指令,因此它不能及时响应定时器的溢出中断。当CPU执行此指令后再响应中断所延迟的最长时间为该指令的指令周期,即误差的最大值为执行该指令所需的时间。由于各指令都有对应的指令周期,因此这种误差将因CPU正在执行指令的不同而不同。如定时器溢出中断时,CPU正在执行指令MOVA,Rn,其最大误差为1个机器周期。而执行指令MOVRn, direct时,其最大误差为2个机器周期。当CPU正在执行乘法或除法指令时,最大时间误差可达4个机器周期。在8051单片机指令系统中,多数指令的指令周期为1~2个机器周期,因此最大时间误差一般为1~2个机器周期。若振荡器振荡频率为fosc,CPU正在执行指令的机器周期数为Ci,则最大时间误差为Δtmax1=12/fosc×Ci(us)。例如fosc=12MHZ,CPU正在执行乘法指令(Ci=4),此时的最大时间误差为: Δtmax1=12/fosc×Ci=12/(12×106)×4=4×10-6(s)=4(μs) 2.2CPU正在执行某中断服务的程序时的误差及大小 定时器溢出中断信号时,若CPU正在执行同级或高优先级中断服务程序,则它仍需继续执行这些程序,不能及时响应定时器的溢出中断请求,其延迟时间由中断转移指令周期T1、中断服务程序执行时间T2、中断返回指令的指令周期T3及中断返回原断点后执行下一条指令周期T4(如乘法指令)组成。中断转移

单片机定时器汇编

我们在学单片机时我们第一个例程就是灯的闪烁,那是用延时程序做的,现在回想起来,这样做不很恰当,为什么呢我们的主程序做了灯的闪烁,就不能再干其它的事了,难道单片机只能这样工作吗当然不是,我们能用定时器来实现灯的闪烁的功能。例1:查询方式ORG 0000H AJMP START ORG 30H START: MOV P1,#0FFH ;关所灯 MOV TMOD,#00000001B ;定时/计数器0工作于方式1 MOV TH0,#15H MOV TL0,#0A0H ;即数5536 SETB TR0 ;定时/计数器0开始运行 LOOP: JBC TF0,NEXT ;如果TF0等于1,则清TF0并转NEXT处(LOOP:JNB TF0,$) AJMP LOOP ;不然跳转到LOOP处运行 NEXT: CPL MOV TH0,#15H MOV TL0,#9FH;重置定时/计数器的初值 AJMP LOOP END 键入程序,看到了什么灯在闪烁了,这可是用定时器做的,不再是主程序的循环了。简单地分析一下程序,为什么用JBC呢TF0是定时/计数器0的溢出标记位,当定时器产生溢出后,该位由0变1,所以查询该位就可知宇时时间是否已到。该位为1后,要用软件将标记位清0,以便下一次定时是间到时该位由0变1,所以用了JBC指令,该指位在判1转移的同时,还将该位清0.以上程序是能实现灯的闪烁了,可是主程序除了让灯闪烁外,还是不能做其他的事啊!不对,我们能在LOOP:……和AJMP LOOP指令之间插入一些指令来做其他的事情,只要保证执行这些指令的时间少于定时时间就行了。那我们在用软件延时程序的时候不是也能用一些指令来替代DJNZ吗是的,但是那就要求你精确计算所用指令的时间,然后再减去对应的DJNZ循环次数,很不方便,而现在只要求所用指令的时间少于定时时间就行,显然要求低了。当然,这样的办法还是不好,所以我们常用以下的办法来实现。程序2:用中断实现 ORG 0000H AJMP START ORG 000BH ;定时器0的中断向量地址 AJMP TIME0 ;跳转到真正的定时器程序处 ORG 30H START: MOV P1,#0FFH ;关所灯 MOV TMOD,#00000001B ;定时/计数器0工作于方式1 MOV TH0,#15H MOV TL0,#0A0H ;即数5536 SETB EA ;开总中断允许 SETB ET0 ;开定时/计数器0允许 SETB TR0 ;定时/计数器0开始运行 SJMP $ ;LOOP: AJMP LOOP ;真正工作时,这里可写任意程序 TIME0:

相关文档
相关文档 最新文档