嵌入式 C 语言入门:分支结构(if/switch)的用法与硬件控制实践
前言
在上一篇笔记中,我们掌握了关系运算和逻辑运算,这些运算就像 “数字开关”,能帮助我们判断条件的真假。而在实际开发中,我们需要根据不同的条件执行不同的代码 —— 比如检测到按键按下时点亮 LED,或者根据传感器数据选择不同的处理方式。这就需要用到 C 语言中的分支结构:if 语句和switch 语句。它们是代码 “智能决策” 的基础,也是控制硬件行为的关键工具。
🔀 if 语句:条件判断的基石
基础语法与执行逻辑
if 语句的基本形式如下:
if(条件表达式1){// 条件表达式1为真时执行的代码
} else if(条件表达式2){// 条件表达式2为真时执行的代码
} else{// 所有条件都不满足时执行的代码
}
我们通过一个 “判断数字位数” 的例子来理解:
#include <stdio.h>
#include <string.h>
int mymain(void)
{int num;printf("请输入一个正整数:\n\r");scanf("%d", &num);if(num >= 1000) {printf("这个数是四位及以上的数\n\r");}else if(num >= 100) {printf("这个数是三位数\n\r");}else if(num >= 10) {printf("这个数是两位数\n\r");}else if(num >= 1) {printf("这个数是一位数\n\r");}else {printf("这个数是负数\n\r");}return 0;
}
这里有个重要的隐含逻辑:当执行到else if(num >= 100)
时,其实已经隐含了num < 1000
的条件 —— 因为如果num >= 1000
,就会执行第一个 if 分支并跳出整个 if 语句。因此,这个条件等价于num >= 100 && num < 1000
,只是被隐含省略了。
在硬件控制中的应用:LED 状态翻转
在嵌入式开发中,if 语句常用于根据硬件状态执行相应操作。比如我们要实现 LED 状态的翻转:
有关点灯的基础知识可见我结构体(三)的笔记
#include <stdio.h>
#include <string.h>
int mymain(void)
{// 获取GPIO输出数据寄存器(ODR)的地址(不同开发板可能不同)volatile unsigned int *p = (volatile unsigned int *)0x40021414;// 判断LED当前状态并翻转if((*p & (1 << 9)) == 0) { // 若LED当前为熄灭状态(bit9为0)*p |= (1 << 9); // 点亮LED(将bit9置1)}else { // 若LED当前为点亮状态(bit9为1)*p &= ~(1 << 9); // 熄灭LED(将bit9清0)}return 0;
}
这里的*p & (1 << 9)
用于检测 ODR 寄存器的第 9 位是否为 1,结合按位与和逻辑判断,就能根据 LED 当前状态做出相反操作。这种 “检测 - 决策 - 执行” 的模式在硬件控制中非常常见。
🎛️ switch 语句:多分支选择的利器
语法结构与执行流程
当需要根据一个变量的多个可能值执行不同代码时,switch 语句比 if 更简洁:
switch(表达式){case 值1:// 执行代码块1break;case 值2:// 执行代码块2break;...default:// 表达式不匹配任何case时执行的代码
}
需要注意的是,break 语句决定了执行完当前 case 后是否继续执行后续 case。如果没有 break,会发生 “穿透” 现象 —— 继续执行下一个 case 的代码,直到遇到 break 或 switch 结束。
我们通过一个 “星期判断” 的例子验证:
#include <stdio.h>
#include <string.h>int main(void)
{int day;printf("请输入一个1-7的整数:");scanf("%d", &day);switch(day){case 1:printf("星期一\n\r");case 2:printf("星期二\n\r");break;case 3:printf("星期三\n\r");break;// 其余case省略...default:printf("输入错误\n\r");break;}return 0;
}
当输入 1 时,代码会输出 “星期一” 和 “星期二”—— 因为 case 1 没有 break,执行完后会继续执行 case 2,直到遇到 break 才跳出:
switch 在硬件控制中的应用
同样是 LED 状态翻转,我们用 switch 语句实现:
#include <stdio.h>
#include <string.h>
int mymain(void)
{volatile unsigned int *p = (volatile unsigned int *)0x40021414;// 根据LED当前状态选择操作switch((*p & (1 << 9))){case 0: // 若LED当前为熄灭状态*p |= (1 << 9); // 点亮LEDbreak;case (1 << 9): // 若LED当前为点亮状态(注意这里是1<<9而非1)*p &= ~(1 << 9); // 熄灭LEDbreak;}return 0;
}
这里有个细节:case (1 << 9)
而非case 1
—— 因为*p & (1 << 9)
的结果是 “第 9 位为 1,其余位为 0” 的数值(即0x00000200
),而不是简单的 1。直接点说,这里的 (1 << 9)
甚至可以换成(0x00000200)
。
🔄 if vs switch:何时该用谁?
- if 语句适合处理连续的范围判断(如数值区间),或逻辑复杂的条件组合;
- switch 语句适合处理离散的固定值判断(如枚举值、状态码),代码更清晰;
- 穿透特性可用于实现 “多个条件执行相同代码” 的场景(如多个按键触发同一操作)。
结尾
这篇笔记中,我们学习了 if 和 switch 两种分支结构,它们就像代码中的 “智能开关”,能根据不同条件控制程序走向。在嵌入式开发中,这些分支结构是实现硬件状态检测、事件响应的基础 —— 比如根据按键状态切换 LED 模式,或者根据传感器数据选择不同的处理策略。
下一篇,我们将学习循环结构,它能让代码 “重复做同一件事”,是实现定时任务、数据采集的关键工具。Hello_Embed 与你一起,步步深入嵌入式开发的核心。下篇见!