打印

求解一道关于定时器的c编程题目

[复制链接]
4866|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
s675|  楼主 | 2009-10-21 17:34 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
同时用两个定时器控制蜂鸣器发声,定时器0控制频率,定时器1控制同个频率持续的时间,间隔300ms依次输出1,10,50,100,200,400,800,1K(Hz)的方波。晶振为12MHz,P2.3口接蜂鸣器,低电平有蜂鸣器响。

相关帖子

沙发
xwj| | 2009-10-21 17:43 | 只看该作者
太简单,自己去想。

使用特权

评论回复
板凳
for_fun| | 2009-10-21 19:20 | 只看该作者
1,10,50,100,200,400,800,1K(Hz)对应的时间分别为
1000ms,100ms,20000us,10000us,5000us,2500us,1250us,1000us他们的最大公约数是50us,
若用定时器0控制频率
弄个for(i=需要计数的个数;i>0;i--){delay_us(50);}的循环即可!

使用特权

评论回复
地板
kfawj| | 2009-10-22 10:50 | 只看该作者
自己动手吧!!!
问题是过于简单了一点!!!
你可以先找找跑马灯的程序!!!没有什么难度的!!!

使用特权

评论回复
5
awmc_m| | 2009-10-22 12:57 | 只看该作者
间隔300ms输出1hz?~~~~~

使用特权

评论回复
6
s675|  楼主 | 2009-10-23 10:03 | 只看该作者
谢谢ls各位解答,根据 for_fun 的提示,我编写了以下程序:
#include <reg52.h>
#define uint unsigned int
sbit beep = P2^3;
uint num1,num2,tnum;
uint code table[] = {4,5,10,20,40,80,400,4000}; //{4000,400,80,40,20,10,5,4};

void main()
{
        TMOD = 0x11;
        TH0 = (65536-250)/256;
        TL0 = (65536-250)%256;
        TH1 = (65536-50000)/256;
        TL1 = (65536-50000)%256;
        EA = 1;
        ET0 = 1;
        ET1 = 1;
        TR0 = 1;
        TR1 = 1;
        while(1);
}

void T0_time() interrupt 1
{
        TH0 = (65536-250)/256;
        TL0 = (65536-250)%256;
        num1++;
        if(num1 == table[tnum])
        {
                num1 = 0;
                beep = ~beep;
        }
}

void T1_time() interrupt 3
{
        TH1 = (65536-50000)/256;
        TL1 = (65536-50000)%256;
        num2++;
        if(num2 == 6)
        {
                num2 = 0;
                tnum++;
                if(tnum == 8)
                        tnum = 0;
        }
}

但还是存在 awmc_m 所提的问题: 间隔300ms输出1hz?~~~~~
最后程序到4000处停止,不能循环。因为num1不能检测到4000这个点吧。不知道应该怎么解决这个问题呢?请各位指点小弟一下!

使用特权

评论回复
7
s675|  楼主 | 2009-10-23 10:04 | 只看该作者
谢谢ls各位解答,根据 for_fun 的提示,我编写了以下程序:
#include <reg52.h>
#define uint unsigned int
sbit beep = P2^3;
uint num1,num2,tnum;
uint code table[] = {4,5,10,20,40,80,400,4000}; //{4000,400,80,40,20,10,5,4};

void main()
{
        TMOD = 0x11;
        TH0 = (65536-250)/256;
        TL0 = (65536-250)%256;
        TH1 = (65536-50000)/256;
        TL1 = (65536-50000)%256;
        EA = 1;
        ET0 = 1;
        ET1 = 1;
        TR0 = 1;
        TR1 = 1;
        while(1);
}

void T0_time() interrupt 1
{
        TH0 = (65536-250)/256;
        TL0 = (65536-250)%256;
        num1++;
        if(num1 == table[tnum])
        {
                num1 = 0;
                beep = ~beep;
        }
}

void T1_time() interrupt 3
{
        TH1 = (65536-50000)/256;
        TL1 = (65536-50000)%256;
        num2++;
        if(num2 == 6)
        {
                num2 = 0;
                tnum++;
                if(tnum == 8)
                        tnum = 0;
        }
}

但还是存在 awmc_m 所提的问题: 间隔300ms输出1hz?~~~~~
最后程序到4000处停止,不能循环。因为num1不能检测到4000这个点吧。不知道应该怎么解决这个问题呢?请各位指点小弟一下!

使用特权

评论回复
8
hyg1984| | 2009-10-23 12:23 | 只看该作者
本帖最后由 hyg1984 于 2009-10-23 12:32 编辑

晕啊,这个延时是不是计算错了?3楼讲的很不错,不知道你明白没有。
这个程序浪费太多的空间了,8位单片机最好不要用16位的变量,最好像3楼说得那样循环,当然,软件延时改成定时器延时最好。
1、if(num2 == 6)这里是不是应该改成60,因为5ms*60才等于300ms吧?
2、定时器0频率计算的好像不对头。
这样改看行不行,至于4000处停止的问题,应该是跑飞了吧,这个你再检查检查。

unsigned char count1,count2;
unsigned char num,tnum;

void T0_time() interrupt 1
{
        TH0 = (65536-50)/256;            //12M晶振,一次中断约等于50us吧
        TL0 = (65536-50)%256;
/*1000ms=50us*20000;100ms=50us*2000;20000us=50us*400;10000us=50us*200;5000us=50us*100;2500us=50us*50;1250us=50us*25;1000us=50us*20*/
        if(tnum == 0x00)  
        {
                if(++count1 == 20)
                {
                          count1 = 0;
                          beep = ~beep;
                }
        }
        else if(tnum == 0x01)  
        {
                if(++count1 == 25)
                {
                          count1 = 0;
                          beep = ~beep;
                }
        }
        else if(tnum == 0x02)  
        {
                if(++count1 == 50)
                {
                          count1 = 0;
                          beep = ~beep;
                }
        }

        ..............自己对照着时间来改

        else if(tnum == 0x05)  
        {
                if(++count1 == 200)
                {
                         count1 = 0;
                         if(++count == 2)
                         {
                                  count2 = 0;
                                  beep = ~beep;
                         }
                }
        }

         ...........自己对照着时间来改
}

void T1_time() interrupt 3
{
        TH1 = (65536-50000)/256;    //12M的晶振约等于5ms
        TL1 = (65536-50000)%256;
        num++;
        if(num == 60)         //约300ms
        {
                num = 0;
                tnum++;
                if(tnum == 8)
               {
                        tnum = 0;
                        count1 = 0;
                        count2 = 0;//清零,不然不准了
               }
        }
}

使用特权

评论回复
9
for_fun| | 2009-10-23 12:45 | 只看该作者
LS正解哦!:)

LZ别着急,再好好想想!

使用特权

评论回复
10
s675|  楼主 | 2009-10-24 10:45 | 只看该作者
hyg1984 谢谢你细心的回复,但有些疑问还要向你请教!

这个程序浪费太多的空间了,   //浪费空间是指数据存储器(RAM)空间吗?
8位单片机最好不要用16位的变量,最好像3楼说得那样循环,
当然,软件延时改成定时器延时最好。  //我俩都是用定时器来延时的呀,不知道你说的软件延时在哪里?
1、if(num2 == 6)这里是不是应该改成60,因为5ms*60才等于300ms吧?  //12M晶振,50000个机器周期应该是50ms吧?
2、定时器0频率计算的好像不对头。
这样改看行不行,至于4000处停止的问题,应该是跑飞了吧,这个你再检查检查。  //应该是跑飞了

unsigned char count1,count2;
unsigned char num,tnum;

void T0_time() interrupt 1
{
        TH0 = (65536-50)/256;            //12M晶振,一次中断约等于50us吧 //我用的是250us一次中断,50us和250us中断有没有区别?
        TL0 = (65536-50)%256;
/*1000ms=50us*20000;100ms=50us*2000;20000us=50us*400;10000us=50us*200;5000us=50us*100;2500us=50us*50;1250us=50us*25;1000us=50us*20*/
/*1000ms=250us*4000;100ms=250us*400;20000us=250us*80;10000us=250us*40;5000us=250us*20;2500us=250us*10;1250us=250us*5;1000us=250us*4*/
        if(tnum == 0x00)  
        {
                if(++count1 == 20)
                {
                          count1 = 0;
                          beep = ~beep;
                }
        }
        else if(tnum == 0x01)  
        {
                if(++count1 == 25)
                {
                          count1 = 0;
                          beep = ~beep;
                }
        }
        else if(tnum == 0x02)  
        {
                if(++count1 == 50)
                {
                          count1 = 0;
                          beep = ~beep;
                }
        }

        ..............自己对照着时间来改

        else if(tnum == 0x05)      // 知道怎么分解4000了   
           {
                if(++count1 == 200)
                {
                         count1 = 0;
                         if(++count == 2)
                         {
                                  count2 = 0;
                                  beep = ~beep;
                         }
                }
        }

         ...........自己对照着时间来改
}

void T1_time() interrupt 3
{
        TH1 = (65536-50000)/256;    //12M的晶振约等于5ms  //50ms??
        TL1 = (65536-50000)%256;
        num++;
        if(num == 60)         //约300ms    //num == 6??
        {
                num = 0;
                tnum++;
                if(tnum == 8)
               {
                        tnum = 0;
                        count1 = 0;
                        count2 = 0;//清零,不然不准了      //如果继续用16位变量方法,是不是只要这里将num1清0就能解决4000跑飞的问题了?
          }
        }
}

使用特权

评论回复
11
s675|  楼主 | 2009-10-24 10:50 | 只看该作者
这里1Hz频率(1000ms)的方波是不是不能改变蜂鸣器的电平,只能保持?

使用特权

评论回复
12
hyg1984| | 2009-10-24 12:14 | 只看该作者
//浪费空间是指数据存储器(RAM)空间吗?
答:是的,是指内部存储器RAM

//我俩都是用定时器来延时的呀,不知道你说的软件延时在哪里?
答:3楼的意思是用软件延时,我们都用定时器延时
1、if(num2 == 6)这里是不是应该改成60,因为5ms*60才等于300ms吧?  //12M晶振,50000个机器周期应该是50ms吧?
答:恩,这里是我错了,应该是50ms

//12M晶振,一次中断约等于50us吧 //我用的是250us一次中断,50us和250us中断有没有区别?
答:我是按3楼的最大公约数来算的,你能算的通就行

//清零,不然不准了      //如果继续用16位变量方法,是不是只要这里将num1清0就能解决4000跑飞的问题了?
答:试一试再说
1HZ的方波不就是500ms低电平,500ms高电平吗?

使用特权

评论回复
13
s675|  楼主 | 2009-10-25 11:36 | 只看该作者
//清零,不然不准了      //如果继续用16位变量方法,是不是只要这里将num1清0就能解决4000跑飞的问题了?
答:试一试再说

谢谢,我试过了,可以
1HZ的方波不就是500ms低电平,500ms高电平吗?

原来是这样啊:$   
那么每次的定时时间都应该减半了

使用特权

评论回复
14
for_fun| | 2009-10-25 13:33 | 只看该作者
:)恭喜LZ了!

使用特权

评论回复
15
llf2385668061| | 2016-3-5 16:09 | 只看该作者
#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
sbit beep=P2^3;
uchar num1,num2,tt,aa,i;
uchar table[]={20000,2000,400,200,100,50,25,20};
uchar temp[]={0,3,15,30,60,120,240,300};
void main()
{  tt=0;
   num1=0; num2=0;
   aa=0;
TMOD=0x01;  //定时器0,1采用工作方式1中断
        TH0=(65536-25000)/256;
        TL0=(65536-25000)%256;
        TR0=1;
        TH1=(65536-50000)/256;
        TL1=(65536-50000)%256;
        TR1=1;
        EA=1;
        ET0=1;
        ET1=1;
        TF1=1;
        while(1)
        {       
                if(aa==6)
                {        if(num1==8)
                      num1=0;
                         if(num2==8)
                           num2=0;
                aa=0;
                for(i=0;i<temp[num1];i++)
                    {
                          beep=0;
                          if(tt==table[num2])
                          beep=1;
                          if(tt==2*table[num2])
                          beep=0;
                       
                        }
                        num1++;
                        num2++;
       
                }       
        }
}
void timer0() interrupt 1
{          TH0=(65536-25000)/256;
        TL0=(65536-25000)%256;
        tt++;
}
void timer1() interrupt 3
{        TH1=(65536-50000)/256;
        TL1=(65536-50000)%256;
        aa++;
}

使用特权

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

本版积分规则

2

主题

12

帖子

1

粉丝