2016-08-13 09:24:15 q392493617 阅读数 8272
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4003 人正在学习 去看看 朱有鹏

    单片机中,中断算是一个比较重要的部分,在51单片机中有八种中断方式 ,其中常用的的有五种,分别是外部中断0,计时器中断0,外部中断1,计时器中断1,和串口中断。今天主要介绍的是计时器中断。

    51单片机给我们提供了2个计时器中断,分别是计时器0和计时器1,他们对应的优先级分别是1和3,开启计时器并允许其中断后,计时器会从给定的初始值开始,每个指令周期加1,直到加到65535,再加一时计时器溢出,计时器此时会进入中断,并执行中断服务函数。

    在编程过程中发现有许多人搞不清中断服务函数与一般函数的区别,他们总是问出诸如中断服务函数在程序中哪一句之前或哪一句之后执行的问题。其实中断服务函数虽然也是个函数,但是它与一般函数还是有一定的区别的。一般函数想使用时,必须要在主函数或其他函数中调用。而中断服务函数,只要在主函数中初始化计时器后,当计时器进入中断时会中止单片机进行的所有操作,开始执行中断服务函数,在执行完中断服务函数后再回到执行中断服务函数前执行的地方继续执行。其实中断服务函数也是被调用了,但它不是被程序中的某一句话调用了,而是被单片机调用了。

    单片机单片机存储程序并不是从0地址开始保存,而是在中端向量表后保存,中断向量表中保存的是中断的优先级和中断服务函数的地址。程序执行后一旦计时器进入中断状态,单片机会回到中断向量表查询中断的优先级和中断服务函数的地址,然后跳转到中断服务函数所在地址开始执行,执行完成后回到中断向量表,然后回到中断前的地方执行。

    单片机的初始化有5步:

    1.打开总中断。

    2.选择工作方式。

    3.计时器初始化。

    4.打开计时器中断允许。

    5.开始计时。

 

   下面以定时器0为例就按照上面五个步骤写一个1ms执行一次中断函数的初始化函数。

    void tiemr0_init()

   {

          EA = 1;        //打开总中断

          TMOD |= 0x01;   //选择工作方式1      *注1

          TH0 = (65536 - 1000) / 256;     //定时器高八位初始化

          TL0 = (65536 - 1000) %256;    // 定时器低八位初始化

          ET0 = 1;  //打开定时器0中断允许

          TR0 = 1; //定时器0开始计时

    }

注1:TMOD寄存器有八位,其中高八位用于选择定时器1的工作方式,低八位用于选择定时器0 的工作方式,定时器1有三种工作方式,定时器1有四种工作方式。

一般定时器中断时使用方式一,也就是用定时器0(T0)时 TMOD |= 0x01,用定时器1(T1)时 TMOD |= 0x10,方式2一般用于串口中断,其余两种涉及不多。

中断服务函数只需要在函数名后加interrupt X ,X就是中断对应的优先级,如定时器0中断对应的优先级是1,那他的中断服务函数名后面就加interrupt 1,下面就以定时器0为例编写一个使count一毫秒加一的中断服务函数(晶振为12M)

unsigned char count = 0;

void timer0_isr() interrupt 1

{   

      TH0 = (65536 - 1000) / 256;

      TL0 = (65536 - 1000) % 256;   

      count++;

}

2019-10-08 20:09:49 qq_27061049 阅读数 82
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4003 人正在学习 去看看 朱有鹏

1.计时器

因为51单片机的机器周期计算公式是12/晶振频率MHz,若晶振为12MHz,则机器周期就是12/(12×10^6)=1us,也就是说计数器没1us计数一次。
一般来说,12MHz晶振下,16位定时器满计数是65536次,每次1us,最大就能计时65.536ms,则65536减去多少就是定时多少,如(65536-X)/256,就是定时X微秒。
那么T=1/(X/12)就是一个机器周期 ,(65536-Z(初值))*T就是定时的时间
比如是12M的晶振那么 设置TMOD=0x01, 计时器模式

TH0=(65536-50000)/256;
TL0=(65536-50000)%256;就是设置了50ms的定时

2、计时器中断 1S 闪光灯

我们使用计时器中断来设置 1S 闪光灯

#include <reg52.h> //51头文件

sbit LED1 = P1^0; //位定义 LED1硬件接口

int num = 0;
//中断服务特殊功能寄存器配置
void init()
{
	
	TMOD = 0x01;  //定时器16为计数工作模式
	TH0 =(65536-50000)/256;;
	TL0 =(65536-50000)%256; //50ms  定时
	ET0 = 1; //开定时器0中断
	TR0 = 1;//启动定时器0
	EA = 1;	//开总中断
}
//定时器0中断服务程序 不用软件延时
void timer0() interrupt 1
{
	TH0 =(65536-50000)/256;;
	TL0 =(65536-50000)%256; //50ms  定时  模式1非自动重装需要手动重装再次定时

	num++;
	if (num == 20) { // 20 * 50ms 为 1s
    	num = 0;
	   LED1 = ~LED1;
	}
}

void main()
{
	LED1 = 0;  //拉低IO点亮LED1
	init();//初始化定时器0
	while(1);//程序停留	
}

在这里插入图片描述

文档参考:
关于51单片机的定时器T0、T1总结
http://www.51hei.com/bbs/dpj-103111-1.html

2017-06-12 21:10:58 zb756999355 阅读数 10618
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4003 人正在学习 去看看 朱有鹏

Ps:
使用的是51单片机, 晶振为11.0592M的, 时间选择5ms。
这篇博客好像是第一篇单片机博客诶~。

算法:
简单的计时器应用, 最开始 根据 2^16 - (t - f)/12 计算得到值, 将其转换为16进制 (注意:单位的改变, 例如晶振要乘上 10e6 时间 要转换为秒s 乘上 10e-3)
由此可以得到 TH0/TL0的值。
例如:
设计的是5ms, 则 算式为 2^16 - (5 * 10^-3 - 11.0592 * 10^6) / 12; 转换为16进制 为DC00; 所以 TH0 = 0XDC __ TL0 = 0X00;

显示:
拆字什么的 就不说了~~, 反正就是 分和秒 对 10取余 和 整除。
下面函数中的 counter 和 second 分别对应 秒和分。

Hint:
老师说, 最好在 tmp=counter%4; 前 加上 if(changed == 1)执行拆字显示, 然后再将执行空语句 如此循环。 但还是不怎么明白为什么。 好像是说 保护 IO 之类的~~~~

#include<reg52.h>
#define uchar unsigned char
uchar counter=0,tmp,second=0,minute=0, changed = 1;
main()
{   //TMOD=0X21;                            //设置TMOD寄存器
    TMOD=0X01;                          //设置TMOD寄存器
    TH0=0xDc;              //装初值
    TL0=0x00;

    //TH1=0XFD;
    //TL1=0;
    //TR1=1;
    //SCON=0X50;

    EA=1;       //开 中断
    ET0=1;
    TR0=1;
    while(1)
    {
         char a[10] = {0xc0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90};
    //拆字

    //显示

    tmp=counter%4;
    switch(tmp)
    {
    case 0:{
                P2 = 0x7f;
                P0 = a[second%10];
            }
        break;
    case 1:{
                P2 = 0xbf;
                P0 = a[second/10];
            }
        break;
    case 2: {
                P2 = 0xdf;
                P0 = a[minute%10];
            }
        break;
    case 3: {
                P2 = 0xef;
                P0 = a[minute/10];
            }
        break;

    }
    }



    /*
        if(j==2)
        {
            j=0;
            P2=~P2;

        } 
    */

}
void zhongduan()interrupt 1
{
    TH0=0xee;              //装初值
    TL0=0x00;
    TF0=0;
    TR0=1;

    /*
    i++;
    if(i>=5)
    { 
        i=0;    
        //SBUF=j;
        //while(!TI);
        //TI=0;
        j++;
    }
    */
    counter++;
    if(counter==200)
    {
       counter=0;
       second++;
       if(second==60)
       {
          second=0;
          minute++;
       }
     }
}      
2012-08-21 10:42:03 xmfthu 阅读数 4526
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4003 人正在学习 去看看 朱有鹏

     用51单片机的定时器0的方式1计时,结果用4位数码管显示,分别为秒十位,秒个位,毫秒百位,毫秒十位。所以总共最大计时为1分钟,精确到了0.01s。同时,加上3个独立按键,分别控制秒表的清零,暂停和开始功能。

   按照模块化的思想,首先先把要用的函数和预定义写到一个头文件中,要用到的预定义和全局变量如下:

#include <reg52.h>
#define uchar   unsigned char

sbit Clear=P3^7;   //按键实现清零
sbit Stop=P3^6;    //按键实现暂停
sbit ReStart=P3^5;  //按键实现开始
sbit dula=P2^6;     //段选线接P2^6口
sbit wela=P2^7;     //位选线接P2^7口

//table数组中存储数码管显示0~F对应的编码
uchar code   table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};

//计时时间,计时中断发生一次,则加1,最大为5999
int time;

 

接下来是将要用到的函数声明:

//用于动态扫描数码管的时间较短的延时函数
void ShortDelay();    

//用于键盘消抖的时间较长的延时函数
void LongDelay();

//初始化
void Inital();

//在数码管显示秒十位,秒个位,微秒百位,微秒十位
//用拼音表示很不好,将就着看吧
void Display(uchar shimiao,uchar gemiao,uchar baiwei,uchar shiwei);

//清零函数,按下清零键的时候调用
void Clc();

//暂停函数,按下暂停键时候调用
void StopTimer();

//开始或重新开始函数,按下开始键时候调用
void ReStartTimer();

//键盘扫描函数,是否有键被按下,并且执行相应操作
void KeyScan();


 

接下来是主函数:

void main()
{
  uchar shimiao,gemiao,baiwei,shiwei;
  Inital();   //初始化
  while(1)
  {
    if(time==6000)    //到了秒表最大值,自动归零
    {
      time=0;
    }
    
    //分解出要显示的各个数位
    shimiao=time/1000;
    gemiao=time%1000/100;
    baiwei=time%100/10;
    shiwei=time%10;
    
    //显示
    Display(shimiao,gemiao,baiwei,shiwei);
    ShortDelay();
    //键盘扫描,有键按下执行相应操作
    KeyScan();
  }
}


下面的工作就是要写相应的处理函数了:

首先是两个延时函数:

void ShortDelay()
{
  uchar a=100;
  while(a--);
}

void LongDelay()
{
  int a=5000;
  while(a--);
}


初始化函数:

void Inital()
{
  dula=0;
  wela=0;
  time=0;
  EA=1;
  ET0=1;    //开定时器0中断
  TMOD=0x01;
  TH0=0xdc;
  TL0=0x01;   //装载初值,计时方式1  
  Clear=1;
  Stop=1;
  ReStart=1;   //按键接口管脚输出高电平
}


在数码管上显示时间的函数:

void Display(uchar shimiao,uchar gemiao,uchar baiwei,uchar shiwei)
{
  //输出秒十位
  wela=1;
  P0=0xfb;
  wela=0;
  P0=0xff;
  dula=1;
  P0=table[shimiao];
  dula=0;
  ShortDelay();
  
  //输出秒个位
  wela=1;
  P0=0xf7;
  wela=0;
  P0=0xff;
  dula=1;
  P0=table[gemiao];
  dula=0;
  ShortDelay();
  
  wela=1;
  P0=0xef;
  wela=0;
  P0=0xff;
  dula=1;
  P0=table[baiwei];
  dula=0;
  ShortDelay();
  
  wela=1;
  P0=0xdf;
  wela=0;
  P0=0xff;
  dula=1;
  P0=table[shiwei];
  dula=0;
  ShortDelay();
  
}


键盘扫描函数:

void KeyScan()
{
   if(Clear==0)    
    {
      LongDelay();    //消抖
      if(Clear==0)    //确实是被按下
      {
        //Do somthing
        Clc();
      }
    }
    
    //Stop和ReStart检测方法相同
    if(Stop==0)     
    {
      LongDelay();
      if(Stop==0)
      {
        //Do somthing
        StopTimer();
      }
    }
    if(ReStart==0)
    {
      LongDelay();
      if(ReStart==0)
      {
        //Do somthing
        ReStartTimer();
      }
    }
}


最后是3个按键按下后的处理函数:

void Clc()
{
  TR0=0;   //计时暂时停止
  time=0;   //时间归零
  Display(0,0,0,0);   //显示0000
  ShortDelay();    
}

void StopTimer()
{
  //计时暂时停止,仅此而已
  TR0=0;    
}

void ReStartTimer()
{
  //计时重新开始,仅此而已
  TR0=1;
}


至此,编译链接后生成的.HEX文件就能下载到51单片机里了。

 

2018-05-15 17:07:03 GF__marry 阅读数 975
  • 单片机控制第一个外设-LED灯-第1季第6部分

    本课程是《朱有鹏老师单片机完全学习系列课程》第1季第6个课程,主要讲解LED的工作原理和开发板原理图、实践编程等,通过学习目的是让大家学会给单片机编程控制LED灯,并且为进一步学习其他外设打好基础。

    4003 人正在学习 去看看 朱有鹏
#include <reg52.h>
#define uint8 unsigned char
#define uint16 unsigned short int


//数码管段码显示:0~f,不亮
uint8 code LED_Disp[] = {0xC0,0xF9,0xA4,0xB0,    //这一组编码当中不包含小数点
                        0x99,0x92,0x82,0xF8,
0x80,0x90}; //十个分别显示 0 1 2 3 4 5 6 7 8 9 
uint8 code LED_Disp1[] = {0x40,0x79,0x24,0x30,    //这一个数组的编码中包含小数点
                        0x19,0x12,0x02,0x78,
0x00,0x10}; //十个分别显示 0 1 2 3 4 5 6 7 8 9 


int minute  = 0;
int second = 0;
void mDelay(uint16 mtime)
{
for(; mtime > 0; mtime--)
{
uint8 j = 244;
while(--j);

}

void LED_Disp_Seg7()
{
  

int minute_1;
int minute_2;
int second_1;
int second_2 ;
 
  


if(second == 60)
{
minute++;
second = 0;



if(minute == 60)
{
minute = 0;
}
minute_1 = minute/10;
minute_2 = minute%10;
  second_1 = second/10;
second_2 = second%10;
P2 = 0x7f;
     P0 = LED_Disp[second_2];
     mDelay(5);
 




     P2 = 0xbf;
     P0 = LED_Disp[second_1];
     mDelay(5);
   




     P2 = 0xdf;
     P0 = LED_Disp1[minute_2];
     mDelay(5);
 




     P2 = 0xef;
     P0 = LED_Disp[minute_1];     
     mDelay(5);




  
}
void timeDelay(unsigned int  time)
{
while(time--)
{
LED_Disp_Seg7();
}
}




 
void main()
{
while(1)
{  
timeDelay(80);
  second++;
}  
}
 

单片机_ADC详解

阅读数 1829

没有更多推荐了,返回首页