51单片机子程序设计编写

不设计硬件,假定有一40个灯的控制系统,设计一子函数实现其中任一灯的亮、灭切换。
(怎么用一个八位数的五个单元数组去控制)

你可以使用一个八位数的五个单元数组来控制这40个灯,每个单元包含八个二进制位,可以控制8盏灯。以下是实现其中任一灯的亮、灭切换的示例代码:

#include <stdio.h>

// 定义一个八位数的五个单元数组控制40个灯
unsigned char lamp[5] = {0x00, 0x00, 0x00, 0x00, 0x00};

// 定义一个函数实现其中一盏灯的亮灭切换
void switch_lamp(int n, int state) {
    // 计算该灯所在单元和位
    int unit = (n - 1) / 8;
    int bit = (n - 1) % 8;
    // 设置或清除该灯的状态
    if (state == 1) {
        lamp[unit] |= (1 << bit);
    } else {
        lamp[unit] &= ~(1 << bit);
    }
}

int main() {
    int n = 15; // 假设要控制第15盏灯
    printf("初始状态:0x%02x%02x%02x%02x%02x\n", lamp[4], lamp[3], lamp[2], lamp[1], lamp[0]);
    switch_lamp(n, 1); // 打开第15盏灯
    printf("打开第%d盏灯后状态:0x%02x%02x%02x%02x%02x\n", n, lamp[4], lamp[3], lamp[2], lamp[1], lamp[0]);
    switch_lamp(n, 0); // 关闭第15盏灯
    printf("关闭第%d盏灯后状态:0x%02x%02x%02x%02x%02x\n", n, lamp[4], lamp[3], lamp[2], lamp[1], lamp[0]);
    return 0;
}

在这个示例代码中,使用一个八位数的五个单元数组来控制40个灯,其中每个单元包含八个二进制位,可以控制8盏灯。通过 switch_lamp 函数可以实现其中一盏灯的亮灭切换,该函数的参数 n 表示要控制的灯的编号,state 表示要设置的状态。如果 state 为 1,则表示将该灯打开,否则将该灯关闭。在 main 函数中测试了实现。

  • 你可以看下这个问题的回答https://ask.csdn.net/questions/7779053
  • 我还给你找了一篇非常好的博客,你可以看看是否有帮助,链接:基于51单片机的智能汽车雨刷控制系统方案原理图程序设计
  • 除此之外, 这篇博客: 51单片机的延时计算中的 最后是指令周期:这个是单片机执行一条指令所需要的时间,它是由机器周期组成的。 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 现在可以回到正文开头的代码中了。这个10us的函数是怎么得出来的呢?
    这个我之前查过很多资料,比如执行while语句需要多少个机器周期。赋值需要多少个周期。也就是查这个占用了我很大一部分时间。直到最后将上面的延时函数直接调到main函数中debug调试,才明白,问题其实很简单啊。
    无论是执行什么语句,最终都会回到汇编上来,debug里单步调试,所有的指令周期就会明明白白了。
    我用main函数直接调用延时函数,如下:

    void Delay10us()		//@12.000MHz
    {
    	unsigned char i;
    
    	_nop_();
    	_nop_();
    	i = 27;
    	while (--i);
    }
    main
    {
        Delay10us();
    }
    

    我用的keil软件,将上述build之后,点击debug,开始调试
    .在这里插入图片描述
    看图片上,开始debug,程序的起始就在C:0x0183 020171 LJMP Delay10us(C:0171),
    这里有个长转移指令LJMP,它要转移到C:0171行去执行Delay10us这个函数。
    那执行LJMP这个指令需要多长时间呢,查找STC数据手册,在1T模式下,此条指令在单片机上运行需要4个时钟周期。
    接下来,按单步调试F11键,如下图:
    在这里插入图片描述
    程序成功转移到C:0171行,跳转到Delay10us函数中,此行程序执行NOP指令,空操作。查STC数据手册,NOP指令占用1个时钟周期。
    接下来C:0172行,依然是NOP指令,1个时钟周期。
    接下来C:0173行,此行执行 MOV R7,#0x1B,将立即数送入寄存器。是将27赋值给i。依然查手册,此条指令2个时钟周期。
    继续:
    在这里插入图片描述
    此时执行到while语句了,这里执行的指令时 DJNZ R7,C:0175,寄存器减1非0转移。此条指令执行1次4个时钟周期。
    上面已经将寄存器填入27了,因此这条指令将执行27次。
    继续:
    在这里插入图片描述
    循环了27次,终于到0了,程序继续向下执行,此行指令RET,子程序返回。此条指令4个时钟周期。
    继续:
    在这里插入图片描述
    程序又回到了起点。
    好了,可以计算一下此次延时的时间了。1个LJMP,4时钟;2个NOP,2时钟;1个MOV,2时钟;27个DJNZ,108时钟;1个RET,4时钟。
    4+2+2+108+4=120。
    单片机的时钟周期是:1(S)/12MHz = 1/12(us)
    此次延时的时间是:120 × 1/12(us)= 10(us)

  • 您还可以看一下 张旭老师的【造物者】手把手带你做快递管理系统课程中的 【造物者】第十五节·快递分页列表编写小节, 巩固相关知识点