单片机彩灯控制

主要是想让灯两个两个的亮,可是程序不知道为什么只执行一遍
/* ch03-3-3.c - 霹雳灯实验程序 *///==声明区============================================#include <reg51.h> // 定义8051暂存器之标头档,P2-17~19 #define LED P1 // 定义LED接至Port 1void delay(int); // 声明延迟函数 //==主程序============================================main() // 主程序开始 { unsigned char i; // 声明无号数字元变数i(占1Bytes) LED=0xfc; // 初值=1111 1100,只有最右1灯亮 while(1) /// 无穷循环,程序一直跑 { for(i=0;i<7;i=i+2)// 左移3次 { delay(100); // 延迟100 5m=0.5s LED=(LED<<2)|0x03; // 左.移2位,并设定最低两位元为11 } // 左移结束,只有最左1灯亮 for(i=0;i<7;i=i+2)// 右移3次 { delay(100); // 延迟100 5m=0.5s LED=(LED>>2)|0xc0; // 右移2位,并设定最高位元为11 } // 结束右移,只有最右1灯亮 } // while循环结束} // 主程序结束 //==子程序=============================================/* 延迟函数,延迟约x 5ms */void delay(int x) // 延迟函数开始 { int i,j; // 声明整数变数i,j for (i=0;i<x;i++) // 计数x次,延迟x 5ms for (j=0;j<600;j++);// 计数600次,延迟5ms } // 延迟函数结束


一、C语言程序中存在的问题
1.“for(i=0;i<7;i=i+2)”是“左移4次”而不是“左移3次”,i=0,i=2,i=4,i=6,当i=8时结束for循环。
2.“LED=(LED<<2)|0x03;”的含义是:将LED左移2位后,将最低两位置1。
3.“LED=(LED>>2)|0xc0;”的含义是:将LED右移2位后,将最高两位置1。
4.两者结合,将“LED=(LED<<2)|0x03;”重复运行4次后,LED=0xff,其中不再存在值等于0的位。
之后无论“LED=(LED>>2)|0xc0;”还是“LED=(LED<<2)|0x03;”都不会再有值等于0的位产生。
看你的程序,发光二极管应该是低电平点亮,所以以后无论如何移位都不再有发光二极管点亮了。
5.解决方法:将“for(i=0;i<7;i=i+2)”改成“for(i=0;i<3;i++)”即可。
二、反汇编实际含义的问题
对“LED=(LED<<2)|0x03;”的反汇编:

;***********************************************************************    38:           LED=(LED<<2)|0x03; // 左.移2位,并设定最低两位元为11      
C:0x000D    E5B0     MOV      A,P1(0x90)
C:0x000F    25E0     ADD      A,ACC(0xE0)
C:0x0011    25E0     ADD      A,ACC(0xE0)
C:0x0013    4403     ORL      A,#0x03
C:0x0015    F5B0     MOV      P1(0x90),A
;***********************************************************************

1.C程序中有从LED取值的指令“=...LED...”,因为LED在宏定义中为P1口,所以其对应汇编指令为“MOV A,P1”。
2.在单片机实验中,P1口控制LED,常用灌电流直接驱动的方法。
在这样的电路下,即使引脚被内置置0,其对应外部引脚实际上还是被上拉成了高电平。
3.因此,读取P1口值时将得到0xff,故而“LED=(LED<<2)|0x03;”后LED将直接的到0xff,所以以后发光二极管都不会亮了。
4.解决办法:先对某个自定义寄存器进行移位处理,最后再将结构赋值给P1口。

 

修改后的程序:

/*主要是想让灯两个两个的亮,可是程序不知道为什么只执行一遍*/
/* ch03-3-3.c - 霹雳灯实验程序  */
/*
一、C语言程序中存在的问题
1.“for(i=0;i<7;i=i+2)”是“左移4次”而不是“左移3次”,i=0,i=2,i=4,i=6,当i=8时结束for循环。
2.“LED=(LED<<2)|0x03;”的含义是:将LED左移2位后,将最低两位置1。
3.“LED=(LED>>2)|0xc0;”的含义是:将LED右移2位后,将最高两位置1。
4.两者结合,将“LED=(LED<<2)|0x03;”重复运行4次后,LED=0xff,其中不再存在值等于0的位。
之后无论“LED=(LED>>2)|0xc0;”还是“LED=(LED<<2)|0x03;”都不会再有值等于0的位产生。
看你的程序,发光二极管应该是低电平点亮,所以以后无论如何移位都不再有发光二极管点亮了。
5.解决方法:将“for(i=0;i<7;i=i+2)”改成“for(i=0;i<3;i++)”即可。
二、反汇编实际含义的问题
对“LED=(LED<<2)|0x03;”的反汇编:
;**********************************************************************************
    38:                         LED=(LED<<2)|0x03; // 左.移2位,并设定最低两位元为11      
C:0x000D    E5B0     MOV      A,P1(0x90)
C:0x000F    25E0     ADD      A,ACC(0xE0)
C:0x0011    25E0     ADD      A,ACC(0xE0)
C:0x0013    4403     ORL      A,#0x03
C:0x0015    F5B0     MOV      P1(0x90),A
;**********************************************************************************
1.C程序中有从LED取值的指令“=...LED...”,因为LED在宏定义中为P1口,所以其对应汇编指令为“MOV A,P1”。
2.在单片机实验中,P1口控制LED,常用灌电流直接驱动的方法。
在这样的电路下,即使引脚被内置置0,其对应外部引脚实际上还是被上拉成了高电平。
3.因此,读取P1口值时将得到0xff,故而“LED=(LED<<2)|0x03;”后LED将直接的到0xff,所以以后发光二极管都不会亮了。
4.解决办法:先对某个自定义寄存器进行移位处理,最后再将结构赋值给P1口。
*/
//==声明区============================================
#include <reg51.h>   // 定义8051暂存器之标头档,P2-17~19 
#define LED P1   // 定义LED接至Port 1
//==子程序=============================================
/* 延迟函数,延迟约x 5ms */
//void delay(int x)  // 延迟函数开始  
void delay(unsigned char x)  // 延迟函数开始 

 int i,j;   // 声明整数变数i,j 
 for (i=0;i<x;i++) // 计数x次,延迟x 5ms   
 for (j=0;j<600;j++);// 计数600次,延迟5ms 
}      // 延迟函数结束
//==主程序============================================
main()     // 主程序开始

 unsigned char i;   // 声明无号数字元变数i(占1Bytes)   
 unsigned char temp=0x03; 
 //(舍去)LED=0xfc;   // 初值=1111 1100,只有最右1灯亮  
 while(1)     /// 无穷循环,程序一直跑  
 { 
  for(i=0;i<3;i++)// 左移3次   
  { 
   delay(100); // 延迟100 5m=0.5s    
   //(舍去)LED=(LED<<2)|0x03; // 左.移2位,并设定最低两位元为11  
   temp=temp<<2;
   LED=~temp;
  }    // 左移结束,只有最左1灯亮   
  for(i=0;i<3;i++)// 右移3次  
  { 
   delay(100); // 延迟100 5m=0.5s   
   //(舍去)LED=(LED>>2)|0xc0; // 右移2位,并设定最高位元为11 
   temp=temp>>2;
   LED=~temp;
  }    // 结束右移,只有最右1灯亮 
 }     // while循环结束
}      // 主程序结束

温馨提示:答案为网友推荐,仅供参考
第1个回答  2014-01-07
/* ch03-3-3.c - 霹雳灯实验程序  */
//==声明区============================================
#include <reg51.h>   // 定义8051暂存器之标头档,P2-17~19 
#define LED P1   // 定义LED接至Port 1
void delay(int);  // 声明延迟函数 
//==主程序============================================
main()     // 主程序开始 
{
 unsigned char i;   // 声明无号数字元变数i(占1Bytes)
 LED=0xfc;   // 初值=1111 1100,只有最右1灯亮
 while(1)     /// 无穷循环,程序一直跑
 { 
 for(i=0;i<3;i++)// 左移
    { delay(100); // 延迟100 5m=0.5s  
      LED=(LED<<2)|0x03; // 左移2位 
    }    // 左移结束,只有最左1灯
 LED=0x3f;
 for(i=0;i<3;i++)// 右移
   {
    delay(100); // 延迟100 5m=0.5s 
    LED=(LED>>2)|0xc0; // 右移1位 
   }    // 结束右移,只有最右1灯亮 
  }     // while循环结束
}      // 主程序结束 
//==子程序=============================================
/* 延迟函数,延迟约x 5ms */
void delay(int x)  // 延迟函数开始 
{
 int i,j;   // 声明整数变数i,j  
 for (i=0;i<x;i++) // 计数x次,延迟x 5ms   
 for (j=0;j<600;j++);// 计数600次,延迟5ms
}      // 延迟函数结束