zl程序教程

您现在的位置是:首页 >  其他

当前栏目

C51入门之跑马灯

入门 c51 跑马灯
2023-09-14 09:06:41 时间
  • 跑马灯

  • 使用protues仿真图如下 

 

 

 

 

 

 

 

 

  • 延时函数实现 

使用硬延时空等待来实现达到延时的目的

   注意:实现产品软件开发中,不建议使用硬延时,使用硬延时会降低产品的实时性

实现方法:

 1. 写一个函数,带一个形参,延时值由其传入函数

2.函数体内由2for循环组成

3.由分号语句实现空等待操作 

void delayMills(unsigned int ms)
{
      unsigned int i,j;              //局部变量定义
      for(i=ms; i>0; i--)          //第一层for
          for(j=100; j>0; j--);        //第二层for
			//分号语句,空操作			
}

       延时值,可以通过调整循环体变量j所赋的初值

  • IO口定义声明

P0,P1,P2,P3这四组IO口都是由特殊功能声明寄存器进行声明定义的。

reg52.h头文件中对4IO口进行了定义声明

  1. sfr P0    = 0x80; // 将符号P0与功能寄存器地址0x80关联
  2. sfr P1    = 0x90; // 将符号P1与功能寄存器地址0x90关联
  3. sfr P2    = 0xA0; // 将符号P2与功能寄存器地址0xA0关联
  4. sfr P3    = 0xB0; // 将符号P3与功能寄存器地址0xB0关联

对符号P0,P1,P2,P3操作,相当于是对功能寄存器地址0x80,0x90,0xA0,0xB0操作 

sfrC51内核MCUkeil编译环境定义功能寄存器特有的关键字

因此,使用sfr可以自己重新对功能寄存器赋于新的符号,例如将P0口重新定义符号为PORT0,

    那么使用sfr定义如下:

   sfr PORT0 = 0x80;

 

   定义后,可以使用PORT0这个符号操作IOP0

   应的引脚,如果将P0.01个引脚输出低,其余输出高,则:

                       PORT0 = 0xfe;    // 1111 1110

 

 

 

 

  • 跑马灯代码输入 

#include <reg52.h>  //引用单片机头文件

void main(void)    //主函数,程序的入口

  while(1)   //无限循环

  { 

  }

}

1.操作单片机首先要引入与MCU相关的头文件

2.C语言的程序入口是main函数

3.  while(1)大循环实现单片机的轮循工作结构

选点亮P0.0上的LED,根据线路接法,将此脚置低即可点亮,则:

P0 = 0xfe;

#include <reg52.h>  //引用单片机头文件

void main(void)    //主函数,程序的入口

  while(1)   //无限循环

  {

  P0 = 0xfe;

  }

}

1.点亮后需要延时一段时间才能点另一个LED,这样才能看出灯亮灭的过程,如果不延时,人眼无法区分

2.采用2for循环实现延时功能

void delayMills(unsigned int ms) 
{	
         unsigned char i,j;
	for(j=ms; j>0; j--)	
		for(i=100;i>0;i--);	//空操作等待
}

现在来使用跑马灯流动时序,main函数while循环中,编写代码

#include <reg52.h>  //引用单片机头文件


void delayMills(unsigned int ms) 
{	
         unsigned char i,j;
	for(j=ms; j>0; j--)	
		for(i=100;i>0;i--);	//空操作等待
}

void main(void)    //主函数,程序的入口
{    
    while(1)   //无限循环
    {  
       P0 = 0xfe;    //P0.0亮  1111 1110
       delayMills(1000);   //延时约1秒
       P0 = 0xfd;    //P0.1亮     // 1111 11 0 1
       delayMills(1000);   //延时约1秒
       P0 = 0xfb;    //P0.2亮  //1111 1011
       delayMills(1000);   //延时约1秒
       P0 = 0xf7;    //P0.3亮   1111 0111
       delayMills(1000);   //延时约1秒
       P0 = 0xef;    //P0.4亮  1110 1111
       delayMills(1000);   //延时约1秒
       P0 = 0xdf;    //P0.5亮   1101 1111
       delayMills(1000);   //延时约1秒
       P0 = 0xbf;    //P0.6亮   1011 1111
       delayMills(1000);   //延时约1秒
       P0 = 0x7f;    //P0.7亮 0111 1111
       delayMills(1000);   //延时约1秒

    }
}

 

 

生成的HEX档可以加载到最上面的protues中运行仿真,也可以烧到实体开发板中,以下为STC90C516RD+ 为例

接好开发板后,双击stc-isp-15xx-v6.85I.exe打开烧录工具,选择STC90C516RD+ 

 

 

 

由于跑马灯是有规律的,因此可以对上面的代码进行优化,使用一个循环来实现

这里采用for来实现,8LED循环8,循环框架如下 

现将8组点亮数值做成一张table表,用一维数组实现,将表存在程序表中,用code关键字来修饰,这个关键字是C51keil编译

环境 中特有的。定义数组如下: 

code unsigned char led_table[] = {
     0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
  };

  在for循环中约每1秒查询一次led_table的值,取出赋给P0寄存器。

#include <reg52.h>   //单片机内核头文件
// 数据表格,存放在程序表格中
code unsigned char led_table[] = {
     0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
 };
// 延时函数
void delayMills(unsigned int ms) 
{	
         unsigned char i,j;
	for(j=ms; j>0; j--)	
		for(i=100;i>0;i--);	//空操作等待
}

void main(void)  {  //主函数,程序的入口
   unsigned char i;
   while(1)  
   {   //无限循环
      for(i=0; i<8;i++)    //for循环,循环8次
     {
	 P0 =  led_table[i];   //查表点灯
         delayMills(1000);   // 硬延时
      }
   }
}
  • 将上例使用移位操作来实现 

>>右移操作运算符,例如:y = x>>1,表示

 x右移一位后赋给变量y,右移移出的值扔掉,高

位移入的补0(正数)或补1(有符号且是负数)

例如: char x = 0xfe;   //-2    1111 1110-> 1 1111 111

              x >>= 1;           // -1     1111 1111

    x右移1位操作,低位0移出丢弃,高位补1

     因为变量x是有符号字符型变量,且值为负数

     char x = 0x7f;   // 0111 1111 ,为正数

     x >>= 1;            // 0011 1111 

    x虽然是有符号字符型变量,但其值为正数,右移操作,低位丢弃,高位补0  

对有无符号右移操作,低位移出丢弃,高位始终都是补0

unsigned char x = 0xfe;  // 1111 1110

 x >>= 1;                            // 0111 1111

左移移位操作,高位移出丢弃,低位始终都是补0

  char x = 0xfe;   //-2      1111 1110

    x <<= 1;         //-4        1111 1100

 

   x <<= 4;        //-64        1100 0000

   左移4位,高4位移出,低4位补0    

用移位实现跑马灯步骤

第一步,定义一个变量x赋初值0xfe,也就是点亮P0.0引脚上的灯

第二步,使用for循环,循环8

第三步,在for循环体中,先将x的值赋给P0点亮,再将x左移1位后赋给自己,由于左移后低位会

0,所以在移完后,将低位按位或1操作

       x <<= 1;     // 1111 1110  -> 1111 1100

       x |= 1;      // 1111 1101 ->1111 1011

   然后调用延时函数delayMills进行延时操作 

#include <reg52.h>   //单片机内核头文件
// 数据表格,存放在程序表格中
code unsigned char led_table[] = {
     0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f
 };
// 延时函数
void delayMills(unsigned int ms) 
{	
         unsigned char i,j;
	for(j=ms; j>0; j--)	
		for(i=100;i>0;i--);	//空操作等待
}


void main(void){
    unsigned char i,x;
    while(1) 
    {
          x = 0xfe;
         for(i=0; i<8; i++)   
        {
          P0 = x;         //点灯
          x = (x<<1) |1;     //左移1位,再低位或1
          delayMills(1000);
        }
   }
}

           P0 = x;         //点灯

          x = (x<<1) |1; 

 此操作也可以使用移位取反实现,如下

   unsigned char i;         0000 0100

    for(i=0; i<8; i++)      // 1<<0  = 1 ~1= 1111 1110

   {                                 // 1<<1 = 2 ~2 = 1111 1101

          P0 = ~(1<<i);     //1<<2=4   ~4 = 1111 1011

         delayMills(1000);

   }