3-1 独立按键控制LED状态(SDCC + Notepad++ + STC-ISP/普中ISP)

问题分析

上节实现了按下按键LED亮,松开按键LED 灭,这节需要实现的是第一次按下按键LED会亮,第二次按下按键LED会灭,如此循环。

像要实现这个功能,可以先读取灯的值,当按键按下后,如果是高电平就设置为低电平,如果是低电平就设置为高电平,即进行取反。

按键抖动

通过上述思路会有一个问题,独立键盘的按键按下和松开时会有波动,如果不消除抖动,直接对LED进行取反,那么就会一直亮灭。如下图,按下和松开的时候会有10ms左右的抖动,如果在20s后即抖动之后再进行取反,则跟预期效果一致。

txt 复制代码
理想情况(无抖动):
高 ─────┐         ┌─────
        │         │
低      └─────────┘

实际情况(有抖动):
高 ──┐ ┌┐ ┌───┐   ┌─┐ ┌─────
     │ ││ │   │   │ │ │
低   └─┘└─┘   └───┘ └─┘
     ↑         ↑
   按下抖动   松开抖动

完整代码

sdcc -mmcs51 --model-small --iram-size 256 --xram-size 0 --code-size 8192 .\key_led_32.c

c 复制代码
#include <mcs51/8051.h>

void DelayXms(unsigned int xms)
{
    unsigned char i, j;
    if(xms == 0) return;
    do {
        i = 2;
        j = 239;
        do {
            while (--j);
        } while (--i);
    } while (--xms);
}

void main(void)
{
    while(1)
    {
        if(P3_1 == 0)           // 按键按下
        {
            DelayXms(20);       // 消抖
            while(P3_1 == 0);   // 等待松手
            DelayXms(20);       // 消抖
            P2_0 = !P2_0;       // 按下为高电平灯灭,第一次按下灯亮,第二次灯灭。
        }
    }
}

直接~P2_0没有效果

为什么 ~ 在 SDCC 里"失灵"了?

关键在于 "整数提升"(Integer Promotion) 和 "截断"(Truncation) 这两个标准 C 的行为:

  • 取值:当 P2_0 的值是 1(高电平)时,参与运算前会被提升为 int 类型的 0x0001。
  • 取反:~0x0001 得到 0xFFFE。
  • 截断:因为 P2_0 只能存 0 或 1,0xFFFE 被截断后,非零值变成了 1(真值)。

最终结果就是 1 取反还是 1,P2_0 永远被置为高电平,你自然看不到它翻转。所以 SDCC 会警告你,但不报错,因为从 C 标准看这个行为是"合法"的。

正确的做法是用 ! 或 ^= 1

在 SDCC 中操作 51 单片机的位变量,应该使用逻辑非 ! 或异或 ^=,它们不会触发整数提升,能精确地翻转位状态。

操作符 代码示例 效果
逻辑非 ! P2_0 = !P2_0; 推荐,清晰直观,翻转电平
异或赋值 ^= P2_0 ^= 1; 同样有效,更接近底层翻转的意图
按位取反 ~ P2_0 = ~P2_0; 避免使用,会导致引脚被强制置高

效果展示

相关推荐
Frag0ut21 分钟前
Notepad++ 宏录制自动化实战:让重复操作一键完成(2026效率版)
自动化·notepad++·macros·批量处理·宏录制·一键操作·重复操作自动化
AI源码1 小时前
在线考试小程序
小程序·notepad++
Frag0ut1 天前
Notepad++ 正则表达式完全手册:文本处理的终极武器(2026实战版)
正则表达式·notepad++·数据清洗·日志分析·正则替换·提取ip·正则表达式实战
Frag0ut2 天前
Notepad++ 零基础入门:从记事本到代码编辑器的平滑过渡(2026最新版)
python·编辑器·html·json·notepad++·markdown·记事本
星核0penstarry5 天前
企业 API 向后兼容实战:版本控制、废弃字段通知与灰度发布策略
人工智能·后端·api·接口隔离原则·版本控制·架构设计·后端架构
OCR_133716212757 天前
户外强光下护照OCR为什么崩?从ISP到边缘AI,拆一下ER阅读器的抗眩光架构
人工智能·ocr·接口隔离原则
ccbw167 天前
CH634 四端口 USB3.0 HUB 控制器方案拆解与国产替代选型
接口隔离原则·摄像头
Software攻城狮8 天前
【uniapp和普通web 端开发的区别】
前端·uni-app·notepad++
xunyan623410 天前
4-2 动态数码管显示(SDCC + Notepad++ + STC-ISP/普中ISP)
接口隔离原则
AI源码14 天前
家乡介绍小程序
小程序·notepad++