找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2638|回复: 4
打印 上一主题 下一主题
收起左侧

在实践中关于单片机晶振与计时器问题的困惑

[复制链接]
跳转到指定楼层
楼主
来51hei论坛有些时间了,想自己动手做点什么,就焊了个stc11f02e单片机的最小系统,使用外接12Mhz晶振。但是在实际应用时有些困惑。使用11f02e的1T工作模式,晶振使用12Mhz的,写了个5分钟的倒计时程序,外接数码管显示。
    1T工作模式:
    12Mhz晶振
    一个机器周期为1/12000000s
    定时器最大值为:65536   
    工作60000次
    60000/12000000 = 0.005s
    TH0 = (65536-60000)/255 = 0x15;
    TL0 = (65536-60000)%255 = 0xb5
    1s = 1/0.005 = 200(次)

计算出循环200次为1秒,但是实际测出来需要循环1600次才是1秒。不知道时哪里出错了,请老师指正。
由于没有画电路图,直接焊的洞洞板,如果分析需要我待会儿手绘一张电路图。

附上源码:
#include <stc11f02e.h>
unsigned char code ledTable[] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char ledBuffer[] = {0xff,0xff,0xff,0xff};

unsigned char p = 0;    //显示位数指示标志
unsigned int time = 300;    //倒计时300秒

sbit A1 = P3^2;    //数码管第一位
sbit A2 = P3^3;    //数码管第二位
sbit A3 = P3^4;    //数码管第三位
sbit A4 = P3^5;    //数码管第四位
sbit led = P3^7;    //计时完成时点亮小灯

void init();
void display();
void delay();

unsigned cnt = 0;
void main(void)
{
    init();
    while(1)
    {   
        if((time/600) == 0)
        {
            ledBuffer[0] = 0xff;    //小于10分钟,首位不亮
        }
        else
        {
            ledBuffer[0] = ledTable[(time/60)/10];
        }
        
        ledBuffer[1] = ledTable[(time/60)%10] & 0x7f;    //小数点
        ledBuffer[2] = ledTable[(time%60)/10];
        ledBuffer[3] = ledTable[(time%60)%10];   
        display();
    }
}


void init()
{
    AUXR |= 0x80;    //1T工作模式
    TMOD &= 0xf0;    //选择计时模式
   
    EA = 1;
    ET0 = 1;
   
    TF0 = 0;
    TR0 = 1;
   
    TL0 = 0xb5;
    TH0 = 0x15;
   
    led = 0;    //led灯默认关闭
}

void display()
{
    P1 = 0xff;
    switch(p)
    {
        case(0):A1=0;A2=1;A3=1;A4=1;P1=ledBuffer[0];p++;break;
        case(1):A1=1;A2=0;A3=1;A4=1;P1=ledBuffer[1];p++;break;
        case(2):A1=1;A2=1;A3=0;A4=1;P1=ledBuffer[2];p++;break;
        case(3):A1=1;A2=1;A3=1;A4=0;P1=ledBuffer[3];p=0;break;
        default:break;
    }
    delay();
}
   

void delay()    //给led灯一个过渡时间
{
    unsigned char i,j;
    for(i=0;i<110;i++)
    {
        for(j=0;j<10;j++);
    }
}

void timeUp() interrupt 1
{
    TL0 = 0xb5;
    TH0 = 0x15;
   
    cnt++;
   
    if(cnt==1600)    //经实测1600个循环才等于1秒
    {
        cnt = 0;    //经过1s秒置零
        time--;        //时间减少1秒
        if(time==0)    //如果计时完成
        {   
            TR0 = 0;    //计数器运行标志位置零,停止计时
            time = 0;    //及时完成显示函数显示0.00
            delay();    //给点亮led灯一个过渡时间,减小瞬间电流
            led = 1;    //led小灯常量,标志计时完成
            
        }
    }
}

贴上实物图:

index.jpg (104.93 KB, 下载次数: 39)

正在运行中

正在运行中

index2.jpg (105.57 KB, 下载次数: 26)

最小系统

最小系统

index3.jpg (95.98 KB, 下载次数: 23)

整体

整体

index4.jpg (78.37 KB, 下载次数: 19)

计时结束,点亮小灯

计时结束,点亮小灯
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:123289 发表于 2019-1-19 16:15 | 只看该作者
1、T0有几种工作模式,分别代表什么意思?(提示:TMOD的B1B0位,你用的是什么模式?)
2、TH0TL0=15B5H=5557,它与65536的差是多少?(好在不是主要问题)
回复

使用道具 举报

板凳
ID:213173 发表于 2019-1-19 20:06 | 只看该作者
你的定时器初始化程序错误,给你一个示例。
void Timer0Init()                //5毫秒@12.000MHz
{
        AUXR |= 0x80;                //定时器时钟1T模式
        TMOD &= 0xF0;                //设置定时器模式1
        TMOD |= 0x01;                //设置定时器模式1
        TL0 = 0xA0;                //设置定时初值
        TH0 = 0x15;                //设置定时初值
        TR0 = 1;                        //定时器0开始计时
        EA = 1;                        //开总中断
        ET0 = 1;                        //开T1中断
}
回复

使用道具 举报

地板
ID:399129 发表于 2019-1-20 00:48 | 只看该作者
yzwzfyz 发表于 2019-1-19 16:15
1、T0有几种工作模式,分别代表什么意思?(提示:TMOD的B1B0位,你用的是什么模式?)
2、TH0TL0=15B5H=5 ...

谢谢,我去查查手册。老师,关于初值我这样算具体错在哪里了。
回复

使用道具 举报

5#
ID:399129 发表于 2019-1-20 00:49 | 只看该作者
wulin 发表于 2019-1-19 20:06
你的定时器初始化程序错误,给你一个示例。
void Timer0Init()                //5毫秒@12.000MHz
{

谢谢老师,确实是定时器模式这里错了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表