单片机的延时与中断问题及解决方法
定时计数器2产生的中断100MS一次的数据采集。另一个是向上位机发送采集来的数据,使用的串口来实现的,用的单片机的UART来实现。也是一个中断。这两个中断在一起工作时需要注意些什么?我的中断程序出了一些问题。
(就是默认情况下,UART的中断级别更高,但是有的时候UART的中断不能及时响应,这是为甚?)
答:
之前和你做的一样就两个中断 UART0加一个定时器 我用的是C8051F040
你向上位机发送数据使用UART0时 要确认定时器工作完毕
T2定时中断后 你加一个完成标志如T2FLAG
if(T2FLAG==1) 将采集的数据放入 UART0的SBUF0 是UART0工作
你100ms的中断时间 C8051这么快速的单片机怎么都该发送完成了吧。
13、MSP430单片机中断嵌套,如何跳出中断?
当进行A中断时,来了一个B中断,我想让B中断程序执行完后不继续
执行A中断而跳出整个中断,去执行主程序,请问这个怎么设置呢?
答:
中断的时候会把SR状态跟中断下来要执行语句的地址放进堆栈中,实现处理完中断以后cpu要执行的语句,注意是地址先进,SR后进,出栈时SR先出,地址后出,当然了在中断里面可以嵌套中断的,对可屏蔽中断来说,主要是CPU响应中断以后,GIE会自动复位,所以不能对可屏蔽中断进行嵌套,如果在中断中要嵌套可屏蔽中断的话可以开GIE,但要注意的是如果此时正在响应的中断标志还是置位的情况下会反复进入此中断,就像死循环一样,这时会引起堆栈的溢出,而在响应可屏蔽中断时,不可屏蔽中断不受此影响,因为他不受GIE的影响,只受自己单独的使能位影响。在堆栈中的操作原理类似。
14、MSP430单片机有几个需要软件清除的中断标志?如何清除?
(1)清除各个端口的外中断用:PxIFG,相应的位置0即可;
(2)清除Timer中断用:TAIFG,TBIFG,相应的位置0即可;
答:
MSP430的16个外中断比如软件清除Flag,在进入外中断后,首先要做的就是把相应的PxIFG清0;
而定时器Timer中断是自动清除Flag;
还有在中断嵌套的时候会用到,在进入中断后,MCU会自动把全局中断位GIE清零,这样在进入本中断后就不会再相应其他中断,若要进行中断嵌套,必须在进入中断后把GIE再置1.
15、MCS-51系列单片机的有几个中断源?各中断标志是如何产生的?如何清除各中断标志?
答:
标准51有5个中断向量(不算复位),分别是外部中断0,定时器0,外部中断1,定时器1,串行口;总共有6个中断标志,串行口的发送和接受共享一个中断向量。
各个终端标志产生情况如下:
外部中断可以设置边沿触发或者电平触发,边沿触发进入中断程序后硬件自动清中断标志,电平触发需要软件清标志位;
定时器T0,T1计数溢出产生中断,进入中断程序硬件自动清标志位;
串行口发送完成或者接收到数据就触发中断,由于是两个中断标志共享一个中断向量,所以需要在中断程序里由软件判断是发送中断还是接受中断,并且只能由软件清标志位;
以上是标准51的中断系统,52由于多了一个T2定时器(T2定时器跟T0,T1功能相差很大,T2要强大很多),因此多了一个中断向量2个中断标志(溢出中断和T2外部中断),T2中断标志必须由软件清除标志位
中断使能位于IE寄存器
各中断标志位于相应的模块控制寄存器里面
模块 位地位 位名称 说明
T1 TCON.7 TF1 T1溢出标志
T0 TCON.5 TF0 T0溢出标志
T2 T2CON.7 TF2 T2溢出中断标志
T2CON.6 EXF2 T2外部中断标志
外部中断1 TCON.3 IE1 外部中断1标志
外部中断0 TCON.1 IE0 外部中断0标志
串行口 SCON.1 TI 发送中断标志
SCON.0 RI 接受中断标志
16、MCS51单片机的汇编语言的中断服务程序最多有几个?
答:一般而言有5个对:2个外中断 ,2个定时器中断, 1个串口中断。
但是单片机的中断服务资源是根据硬件的结构设计,会有不同的数量和类型的中断服务,,,因此中断并不是对语言来讲的,而是对于硬件资源来讲的。比如52有6个中断。
基于语言编译器来讲,我就举例个人感觉最好的开发51大系列的开发环境Keil,其编译器最多支持32个中断服务,,,,因此中断对编译来说,是一个“模拟”的概念。
17、单片机中断改变频率,为什么几个输出频率无法改变? 程序如下?
#include
#define uchar unsigned char
#define uint unsigned int
uchar T,t1;
unsigned char data table[5] = {486,236,151,111,86} ;
sbit CLK=P2^3 ;
sbit EN=P2^0 ;
void init();
void main()
{
init();
}
void init()
{
EN=1;
T=0;
TMOD=0x01;
EA=1;
TR0=1;
ET0=1;
t1=table[T];
TH0=(65536-t1)/256;
TL0=(65536-t1)%256;
}
void timer0() interrupt 1
{
TMOD=0x01;
EA=1;
TR0=1;
ET0=1;
t1=table[T];
TH0=(65536-t1)/256;
TL0=(65536-t1)%256;
CLK=~CLK;
}
答:
T你只付了0值,怎么会变化频率呢?你在主函数里加个T的赋值语句就行了,例如:while(T){T--;delay1s();}
18、单片机中断程序的书写步骤?
答:
标准形式:
void 函数名(void)interrupt n using m
{函数体语句}
n ----中断编号
m-----要使用工作寄存器组号
19、我想知道单片机的蜂鸣器音乐程序中断是如何响应的?从main主程序中如何到中断程序?具体步骤是啥?谢谢!
#include
sbit speaker = P1^5;
unsigned char timer0h, timer0l, time;
//--------------------------------------
//单片机晶振采用11.0592MHz
// 频率-半周期数据表 高八位 本软件共保存了四个八度的28个频率数据
code unsigned char FREQH[] = {
0xF2, 0xF3, 0xF5, 0xF5, 0xF6, 0xF7, 0xF8, //低音1234567
0xF9, 0xF9, 0xFA, 0xFA, 0xFB, 0xFB, 0xFC, 0xFC,//1,2,3,4,5,6,7,i
0xFC, 0xFD, 0xFD, 0xFD, 0xFD, 0xFE, //高音 234567
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF}; //超高音 1234567
// 频率-半周期数据表 低八位
code unsigned char FREQL[] = {
0x42, 0xC1, 0x17, 0xB6, 0xD0, 0xD1, 0xB6, //低音1234567
0x21, 0xE1, 0x8C, 0xD8, 0x68, 0xE9, 0x5B, 0x8F, //1,2,3,4,5,6,7,i
0xEE, 0x44, 0x6B, 0xB4, 0xF4, 0x2D, //高音 234567
0x47, 0x77, 0xA2, 0xB6, 0xDA, 0xFA, 0x16}; //超高音 1234567
//--------------------------------------
//世上只有妈妈好数据表 要想演奏不同的乐曲, 只需要修改这个数据表
code unsigned char sszymmh[] = {5,1,1,5,1,1,6,1,2,5,1,2,1,2,2,7,1,4,5,1,1,5,1,1,6,1,2,5,1,2,2,2,2,1,2,4,
5,1,1,5,1,1,5,2,2,3,2,2,1,2,2,7,1,2
};
//--------------------------------------
void t0int() interrupt 1 //T0中断程序,控制发音的音调
{
TR0 = 0; //先关闭T0
speaker = !speaker; //输出方波, 发音
TH0 = timer0h; //下次的中断时间, 这个时间, 控制音调高低
TL0 = timer0l;
TR0 = 1; //启动T0
}
//--------------------------------------
void delay(unsigned char t) //延时程序,控制发音的时间长度
{
unsigned char t1;
unsigned long t2;
for(t1 = 0; t1 < t; t1++) //双重循环, 共延时t个半拍
for(t2 = 0; t2 < 8000; t2++); //延时期间, 可进入T0中断去发音
TR0 = 0; //关闭T0, 停止发音
}
//--------------------------------------
void song() //演奏一个音符
{
TH0 = timer0h; //控制音调
TL0 = timer0l;
TR0 = 1; //启动T0, 由T0输出方波去发音
delay(time); //控制时间长度
}
//--------------------------------------
void main(void)
{
unsigned char k, i;
TMOD = 1; //置T0定时工作方式1
ET0 = 1; //开T0中断 IE=0x82;
EA = 1; //开CPU中断
while(1) {
i = 0;
time = 1;
while(time) {
k = sszymmh[i] + 7 * sszymmh[i + 1] - 1;
//第i个是音符, 第i+1个是第几个八度
timer0h = FREQH[k]; //从数据表中读出频率数值
timer0l = FREQL[k]; //实际上, 是定时的时间长度
time = ssz
ymmh[i + 2]; //读出时间长度数值
i += 3;
song(); //发出一个音符
}
}
}
答:
你看main()函数就行了,首先进行k、i的定义,然后是定义中断的类型(程序中用的是定时器中断),这个定时器有点特殊,它的作用是定义频率的,频率间隔小则声调高,反之声调低。这个频率就是时间的倒数呗,所以TH的值越大,声调越高;TL的值越小,声调越低。接着往下走,while(1) 就是等待中断的意思,这个程序中的定时器中断没有设置初值,所以中断几乎没有等待,时时触发(要是有等待时间,音乐不就连不上了么)。综上:这个定时器中断完成两个任务:1、使单片机时时触发(等待时间几乎为0);2、控制了音符的演奏频率。
再往下 while(time) 的循环就是为演奏的音符赋值的操作了。
20、单片机中断该什么时候进如?
答:
中断看是外部中断、定时器还是串行口中断了。
如果是外部中断,就是p3.2、p3.3检测到这两个口电平变化时(假设这两个口接上按键,那么当按键按下时表明产生中断),然后跳到中断程序执行。
如果是定时器中断的话,有个中断标志位TFx(x表示0或者1),比如说你设置一个1S的
单片机延时中断问 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)