单片机小结之各种方案点亮流水灯

单片机小结(1

——之流水灯的各种方法点亮

    我们将8个流水灯均放置在P0口,且假设已经定义好各端口,流水灯的阳极接到P0口上,利用各种方法控制流水灯。    

1.1用移位和查表控制流水灯

(1):用移位控制流水灯

void main(void)

{  uchar i;

         while(1)

           {   

                P0=0xfe;//先点亮P0^0;

                Delay(10000);//延时10毫秒

                for(i=0;i<7;i++)

                   {

                      P0=(P0<<1)&0x01

                      Delay(10000);//延时100毫秒

}

}

}

  或者改为如下也可以实现左移,先给temp=0xfe;

       for(i=1;i<8;i++)

        {

    a=temp<<i; b=temp>>(8-i); P0=a|b; Delay();

}

在仿真中或者开发板上可以看到led灯有规律的一个一个的点亮如此循环。如果在

P0=0xfe下加延时,那么第一次点亮时可以看到小灯的亮下再灭,否则第一次看不到小灯亮。

    以上即一直往左移移位,我们可以修改程序让其左右循环来点亮流水灯,程序如下while(1)

    {

        for(i=0;i<7;i++)

       {

         LED=_crol_(LED,1); //P2口向左移,注意左移和右移都住需要移动7次

          Delay(50000);

       }    

for(i=0;i<7;i++)

      {

        LED=_cror_(LED,1);//左移,头文件必须加#include<intrins.h>方可使用,             Delay(50000);

      }

    }

(2)用查表控制流水灯

在上个程序中我们利用左移的方法点亮小灯,即移位的思想。同时我们还可以利用查表的方法点亮led灯。程序如下:

       uchar code Led_Data[]=

{

             0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f

} ;//此处一定要记住加分号,否者编译的时候会报错。

   在将上个程序中左移的语句改为如下即可实现查表,并且将P0=0xfe;去掉

          for(i=0;i<8;i++)

{

P0=Led_Data[i];

            Delay(10000);//延时10毫秒

          }

    

(3)利用硬件的方法控制流水灯

 除了以上移位我们还可以利用硬件来实现点亮小灯,例如利用74HC573,74HC595

1.1:74HC573为8位锁存器,

     

1脚OE为使能端,低电平有效。D1-D7为输入端,Q1-Q7为输出端。11脚为锁存端,高电平有效

当OE为低电平,并且LE为高电平时,芯片才正常工作,输入等于输出。

当OE为低电平,LE也为低电平时,芯片锁存。

    当 OE为高电平时,输出为高阻态。

下面我们还是利用该芯片编写下控制流水灯的程序,并且是利用移位的思想。

 使用之前先说明下74HC573的工作方法:

1.  先将OE置为低电平,并且LE也置为低电平,也就是开锁。

2.  将需要输出的数据发送到D端。

3.  再将LE置为低电平,即锁存数据,不在随输入

/***********************源程序代码如下*************************/

 #include<reg51.h>

#define uchar unsigned char

#define uint unsigned int

#define LED P3

sbit LE=P2^2; //定义锁存端

void Delay(uint ms);

void main(void)

   { 

      uchar i,Temp;

       while(1)

        {   

            Temp=0xfe;  //先点亮P3^0口的LED灯

            for(i=0;i<7;i++)

              {   

                  LE=1; //开锁,注意OE端默认已经接到低电平

                  LED=Temp;//送数据到P3口,点亮小灯

                  LE=0;//输出锁存

                  Delay(5000); //延时

                  Temp=(Temp<<=1)&0x01;//左移一位

                 

              }

         }

     }

void Delay(unsigned int ms)

{

    unsigned char i;

    for(;ms>0;ms--)

        for(i=127;i>0;i--);

}

我们还可以利用其去控制数码管,原理和控制流水灯差不多。此处利用74HC595控制流水灯将在数码管部分提到如何利用,以及原理。

1.2 利用中断和定时器以及串口控制流水灯

1.2.1 利用外部中断0控制流水灯

  说明:利用按键来控制流水灯,采用移位的方法实现控制,利用外部中断0。

(1)   中断的概念:由于内部或者外部的原因,使CPU暂停当前的工作,转到需处理的中断的服务程序入口(中断响应),去执行中断程序,执行完毕后接着刚才未执行完的程序继续接着执行。

(2)   中断的控制和实现:主要是通过四个与中端有关的特殊功能寄存器配置完成。

定时器/计数器控制寄存器TCON,串口控制寄存器SCON,中断控制寄存器IE,

中断优先级控制寄存器IP。

(3)   51单片机中中断优先级可以通过设置来完成,当你没有设置的时候,在内部有默认中断优先级,即从高到低为:外部中断0(INT0),定时器/计数器0(T0),外部中断1(INT1),定时器/计数器1(T1),串口中断。

以下为外部中断0的初始化流程:

1.   设置外部中断0的中断控制位(即寄存器IE),将EX0设置为1,表示允许外部中断0触发中断。

2.   设置外部中断0的触发方式IT0,如IT0=0,表示采用电平触发,为1表示采用边沿触发方式。

3.   设置中断优先级,PXO=1,设置了外部中断0为高优先级。也可以不设置,即在内部(CPU)默认了优先级。

外部中断请求有两种触发方式:电平触发和边沿脉冲触发。

   (1):电平触发:低电平有效,只要单片机在中断请求输入端上采样到有效电平的低电平时,就激活外部中断。外部请求必须保持到获得中断响应为止,中断过后又必须撤销其有效的低电平。

   (2):边沿脉冲触发:脉冲的下降沿有效。若该CPU第一个机器周期采样到高电平,在另一个机器周期内采样到低电平,即在两次采样周期间产生了先高后低的负跳变时,则认为中断请求有效。

以下为利用外部中断0来实现流水灯的效果

附图如下:

 

/****************************外部中断0******************************/

//-----------------------------------------------------

//****本例:通过中断程序来控制按键*****

//时间:2011.7.6

//-----------------------------------------------------

#include <reg51.h>

#include <intrins.h>

#define uchar unsigned char

#define uint unsigned int

uchar LED;//定义中断

void Init_intr();

/********************主函数************************/

void main()

{

    Init_intr();

    LED=0xfe;  //设置中间变量可以使得流水灯一个一个被点亮

    P0=0XFF;

   while(1); //如果写成 while(1)LED=1;则按键没有作用,因为已经构成死循环,无法跳出

}

/*******************中断初程序始化******************/

void Init_intr()

{

   IE=0x81; //开总中断 EA=1;开外部中断0 EX0=1;

   IT0=1;//采用边沿触发方式,如果采用电平触发则IT0=0;

  // IT0=0;//采用电平触发 按键的一致按下去才会改变 松开后不会在变化

}

/***************************中断程序**************************/

/*不需要定义按键口,当P3作为第二功能时,单片机内部已经有***/

void intrr_int_0() interrupt 0    //中断程序不需要函数声明

{

     P0=LED;

     LED=_crol_(LED,1); //LED左移一位,注意在头文件#include<intrins.h>

}

   

   

1.2.2 利用定时器/计数器的TIME0中断控制两组LED滚动显示

   定时器和计时器只是输入的计数脉冲来源不同,做定时器时脉冲来自于内部时钟振荡器,做计数器时脉冲来自外部引脚。

定时器/计数器的初始化

(1):设置TMOD的工作模式,以确定T0和T1的工作方式。

(2):计算定时器/计数器初值,并填充TH1/TL1。

(3):当定时器/计数器工作在中断方式时,则进行中断初始化,即设置IE和IP。

(4): 置位TRO或TR1,启动定时器/计数器开始定时或者计数。

注意单片机定时器/计数器T0有4(0,1,2,3)种工作方式,T1有3种工作方式(0,1,2)。

设置工作方式TMOD可以设置工作方式。且当C/T=0,用于定时,C/T=1,用于计数。

使用定时器时主要有两种方法:

(1):用定时中断法,计数溢出的时候触发中断,预先设置的中断函数将被自动调用

(2):使用查询法检查是否出现计时溢出,溢出时执行指定代码。

下面程序为利用定时中断点亮流水灯,并且经过开发板测试过P0口。

/*******************利用定时器中断点亮流水灯*************************/

#include<reg51.h>

#include<intrins.h>

#define uchar unsigned char

#define uint unsigned int

#define LED1 P0

#define LED2 P2

sbit CS_LED=P2^5;//此处为74HC573的锁存端

void TIME0_Init(void);

uchar Count=0;

/*******************主函数****************************/

void main(void)

{

    TIME0_Init();

    LED1=0xfe;

    LED2=0xfe;

    while(1);

}

/******************定时器0的初始化***************************/

void TIME0_Init(void)

{

     TMOD=0x01;   // 定时器0工作在方式1    且定义10ms中断一次

     TH0=0xd5;    //

     TL0=0x9e;    //

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

     IE=0x82;     // 打开中断标志位

}

/******************定时器T0的中断函数*****************************/

void TIME0_interrupt(void) interrupt 1 using 1

{

     TH0=0xd5; //方式0,1,3,在中断函数内都必须重置初值

     TL0=0x9e;  //方式2为8位自动装载模式,此模式下在中断函数里不要再写初值

     Count++;      

     if(Count==100)    //1s钟后P0口和P2口都开始滚动一次

      {

         CS_LED=1;//打开74HC573的锁存端

         Count=0;

         LED1=_crol_(LED1,1);

         LED2=_crol_(LED2,1);

      }

}

说明:我们定义定时时间为10ms产生一次中断,定时器中断标志位TF0会自动置1,发出中断请求。并且定义了一个累加变量,当1s后P0口和P2口流水灯滚动显示。

1.2.3利用串口给单片机发送数据来控制流水灯

 //------------------------------------------

//  功能:本例是利用串口助手向单片机发送数据

//        来控制led

//------------------------------------------

#include<AT89X52.H>

#define    uchar   unsigned char

#define    uint        unsigned int

#define LED P0

sbit   LED0 = P0^0;

sbit   LED1 = P0^1;

sbit   LED2 = P0^2;

sbit   LED3 = P0^3;

sbit   LED4 = P0^4;

sbit   LED5 = P0^5;

sbit   LED6 = P0^6;

sbit   LED7 = P0^7;

void   Init_Uart(void);

void main(void)

{

   uchar i = 0;

   Init_Uart();

   while(1)

     {

           LED=0xff;

           while(!RI); //通过查询来控制寄存器

            {  RI = 0;

              i = SBUF;

              switch(i)

               {

                   case 0x01: LED0 = ~LED0;break;

                   case 0x02: LED1 = ~LED1;break;

                   case 0x03: LED2 = ~LED2;break;

                   case 0x04: LED3 = ~LED3;break;

                   case 0x05: LED4 = ~LED4;break;

                   case 0x06: LED5 = ~LED5;break;

                   case 0x07: LED6 = ~LED6;break;

                   case 0x08: LED7 = ~LED7;break;

                } 

}

      }

}

void Init_Uart(void)  //串口初始化程序

{

   TMOD = 0x20;

   TH1 = 0xFD;

   TL1 = 0xFD;

   TR1 = 1;

   SCON = 0x50;

   PCON = 0;

   EA = 1;

}

 

第二篇:单片机流水灯

查表法(实现P113页程序): LIST P=16F877a

INCLUDE"P16F877a.INC"

ABC EQU 20H

ORG 0000H

NOP

BSF STATUS,RP0 MOVLW 00H MOVWF TRISC BCF STATUS,RP0

MAIN MOVLW 00H MOVWF ABC MOVLW 00H MOVWF PORTC

ST MOVF ABC,W CALL SHUZH MOVWF PORTC CALL DELAY1S INCF ABC,F BTFSS ABC,4 GOTO ST GOTO MAIN

SHUZH ADDWF PCL,F RETLW 00H RETLW 01H RETLW 03H RETLW 07H RETLW 0FH RETLW 1FH RETLW 3FH RETLW 7FH RETLW 0FFH RETLW 0FEH RETLW 0FCH RETLW 0F8H RETLW 0F0H RETLW 0E0H RETLW 0C0H RETLW 80H

DELAY1S MOVLW 06H MOVWF 30H LOOP1 MOVLW 0EBH MOVWF 31H LOOP2 MOVLW 0ECH MOVWF 32H LOOP3 DECFSZ 32H GOTO LOOP3 DECFSZ 31H GOTO LOOP2 DECFSZ 30H GOTO LOOP1 RETURN

END

法二(第一次实验程序): LIST P=16F877a

INCLUDE"P16F877a.INC"

ORG 0000H NOP

BSF STATUS,RP0 MOVLW 00H

MOVWF TRISC BCF STATUS,RP0

MAIN MOVLW 01H MOVWF PORTC CALL DELAY1S

MOVLW 02H MOVWF PORTC CALL DELAY1S

MOVLW 04H MOVWF PORTC CALL DELAY1S

MOVLW 08H MOVWF PORTC CALL DELAY1S

MOVLW 10H ;注:左边有空格 ;选择数据存储器体1 ;将C端口设为输出 ;回到数据存储器体0 ;即000000001B,MAIN顶格 ;RC0引脚输出高电平,其他引脚输出低电平 ;调用1s延时子程序,LED亮1s ;即000000010B ;RC1引脚输出高电平,其他引脚输出低电平,依次类推

MOVWF PORTC CALL DELAY1S

MOVLW 20H MOVWF PORTC CALL DELAY1S

MOVLW 40H MOVWF PORTC CALL DELAY1S

MOVLW 80H MOVWF PORTC CALL DELAY1S

GOTO MAIN

DELAY1S MOVLW 06H MOVWF 30H LOOP1 MOVLW 0EBH MOVWF 31H LOOP2 MOVLW 0ECH MOVWF 32H LOOP3 DECFSZ 32H GOTO LOOP3 DECFSZ 31H GOTO LOOP2 DECFSZ 30H GOTO LOOP1 RETURN

END ;

;8个LED依次点亮结束,回到开头重新循环; 1s延时子程序,见课本111页

相关推荐