1、单片机的C51语言基础,C51的程序结构 C51的数据结构 C51与汇编语言的混合编程 C51初步应用编程,51汇编语言能直接操作单片机的系统硬件,指令执行速度快。但其程序可读性差,且编写、移植困难。,C51是为51系列单片机设计的一种C语言,其优点:,C51语言已成为51系列单片机程序开发的主流软件方法。,不要求对单片机的指令系统十分熟悉 易于表达,使用方便 C51语言程序容易移植 具有丰富的库函数 源代码可读性较强,容易理解和编程,相同之处: 语法规则、程序结构、编程方法 不同之处:,C51与标准C语言对比,C51的程序结构 C51的数据结构 C51与汇编语言的混合编程 C51仿真开发环境
2、 C51初步应用编程, 程序由函数组成(一个主函数,或一个主函数和若干自定义函数); 利用预处理命令对变量或函数进行集中定义或说明; 函数和变量都需遵循先定义后使用的基本原则; 主函数中的所有语句执行完毕,则程序结束。,C51与标准C程序结构完全相同,举例:LED闪烁控制功能,预处理命令-,函数说明-,全局变量定义-,主函数-,调用函数-,局部变量定义-,程序体,程序体-,C51的程序结构 C51的数据结构 C51与汇编语言的混合编程 C51仿真开发环境 C51初步应用编程,1. C51的变量,在程序执行过程中,数值可以发生改变的量称为变量。,变量名与存储单元地址相对应,变量值与存储单元的内容
3、相对应。,例如,在哈佛结构的存储空间中如何建立变量概念?,【存储种类】 数据类型 【存储类型】 变量名,(标准C),(标准C),* 括号项可以缺省(但需有缺省值),C51变量定义的四要素:,(C51特有),(标准C+C51),【存储种类】 数据类型 【存储类型】 变量名,共有四个说明符: 1、auto(自动型)变量的作用范围在定义它的函数体或语句块内。执行结束后,变量所占内存即被释放。 2、extern(外部型) 在一个源文件中被定义为外部型的变量,在其它源文件中需要通过extern说明方可使用。 3、static(静态型) 利用static可使变量定义所在的函数或语句块执行结束后,其分配的内
4、存单元继续保留。 4、register(寄存器型) 将变量对应的储存单元指定为通用寄存器,以提高程序运行速度。,缺省存储种类为auto (自动)型变量,数据的不同格式叫做数据类型,* 有符号数类型可以忽略signed标识符,标准C语言的数据类型,【存储种类】 数据类型 【存储类型】 变量名,C51扩充数据类型:bit、sfr或sfr16、sbit,bit 型,关键词bit用于定义一个位变量,语法规则:,bit bit_name = 0或1;,例如:bit door = 0 ; /定义一个叫door的位变量且初值为0,标准C的变量定义举例:int a = 5 ; /定义一个初值为5的整形变量a
5、语法规则:int int_name = 常数;,注意:上述变量的物理地址是由编译器分配的,sfr或sfr16型,关键词sfr或sfr16用于定义SFR字节地址变量,语法规则:sfr 或 sfr16 sfr_name = 字节地址常数;,51MCU中有21个SFR,如何定义与这些单元相关的变量?,例如,sfr P0 = 0x80; /定义P0口地址80Hsfr PCON = 0x87; /定义PCON地址87Hsfr16 DPTR=0x82; /定义DPTR的低端地址82H,注意:SFR字节地址变量的物理地址是由MCU资源决定的,sbit型,部分SFR具有位地址,如何定义与这些位地址相关的变量?
6、,绝对位地址,相对位地址,字节地址,两种位地址表达形式:绝对位地址、相对位地址,1)将SFR的绝对位地址定义为位变量名sbit bit_name = 位地址常数;例如, sbit CY = 0xD7;,3)将SFR的相对位位置定义位变量名sbit bit_name = sfr_name 位位置;例如, sbit CY = PSW7;,2)将SFR的相对位地址定义为位变量名sbit bit_name = sfr字节地址 位位置; 例如, sbit CY = 0xD07;,关键词sbit用于定义SFR位地址变量,三种定义形式:,C51编译器在头文件“REG51.H”中定义了全部sfr/sfr16和
7、sbit变量。,用一条预处理命令#include 把这个头文件包含到C51程序中,无需重新定义即可直接使用它们的名称。,应用举例:,【存储种类】 数据类型 【存储类型】 变量名,51单片机的 三个逻辑存储空间:,片内数据存储器,片外数据存储器和程序存储器。,建立C51存储类型与存储空间的对应关系,C51的存储类型与存储空间对应关系表,编译模式,三种编译模式分别对应于三种缺省存储类型:,【存储种类】 数据类型 【存储类型】 变量名,C51编译器可根据当前采取的编译模式自动认定默认的存储类型 约定:若无特殊声明,一般均为“SMALL编译模式”,例 变量的存储模式#pragma small /*变量
8、的存储模式为Small */char k1; /* k1存储模式Small ,存储器类型默认data*/int xdata m1; /* m1存储模式为Small ,存储器类型xdata*/#pragma compact /*变量的存储模式为Compact */char k2; /* k2存储模式Compact , k2存储器类型默认pdata*/int xdata m2; /* m2存储模式Compact ,存储器类型xdata */int func1(int x1,int y1) large /*函数Large , x1和y1存储器类型xdata */return(x1+y1);int f
9、unc2(int x2,int y2) /*函数默认Small , x2和y2存储器类型data */return(x2-y2);,变量名可以由字母、数字和下划线三种字符组成,且第一个字符必须为字母或下划线,变量名长度随编译系统而定。,变量名具有字母大小写的敏感性,如SUM和sum代表不同的变量。 强调:头文件中定义的变量都是大写的,若程序采取小写变量则需要重新定义。,【存储种类】 数据类型 【存储类型】 变量名,C51扩展的若干关键字一览表,变量名不得使用标准C语言和C51语言的关键字。,unsigned char data system_status = 0;,/定义system_stat
10、us为无符号字符型自动变量,该变量位于data区中且初值为0。,数据结构定义举例,变量名为system_status,位于片内RAM区,无符号字符型,自动型,初值为零,unsigned char bdata status_byte;,unsigned int code unit_id2=0x1234, 0x89ab;,static char m, n;,/定义status_byte为无符号字符型自动变量,该变量位于bdata区,/定义unit_id2为无符号整型自动变量,该变量位于code区中,是长度为2的数组,且初值为0x1234和0x89ab。,/定义m和n为2个位于data区中的有符号字
11、符型静态变量。,指针与地址运算符: *(指针运算符 ),&(取地址运算符) 功能:“*”放在指针变量前面,实现访问以指针变量的内容为地址所指向的存储单元。例如:指针变量p中的地址为2000H,则*p所访问的是地址为2000H的存储单元,x=*p,实现把地址为2000H的存储单元的内容送给变量x。“&”放在变量的前面,通过它取得变量的地址,变量的地址通常送给指针变量。例如:设变量x的内容为12H,地址为2000H,则&x的值为2000H,如有一指针变量p,则通常用p=&x,实现将x变量的地址送给指针变量p,指针变量p指向变量x,以后可以通过*p访问变量x。,C51 中的头文件与C语言类似,区别在
12、于包含文件中多了一组与MCS-51系列硬件相关的头文件,对MCS51系列单片机的内部资源说明。 C51 中的头文件通常有:reg51.h或reg52.h: 定义特殊功能寄存器和位寄存器;math.h: 定义(声明)常用数学运算函数;ctype.h:定义字符判断转换库函数stdio.h:定义输入输出流函数stdlib.h:定义存储器分配函数absacc.h:定义了8个宏,确定各存储空间的绝对地址string.h:定义缓冲区处理函数assert.h-定义宏,可以用来建立程序的测试条件函数intins.h-包含指示编译器产生嵌入式固有代码的程序的原型函数setjmp.h-定义jmp_buf类型和se
13、tjmp和longjmp程序的原型函数stdarg.h-可变长度参数列表函数,C51 中的头文件与库函数,C51 中包含的头文件,Keil C51的库函数C-51软件包的库包含标准的应用程序可直接调用的库函数,调用这些库函数可以使程序代码简单、结构清晰、易于调试和维护。每个函数都在相应的头文件(.h)中有原型声明。如果使用库函数,必须在源程序中用预编译指令定义与该函数相关的头文件(包含了该函数的原型声明)。例如: #include ;定义本征库函数,Keil C51的库函数C-51库函数可分为本征库函数和非本征函数。 本征库函数:是指在编译时直接将固定的代码插入当前行,而不是用ACALL或LC
14、ALL进行函数调用(类似于宏的处理),从而大大提高了访问效率。Keil C51的本征库函数只有9个,数量虽少,但非常有用。本征库函数在头文件intrins.h中定义。 非本征函数:并不是把固定代码插入当前行,而是通过ACALL或LCALL进行函数调用。,1. 本征库函数:9个 (1)_crol_和_cror_:将char型变量循环左/右移动指定位数后返回。 (2)_irol_和_iror_:将int型变量循环左/右/移动指定位数后返回。 (3)_lrol_和_lror_:将long型变量循环左/右/移动指定位数后返回。 (4)_nop_:相当于插入汇编指令NOP。 (5)_testbit_:相
15、当于JBC指令。 (6)_chkfloat_:测试并返回浮点数状态。上面所列举的本征函数的说名都包含在头文件中。若想使用上述本征函数,必须在源程序开头包涵该头文件,即:#include。,C51中绝对地址的访问,C51中绝对地址的访问有三种方法:使用C51运行库中预定义宏,通过指针访问,使用C51扩展关键字_at_。 1. 使用C51运行库中预定义宏C51编译器提供了一组宏定义来对MCS-51单片机的地址空间进行绝对寻址。规定只能以无符号数方式访问。在包含头文件absacc.h的前提下,可以使用预处理命令#define指令定义不同存储空间各个变量的绝对地址。形式为:#include ,访问形式
16、:预定义宏名地址 函数原型定义:#define 宏名(数据类型 volatile*)0x存储单元的绝对地址) 预定义宏名:CBYTEcode区(字节)DBYTE data区(字节)PBYTE pdata区(字节)XBYTE xdata区(字节)CWORD code区(字)DWORD data区(字)PWORD pdata区(字)XWORD xdata区(字)预定义宏名表示绝对地址所处的存储空间和数据长度。,例绝对地址对存储单元的访问#include /*将绝对地址头文件包含在文件中*/#include /*将寄存器头文件包含在文件中*/#define uchar unsigned char /
17、*定义符号uchar为数据类型符unsigned char*/#define uint unsigned int /*定义符号uint为数据类型符unsigned int*/void main(void)uchar var1;uint var2;var1=XBYTE0x0005; /*访问片外RAM的0005字节单元*/var2=XWORD0x0002; /*访问片外RAM的0002字单元*/while(1);,2. 通过指针访问 例 通过指针实现绝对地址的访问。#define uchar unsigned char /*定义符号uchar为数据类型符unsigned char*/#defin
18、e uint unsigned int /*定义符号uint为数据类型符 unsigned int*/void func(void)uchar data var1;uchar pdata *dp1; /*定义一个指向pdata区的指针dp1*/uint xdata *dp2; /*定义一个指向xdata区的指针dp2*/uchar data *dp3; /*定义一个指向data区的指针dp3*/dp1=0x30; /*dp1指针赋值,指向pdata区的30H单元*/dp2=0x1000; /*dp2指针赋值,指向xdata区的1000H单元*/*dp1=0xff; /*将数据0xff送到片外R
19、AM30H单元*/*dp2=0x1234; /*将数据0x1234送到片外RAM1000H单元*/dp3= /*给变量var1赋值0x20*/,中断服务程序 格式:void 中断函数名() interrupt n中断号 中断源0 外部中断01 定时器/计数器02 外部中断13 定时器/计数器14 串行口5 定时器/计数器2(52子系列),C51的程序结构 C51的数据结构 C51与汇编语言的混合编程 C51初步应用编程,C51语言编程可胜任单片机的基本测量与控制任务。 对于某些特殊的I/O 接口处理、中断处理、强调程序执行速度等场合,仍希望采用汇编程序。 C51 编译器提供了与汇编语言程序的接
20、口规则,可方便地实现C51 与汇0编语言程序的相互调用。 本节仅讨论在C51中嵌入汇编代码。,概要,C51中嵌入汇编代码,在C51 函数内嵌入汇编代码,可以有三种不同方法。,方法一 直接在函数体内的每个汇编语句前加“asm”预编译指令,例如:,方法二 把asm作为关键字,后续汇编用大括号括起来即可,例如:,方法三 在C 模块内通过语句“ # pragma”嵌入汇编代码,例如:,C51的程序结构 C51的数据结构 C51与汇编语言的混合编程 C51仿真开发环境 C51初步应用编程,1. Keil的编译环境 Vision3,Keil是德国Keil Software公司的51单片机开发软件包,包括C
21、编译器、汇编编译器、连接器、库管理及仿真调试器,通过一个windows下的集成开发环境uVisoin3组合起来。,Vision3的软件界面包括四大组成部分,即菜单工具栏,工程管理窗口,文件窗口和输出窗口。,Vision3中共有11个下拉菜单。工具栏的位置和数量可以通过设置选定和移动。,工程管理窗口用于管理工程文件目录,它由五个子窗口组成,可以通过子窗口下方的标签进行切换,它们分别是:文件窗口,寄存器窗口,帮助窗口,函数窗口,模版窗口。,工程管理窗口:,输出窗口: 输出窗口用于编译过程中的信息交互作用,由三个子窗口组成,可以通过子窗口下方的标签进行切换,它们分别是:编译窗口,命令窗口,搜寻窗口。
22、,信息窗口: 观察窗口(Watch & Call Stack Windows) 输出窗口(Output Windows) 存储器窗口(Memory Window) 反汇编窗口(Dissambly Window) 串行窗口(Serial Window),输入源程序建立工程对工程进行详细设置 将源程序变为目标代码运行调试 。,2、Vision3的基本使用方法,举例:LED闪烁控制功能,(1)建立工程文件,点击“Project-New Project ”菜单,在编缉框中输入一个名字(设为exam1),无需扩展名。,选择目标CPU(Intel系列的80C51BH),(2)源文件的建立 点击新建文件按钮
23、打开一个新的文本编缉窗口,输入程序源代码,以*.c保存该文件。,(3)添加源程序 (右击“Source Group1” 点击“Add file to Group”Source Group1” 添加生成的.c文件),(4)工程设置,右击Project 窗口的Target 1选择“Project-Option for target target 1” 工程设置对话框,设置对话框中的OutPut 页面 (勾选“ Creat Hex file”),设置对话框中的Debug 页面 (选中Use和下拉框“PROTEUS”),(5)编译、连接产生目标代码(hex文件),点击F7或工具按钮启动编译、连接功能。
24、,完成后将在命令窗口中显示编译结果,若有语法错误,双击出错提示可指出错误所在行号,1、将Keil编译形成的*.hex文件加载到*.DSN文件中,通过proteus控制仿真运行(无法在运行过程中进行调试),程序运行的两种方法:,2、在Keil软件里控制Proteus仿真运行(可以在运行过程中进行调试),步骤:下载( ) 运行( ) 停止( ),(6) 一般调试过程,启动调试过程Ctrl+F5、 、Debug-Start/Stop Debug Session 开始调试详见下页 结束调试 、Debug-Stop Running,调试工具栏,复位,运行到光标行,执行完当前子程序,过程单步,单步,停止,
25、运行,调试菜单栏,快捷键,指向下条运行行,基本调试手段: 1、运行到光标行从当前行运行到光标所在行(Ctrl+F10) 2、严格单步运行遇到函数时亦单步进行(F11) 3、跨函数单步运行遇到函数时将其视作一行语句(F10) 4、断点运行 全速运行到断点行停止(双击设置/解除断点) 5、监视输出端口打开IO窗口 (Peripherals-I/O-Ports) 6、监视运行变量打开Watch#1窗口(点击 ),C51的程序结构 C51的数据结构 C51与汇编语言的混合编程 C51仿真开发环境 C51初步应用编程IO端口的简单应用IO端口的进阶实践,1 I/O端口的简单应用,(1)基本输入输出单元与
26、编程,输出单元: 发光二极管(Light Emitting Diode )基本输出元件,低电平驱动,限流电阻R = 1001k,高电平驱动,灌电流,拉电流,输入单元: 按键(keystroke )、按钮(Button)或开关(Switch) 基本输入元件。,P0口为漏极开路结构需要外接上拉电阻 当按键未按下压时,Px.n端口为高电平;按压按键后为低电平。,实例1 独立按键识别,【要求】采用独立按键方式实现下述功能:开机时LED全熄,然后根据按键动作使相应灯亮,并将亮灯保持到按压其它键时为止。,独立按键每个按键都彼此独立地各占有一位I/O口线。特点是电路简单,但占用I/O口线较多。, 按键的闭合
27、电平为0, 但LED的驱动电平为1,故不能直接将P0口的状态送到P1口,而应使其先取反再送出;, 为使按键抬起后LED能保持先前的点亮状态,需要在按键未压下期间禁止向P2输出P0状态值。,【分析】,参考程序如下:,“取反”操作的优先级高于“与”操作,void main( ) char key = 0; /定义按键变量P2=0; /初始状态为灯全灭while(1)key = P0 /有按键动作时,P0状态值送P2 ,编程界面和运行界面分别如下图,实例1运行效果,实例2 键控流水灯,【要求】 K1为“启动键”,首次按压K1可产生“自下向上” 的流水灯运动;K2 为“停止键”,按压K2可终止流水灯的
28、运动;K3和K4为“方向键”,分别产生 “自上向下”和 “自下向上” 运动。,K1 K2 K3 K4,(键值函数),思路分析:根据键值修改标志位,根据标志位控制灯状态,总体关系流程图,键值: 按压K1xxxx 1110B 按压K2xxxx 1101B 按压K3xxxx 1011B 按压K4xxxx 0111B 无按键 xxxx 1111B,按键动作判断(P0 & 0x0f)是否等于 0x0f?若是,说明无按键动作,反之则有按键动作, 0x0e 0x0d 0x0b 0x07 0x0f,判键流程,亮灯P2输出: xxxx 0001 xxxx 0010 xxxx 0100 xxxx 1000,LED
29、循环流程,char led = 0x01,0x02,0x04,0x08;,for (i=0; i=3; i+) P2 = led i; /移动,for (i=3; i=0; i- ) P2 = led i; /移动,实例2 原理图与程序界面图,程序运行效果,实例3 混合编程,将实例2中C51的delay函数改用汇编语言实现,并完成系统的混合编程。,程序说明,分别编写汇编语言(delay.asm)与C51语言(实例3.c)两个程序文件,并将其添加到Keil的同一项目中。,C51部分与实例2基本相同,delay函数声明,delay.asm,与实例3.c文件中函数delay同名的子程序,汇编子程序的
30、头部格式,;延时处理函数(汇编语言) PUBLIC _DELAY DE SEGMENT CODE RSEG DE_DELAY:MOV R0,#225 DEL2: DJNZ R0,DEL2DJNZ R7,_DELAYRETEND,LED数码管原理与编程,LED显示元件人机交互输出设备,其作用是指示中间运行结果与运行状态。,com为公共端,共阳极LED,共阴极LED,引脚配置,七段式LED显示器,(7-Segment Display),采用不同LED组合关系(显示码)能形成不同的显示字符,以共阴极为例,部分字符的显示码(字模)为:,七段LED数码管的标准显示字符为09,AF,显示字符,显示码(共阴
31、),其它字符:,0x38,“L”字符的显示码,“H”字符的显示码,0x76,实例4 LED数码管显示,在P0口连接一个共阴极数码管,使之循环显示09数字。,分析: 将显示码循环输出到P0口即可实现循环显示。但由于数字09的显示段码没有规律可循,需要采取查表方式进行操作:,将显示码按序存放在一个数组中, 顺序号与代表的显示字符相对应。(如,char led_mod =x1,x2,.,xn) 通过循环变量指定待送出的数组元素,参考程序,实例5 计数显示器,对按键动作进行计数和显示,达到99后重新由1开始计数。,个位LED接P2口,十位LED接P0口(共阴型),按钮接P3.7口线,按压时为0电平,分
32、析:,读P3.7口,进行加1计数和超界处理; 拆分计数器数值个位、十位; 查找/输出显示码到P0和P2口。,计数值拆分: 取模运算(%)个位 整除10运算(/)十位,查找/输出显示码: 按拆分值输出相应数组元素,参考程序,程序运行效果,C51的程序结构 C51的数据结构 C51与汇编语言的混合编程 C51仿真开发环境 C51初步应用编程IO端口的简单应用IO端口的进阶实践,数码管动态显示原理与编程,两种显示接口:静态显示接口和动态显示接口,静态显示接口:一个数码管的引脚独立占据一根I/O口线。 优点:被显示数据只要送入并行口后就不再需要CPU干预,因而显示效果稳定。 缺点:占用资源较多,动态显
33、示接口: 所有数码管的段码线对应并联接在一个并行口上,而每位数码管的公共端分别由一位I/O线控制; 由并口输出的显示码可被所有数码管收到,但只有满足导通条件的数码管可以被驱动。,工作原理: 采用快速切换方式(如10ms),每一时刻只有一只数码管导通工作。利用视力暂留特性,可获得连续显示效果。 优点:占用资源较少 缺点:占用机时较多(需要CPU随时刷新显示值),实例6 数码管动态显示,采用共阴极动态LED显示原理,实现如下功能: SW1向下拨时显示字符“L2”,向上拨时显示字符“H3”。,分析: Proteus中的双联LED数码管相当于两个并联的数码管。,7SEG-MPX2-CC-BLUE,Bl
34、ue,2 Digit,7-segment Cathode Display,A-G “0x38”, 1#“0”,2# “1”,A-G “0x5b”, 1#“1”,2# “0”,进一步说明其工作原理,P2led_mode0, P3 xxxx xx10B =2 P2led_mode1, P3 xxxx xx01B =1,led_mode =0x38,0x5b,如果不考虑开关switch,动态显示“L2”的程序可以如下:,;,/LED “指针”,/显示字模,A-G “0x76”, 1#“0”,2# “1”,A-G “0x4f”, 1#“1”,2# “0”,字符数组 led_mode =0x38,0x5
35、b,0x76,0x4f,开关下拨状态(L2) led_mode 0、1 开关上拨上拨(H3) led_mode 2,3,开关状态标志 switch_sta 0,2,LED指针 led_point 0,1,完整的主函数,#include char led_mod = 0x38,0x5B,0x76,0x4F; /LED字模“L2H3” void delay(unsigned int time); sbit P17=P17; void main() char led_point = 0, switch_sta = 0;while (1) if (P17 = 1) switch_sta = 2; /开
36、关向上else switch_sta = 0; /开关向下P3 = 2 - led_point; /输出LED位码P2= led_modswitch_sta+led_point; /输出字模led_point = 1 - led_point; /刷新LED位码delay(30); ,编程界面,运行效果图,行列式键盘原理与编程,独立式键盘的电路简单,易于编程,但占用的IO口线较多,当需要较多按键时可能产生IO资源紧张问题。,独立式键盘电路,行列式键盘将IO口分为行线和列线,按键跨接在行线和列线上,列线通过上拉电阻接正电源。,44行列式键盘,7407六高压输出缓冲器/驱动器,行列式键盘的特点:占用
37、IO口线少,但软件过程复杂。,键值按键压下时形成的电平编码值,如0F, 键盘扫描,键盘扫描原理(以P3口接44键盘为例) 按键压下前后,所在行线端口电平反转,同时将各行电平置1,分别将各列电平置0。,key_scan = 0xef, 0xdf, 0xbf, 0x7f,读P3: 若P3低4位为f 或(P3 & 0x0f)=0x0f 无键压下 若P3低4位f或(P3 & 0x0f)0x0f 有键压下,其中 0#: 1110 1110B0xee, 按键判断,1#: 1101 1110B0xbe, F#: 0111 0111B0x77, 键值计算,for (j = 0 ; j 16 ;j+) /查找按
38、下键键值if (key_buf j = P3) return j; ,key_buf = 0xee, 0xde, 0xbe, 0x7e,0xed, 0xdd, 0xbd, 0x7d,0xeb, 0xdb, 0xbb, 0x7b,0xe7, 0xd7, 0xb7, 0x77;,键模,实例7 行列式键盘,要求:开机黑屏;按下任意按键后,数码管上显示该键的键值(0F);若没有新键按下,维持前次按键结果。,行列式键盘+静态数码显示,实例7程序流程图,完整程序,编程界面,程序运行效果,按键在闭合和断开瞬间会因弹簧开关的变形产生电压波动,软件消抖法:延时10ms后再次扫描按键状态。若仍判为“闭合”说明确有键压下;若为“非闭合”说明是误动作。,按键抖动波形,键盘消抖原理:,补充实例:,本节小结,C51的数据类型与变量的定义,都必须考虑单片机的存储结构。 在Keil下进行C51开发的基本步骤是:建立项目输入源程序设置编译参数编译连接下载调试。 单片机IO口基本编程应用包括按键(或开关)状态检测、发光二极管输出控制、数码管动态显示以及行列式键盘扫描编程等内容。,