当前位置: 首页 > news >正文

单片机原理及应用笔记:C51流程控制语句与项目实践

作者介绍

周瑞康,男,银川科技学院,计算机人工智能学院,2022级计算机科学与技术8班本科生,单片机原理及应用课程第八组。

指导老师:王兴泽

电子邮箱2082545622@qq.com

前言:

本篇文章是参考《单片机原理及应用(c语言版)第2版》杨居义·编著教材编写的笔记

由周瑞康,王征,汪泽祥,杨立娟,韩旭同学共同完成此篇章,其中杨立娟,韩旭同学负责C51的顺序结构C51的选择结构相关知识。汪泽祥同学负责C51的循环结构。王征同学负责项目实践。周瑞康同学负责以上内容排版整合。

项目12:C51流程控制语句与项目实践

C语⾔的三种基本结构指的是顺序结构、选择结构、循环结构,基本上所有的程序执行过程都可以拆分为这三种结构或者这三种结构的组合。这三种结构是构建任何C语言程序的基础,它们可以相互嵌套和组合,以实现复杂的程序逻辑。

  1. 顺序结构

顺序结构的特点是程序的执行流程是直线型的,即程序从第一条语句开始,从上到下按顺序逐条执行,直到最后一条语句结束,过程中没有任何分支或跳转。

    2.选择结构

通过某个给定条件进行判断,条件为真或假时分别执行不同的程序内容,选择结构分条件语句和开关语句两种。

     

​​​​​​     ​2.1if语句(条件语句)

主要包括if语句和switch语句。If语句在单片机c语言中是极为常用的语句,用来判断某些变量(信号)达到预期的值后,再执行满足条件的指令,或者执行不满足条件的指令。If 语句的基本形式有三种:

  1. 直接的if语句;

if (condition) {

    // 当条件为 true 时执行的代码

}

if……else……语句;

在需要根据条件执行不同操作时,if-else 语句提供了更好的结构。当第一个条件为 false 时,程序会执行 else 块中的代码。

if (condition) {

    // 当条件为 true 时执行的代码

} else {

    // 当条件为 false 时执行的代码

}

if的嵌套形式;

如果程序需要处理多个条件,else if 语句可以帮助实现更复杂的逻辑结构。else if 语句允许在多个条件中进行选择。

if (condition1) {

    // 如果 condition1 为 true,则执行这段代码

} else if (condition2) {

    // 如果 condition1 为 false 且 condition2 为 true,则执行这段代码

} else if (condition2) {

    // 如果 condition1 为 false 且 condition2 为 true,则执行这段代码

else {

    // 如果以上条件均为 false,则执行这段代码

}

​​​​​​     2.2switch语句(开关语句)

 if语句比较适合于从两者之间选择。当要实现从多种选一时,采用switch…case多分支开关语句,可使程序变得更为简洁。

Switch(表达式)

{

Case  常量表达式1:/*如果常量表达式1满足,则执行语句1*/

语句1;

break;  /*执行完语句1后,使用break跳出switch结构*/

Case  常量表达式2: /*如果常量表达式2满足,则执行语句2*/

语句2;

break;  /*执行完语句2后,使用break跳出switch结构*/

:

:

Case  常量表达式n: /*如果常量表达式n满足,则执行语句n*/

语句n;

break;  /*执行完语句n后,使用break跳出switch结构*/

default:  /*条件都不满足时,执行语句n+1*/

语句n+1;

}

当switch括号中表达式的值与某一个case后面的常量表达式的值相等时,就执行它后面的语句,然后因遇到break而退出switch语句。

当所有case中常量表达式的值都没有与表达式的值相匹配时,就执行default后面的语句。

每个case的常量表达式必须是互不相同的,否则出现对表达式的同一个值有两种以上的选择。

如果case语句中遗忘了break,则程序在执行了本行case选择之后,不会按规定退出switch语句,而是执行后续的case语句。

注意:对于Switch语句,需要注意两点:一是常量表达式的值必须是整型或字符型;二是最好使用“break”。

实例:

void main(void)

{unsigned char i;

i=2;

Switch(i)

{

Case 0: P0=0xff ;  /*如果i=0,则执行“P0=0xff”*/

break;

Case 1:P1=0xff;

break;

Case 2:P2=0xff;   /*常量表达式2满足,则执行“P2=0xff”*/

break;  /*执行完后,跳出switch结构*/

default:P1=0x00;  /*当所有的case中的常量表达式的值都没有与表达式的值相匹配时,就执行default后面的语句*/

}

}

3.C51的循环结构

循环结构是结构化程序设计的3种基本结构之一,因此掌握循环结构的概念是程序设计,尤其是C程序设计最基本的要求。

在C51语言中,实现循环的语句主要有3种。

(1)While语句的一般形式

While(表达式)

{语句;/*循环体*1}

While语句的语义是:计算表达式的值,当值为真(非0)时,执行循环体语句,否则,跳出循环体,执行后续操作。

使用while语句应注意以下几点:

●While语句中的表达式一般是关系表达式或逻辑表达式,只要表达式的值为真(非0)即可继续循环。

●循环体如包含一个以上的语句,则必须用“{}”括起来,组成复合语句。

●While循环体中,应有让循环最终能结束的语句,否则将造成死循环。一直运行直至关机。

实例:

while(1)

{}

这个语句的作用就是无限循环,一直运行直至关机。

实例:用while求1到10的和,程序如下:

void main(void)

{

unsigned char i,sum;

sum=0;

i=1;

while(i<=10)

{

sum=sum+i

i++;

}

PO=sum;  //将结果送P0口显示

}

(2)do…while语句的一般形式

do

{语句;}   /*循环体*/

while(表达式);

do…while循环语句的执行过程如下:首先执行循环体语句一次,再判断表达式的值。如果表达式的值为真(非0值),则重复执行循环体语句,直到表达式的值变为假(0值)时循环结束。对于这种结构,在任何条件下,循环体语句至少会被执行一次。注意:

●do是C语言关键字,必须和while联合使用;

● while(表达式)后的分号“;”不能少,它表示整个循环语句的结束。

实例:用do…while求1到10的和,程序如下:

    void main(void)

{

unsigned char i,sum;

sum=0;

i=1;

do{

sum=sum+i;  /*注意{}不能省,否则跳不出循环体*/

i++;

}

while(i<=10);/1分号“;”不能少

PO=sum;  //将结果送P0口显示

}

(3)for语句的一般形式

For  (初始化表达式;条件表达式;增量表达式)

{语句;}  /*循环体*/

For 循环语句结构可使程序按指定的次数重复执行

一个语句或一组语句。for循环语句的执行过程如下:

●初始化表达式;

●求解条件表达式。若其值为“真”,则执行for后面的语句;如果其值为“假”,那么跳过for循环语句;

●若条件表达式为“真”,则执行指定的语句后,执行增量表达式;

●执行for后面的语句。

4.项目实践

任务12-2-1:用按键S控制P1口8只LED显示状态

任务实现

(1)分析:先设置一个变量i,当i=1时,LED1发光;当i=2时,LED1、LED2发光;当i=3时,LED1、LED2、LED3发光;...;当i=8时,LED1~LED8都发光。由“switch”语句根据i的值来实现LED发光。i值的改变可以通过按键S来控制,每按下S按键一次,i自增1,当增加到9时,将其值重新置为1。

(2)程序设计

#includesreg51.h> //包含单片机寄存器的头文件

sbit S=P3^0; 1/定义按键S接入P3.0引脚

/*********************************

函数功能:延时约150ms

**********************************/

Void delay(void)

{

Unsigned char i,j;

for(i=0;i<200;i++)

for(j=0;j<250;j++)

       }

/*********************************

函数功能;主函数

**********************************/

void main(void)

{

unsigned chari;

i=0;  //初始化

while(1)  //无限循环

{

if(S==0) //判断S按键是否被按下,如果S=0被按下

{

delay();  150ms延时,消除键盘抖动

if(S==0)  /*再判断S按键是否被按下,如果S=0确被按下*/

i++;  //自增1

if(i==9) //如果i=9,将其值重新置为1

i=1;

}

switch(i)  //7使用多分支语句

{

case1:P1=0xfe;  //LED1发光

break;  //退出switch语句

case2:P1=0xfc; //LED1、LED2发光

break;  //退出switch语句

case3:P1=0xf8;  //LED1、LED2、LED3发光

break;  //退出switch语句

case4:P1=0xf0;  //LED1、LED2、LED3、LED4发光

break;  //退出switch语句

case5:P1=0xe0;  //LED1、LED2、LED3、LED4、LED5发光

break;  //退出switch语句

case6:P1=0xc0;  //LED1、LED2、LED3、LED4、LED5、LED6发光

break;  //退出switch语句

case7:P1=0x80;  //LED1、LED2、LED3、LED4、LED5、LED6、LED7发光

break;  //退出switch语句

case8:P1=0x00;  //LED1~LED8发光

break;  //退出switch语句

defauit:  //默认值,关闭所有LED

P1=0xff;}

}

             }

任务12-2-2:用for语句实现蜂鸣器发出1kHZ音频

任务实现

(1)分析:设单片机晶振频率为12MHz,则机器周期为1μs。只

要让单片机的P1.0引脚的电平信号每隔音频的半个周期取反一次即可发出1KHz音频。音频的周期为T=1/1000Hz=0.001s,即1000μs,半个周期为1000μs/2=500μs,即在P1.0引脚上每500μs取反一次即可发出1KHz音频。而延时500μs需要消耗机器周期数N=500μs /3=167,即延时每循环167次,就可让P1.0引脚上取反一次就可以得到1KHz音频。

(2)程序设计

#include<reg51.h>  //包含单片机寄存器的头文件

sbit sound=P1^0;   //将sound位定义为p1.0引脚

/**********************************************

函数功能:延时以形成约1KHz音频

/**********************************************

            void delay500us(void)

{

unsigned char i;

for(i=0;i<167;i++)

;

}

/**********************************************

函数功能:延时1000μs以形成一个周期约500Hz音频

/**********************************************

void delay1000us(void)

{

unsigned int i;

for(i=0;i<333;i++)

;

}

/**********************************************

函数功能:发声1s时间的控制

/**********************************************

void sound1s(void)

{

unsigned int i;

for(i=0;i<1000;i++)

{

sound = 0;

delay500us();

sound = 1;

delay500us();

}

}

/**********************************************

函数功能:发声0.5s时间的控制

/**********************************************

void soundBans(void)

{

unsigned char i;

for(i=0;i<250;i++)

{

sound=0;

delay1000us();

sound=1;

delay1000us();

}

}

(4)实践探索——用单片机开发版来实现

          由于开发板蜂鸣器连接在P2.4引脚,因此只需要修改代码”sbit sound=P2^4”就可以了。

小结:消耗机器周期数的计算(近似值):

(1)一重循环

for(i=0;i<n;i++)    //n必须为无符号字符型数据

消耗机器周期数为:

N=3×n

式中:N为消耗机器周期数;n为需要设置的循环次数(n必须为无符号字符型数据)。

(2)二重循环

for(i=0;i<n;i++)    //n必须为无符号字符型数据

for(i=0;i<m;i++)   //m必须为无符号字符型数据消耗机器周期数为:

N=3×n×m

任务12-2-3:用while语句控制P1口8只LED的显示状态

任务实现

(1)分析

设计一个用while语句实现P1口8只LED显示状态的程序,根据要求在while语句循环中设置一个变量i,当i小于0x64(十进制数100)时,将i的值送P1口显示,并i自增1,当i等于0×64时,就跳出while循环。

(2)程序设计

#include<reg51.h>  //包含单片机寄存器的头文件

/**********************************************

函数功能:延时约150ms

/**********************************************

void delay(void)

{

unsigned char i,j;

for(i=0;i<200;i++)

for(j=0;j<250;j++)

;

}

/**********************************************

函数功能:主函数

/**********************************************

void main(void)

{

unsigned char i;

while(1)  //无限循环

{

i=0;  //将i置为0,即初始化

while(i<0x64)  //i小于100时执行循环体

{

P1=i;

delay;

i++;  //i自增1

}

}

}

任务12-2-4:用do…while语句控制P1口8只LED的显示状态

任务实现

(1)分析:只要在循环体中按照点亮次序依次点亮,再将循环条件设置为死循环即可。现在来讨论点亮LED的控制码。LED1发光的控制码为0xfe;LED1、LED2发光的控制码为0xfc;LED1、LED2、LED3发光的控制码为0xf8......LED1~LED8都发光的控制码为0x00;LED1发光的控制码为0xfe;LED1、LED2发光的控制码为0xfc...依次循环。

(2)程序设计

#include<reg51.h>

void delay(void)

{

unsigned char i,j;

for(i=0;i<200;i++)

for(j=0;j<200;j++)

;

}

void main(void)

{

do

{

P1=0xfe;  //LED1点亮

delay();  //延时

P1=0xfc;  //LED1、LED2点亮

delay();  //延时

P1=0xf8;  //LED1、LED2、LED3点亮

delay();  //延时

P1=0xf0;  //LED1~LED4点亮

delay();  //延时

P1=0xe0;  //LED1~LED5点亮

delay();  //延时

P1=0xc0;  //LED1~LED6点亮

delay();  //延时

P1=0x80;  //LED1~LED7点亮

delay();  //延时

P1=0x00;  //LED1~LED7点亮

delay();  //延时

}while(1);

}

     

相关文章:

单片机原理及应用笔记:C51流程控制语句与项目实践

作者介绍 周瑞康&#xff0c;男&#xff0c;银川科技学院&#xff0c;计算机人工智能学院&#xff0c;2022级计算机科学与技术8班本科生&#xff0c;单片机原理及应用课程第八组。 指导老师&#xff1a;王兴泽 电子邮箱2082545622qq.com 前言&#xff1a; 本篇文章是参考《…...

大数据日志处理框架ELK方案

介绍应用场景大数据ELK日志框架安装部署 一&#xff0c;介绍 大数据日志处理框架ELK&#xff08;Elasticsearch、Logstash、Kibana&#xff09;是一套完整的日志集中处理方案&#xff0c;以下是对其的详细介绍&#xff1a; 一、Elasticsearch&#xff08;ES&#xff09; 基本…...

VQGAN(2021-06:Taming Transformers for High-Resolution Image Synthesis)

论文&#xff1a;Taming Transformers for High-Resolution Image Synthesis 1. 背景介绍 2022年中旬&#xff0c;以扩散模型为核心的图像生成模型将AI绘画带入了大众的视野。实际上&#xff0c;在更早的一年之前&#xff0c;就有了一个能根据文字生成高清图片的模型——VQGAN…...

docker中使用ros2humble的rviz2不显示问题

这里写目录标题 docker中使用ros2humble的rviz2不显示问题删除 Docker 镜像和容器删除 Docker 容器Linux服务器下查看系统CPU个数、核心数、(make编译最大的)线程数总结&#xff1a; RVIZ2 不能显示数据集 docker中使用ros2humble的rviz2不显示问题 问题描述&#xff1a; roo…...

【AIGC】2024-arXiv-Lumiere:视频生成的时空扩散模型

2024-arXiv-Lumiere: A Space-Time Diffusion Model for Video Generation Lumiere&#xff1a;视频生成的时空扩散模型摘要1. 引言2. 相关工作3. Lumiere3.1 时空 U-Net (STUnet)3.2 空间超分辨率的多重扩散 4. 应用4.1 风格化生成4.2 条件生成 5. 评估和比较5.1 定性评估5.2 …...

正则表达式:文本处理的强大工具

正则表达式是一种强大的文本处理工具&#xff0c;它允许我们通过定义一系列的规则来匹配、搜索、替换或分割文本。在编程、文本编辑、数据分析和许多其他领域中&#xff0c;正则表达式都扮演着重要的角色。本文将介绍正则表达式的基本概念、语法和一些实际应用。 正则表达式的…...

Doris单机安装

1、安装包下载 官网地址&#xff1a;https://doris.apache.org/zh-CN/docs/gettingStarted/quick-start/ 下载地址&#xff1a;https://apache-doris-releases.oss-accelerate.aliyuncs.com/apache-doris-3.0.2-bin-x64.tar.gz 2、操作系统环境准备 #环境准备 cat /proc/cp…...

ubuntu内核更新导致显卡驱动掉的解决办法

方法1&#xff0c;DKMS指定内核版本 用第一个就行 1&#xff0c;借鉴别人博客解决方法 2&#xff0c;借鉴别人博客解决方法 方法2&#xff0c;删除多于内核的方法 系统版本&#xff1a;ubuntu20.24 这个方法是下下策&#xff0c;如果重装驱动还是不行&#xff0c;就删内核在…...

【Java数据结构】树】

【Java数据结构】树 一、树型结构1.1 概念1.2 特点1.3 树的类型1.4 树的遍历方式1.5 树的表示形式1.5.1 双亲表示法1.5.2 孩子表示法1.5.3 孩子双亲表示法1.5.4 孩子兄弟表示法 二、树型概念&#xff08;重点&#xff09; 此篇博客希望对你有所帮助&#xff08;帮助你了解树&am…...

Java面试题——微服务篇

1.微服务的拆分原则/怎么样才算一个有效拆分 单一职责原则&#xff1a;每个微服务应该具有单一的责任。这意味着每个服务只关注于完成一项功能&#xff0c;并且该功能应该是独立且完整的。最小化通信&#xff1a;尽量减少服务之间的通信&#xff0c;服务间通信越少&#xff0c…...

Python 中 print 函数输出多行并且选择对齐方式

代码 # 定义各类别的标签和对应数量 categories ["class0", "class1", "class2", "class3", "class4", "class5"] counts [4953, 547, 5121, 8989, 6077, 4002]# 设置统一的列宽 column_width 10# 生成对齐后…...

书生营L0G3000 Git 基础知识

任务1: 破冰活动&#xff1a;自我介绍 用vi就行了 按照教程来就好了 git会报错密码&#xff0c;输入的时候换成token就好了 https://stackoverflow.com/questions/68775869/message-support-for-password-authentication-was-removed 提交。&#xff08;github上预览自己的…...

【C++初阶】模版入门看这一篇就够了

文章目录 1. 泛型编程2. 函数模板2. 1 函数模板概念2. 2 函数模板格式2. 3 函数模板的原理2. 4 函数模板的实例化2. 5 模板参数的匹配原则2. 6 补充&#xff1a;使用调试功能观察函数调用 3. 类模板3 .1 类模板的定义格式3. 2 类模板的实例化 1. 泛型编程 在C语言中&#xff0…...

Spring Bean创建流程

Spring Bean 创建流程图 大家总是会错误的理解Bean的“实例化”和“初始化”过程&#xff0c;总会以为初始化就是对象执行构造函数生成对象实例的过程&#xff0c;其实不然&#xff0c;在初始化阶段实际对象已经实例化出来了&#xff0c;初始化阶段进行的是依赖的注入和执行一…...

重学SpringBoot3-怎样优雅停机

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-怎样优雅停机 1. 什么是优雅停机&#xff1f;2. Spring Boot 3 优雅停机的配置3. Tomcat 和 Reactor Netty 的优雅停机机制3.1 Tomcat 优雅停机3.2 Reac…...

【数据结构】顺序表和链表

1.线性表 我们在C语言当中学过数组&#xff0c;其实呢&#xff0c;数组可以实现线性表&#xff0c;线性表理解上类似于数组&#xff0c;那么什么是线性表呢&#xff1f;线性表是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使 用的数据结构&#xff0c;常见…...

Training language models to follow instructions with human feedback解读

前置知识方法数据集结论 前置知识 GPT的全称是Generative Pre-Trained Transformer&#xff0c;预训练模型自诞生之始&#xff0c;一个备受诟病的问题就是预训练模型的偏见性。因为预训练模型都是通过海量数据在超大参数量级的模型上训练出来的&#xff0c;对比完全由人工规则…...

线性回归矩阵求解和梯度求解

正规方程求解线性回归 首先正规方程如下&#xff1a; Θ ( X T X ) − 1 X T y \begin{equation} \Theta (X^T X)^{-1} X^T y \end{equation} Θ(XTX)−1XTy​​ 接下来通过线性代数的角度理解这个问题。 二维空间 在二维空间上&#xff0c;有两个向量 a a a和 b b b&…...

M3U8不知道如何转MP4?包能学会的4种格式转换教学!

在流媒体视频大量生产的今天&#xff0c;M3U8作为一种基于HTTP Live Streaming&#xff08;HLS&#xff09;协议的播放列表格式&#xff0c;广泛应用于网络视频直播和点播中。它包含了媒体播放列表的信息&#xff0c;指向了视频文件被分割成的多个TS&#xff08;Transport Stre…...

C++第4课——swap、switch-case-for循环(含视频讲解)

文章目录 1、课程代码2、课程视频 1、课程代码 #include<iostream> using namespace std; int main(){/* //第一个任务&#xff1a;学会swap int a,b,c;//从小到大排序输出 升序 cin>>a>>b>>c;//5 4 3if(a>b)swap(a,b);//4 5 3 swap()函数是用于交…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

通过Wrangler CLI在worker中创建数据库和表

官方使用文档&#xff1a;Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后&#xff0c;会在本地和远程创建数据库&#xff1a; npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库&#xff1a; 现在&#xff0c;您的Cloudfla…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

P3 QT项目----记事本(3.8)

3.8 记事本项目总结 项目源码 1.main.cpp #include "widget.h" #include <QApplication> int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); } 2.widget.cpp #include "widget.h" #include &q…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...