最近实验室对24级新生开展了第一次培训,培训的内容是C语言基础知识直到数组那一章。作为23级的学长,为了能让学弟学妹们能够在巩固已学知识的基础上提前认识和熟悉未来单片机开发的代码结构,这两天自己灵感突发,编了一道小题目作为扩展学习。其中内容如有不妥,还请多多指教哦!
题目大致如下:
资料阅读
一、关于’while(1)’
`while(1)` 是一个在编程语言中常见的无限循环结构。它通常用于需要程序持续运行,直到遇到特定的退出条件或外部中断的情况。这里的 `1` 表示的是一个总是为真的条件,因为在大多数编程语言中,非零值都被视为真(true),而 `1` 显然不是零,因此这个条件总是成立的。这意味着,除非在循环体内部有明确的退出机制(如使用 `break` 语句),否则 `while(1)` 循环将无限执行下去。
二、使用场景
- 服务程序:很后台服务程序需要持续运行,监听网络请求或处理数据流,这类程序常使用 `while(1)` 来保持其活跃状态。
- 游戏开发:在游戏开发中,主循环通常也是用 `while(1)` 来实现,确保游戏可以持续地接收用户输入、更新游戏状态并渲染画面。
- 嵌入式系统:在嵌入式系统中,控制程序往往需要不断地监测传感器数据,并根据这些数据做出响应,`while(1)` 循环非常适合这种需求。
三、在单片机与嵌入式系统中的应用
while(1)通常用来表示一个无限循环,也叫做死循环。它在系统中的作用非常重要,特别是在主循环(Main Loop)中。以下是while(1)在单片机嵌入式系统中的几个重要作用:
1. 提供任务调度机制
在许多嵌入式系统中,主循环while(1)是程序的中心。在这个循环里,可以安排各种任务的执行顺序,实现任务的调度。例如:
int main(void)
{
while (1)
{
// 任务1:读取某些传感器数据的函数
readSensorData();
// 任务2:处理某些数据的函数
processData();
// 任务3:控制LED状态的函数
controlLEDState();
// 其他完成其他任务的代码或函数...
}
}
2. 保持程序运行
while(1)的作用之一是保持程序的运行状态。如果没有这个无限循环,程序执行完所有代码后就会停止。在嵌入式系统中,程序通常需要一直运行,直到系统被显式地关闭或者复位。
3. 事件处理
在while(1)循环中,可以处理各种事件,如按键输入、网络通信、外部中断等。这种处理方式可以保证事件能够及时得到响应.
int main(void)
{
while (1)
{
//如果按键被按下
if (buttonPressed == 1)
{
//执行’按键被按下’函数中的代码
handleButtonPress();
}
// 其他事件处理函数...
}
}
4.关于上电初始化
所谓上电初始化(Power-On Initialization),就是指电子设备或系统在首次加电启动或重启时进行的一系列初始化操作。上电初始化是在进行死循环之前就已经完成的工作,可以理解为是系统开始处理相关复杂任务之前的准备工作。例如:
int main(void)
{
//我是上电初始化的位置
while (1)
{
// 我是实现其他主要功能代码的放置位置
}
}
四、小结
while(1)在单片机嵌入式系统中扮演着核心的角色,它是任务调度、事件处理等操作的基础。通过这个无限循环,系统可以保持持续运行的状态,并且能够有效地管理资源、处理事件和错误。此外,它还提供了一种结构化程序设计的思路,使得系统能够按照预定的方式持续运作。
仔细阅读并理解以上内容,并编写一个C语言程序模拟单片机实现一个简易的温控声光同步报警系统。具体要求如下:
1.上电初始化时使用OLED屏幕显示自己的班级、姓名和学号,并在1秒后清除相关信息,然后显示“即将随即开始进行温度检测”的提示信息,并开始对环境温度为期8秒的监测;
2. 监测期间,LED灯即刻开始以0.25Hz的频率“闪烁”,一亮一灭。且每当“LED灯”亮灭状态发生变化时蜂鸣器会同步报警,以模拟每次对温度的采样;
3. 当监测周期结束时,单片机希望从温度传感器处获取对监测期间采集到的所有温度数据的平均值,这时你需要按下某个按键以模拟温度传感器发送给单片机的平均温度数据。
(1)当按下按键‘KEY1’时,即表示温度传感器向单片机发送“平均温度处于安全范围” 的信息,LED灯随后不再闪烁、蜂鸣器不再报警,OLED屏显示信息“Safe”,此时用户可以自主输入指令决定使系统强制报警、维持原状态或者退出系统;
(2)当按下按键‘KEY2’时,即表示温度传感器向单片机发送“温度超过安全范围”的信 息,此时LED灯以原先两倍的频率闪烁、蜂鸣器同步鸣叫。持续8秒后自动进行下一轮为期8秒的温度监测;
(3)当按下按键‘KEY3’时,系统断电退出。
提示:
- 上电初始化时可以利用printf函数在终端窗口中打印个人信息和提示信息,并使用stdlib.h包含的系统指令函数system清除相关信息,随后具体可在优快云上查询system函数的常用指令;
- 可以使用1模拟LED灯亮、0模拟LED灯灭;
- 三个按键操作可以用数字指令 '111' 、'222' 、 '333' 模拟;
- 可以使用unistd.h头文件中的sleep()函数模拟延时,具体可在优快云上查询;
- 提“蜂鸣器”的鸣叫功能可以通过使用某个转义字符实现 : ) ;
- 在使用1、0模拟LED亮灭的过程中终端窗口中能且只能显示这个LED灯的一个状态,这就要求我们在合适的时候清空LED状态的0、1标志。
- 可能涉及到的知识:输入输出函数、条件判断、for循环、无限循环(while1循环)、宏定义、枚举类型,以及一些其他库文件中常见或有趣的小玩意……
示例代码参考如下,如有不足,恳请批评指正~
#include <stdio.h>
#include <stdlib.h> // 用于system系统指令函数
#include <unistd.h> // 用于sleep函数
enum state{
Monitoring,
Safe,
Danger,
Exit,
Error
};
int led_state = Monitoring; //上电时默认为监测模式
int main(void)
{
/* 步入main之后、进入死循环之前即为上电初始化区域*/
int i, T_sta_fdbck; //循环变量、温度状态反馈
int is_flashing; //标志LED是否处于闪烁状态
// 显示相关个人信息
printf("测控231班 zxa 5913123011");
sleep(1); //延时1秒
system("cls"); //清屏
//提示开始监测温度
printf("现在开始监测温度!");
sleep(1); //延时1秒
system("cls"); //清屏
while(1)
{
if(led_state == Monitoring)
{
for(i = 0; i < 2; i++)
{
is_flashing = 1;
printf("%d",is_flashing);
printf("\a"); //响铃
sleep(2);
system("cls");
is_flashing = 0;
printf("%d",is_flashing);
printf("\a");
sleep(2);
system("cls");
}
//监测完成后等待用户输入以模拟反馈温度数据
printf("请按下一个按键以模拟反馈的平均温度数据或强制断电:\n");
scanf("%d",&T_sta_fdbck);
system("cls");
}
switch(T_sta_fdbck)
{
case 111: //温度正常
led_state = Safe;
printf("Safe\n你现在可以选择:\n1.按下KEY1重新监测\n2.按下KEY2强制报警\n3.按下KEY3退出系统\n");
scanf("%d",&T_sta_fdbck);//等待用户进一步输入
system("cls");
if(T_sta_fdbck == 111)
{
led_state = Monitoring;
}
if(T_sta_fdbck == 222)
{
led_state == Danger;
}
if(T_sta_fdbck == 333)
{
led_state == Exit;
}
break;
case 222: //温度异常
system("cls");
for(i = 0; i < 4; i++)
{
is_flashing = 1;
printf("%d",is_flashing);
printf("\a"); //响铃
sleep(1);
system("cls");
is_flashing = 0;
printf("%d",is_flashing);
printf("\a");
sleep(1);
system("cls");
}
printf("由于温度异常,将会重新测温!");
sleep(1);
system("cls");
led_state = Monitoring;
break;
case 333: //强制断电
printf("系统已断电!");
led_state = Exit;
break;
default: //若收到的数据并非以上任一 则数据传输过程中可能出错
//此时此处可以写一些处理系统错误代码...
printf("你貌似输入了错误的数据,系统将在3秒后自动退出!");
sleep(3);
led_state = Error;
break;
}
if(led_state == Exit || led_state == Error)
{
break;
}
}
return 0;
}
看到这的小伙伴们,不妨留下一个点赞和收藏吧,谢谢你的支持与关注~