1要注意中断程序的优先级。
2中断子程序尽量短。不要把耗费资源的计算放在中断子程序中,除非是对时间要求非常敏感应用,如电机的FOC算法,才能在中断程序里面之行。
3 各个中断程序中的处理不要相互冲突,中断是否能嵌套也要小心。
/
文件名 : 定时器的使用c
描述 : 相对前面的软件延时,定时器的延时更为精确。
定时时间可用光盘中的“51定时器计算exe”计算。该软件
位于单片机开发辅助工具文件夹中。
相应的视频为“定时器的使用exe”。
创建人 : 东流,2009年4月8日
版本号 : 20
/
#include<reg52h>
#define uchar unsigned char
#define uint unsigned int
uchar Count = 0;
uchar code table[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar code LED_W[8] = {0,4,2,6,1,5,3,7};
/
名称 : Time0_Init()
功能 : 定时器的初始化,110592MZ晶振,50ms
输入 : 无
输出 : 无
/
void Time0_Init()
{
TMOD = 0x01;
IE = 0x82;
TH0 = 0x4c;
TL0 = 0x00;
TR0 = 1;
}
/
名称 : Time0_Int()
功能 : 定时器中断,中断中实现 Count 加一
输入 : 无
输出 : 无
/
void Time0_Int() interrupt 1
{
TH0 = 0x4c;
TL0 = 0x00;
Count++; //长度加1
}
/
名称 : Main()
功能 : 主函数
输入 : 无
输出 : 无
/
void main()
{
uchar i = 0;
Time0_Init();
while(1)
{
P0 = table[i % 10]; //取 i 的个位
P2 = LED_W[0];
while(1)
{
if(Count == 20) //当Count为 20 时,i 自加一次,20 50MS = 1S
{
Count = 0;
i++;
break;
}
}
}
}
主要是出于效率方面的考量。中断处理程序需要在尽量短的时间内完成所需的必要处理,尽量减少对线程/程序流造成的影响,因此大部分情况下用汇编直接编写,跳过了通用编译过程中冗余的适配部分。
汇编语言是汇编指令集、伪指令集和使用它们规则的统称,使用具有一定含义的符号为助记符。由于汇编语言是完全依赖于硬件的,因此通过适当的汇编程序设计,能够充分发挥出硬件的潜力,产生高效率的运行代码。
不光是中断处理程序,有许多软件系统的内核(例如 *** 作系统内核)都是用汇编语言编写的。
主程序:
push ds ;保存数据段
mov ax,0000
mov ds,ax ;数据段清零
mov ax,offset irq7 ;取中断程序入口地址
add ax,2000 ;加装时IP=2000地址
mov si,003c ;填8259中断7中断矢量
mov w[si],ax ;填偏移量矢量
mov ax,0000 ;段地址CS=0000H
mov si,003e
mov w[si],ax ;填段地址矢量
pop ds ;d栈
in al,21 ;读8259中断屏蔽字
and al,7f ;开8259中断7
out 21,al
mov al,b4 ;8253的计数器2为方式2,采用二进制计数,先低后高写入计数值 10110100
out 43,al ;写入方式控制字
mov ax,2e9c 0010 1110 1001 1100B 11932D
out 42,al ;写入低字节计数值 1001 1100
mov al,ah
out 42,al ;写入高字节计数值 0010 1110
mov al,81 ;8255的A口为方式0输出,B口为方式0输出,C口下部输入 1000 0001
out 63,al ;写方式控制字
call first ;调用first子程序,赋计数初值
begi:hlt 延时等待
sti ;开中断
mov ah,01
int 16 ;检测是否按了键盘
jz begi
mov ah,00 ;读键值
int 16
cmp al,0d ;是否按了回车
jnz A1
mov si,4000
not [si+04] ;偏移地址为4004的内存单元内容取反
jmp begi
A1:cmp al,1b ;是否按了ESC键
jnz A2
call first ;重新赋初值,相当于清零
A2:jmp begi
中断程序:
irq7:call disp ;调用disp子程序,用来在数码管显示数据
mov si,4000
cmp [si+04],00 ;判断是否按了第2次回车键
je A4
call addn ;调用addn子程序,用来计数
A4:mov al,20
out 20,al
cli ;关中断
iret ;返回
addn程序:
addn:mov si,4000
add [si+03],01 ;百分之一秒加1
cmp [si+03],0a ;判断是否大于10
jz A5
jmp A9
A5:mov [si+03],00
Add [si+02],01 ;十分之一秒加1
cmp [si+02],0a ;判断是否大于10
jz A6
jmp A9
A6:mov [si+02],00
add [si+01],01 ;秒位加1
cmp [si+01],0a ;判断是否大于10
jz A7
jmp A9
A7:mov [si+01],00
add [si],01 ;十秒位加1
cmp [si],06 ;判断是否大于6
jz A8
jmp A9
A8:mov [si],00 ;大于60:00重新开始
A9: ret
赋初值程序:
first:mov si,4000
mov al,00
mov [si],al
mov [si+01],al
mov [si+02],al
mov [si+03],al
mov [si+04],al
ret
显示程序:
disp:push ax ;保存AX
mov si,4000 ;指向数据缓冲区
mov dl,f7 ;1111 0111 指向数码管
mov al,dl ;al=1111 0111
again:out 60,al ;写端口A
mov al,[si]
mov bx,4100 ;指向数码缓冲区 bx=0100 0001 0000 0000
and ax,00ff ; ax=0000 0000 al
add bx,ax ;得到显示代码 bx=0100 0001 al
mov al,[bx]
out 61,al ;写端口B
call dally :调用延时程序dally
inc si
mov al,dl
test al,01
jz out
ror al,1 ;指向下一个数码管
mov dl,al
jmp again
out: pop ax ;d出AX
ret
dally:push cx ;延时程序
push ax
mov cx,0010
t1 :mov ax,0010
t2 dec ax
jnz t2
loop t1
pop ax
pop cx
ret
数码缓冲区:
0000:4000 3f,06,5b4f,66,6d,7d,07,7f,6f
二、 设计思想
电子秒表要实现的功能:用键盘中断来控制整个程序,按一下回车键启动电子秒表,再按一下暂停,按一下ESC键清零,用七段数码管显示时间。整个程序涉及到8255、8253与8259三个芯片。8253的OUT2,CLK2分别连接8259的IRQ7与PCLK,8253的GATE2连接正5伏电压,采用计数器2每隔001秒产生一次中断并且计数,写入以偏移地址4000H开始的4个内存单元,然后利用8255将内存单元的数据输出到七段数码管。由于键盘中断优先于8259的7号中断,所以程序只有在按一下回车键才启动电子秒表,再按一下暂停,按一下ESC键清零,如果超出了60秒,整个程序自动重新开始。
三、 所用芯片工作原理
8255:接口电路在CPU和I/O设备之间起着信号的变换和传输的作用。 任何接口电路与CPU之间的信息传输方式都是并行的,即CPU与接口电路之间以数据字节/字为单位传送信息。接口电路与I/O设备之间的信息传送方式,有并行和串行两种,相应的接口电路称为并行接口和串行接口。
并行接口是在多根数据线上,以数据字节/字与I/O设备交换信息。在输入过程中,输入设备把数据送给接口,并且使状态线“输入准备好”有效。接口把数据存放在“输入缓冲寄存器”中,同时使“输入回答”线有效,作为对外设的响应。外设在收到这个回答信号后,就撤消数据和“输入准备好”信号。数据到达接口中后,接口会在“状态寄存器”中设置输入准备好标志,或者向CPU发一个中断请求。CPU可用查询方式或中断方式从接口中读取数据。接口中的数据被读取后,接口会自动清除状态寄存器中的标志,且撤消对CPU的中断请求。
在输出过程中,每当输出寄存器可以接收数据,接口就会将状态寄存器中“输出准备好”状态置1或向CPU发一个中断请求,CPU可用查询或中断方式向接口输出数据。当CPU输出的数据到达接口后,接口会清除“输出准备好”状态,把数据送往外设,并向外设发一个“数据输出准备好”信号。外设受到驱动后,便接收数据,并向接口电路发一个“输出回答”信号,接口收到该回答信号后,又将状态寄存器中“输出准备好”置位,以便CPU输出下一个数据。
8253:对CLK信号进行“减1计数”。首先CPU把“控制字”,写入“控制寄存器”,把“计数初始值”写入“初值寄存器”,然后, 定时/计数器按控制字要求计数。计数从“计数初始值 开始,每当CLK信号出现一次,计数值减1,当计数值减为0时,从OUT端输出规定的信号(具体形式与工作模式有关)。当CLK信号出现时,计数值是否减1(即是否计数),受到“门控信号”GATE的影响,一般,仅当GATE有效时,才减1门控信号GATE如何影响计数 *** 作,以及输出端OUT在各种情况下输出的信号形式与定时/计数器的工作模式有关。
8259:1 IR线上提出了中断请求的中断源,即出现请求,IRR中断请求寄存器(共有8位D7~D0)对应于连接在IR0~IR7线上的外设的中断请求,哪一根输入线有请求,哪一根输入线就置1。
2 若OCW1(IMR中断屏蔽寄存器)未使该中断请求屏蔽(对应位为0时不屏蔽),该请求被送入PR(优先权分析器)比较。否则,不送入PR比较。
3 PR把新进入的请求与ISR(服务中寄存器)中正在被处理的中断进行比较。如果新进入的请求优先级较低,则8259不向CPU提出请求。如果新进入的请求优先级较高,则8259使INT引脚输出高电平,向CPU提出请求。
4 如果CPU内部的标志寄存器中的IF(中断允许标志)为0,CPU不响应该请求。若IF=1,CPU在执行完当前指令后,从CPU的INTA引脚上向8259发出两个负脉冲。
5第一个 INTA负脉冲到达8259时,8259完成以下三项工作:
a使IRR(中断请求寄存器)的锁存功能失效。这样一来,在IR7~IR0上的请求信号就不会被8259接收。直到第二个INTA负脉冲到达8259时,才又使IRR的锁存功能有效。
b使ISR(服务中寄存器)中的相应位置1。
c使IRR中的相应位清0。
6第二个INTA负脉冲到达8259时,8259完成以下工作:
a将中断类型码(ICW2中的值)送到数据总线上,CPU将其保存在“内部暂存器”中。
b如果ICW4(它设定级中断联方式之特定完全嵌套方式,将在8259的工作方式中详述ICW4)中设置了中断自动结束方式,则将ISR的相应位清0。
欧姆龙CP1H型号的PLC编写定时器中断程序:
在项目管理器中右键点击程序,选择插入新程序,任务类型中选择中断任务02(间隔定时器0),在此处理中断。
PLC的用户程序可以在实验室模拟调试,输入信号用小开关来模拟,通过PLC上的发光二极管可观察输出信号的状态。完成了系统的安装和接线后,在现场的统调过程中发现的问题一般通过修改程序就可以解决,系统的调试时间比继电器系统少得多。
中断是为了使时间更精确。使用中断一般要先设置使用哪个定时/计数器的模式几,之后再设置定时器的使能为,再打开总中断使能位,启动定时器。外部中断比定时器的优先级高,如果有更重要的事等着去处理则交给外部中断,当检测到有外部中断时,会去执行外部中断服务,执行完后回到之前未执行的地方接着继续执行;串口用到定时器,因为在串口的模式1和模式3中需要用定时器的溢出率来设置波特率。我说得不怎么详细,这个几句话说不清。这个你可以先把概念搞懂,之后用列子去理解概念会比较好,不懂的就多问问。
这是我在网上看到的一点资料
ORG 0000H
LJMP START
ORG 000BH
LJMP Timer0Interrupt
START:
MOV SP,#60H
LCALL InitTimer0
LOOP:
;add your code here!
LJMP LOOP
InitTimer0:
MOV TMOD,#01H
MOV TH0,#0FCH
MOV TL0,#18H
SETB EA
SETB ET0
SETB TR0
RET
Timer0Interrupt:
PUSH DPH
PUSH DPL
PUSH ACC
MOV TH0,#0FCH
MOV TL0,#18H
CPL P10
POP ACC
POP DPL
POP DPH
RETI
END
这是定时器0的一个1ms中断一次的程序 在P10端口输出1KHz方波
以上就是关于编写中断子程序的基本规则全部的内容,包括:编写中断子程序的基本规则、如何编写定时器中断程序。。。c语言的~~~、为什么现代计算机系统中还有中断处理程序是用汇编语言编写等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)