51单片机考试 希望在两小时内回答

51单片机阶段性测试使单片机所有LED小灯频闪3次,3次后使LED小灯从左向右按照顺序亮起,最后一个LED小灯亮起后所有LED小灯长亮3秒,3秒后往返流水灯三次,三次后所有LED小灯熄灭3秒,3秒后中间两个LED小灯长亮一秒,一秒后从两个长亮的LED小灯向左右两边依次亮起,每亮起一个后面亮起的LED小灯熄灭。完成之前动作后LED小灯从左向右开始亮起,到达最右边后依次返回,所有小灯频闪三次结束。

需要金沙滩51板子的吗

【请采纳,谢谢!】以下是一个简单的程序,可以实现题目描述的功能,假设51单片机的开发环境是Keil C:

#include <reg52.h>
#include <intrins.h>

#define LED_PORT P0

void delay(int ms) {
    int i, j;
    for (i = 0; i < ms; i++) {
        for (j = 0; j < 125; j++) {
            _nop_();
        }
    }
}

void flash_all_leds() {
    int i;
    for (i = 0; i < 3; i++) {
        LED_PORT = 0xff;
        delay(500);
        LED_PORT = 0x00;
        delay(500);
    }
}

void light_up_from_left_to_right() {
    int i;
    for (i = 0; i < 8; i++) {
        LED_PORT = ~(0xff << i);
        delay(500);
    }
    delay(3000);
}

void light_up_from_right_to_left() {
    int i;
    for (i = 7; i >= 0; i--) {
        LED_PORT = ~(0xff >> i);
        delay(500);
    }
    delay(3000);
}

void flow_lights() {
    int i, j;
    for (i = 0; i < 3; i++) {
        LED_PORT = 0x81;
        for (j = 0; j < 7; j++) {
            LED_PORT = (LED_PORT << 1) | 0x01;
            delay(100);
        }
        for (j = 0; j < 7; j++) {
            LED_PORT = (LED_PORT >> 1) | 0x80;
            delay(100);
        }
    }
}

void light_up_middle_two() {
    LED_PORT = 0x18;
    delay(1000);
}

void light_up_from_middle_to_edges() {
    int i;
    for (i = 1; i < 4; i++) {
        LED_PORT = ~(0x18 << i) & ~(0x18 >> i);
        delay(200);
        LED_PORT = ~(0x18 << i) & ~(0x18 >> i) & ~(0x10 >> i);
        delay(200);
    }
    LED_PORT = 0x00;
}

void main() {
    int i;

    while (1) {
        flash_all_leds();
        light_up_from_left_to_right();
        light_up_from_right_to_left();
        flow_lights();
        LED_PORT = 0x00;
        delay(3000);
        light_up_middle_two();
        light_up_from_middle_to_edges();
        LED_PORT = 0x00;
        delay(3000);
        for (i = 0; i < 3; i++) {
            light_up_from_left_to_right();
            light_up_from_right_to_left();
        }
    }
}

这段代码使用了单片机的计时器来实现延时功能,使用了位运算来控制LED小灯的亮灭。你可以根据自己的需要对程序进行修改和优化。

以下是一种可能的51单片机程序实现:


#include <reg51.h>  // 引入单片机头文件

// 定义控制LED小灯亮灭的函数
void light(int num) {
    switch (num) {
        case 1: P1 = 0x7F; break; // 0111 1111,第1个灯亮,其余灯灭
        case 2: P1 = 0xBF; break; // 1011 1111,第2个灯亮,其余灯灭
        case 3: P1 = 0xDF; break; // 1101 1111,第3个灯亮,其余灯灭
        case 4: P1 = 0xEF; break; // 1110 1111,第4个灯亮,其余灯灭
        case 5: P1 = 0xF7; break; // 1111 0111,第5个灯亮,其余灯灭
        case 6: P1 = 0xFB; break; // 1111 1011,第6个灯亮,其余灯灭
        case 7: P1 = 0xFD; break; // 1111 1101,第7个灯亮,其余灯灭
        case 8: P1 = 0xFE; break; // 1111 1110,第8个灯亮,其余灯灭
        default: P1 = 0xFF; break; // 所有灯灭
    }
}

// 定义LED小灯频闪的函数
void blink() {
    for (int i = 0; i < 3; i++) { // 闪3次
        P1 = 0x00;  // 所有灯灭
        delay(500); // 延时0.5秒
        P1 = 0xFF;  // 所有灯亮
        delay(500); // 延时0.5秒
    }
}

// 定义LED小灯从左向右按照顺序亮起的函数
void from_left_to_right() {
    for (int i = 1; i <= 8; i++) {
        light(i);
        delay(500); // 延时0.5秒
    }
}

// 定义所有LED小灯长亮的函数
void all_on() {
    light(8);
    delay(3000); // 延时3秒
}

// 定义往返流水灯的函数
void shuttle() {
    for (int i = 0; i < 3; i++) { // 往返3次
        for (int j = 1; j <= 7; j++) { // 从左向右流水
            light(j);
            delay(200); // 延时0.2秒
        }
        for (int j = 7; j >= 1; j--) { // 从右向左流水
            light(j);
            delay(200); // 延时0.2秒
        }
    }
}

// 定义所有LED小灯熄灭的函数

  • 这篇博客: 51单片机实验——LED小灯的操作(一)中的 总线操作-循环位移函数法 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • #include <reg52.h>  //包含头文件
    #include <intrins.h>
    //宏定义
    #define led P2  //宏定义P2口
    
    //使用typedef关键字
    //类型重命名
    typedef unsigned char uchar;
    typedef unsigned int uint;
    
    //函数声明
    void delay(uint i);  //延时函数
    
    //主函数
    void main()
    {
    	//定义for循环计数变量i
    	uchar i;
    	while(1)
    	{
    		//利用左移循环函数实现循环点亮led小灯
    		for(i = 0; i < 8; i++)
    		{
    			led = _crol_(0xfe,i);  //点亮led小灯
    			delay(50000);  //延迟一会
    		}
    	}
    }
    
    //函数定义
    
    //延时函数
    void delay(uint i)
    {
    	while(i--);
    }
    

      操作解析:
      需要用到包含在intrins.h的头文件中的循环左移和循环右移函数:

    unsigned char _cror_  (unsigned char, unsigned char);  //循环左移函数
    unsigned char _crol_  (unsigned char, unsigned char);  //循环右移函数
    

      其中第一个参数为需要循环左移(或循环右移)的16进制数,第二个参数为需要循环左移(或循环右移)的位数。
      循环左移(或循环右移),循环就是相应的高位(或低位)会依次循环补到相应的低位或高位),这样的话,就无需取反,即可达到点亮下一个小灯的操作数。例如:

    _cror_(0xfe,1);  //即将十六进制0xfe循环左移一位
    

      该过程为:
    在这里插入图片描述
      循环右移刚好与之相反

    _crol_(0x7f,1);  //即将十六进制0x7f循环右移一位
    

    在这里插入图片描述
      若一次移位多位的话,根据以上过程举一反三即可。