目录

硬件地址反序用位操作为LED灯序纠偏反转二进制数即可解决

目录

硬件地址反序?用位操作为LED灯序“纠偏”。反转二进制数即可解决

特别有意思,LED的灯序与其硬件地址刚好相反,没办法直接通过加1实现二进制进位的亮灯操作,查了一些资料说用数组和switch实现,觉得太麻烦了,思索良久,就想到了反转二进制数解决这个问题。

reverse_bits( )是实现反转二进制数:

/* 位反转函数
   @param num 待反转的8位数据
   @return 返回位顺序反转后的数值 */
unsigned char reverse_bits(unsigned char num) {
    unsigned char reversed = 0;
    int i;
    for (i = 0; i < 8; i++) {               // 遍历每一位
        reversed |= ((num >> i) & 1) << (7 - i); // 将第i位移至对称位置
    }
    return reversed; // 例如:0b00000001 -> 0b10000000
}

说明:

        将操作数的所有位向右移动指定的位数。

«        将操作数的所有位向左移动指定的位数。

&         对两个操作数的每一位执行逻辑与操作,如果两个相应的位都为 1,则结果为 1,否则为 0。(全1则1)

|          对两个操作数的每一位执行逻辑或操作,如果两个相应的位都为 0,则结果为0 ,否则为 1。(有1则1)

以下代码是通过按键实现二进制进位的亮灯操作(STC89C52RC):

#include <REGX52.H>       // 包含8052单片机寄存器定义头文件
#include <INTRINS.H>      // 包含内联函数库(如_nop_())

/* 延时函数
   @param num 延时次数,次数越多总延时越长
   @11.0592MHz晶振下,每次循环约1ms */
void Delay(int num)        //@11.0592MHz
{
    while(num){
        unsigned char i, j;
        _nop_();          // 插入一个空指令周期(1.085us)
        i = 2;
        j = 199;
        do {               // 双重循环实现精确延时
            while (--j);   // 内层循环约0.5ms
        } while (--i);     // 外层循环2次,总延时约1ms
        num--;             // 控制总延时次数
    }
}

/* 位反转函数
   @param num 待反转的8位数据
   @return 返回位顺序反转后的数值 */
unsigned char reverse_bits(unsigned char num) {
    unsigned char reversed = 0;
    int i;
    for (i = 0; i < 8; i++) {               // 遍历每一位
        reversed |= ((num >> i) & 1) << (7 - i); // 将第i位移至对称位置
    }
    return reversed; // 例如:0b00000001 -> 0b10000000
}

/* 主函数:检测按键控制LED显示 */
void main() {
    //8051/52 系列单片机的寄存器是 8 位
    // 代码中 P2 端口驱动 8 个 LED,每个引脚对应 1 个 LED
    //通过 char 类型的位操作可以直接控制每个 LED 的状态:
    unsigned char num=0;          
    while(1) {                    // 主循环
        if (P3_1 == 0) {          // 检测P3.1引脚(如按键)是否按下(低电平)
            Delay(20);            // 延时20ms消抖
            while (P3_1 == 0);    // 等待按键释放(保持阻塞直到松开)
            Delay(20);            // 再次消抖
            num++;                
            P2=~(reverse_bits(num)); // 数值取反后发送到P2口驱动LED
            /* 执行流程:
               1. reverse_bits(num):将数值位反转
               2. ~:按位取反(因LED通常低电平点亮)
               示例:num=1(0x01) 
                     → 反转后0x80 
                     → 取反0x7F → P2.7引脚低电平点亮LED */
        }
    }
}

效果展示:

https://i-blog.csdnimg.cn/direct/8e3911df8df249d3940a2665a0f604d6.gif