打印

初学51,定时器问题请教

[复制链接]
1823|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
njgx|  楼主 | 2009-3-11 16:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
这个程序想用计时器2方式自动装载生成200us中断,进而产生1ms 嘀嗒(jiffie),为了检测程序对不对,将1ms嘀嗒 / 1000 ,模十后用一个数码管显示,但是调试中发现无论定时器TH0 赋什么值,从1到FF,最后产生的1S间隔都不变,有4~5秒之多,请高手帮忙

#include <REG52.H> 
#include <stdio.h> 


unsigned long jiffies = 0;          // (ms)嘀嗒
const unsigned char Num[] = {       //7段数码管
    0xc0, /* 0 */0xf9, /* 1 */
    0xa4, /* 2 */0xb0, /* 3 */
    0x99, /* 4 */0x92, /* 5 */
    0x82, /* 6 */0xf8, /* 7 */
    0x80, /* 8 */0x90, /* 9 */
};
//串口初始化
void Timer_initial(void)
{

    TMOD |= 0x02; //timer 0, mode 2, 8-bit reload
    TL0 = 0x48;       //无论这里写什么值,产生时钟间隔都不变
    TH0 = 0x48;       //200us
    TR0 = 1; 
    ET0 = 1;
    EA = 1;//START INT
}
//200us中断
void Interrupt200us() interrupt 1
{
    static long cnt;
    if(!(cnt % 5))            //200us => 1ms
        jiffies++;
    cnt++;
}
void disp8( int i )
{
    P0 = Num[i%10];       //p0接数码管
}
void main()
{
    int sec;    

    Timer_initial();
    while(1){
        if( sec != jiffies/1000 ){
            disp8( (jiffies/1000) );
            sec = jiffies/1000;
        }
    }
}

相关帖子

沙发
ayb_ice| | 2009-3-11 20:35 | 只看该作者

晶振多少

使用特权

评论回复
板凳
松松电子| | 2009-3-11 21:05 | 只看该作者

恩,来看看。。上传点初学者的东西。

1. 闪烁灯
1.  实验任务 
如图4.1.1所示:在P1.0端口上接一个发光二极管L1,使L1在不停地一亮一灭,一亮一灭的时间间隔为0.2秒。 
2.  电路原理图 
 
图4.1.1 
3.  系统板上硬件连线 
把“单片机系统”区域中的P1.0端口用导线连接到“八路发光二极管指示模块”区域中的L1端口上。 
4.  程序设计内容 
(1). 延时程序的设计方法 
作为单片机的指令的执行的时间是很短,数量大微秒级,因此,我们要求的闪烁时间间隔为0.2秒,相对于微秒来说,相差太大,所以我们在执行某一指令时,插入延时程序,来达到我们的要求,但这样的延时程序是如何设计呢?下面具体介绍其原理: 
如图4.1.1所示的石英晶体为12MHz,因此,1个机器周期为1微秒 
机器周期 微秒 
MOV R6,#20 2个机器周期  2 
 D1: MOV R7,#248 2个机器周期  2       2+2×248=498 20× 
  DJNZ R7,$ 2个机器周期  2×248             498 
DJNZ R6,D1 2个机器周期   2×20=40         10002 
因此,上面的延时程序时间为10.002ms。 
由以上可知,当R6=10、R7=248时,延时5ms,R6=20、R7=248时,延时10ms,以此为基本的计时单位。如本实验要求0.2秒=200ms,10ms×R5=200ms,则R5=20,延时子程序如下: 
DELAY: MOV R5,#20
D1: MOV R6,#20
D2: MOV R7,#248
DJNZ R7,$
DJNZ R6,D2
DJNZ R5,D1
RET 
(2). 输出控制 
如图1所示,当P1.0端口输出高电平,即P1.0=1时,根据发光二极管的单向导电性可知,这时发光二极管L1熄灭;当P1.0端口输出低电平,即P1.0=0时,发光二极管L1亮;我们可以使用SETB P1.0指令使P1.0端口输出高电平,使用CLR P1.0指令使P1.0端口输出低电平。 
5. 程序框图 
   如图4.1.2所示 
  
  
  
  
  
  
  
 
图4.1.2 
6. 汇编源程序
ORG 0
START: CLR P1.0
LCALL DELAY
SETB P1.0
LCALL DELAY
LJMP START
DELAY: MOV R5,#20 ;延时子程序,延时0.2秒
D1: MOV R6,#20
D2: MOV R7,#248
DJNZ R7,$
DJNZ R6,D2
DJNZ R5,D1
RET
END

7. C语言源程序
#include <AT89X51.H>
sbit L1=P1^0;

void delay02s(void) //延时0.2秒子程序
{
unsigned char i,j,k;
for(i=20;i>0;i--)
for(j=20;j>0;j--)
for(k=248;k>0;k--);
}


void main(void)
{
while(1)
{
L1=0;
delay02s();
L1=1;
delay02s();
}
}

相关链接:https://bbs.21ic.com/upfiles/img/20093/200931121020600.rar

使用特权

评论回复
地板
raininthes| | 2009-3-11 22:32 | 只看该作者

你的1ms都产生不了呢

你的1ms都产生不了呢。
void Interrupt200us() interrupt 1
{
    static long cnt;
    TF0=0;
    cnt++;
    if(cnt==5)
    {
        cnt=0;
        jiffies++;
    }        //cnt5次相当于t0溢出5次,每次200us,5次就是1ms,然后jiffies计数加一;
   // if(!(cnt % 5))            //200us => 1ms
   // cnt++;你前面的那个cnt%5,会把所得的结果送cnt,这样的cnt就不准了,你这里无非是弄一个1ms的延时出来,你看这样如何。
}

使用特权

评论回复
5
njgx|  楼主 | 2009-3-12 09:15 | 只看该作者

回楼上

if(cnt%5) 并不会改变cnt的值

现在发现    

TL0 = 0x48;       //无论这里写什么值,产生时钟间隔都不变
TH0 = 0x48;       //200us
这两条指令不起作用,无论这里写什么值,程序得出的1秒都是4秒左右
但是在KEIL里确实看到TH0 TL0两个寄存器改变了。晶振是11。0592

使用特权

评论回复
6
wjy1107| | 2009-3-12 13:42 | 只看该作者

我试了你的程序

没问题。
我是在disp8( (jiffies/1000) );这里设置的断点,每次到这里大概都是1秒的时间,而且也修改了TH0的值,中断的时间会改变。
你的仿真软件是不是出了问题啊?

使用特权

评论回复
7
yysmcu| | 2009-3-12 14:30 | 只看该作者

飘过,学习了

使用特权

评论回复
8
njgx|  楼主 | 2009-3-12 16:43 | 只看该作者

谢谢wjy1107

谢谢wjy1107,芯片是SST的89E564,这小程序应该没有问题,可能是MCU或者是仿真器的问题吧,曾经还出现过计时器0,1模式不相同(分别在1,2模式)时,TIMER1不能产生中断,将TIMER0,1作用互换就可以用的情况,非常奇怪。周末去换个单片机试试,谢谢大家

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

主题

3

帖子

0

粉丝