很多新手在单片机上走的第一步是点亮第一个LED灯,实际上因为开发板的不同,所编写的代码也不同,关键是你要去了解你用的开发板的电路布局。对于电路方面的知识我这里也不祥讲,我要做的是无论你用哪一种开发板我的文章都能帮助你。

  P0  =  0xFE;

  这句代码大家不陌生。

  void main(){

    unsigned char count = 0;

    while(1){

      

      P0  =  ~(0x01  <<  count);

      Delay();    //单独实现一个延时函数

      count++;

      if(count>=8){

        count = 0;

      }

    }

  }

以上就是实现流水灯的基本代码,这里没有电路供你分析,但是无论什么开发板,核心代码可以用以上代码实现。

  我相信你能看到这里也是有点基础的,这里的延时函数Delay,接下来要讲的是定时器,定时器就是可以替代延时函数的。

定时器

标准的51单片机内部有T0和T1两个定时器,实际上就是TCON特殊功能的寄存器来控制这两个定时器的。

 

除此之外,定时值存储寄存器有TH和TL,给TL赋值后,TL会自动加1,加到255后TH加1,有趣的TH也可以提前赋值,但这只是定时器工作的一种模式,定时器有四种模式,这里我不祥讲,而且我们几乎用的模式就是这种,后面涉及到会详细讲解。这里只需要知道TCON(地址0x88)位分配,以后会经常用到。

还有一个TMOC就是定时器作用的模式,位分配如下图:

代码:

void main()

{

  TH0 = 0xB8;  //给TH0赋值,后面的0代表是给定时器T0的TH赋值

  TL0 = 0x00;

  TR0 = 1;   //启动T0定时器

  if(TF0 == 1)    //判断T0是否溢出,TF是个标志位

  {

    //重置

  TH0 = 0xB8;  

  TL0 = 0x00;

  }

  

}

以上就是定时器,时间多少呢?

我们以晶振位11.0592为例,时钟周期是1/11059200,机器周期(1ms)12/11059200,如果我们定时20ms,那个要执行20*(12/110592)次,算出来是18432次,换成十六进制是B800,所以对TH0赋值B8,对TL0赋值00;

 

数码管

#include <reg52.h>

sbit ADDR0 = P1^0; sbit ADDR1 = P1^1; sbit ADDR2 = P1^2; sbit ADDR3 = P1^3; sbit ENLED = P1^4;

void main() {  ADDR2 = 1;  ADDR1 = 0;  ADDR0 = 1;  ADDR3 = 1;  ENLED = 0;

 P0 = 0XF8;  while(1); }

上面代码是用位STC-51开发板写的,在最后一个数码管上显示数字7,数码管难度简单,只需要针对数码管等的排布编程即可。

下面我们用关键字code定义数码管所能够显示所有字符的数组,这里再结合定时器一起。

#include <reg52.h>

sbit ADDR0 = P1^0; sbit ADDR1 = P1^1; sbit ADDR2 = P1^2; sbit ADDR3 = P1^3; sbit ENLED = P1^4;

//数组 unsigned char code led[] = {  0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,  0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E };

void main() {  unsigned char count = 0;//记录T0中断次数  unsigned char secnt = 0;//记录经过的秒数

 ADDR2 = 1;  ADDR1 = 0;  ADDR0 = 0;  ADDR3 = 1;  ENLED = 0;

 //设置T0模式  TMOD = 0x01;  //为T0的TH0,TL0初始化  TH0 = 0xB8;  TL0 = 0x00;  //启动T0  TR0 = 1;

 while(1)  {   if(TF0 ==1)   {    TH0 = 0xB8;    TL0 = 0x00;    count++;    TF0 = 0;   }   if(count >=50)   {    count = 0;    P0 = led[secnt];    secnt++;    if(secnt>=16)    {     secnt = 0;    }   }  }

}

这里代码比较紧凑,不过不影响。上面的代码我相信你也能懂,但是你能发现定时器在这里起到了一个定时中断的作用。

这里讲一下中断。

中断

下面是中断IE寄存器位分配图:

 

直接上代码:

#include <reg52.h> //数码管显示字符真值数组 unsigned char code ledchar[]={  0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,  0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E }; //数码管显示区数组 unsigned char ledbuff[6] = {  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; sbit ADDR0 = P1^0; sbit ADDR1 = P1^1; sbit ADDR2 = P1^2; sbit ADDR3 = P1^3; sbit ENLED = P1^4;

  unsigned char i = 0;//动态扫描索引   unsigned int c = 0;//记录中断次数 void main() {   unsigned long s = 0;//记录秒数 //使能U3  ADDR3 = 1;  ENLED = 0; //设置T0模式  TMOD = 0x01; //初始化TH0,TL0  TH0 = 0xFC;  TL0 = 0x66; //启动TR0  TR0 = 1; //使能总中断  EA = 1; //使能T0中断  ET0 = 1;  //主循环  while(1)  {      //1s中断    if(c>=1000)    {     s++;     c=0; //为数码管显示区赋值     ledbuff[0] = ledchar[s%10];     ledbuff[1] = ledchar[s/10%10];     ledbuff[2] = ledchar[s/100%10];     ledbuff[3] = ledchar[s/1000%10];     ledbuff[4] = ledchar[s/10000%10];     ledbuff[5] = ledchar[s/100000%10];    }

  }   }

//定时器T0中断服务 void InterruptTimer0() interrupt 1 { //重新赋值  TH0 = 0xFC;  TL0 = 0x66;  c++; //显示消隐  P0 = 0xFE;  //完成数码管动态扫描    switch(i)    {     case 0:      ADDR2 = 1;ADDR1 = 0;ADDR0 = 1;i++;P0 = ledbuff[0];          break;     case 1:      ADDR2 = 1;ADDR1 = 0;ADDR0 = 0;i++;P0 = ledbuff[1];     break;     case 2:      ADDR2 = 0;ADDR1 = 1;ADDR0 = 1;i++;P0 = ledbuff[2];     break;     case 3:      ADDR2 = 0;ADDR1 = 1;ADDR0 = 0;i++;P0 = ledbuff[3];     break;     case 4:      ADDR2 = 0;ADDR1 = 0;ADDR0 = 1;i++;P0 = ledbuff[4];     break;     case 5:      ADDR2 = 0;ADDR1 = 0;ADDR0 = 0;i=0;P0 = ledbuff[5];     break;     default:break;    }  }

这组代码能够按照我们计算好的时间为单位显示秒数。

我们能够提出中断核心代码

EA = 1//中断总开关

ET0 = 1//确认使用T0定时器中断开关

TR0 = 1//肯定要启动T0定时器

void InterruptTimer0() interrupt 1//定时器T0中断服务,中断代码写在这里面,至于interrupt 1是因为interrupt会去寻找地址' 1 ',而T0定时器中断的地址就是1,所以我们可以直接在此函数中写中断期间的代码。至于各种中断的地址我也不再这里多写了。值得一谈的是IP——中断优先级寄存器位分配

各级中断都差不多,中断发生的也很多,当同时有许多中断发生时,可以通过置上面的值为1升级成优先级中断。

 

posted on 2017-08-22 15:08  嵌入式开发员  阅读(689)  评论(0编辑  收藏  举报