找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 8364|回复: 42
收起左侧

求助 51单片机 中断

[复制链接]
ID:76158 发表于 2015-4-5 21:56 | 显示全部楼层 |阅读模式
论坛的各位前辈,请求指点
我本人喜欢单片机,也是自学的,基础不好!学习单片机已经困在定时中断这里很久了,看了很多书,也不理解,心里实在是矛盾,请求有耐心的前辈指点一二
请各位前辈指点;
第一:这里对于中断我想弄清楚以下:
1.装载初始值:例如我晶振为11.0592
机器周期=12/11.0592=1.085us  我需要让它50ms中断一次  50000/1.09=45872   
初始值就是 TH0=(65536-45872)/256=应该是76 ,那么这个76,装载到高八位是装换成16进制吗?还是二进制
                   TL0=(65536-45872)%256=应该是8125 这个装载到低八位中 又是什么样子的!可能问的问题都不对,大家别笑话,我看书上面讲的比较笼统,不明白其中的意思!

2.所谓中断溢出,书上就是说 TH0 和TL0 都满后,那么如何才是 低八位满后向高八位进1?不理解。也没有老师教,自己之前也不是学这些课程的!

郭天祥老师里面的
void main()
{
     TMOD=0X01;
     TH0=(65536-45872)/256;//这个数得出来 76
      TL0=(65536-45872)%256;//这个数得出来8125 就不不懂这个地方 所谓的高八位和低八位的概念
      EA=1;
      ET0=1;
      TR0=1;
      while(1)
     {
      if(num==20)
           {
             num=0;
             led=~led;
            }
      }

}


另外我自己写了个小程序,就是按键 然后LED从第一个到最后一个一次点亮 按键1加 按键2减
里面也有个小问题,请前辈们看看

#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar code table[]={0xff,0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00};
uchar num;
uchar num0;
void delayms(uint);
sbit key_jia=P3^4;
sbit key_jian=P3^5;

void led()  //LED子函数
{
P1=table[num];
}

void keyscan()
{

if(key_jia==0)
{
  delayms(10);
  if(key_jia==0)
  {
   num++;
   if(num==9)  //如果这个地方是if(num==8)的话,当我按键到第8次的时候应该是全部亮吧,但是按第八次的时候全部灭了,只亮了前面7颗LED灯这个                        //是为什么
    num=0;     //非得改成if(num==9)才行,按第八次的时候才会全部亮
     while(!key_jian);//此处的while语句不要 加延时时间长一点是不是也一样,一定要加这个释放按键的语句吗,如果不加的话一直按键LED是从一颗到全                                 //部亮,而加了则需要一次一次按键   
   delayms(200);

  }

}
if(key_jian==0)
{
  delayms(10);
  if(key_jian==0)
  {

   if(num==0)
    num=9;
       num--;
   while(!key_jian);
  }
}
}

void main()  //主函数
{
while(1)
{
keyscan();
  led();
}
}

void delayms(uint xms)//延时函数
{
uint j,l;
for(j=xms;j>0;j--)
  for(l=110;l>0;l--);
}



最后一个问题,我想做一个用定时器产生一个1KHZ的可调PWM波形
用两个按键实现 0-100%  和100-0%的调整
我想了很久,因为上面的中断没有学会不理解,所以纠结了很久
我说下我的思路,请前辈指点一下
利用定时器的中断 100us  为1KHZ的PWM波
应该来说当是100US的时候 应该是最大占空比了
但是如何去固定频率,去调整它的通段时间呢?这里是不是要用到两个定时器呀?
有那个前辈给个思路
谢谢大家!


回复

使用道具 举报

ID:76158 发表于 2015-4-5 21:59 | 显示全部楼层
另外如果那个有经验有耐心的前辈能指点的话,带我学习51的话,本人有偿答谢!
回复

使用道具 举报

ID:69634 发表于 2015-4-6 19:22 | 显示全部楼层
楼主, while(!key_jian);//此处的while语句不要 加延时时间长一点是不是也一样,------这里应是while(!key_jia);,uchar num0;---这没用。num==9是对的,也就是num=0,八个灯加全灭不是九次吗

评分

参与人数 1黑币 +35 收起 理由
admin + 35 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:76158 发表于 2015-4-6 20:17 | 显示全部楼层
888zhjzhj 发表于 2015-4-6 19:22
楼主, while(!key_jian);//此处的while语句不要 加延时时间长一点是不是也一样,------这里应是while(!key ...

谢谢您的回复,很感激,我看了基本没有人会这么耐心的讲解的
恩 uchar num0;只定义了,没有用  说明您是真心的看过我这个小程序,谢谢
num==9是对的,是我理解错误了,你这样一说,反过来一想,就对了 呵呵
对于无极调光的程序 您有什么好的思路吗,能否指点一下!
回复

使用道具 举报

ID:69634 发表于 2015-4-6 22:18 | 显示全部楼层
楼主,这是我编写小程序,八个灯的无极变光,第一个灯从不亮到最亮,最亮到不亮,接着第二个又是这样。
你可以参考一下,我也不太懂的。
#include <reg52.h>
unsigned int  cycle=1000;
unsigned int   high;
unsigned int   low;
unsigned char cnt = 0;
unsigned char array[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f };

void delay(unsigned int t)
{
        while(t--);
}

void configPWM( unsigned char cnt )

             {
                     for(high=1;high<=cycle;high++)
                 {
                         P0=array[cnt];
                        delay(high);
                         P0=0xff;
                        low=cycle-high;
                        delay(low);
                }
                           for(high=1;high<=cycle;high++)
                {
                        P0=0xff;
                        delay(high);
                        P0=array[cnt];
                        low=cycle-high;
                        delay(low);
                }
              }

void main()
            {       
               for(cnt=0;cnt<8;cnt++)
                   {
                      configPWM( unsigned char cnt );

                   }
             }

评分

参与人数 1黑币 +35 收起 理由
admin + 35 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:69634 发表于 2015-4-6 22:25 | 显示全部楼层
cycle=1000,可能长的,可改成600

评分

参与人数 1黑币 +35 收起 理由
admin + 35 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:76158 发表于 2015-4-7 20:18 | 显示全部楼层
888zhjzhj 发表于 2015-4-6 22:25
cycle=1000,可能长的,可改成600

谢谢你,用延时函数写的,很好哦
最后的cofigPWM();括号里面不要带形参了!
用来做精准PWM调光肯定是不行的!大家一起讨论一起学习吧!谢谢你
回复

使用道具 举报

ID:73833 发表于 2015-4-8 20:33 | 显示全部楼层
我来试着解答你的前两个问题。其实应该先说第二个问题即溢出。TH0和TL0是两个8位寄存器,TL0溢出一次TH0加1,8位寄存器寄存的的数最大是256,这样可以认为,低8位的TL0获得256个数后,打个包,记做1包,把这个1存在TH0,同时TL0自身清零,以此类推直到TH0收到第256包时也告仓满,你可知这时这两个寄存器共存储了65536个数,再多一个就全部溢出,所谓溢出就是自身清零向高位进一,这个一,就代表自身进位前的全部内容。
好第一个问题----先说那个45872,被从65536中减去的这个数,正是想让单片机计量的数,其余的空间填上初值,这个初值是不让单片机计量而直接从此基础上累加45872个数,再多一个溢出。至于TH0中的76就是十进制意义上的76,它代表76个256,取余的结果并不是8125,而是可以理解为0.8125,是不足256(即1包)的部分,你算一下0.8125个256应当是208,这个数就是TL0的初值。至于数制,并不重要,在KEIL中可以混用,当然在单片机中肯定是二进制了。

评分

参与人数 1黑币 +35 收起 理由
admin + 35 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:76158 发表于 2015-4-9 14:39 | 显示全部楼层
dingmingzhou 发表于 2015-4-8 20:33
我来试着解答你的前两个问题。其实应该先说第二个问题即溢出。TH0和TL0是两个8位寄存器,TL0溢出一次TH0加1 ...

谢谢!
你这种通俗的讲解好容易理解,跟陈老师讲解一样,对于我们没有基础的人来说很好理解
其实就是将65536个数分成了高低8位两个寄存器,低位满后,向高位进1,依次类推,当高位满后,低位自身满256个数后 再多加1位 相当于高地位都溢出,就表示 这两个寄存器已经满 且溢出了
初始值就像类似于水桶里面已经有一半水了,只需要再原来的基础上再往桶里装水,原来的水加上你需要的水刚刚好就满,是这样吧 就像你说的 TH0=76 TL0=0.8125  TL0加满256后 TH0变成77  一直这样,当TH0=256 TL0=256  刚好是65536个数 TL0再加1的话就产生了溢出!是这样吧,谢谢你,这样算是理解了(高位TH0的初始值是76  低位TL0的初始值 是0.8125)

评分

参与人数 1黑币 +35 收起 理由
admin + 35 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:73833 发表于 2015-4-9 22:58 | 显示全部楼层
对头,是这样的。
回复

使用道具 举报

ID:73833 发表于 2015-4-9 23:36 | 显示全部楼层
楼主,看了你的回复,大部分是对的,但那个TL0=0.8125,是不对的,应当是0.8125*256=208才对,你说呢?
回复

使用道具 举报

ID:76158 发表于 2015-4-10 10:15 | 显示全部楼层
dingmingzhou 发表于 2015-4-9 23:36
楼主,看了你的回复,大部分是对的,但那个TL0=0.8125,是不对的,应当是0.8125*256=208才对,你说呢?

嗯,您这样一说,您的意思是说这个是16位定时器数据 每一位为8个字节 就是16*8*256=32768 低八位装载其实是32768  高八位也一样  32768*2=65536 是这样吗?

回复

使用道具 举报

ID:76471 发表于 2015-4-10 11:50 | 显示全部楼层
算TH0和TL0不用那么麻烦,用windows自带的计算器算出65536-45872=19664后,直接转换16进制4CD0,TH0就是4C,TL0为D0,分开转回去4C就是76,D0就是208

评分

参与人数 1黑币 +70 收起 理由
admin + 70 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:76471 发表于 2015-4-10 11:54 | 显示全部楼层
直接将TH0和TL0合起来看作16位数据,总数65536,预存19664数据,加45872后溢出
回复

使用道具 举报

ID:76158 发表于 2015-4-10 13:40 | 显示全部楼层
panzishi123456 发表于 2015-4-10 11:54
直接将TH0和TL0合起来看作16位数据,总数65536,预存19664数据,加45872后溢出

是的,现在知道了 就以后会这样做的!呵呵
昨天刚才STC那边买了一些STC15W402AS STC15F104W  不知道STC15W402AS中的3路PWM怎么用
正在努力学习
回复

使用道具 举报

ID:76158 发表于 2015-4-10 13:43 | 显示全部楼层
panzishi123456 发表于 2015-4-10 11:54
直接将TH0和TL0合起来看作16位数据,总数65536,预存19664数据,加45872后溢出

好的,现在知道了,我是想知道是如何演变而来的,现在知道是这么一回事,我以后就直接用就好了!呵呵
您会用15W402AS这个片子吗?
回复

使用道具 举报

ID:76471 发表于 2015-4-10 14:40 | 显示全部楼层
danpianji258 发表于 2015-4-10 13:43
好的,现在知道了,我是想知道是如何演变而来的,现在知道是这么一回事,我以后就直接用就好了!呵呵
您 ...

没有用过,用的现代的芯片,之前用的汇编,现在刚开始学C
回复

使用道具 举报

ID:73833 发表于 2015-4-10 16:55 | 显示全部楼层
本帖最后由 dingmingzhou 于 2015-4-10 17:58 编辑

       楼主,您好。13楼14楼在计算上是没错的,用的时候就是那么计算。但是在理解上我觉不是你说的这样“16位定时器数据 每一位为8个字节 就是16*8*256=32768 低八位装载其实是32768  高八位也一样  32768*2=65536 “,这样理解是错误的,也理解不了13楼14楼的做法。       应当这样理解:TH0,TL0都是8位寄存器,在内存中都是这个样子:”****   ****“(*号代表要么是1,要么是 0)。一个8位的寄存器最大存储的数字是256(包括0),只不过这两个寄存器,在单片机计数过程中,先从TL0的最低位存起,满一个256,就自身清零,同时向TH0进1(TH0=B0000 0001),满两个进两个1(TH0=B0000 0010),所以TH0是存储了多少个从低位送来的256.这就是叫做高8位、低8位的道理。一个8位寄存器是存不了32768的。32768在内存中是这个样子(1000 0000 0000 0000)。65535是这个样子(1111 1111 1111  1111),65536是这个样子(0000 0000 0000 0000)。这就是你可能看到有些人在计算初值时写作(-*****)/256、(-***)%256;不写65536,而只写一个(-),因为65536,在内存中表示为零。
      但这种0和从0起步的0,在意义上可能有些不同,你说呢?当在65536那个样子时,65536这一大包存到哪里去了?存到中断标志去了!(从0开始的0是没有这能耐的),但是中断标志似乎是个死脑筋,傻呼呼地只会告诉你一个字---1   !好在用中断服务程序时,定时器的中断标志是由硬件清零,而用查询时,它则更傻B了,连两个数也记不住,还要软件去清零,不过不要紧,记录这个 1出现的次数,就知道溢出几次。


评分

参与人数 1黑币 +35 收起 理由
admin + 35 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:73833 发表于 2015-4-10 17:14 | 显示全部楼层
本帖最后由 dingmingzhou 于 2015-4-10 17:42 编辑

11111111111111111111111
回复

使用道具 举报

ID:76158 发表于 2015-4-11 09:47 | 显示全部楼层
dingmingzhou 发表于 2015-4-10 16:55
楼主,您好。13楼14楼在计算上是没错的,用的时候就是那么计算。但是在理解上我觉不是你说的这样“16 ...

好的,知道了,谢谢你耐心讲解!
回复

使用道具 举报

ID:74245 发表于 2015-4-11 11:58 | 显示全部楼层
我也是自学,刚弄懂这个定时器不久,装初值是这样理解的。
设置为定时器模式后,你这个程序是定时器方式1,16位的二进制数,初始状态就是16个0,假如加满了就变成了16个1,就是65536了,65536的来由就是2的16次方。每来一个机器周期,就往里面加1;你的晶振一个机器周期就是1.085us,那么想要得到50ms就是要45872个机器周期,就是说首先往定时器里面装一个数,然后让它自己加,再加45872次就满了产生中断了,那既然它加了45872次是不是也就是说到了50ms呢。后面就很简单了,初值要装什么数呢,45872+初值=65536满了,那么初值就是65536-45872啊。
其实里面还有很多其他知识的,不能一一说出来,可以跟帖继续解答。

评分

参与人数 1黑币 +50 收起 理由
admin + 50 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:76158 发表于 2015-4-11 13:37 | 显示全部楼层
#include <reg52.h>                                                                                       
#define uint unsigned int
#define uchar unsigned char
sbit pwm=P1^0;                       
sbit pwm_up=P3^6;               
sbit pwm_dn=P3^7;                 
uint i;                                         
char j,k=5;                                  
void timer_init()        
{
        TMOD=0X02;                     
        TH0=56;                             
        TL0=56;                                  
        IE=0X82;                          
        TR0=1;                             
}
void delayms(uint xms)
{
        uint j,k;                       
        for(j=xms;j>0;j--)
                for(k=110;j>0;j--);
}
void timer0()interrupt 1  
{
        i++;                                 
        if(i==5000)                          
        {
         i=0;                                  
         j++;                                  
         j=j%10;                          

        }
       if(j<k)                         
           {
                   pwm=1;                          
           }
                        else                  
                        pwm=0;                 
}

void key_pwm()                         
{
        if(pwm_up==0)                 
        {
                delayms(5);                  
                if(pwm_up==0)         
                {
                         k++;                  
                        if(k>=10)               
                        {
                                k=10;               
                        }
                        while(!pwm_up);
                }                                       

        }
        if(pwm_dn==0)                       
        {
                 delayms(5);                       
                if(pwm_dn==0)               
                {
                        k--;                       
                        if(k<=0)               
                        {
                                k=0;       
                        }
                         while(!pwm_dn);
                }
        }

}

  void main()                               
  {
   timer_init();               
   for(;;)                               
           {
                key_pwm();
        }
  }

  
回复

使用道具 举报

ID:76158 发表于 2015-4-11 13:40 | 显示全部楼层
上面这个程序,也是从网络上半抄半写的
如果我将K的值变成122级
将中断的时间再改短,
这样看起来等还会闪吗
因为在公司 没有带开发板来公司 暂时不知道!

回复

使用道具 举报

ID:76158 发表于 2015-4-11 14:03 | 显示全部楼层
yesonjob 发表于 2015-4-11 11:58
我也是自学,刚弄懂这个定时器不久,装初值是这样理解的。
设置为定时器模式后,你这个程序是定时器方式1, ...

如果定时器的时间太短,中断的频率很高是不是会容易产生问题啊
例如我用定时器中断产生一个5KHZ的占空比50%方波
如果在中断的时间内,我在其他程序里面占用的时间大于中断的时间,是不是程序就乱套了,第一次中断还没有处理完毕,第二中断又来了
应该如何去评估这个中断中 其它程序运行需要的时间呢
回复

使用道具 举报

ID:76158 发表于 2015-4-11 14:19 | 显示全部楼层
本帖最后由 danpianji258 于 2015-4-11 14:27 编辑
yesonjob 发表于 2015-4-11 11:58
我也是自学,刚弄懂这个定时器不久,装初值是这样理解的。
设置为定时器模式后,你这个程序是定时器方式1, ...

#include <reg52.h>                                                                                       
#define uchar unsigned char
sbit pwm=P1^0;        
uchar num;               

void main()
{
        while(1)
        {
        void init();
        void pwmss();
        }

}
void init()
{
  TMOD=0X01;
  TH0=(65536-200)/256;
  TL0=(65536-200)%256;
  EA=1;
  ET0=1;
  TR0=1;
}
void time()interrupt 1
{
  TH0=(65536-200)/256;
  TL0=(65536-200)%256;
  num++;
}
void pwmss()
{
         if(num=2)
        {        
                num=0;
                 pwm=1 ;
        }
                 else
                {
                 pwm=0;
                }
}

你看这个程序是不是产生一个5KHZ的标准的50%的PWM波形?
回复

使用道具 举报

ID:76471 发表于 2015-4-11 14:45 | 显示全部楼层
danpianji258 发表于 2015-4-11 14:19
#include                                                                                         
...

if(num=2)这个应该是 if(num==2)吧。 想学51C,买套学习板,但QQ留言和打电话都没有反应,想知道如何购买本网站的学习板,如果知道告诉一下,谢谢
回复

使用道具 举报

ID:76471 发表于 2015-4-11 14:53 | 显示全部楼层
danpianji258 发表于 2015-4-11 14:19
#include                                                                                         
...

5kHz周期为200us,半周期为100us,半周期翻转一次,所以65536应该要-100
回复

使用道具 举报

ID:76158 发表于 2015-4-11 15:02 | 显示全部楼层
panzishi123456 发表于 2015-4-11 14:53
5kHz周期为200us,半周期为100us,半周期翻转一次,所以65536应该要-100

嗯 是的 你比我厉害多了
书写确实是大意了
写程序真的不能大意
学习板我买的是天详的
这个程序刚运行下还是没有方波出来  还有两个警告
回复

使用道具 举报

ID:76471 发表于 2015-4-11 15:18 | 显示全部楼层
void init();中断初始化放while循环上面,我也不是很厉害,要学的东西很多,你的天详学习板跟这个网站的是不是一样的,有没有链接,我看一下

评分

参与人数 1黑币 +35 收起 理由
admin + 35 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:76158 发表于 2015-4-11 15:30 | 显示全部楼层
panzishi123456 发表于 2015-4-11 15:18
void init();中断初始化放while循环上面,我也不是很厉害,要学的东西很多,你的天详学习板跟这个网站的是 ...

是的 我已经换上去了 结果还是一样的!你先联系一下管理员 它应该卖的!
回复

使用道具 举报

ID:76158 发表于 2015-4-11 15:37 | 显示全部楼层
管理员回复你帖子了 你看看 联系他看看
回复

使用道具 举报

ID:76471 发表于 2015-4-11 15:52 | 显示全部楼层
danpianji258 发表于 2015-4-11 15:37
管理员回复你帖子了 你看看 联系他看看

多谢了,刚上这论坛没多久,不知道他移走我贴子,还以为不见了
回复

使用道具 举报

ID:76471 发表于 2015-4-11 15:52 | 显示全部楼层
danpianji258 发表于 2015-4-11 15:37
管理员回复你帖子了 你看看 联系他看看

多谢了,刚上这论坛没多久,不知道他移走我贴子,还以为不见了
回复

使用道具 举报

ID:76158 发表于 2015-4-11 16:14 | 显示全部楼层
panzishi123456 发表于 2015-4-11 15:52
多谢了,刚上这论坛没多久,不知道他移走我贴子,还以为不见了

是不是这个R52C的IO口跟不上啊!用示波器看 根本就没有方波出来!!!!
回复

使用道具 举报

ID:76471 发表于 2015-4-11 16:30 | 显示全部楼层
danpianji258 发表于 2015-4-11 16:14
是不是这个R52C的IO口跟不上啊!用示波器看 根本就没有方波出来!!!!

才5KHZ,不可能跟不上啊
回复

使用道具 举报

ID:76471 发表于 2015-4-11 16:30 | 显示全部楼层
danpianji258 发表于 2015-4-11 16:14
是不是这个R52C的IO口跟不上啊!用示波器看 根本就没有方波出来!!!!

才5KHZ,不可能跟不上啊
回复

使用道具 举报

ID:76158 发表于 2015-4-11 16:34 | 显示全部楼层
panzishi123456 发表于 2015-4-11 16:30
才5KHZ,不可能跟不上啊

你买到板子没有,如果没有买到的话 你说声 我将天详的地址给你 另外 我们加个QQ吧!呵呵  跟你学习学习
回复

使用道具 举报

ID:76471 发表于 2015-4-11 16:36 | 显示全部楼层
danpianji258 发表于 2015-4-11 16:14
是不是这个R52C的IO口跟不上啊!用示波器看 根本就没有方波出来!!!!

你不用定时器,直接主程序那里将P0口取反看看
回复

使用道具 举报

ID:76471 发表于 2015-4-11 16:36 | 显示全部楼层
说错了,主函数
回复

使用道具 举报

ID:76471 发表于 2015-4-11 16:39 | 显示全部楼层
danpianji258 发表于 2015-4-11 16:34
你买到板子没有,如果没有买到的话 你说声 我将天详的地址给你 另外 我们加个QQ吧!呵呵  跟你学习学习

还没有,我QQ48325047,互相学习
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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