51单片机程序的几个特点
0 2022-08-11

本篇我们将分析所写的程序代码。未来学习单片机的大部分精力,我们也将放在程序代码的编写上。但是不用担心,我会非常详细的介绍每个程序的编写思路和各种注意事项等。

之前我们写的程序如下:

#include
sbit LED = P1^0;

void main()
{
LED = 0;
while(1);
}

头文件

第一行包含头文件,这个和C语言编写HelloWorld时的#include 一样。头文件reg52.h中定义了单片机的一些寄存器,如P0~P3等。至于什么是寄存器,将在原理篇中具体介绍,现在我们只要把它想象成C语言中常说的内存就好了。有兴趣的读者可以右击reg52.h打开头文件看一看。

C51的变量类型

这里我们使用的语言是C51,和标准C语言相比,最主要的特点就是多出来两种变量类型:sfr和sbit。sfr和char一样是一个8位数据类型,表示一个8位的寄存器。例如头文件reg52.h中就有一句sfr P1 = 0x90,它定义了寄存器P1。由于P1是IO口寄存器,所以对P1赋值,则相应的, IO口P1将输出对应的高低电平。而sbit则是一个1位数据类型,只有0和1两种值,它对应寄存器中的一个位。

于是在第二行里,我们定义了sbit型变量LED,并设置LED对应P1的最低位bit0。此时变量LED就和IO口P1.0关联起来。执行赋值语句LED = 0,IO口P1.0就会输出低电平,于是我们电路中的LED就会亮起来了。是不是非常神奇呢?在原理篇中,我会一步一步讲解单片机是如何实现这种功能的。

位寻址

在其他的很多单片机中,我们只能读写整个P1寄存器,而不能直接定义类似sbit这种对应寄存器一位的数据类型,另外51单片机里面有些寄存器也只能整个8位一起读写。这种直接读写一个寄存器位的特性被叫做位寻址功能。

又是一个很难理解的概念,同样,还是需要了解原理篇才能很好的理解它,现在完全不用担心,我提这个就是想让初学者对此提前有个大体印象。毕竟很多知识都是慢慢积累的,如果把大量这样的小知识全部放在原理篇中一并介绍,反而难以接受。

主函数的特点:没有参数和返回值

读者应该已经看到了无参数且无返回值的void main()函数,以及倒数第二行的while(1)语句,并可能疑惑不解。没错,主函数没有参数也没有返回值,倒数第二行的这句是一个死循环,程序永远也不会退出。这和计算机上的程序有很大的不同。下面简单的说明一下这样做的原因何在,更深入的原因,则需要读者看完原理篇后才能理解透彻。

在计算机中,我们开机时看到的启动界面是操作系统,如Windows、Linux等,我们编写的程序则是在操作系统的环境下运行的。程序执行时,相当于系统调用main函数,所以系统可以向main函数传递参数,也可以获取main函数执行结束时的返回值,程序执行结束后,会重新回到操作系统环境下。而在这里,我们写的程序是直接运行在单片机上的,不依赖操作系统。我们程序中的main函数不会被操作系统调用,因此通常它不需要参数,也不需要返回值。事实上,main函数有些情况下是被启动代码调用的,而启动代码是汇编语言写的,还记得上一篇中提到的启动代码么?

主函数的特点:死循环,不会执行结束

在计算机中,我们写的程序执行结束会回到操作系统环境下。而在单片机中,一旦单片机上电复位,就会执行我们写的main函数,直到断电。而如果main函数执行结束,将发生不可预知的结果。

实际实验时,STC单片机会复位并重新开始执行程序,或许只是个巧合,因为官方的芯片手册中并没有明确说明这一点。本着严谨的科学态度,我们不利用这种未经官方确认的特点来开发我们的程序。程序的可靠性是非常重要的,这一点要引起重视。

试想如果你用单片机开发的是医疗相关的产品,或者是控制一些大型机器等,一旦发生意外,后果难以想象。即使你开发的是普通的产品,如果总是出现奇怪的故障,也足以让用户抓狂。因此这一点要引起读者注意。所以,单片机的程序是不应该执行结束的,因此最后必然是一个死循环,这样才能保证单片机系统的可靠性。

总结

于是我们总结出通常情况下51单片机程序的几个特点:

1、包含REG52.H,该文件中定义了P0-P3接口等信息(sfr型和sbit型)。

2、单片机主函数没有参数,没有返回值(当然写成int型也不会报错,但是没必要)。

3、单片机主函数末尾会有个死循环,不会退出。 

声明: 本文转载自其它媒体或授权刊载,目的在于信息传递,并不代表本站赞同其观点和对其真实性负责,如有新闻稿件和图片作品的内容、版权以及其它问题的,请联系我们及时删除。(联系我们,邮箱:evan.li@aspencore.com )
0
评论
  • 报名中:IIC Shenzhen - 2022国际集成电路展览会暨研讨会


  • 相关技术文库
  • 单片机
  • 嵌入式
  • MCU
  • STM
  • CFS任务的负载均衡

    负载均衡的系列文章共分为三篇,第一篇为框架篇,描述负载均衡的相关原理、场景和框架。本篇作为该系列文章第二篇,主要通过对任务放置场景(task placement)的均衡分布进行分析,以便加深读者对内核调度器实现任务均衡分布的理解。 本文基于linux-5.4.24分

    3小时前
  • Multi-queue 架构分析

    Linux上传统的块设备层(Block Layer)和IO调度器(如cfq)主要是针对HDD(hard disk drivers)设计的。我们知道,HDD设备的随机IO性能很差,吞吐量大约是几百IOPS(IOs per second),延迟在毫秒级,所以当时IO性能的瓶颈在硬件,而不是内核。但是,随着高速

    3小时前
  • ARMv8 异常处理简介

    内核稳定性问题复杂多样,最常见的莫过于“kernel panic”,意为“内核恐慌,不知所措”。这种情况下系统自然无法正常运转,只能自我结束生命,留下死亡信息。诸如: “Unable to handle kernel XXX at virtual address XXX” “undefined instruction XXX”

    3小时前
  • 新型 IO 调度器 BFQ 简介

    Linux io调度器有很多种,大多数调度器都经受住了各种市场环境的长时间验证,稳定性、性能得到各种用户的认可,但新的调度器依然展露头角,在4.12内核中出现了一个新的bfq调度器,这个调度器将取代曾经的辉煌的cfq调度器。社区对待大的改动都是很谨慎的,为什

    3小时前
  • CFS任务的负载均衡(框架篇)

    我们描述负载均衡的系列文章一共三篇,第一篇是框架部分,即本文,主要描述了负载均衡相关的原理、场景和框架。后面的两篇是对均衡代码的情景分析,通过对load balance、task placement和active upmigration几个典型的负载均衡来呈现其实现细节,稍后发布,敬

    3小时前
  • linux IO Block layer 解析

    早期的 Block 框架是单队列(single-queue)架构,适用于“硬件单队列”的存储设备(比如机械磁盘),随着存储器件技术的发展,支持“硬件多队列”的存储器件越来越常见(比如 NVMe SSD),传统的单队列架构也因此被改成了多队列(multi-queue)架构。早在 3.

    3小时前
  • eMMC简介

    1 eMMC是什么 eMMC是embedded MultiMediaCard的简称,即嵌入式多媒体卡, 是一种闪存卡的标准,它定义了基于嵌入式多媒体卡的存储系统的物理架构和访问接口及协议,具体由电子设备工程联合委员会JEDEC订立和发布。 它是对 MMC的一个拓展,具有体积小,功耗低,

    3小时前
  • 低纹波、高精度电流源设计

    低纹波、高精度电流源是一种重要的仪器设备;广泛应用于电光源、电化学、通信、测量技术、电子仪器等领域。目前,市场上的电流源不具备连续可调功能;并且输出电流范围小、

    9小时前
  • Linux 电信基站系统解决方案

      自从1991年Linux第一次面世以来,任何人也不会想到这个不起眼的操作系统现在会应用得如此广泛。无论是从嵌入式领域的智能手机到大型计算服务器都可以找到它的

    昨天
  • 单片机振荡电路中如何选择晶体?

    1.单片机晶振的原理晶振一般采用三端式(考毕兹) 交流等效振荡电路;实际的晶振交流等效电路中,其中Cv是用来调节振荡频率,一般用变容二极管加上不同的反偏电压来实

    昨天
  • OpenMV image 模块对象(目标识别基础)

    背景介绍: Sugar 在一文中说过:“OpenMV 在图像里做目标识别的过程就是:不停地取出画面里的每一帧图像,在图像里的每一帧画面上找目标的过程。” 本篇就说一说 OpenMV 怎样在一帧画面上识别目标的。 image 模块 上一篇中说到 OpenMV 通过 sensor.snapshot(

    昨天
  • 代码里开启喷洒装置, ardupilot 是怎么控制的

    背景介绍: 本文面向植保机飞控开发者,以代码解析的方式解读植保机喷洒装置的控制代码。 不仅说明了功能的开启方法,更重要的是表述了如何从代码里找方法的过程。对于进一步掌握 ardupilot 有帮助。 代码里开启喷洒装置 ardupilot 控制喷洒装置的代码在 AC_S

    昨天
下载排行榜
更多
广告