一、 引子
被控制对象、构造、工作原理、性能--控制要求—控制功能与结构—执行元件—技术要求与性能—原理图硬件选择--仿真图与控制软件(控制指令)--仿真与调试修改(各控制点信号特性、软硬件、器件参数等)--施工图(PCB板等)--加工制造—测试安装—调试—维护等
模拟电路的的工作状态可以在线性工作区、非线性工作区、截止区,在截止区工作者表现了开关、高电位与低电位两种状态,将这种特性用作信号处理,则成为数字电路的基础。数字电路对信号的处理,用数学理论表示则有布尔代数,也就是0,1,也称作逻辑代数。用二进制数学进行数字计算来代替原来的十进制,则需要有用二进制表示的十个数字符号0-9,这便有了4位二进位数0000表示的数字对照表及其换算公式。人们发现,要充分发挥二进制的长处(用数字电路的状态组合表示信息),也就是说:将二进制的排列组合充分利用,采用十六进制更合适—充分利用数字电路及其二进制的优势。而十六进制恰好是两个8位,那么,用8位二进制则可表示更多的信息—更复杂的信息。这便有了0000 0000 ---- 1111 1111,也就是:00 ---- FF。
二进制
| 十进制
| 二进制
| 十进制
| 二进制
| 十六进制
| 二进制
| 十六进制
| 0000
| 0
| 0100
| 4
| 1000
| 8
| 1100
| C
| 0001
| 1
| 0101
| 5
| 1001
| 9
| 1101
| D
| 0010
| 2
| 0110
| 6
| 1010
| A
| 1110
| E
| 0011
| 3
| 0111
| 7
| 1011
| B
| 1111
| F
|
注意51系列8位(bit)一个字节,应用汇编语言简洁高效。16位的处理器需要用两个0000 0000H 表示。16或32位以上,使用操作系统(WinCE、Linux等)更有效,可以利用大量的、底层的、专业化、标准化的面向控制的库函数(如:API等)。高级语言具有对底层硬件的无关性,则可移植性好、可重用性好;高级语言描述控制更接近人的自然语言,可描述性好,表达力好。Linux的代码与模块的开放性、可剪裁性、自我构造等特点使其前景广阔。8位1个字节,16位2个字节,32位4个字节,64位8个字节。16进制表示:8位单片机00H~FFH,16位计算机0000H~FFFFH,32位计算机0000 0000H~FFFF FFFFH,64位计算机呢?
用Proteus+Keil软件组合进行实践训练,逐级学习和理解硬件配置及其C语言的编程技术。
单字与单词、单词与句子、控制与计算或判断、函数及其调用、故事情节与段落,整体问题的分解与实现(组合)
二、 C语言指令说明
C语言是在汇编语言的基础上发展演变而来的,它的最初功能是在计算机硬件上进行操作,也就是说,是为计算机的操作系统而设计的语言。后来的发展,可以为非操作系统(应用程序—软件)编写指令,但其与底层硬件的关系一直被保留着。如可以进行位操作等,对于在单片机上应用该语言提供了便利条件。由于涉及到为非操作系统编写指令,其计算方法的指令、数据类型与结构、较抽象的词法(变量类型、算符等)、较复杂的语法结构等应运而生。由此可以应对更丰富与复杂的故事情节—软件系统。对于更复杂的软件系统、更大的软件系统,使用C++语言则是更合适的。虽然C++语言是面向对象的,但是,仍然要应用C语言提供的结构化的编程机制来实现面向对象中的对象内部的底层细节实现,如成员函数等。面向对象的基础是面向过程。C++是面向对象的语言,C是面向过程的,学起来比C语言困难得多,所以不太适合程序编写与设计的初学者,尤其是学习目的是用C语言来编写单片机的控制系统指令。C++中对象的概念、由对象构成的类的概念对初学者都是难以建立的。其实,本质上来说,对象是自然事物、事务的数量化抽象及其表达。也就是说,表达了对象要表达的事物的诸多属性而已。或说表达了对象要表达的概念的内涵与外延。内涵表征该事物的最基本特征,外延表征该事物基本特征以外的关系密切的其他特征。但该特征或属性与基本特征构成的组合体,必定是该事物。也就是说,特征属性组成的数据结构体为统一整体。作为一种语言,用来写什么--歌词、诗歌、小说、散文、科技论文、控制软件、管理软件、计算软件、分析软件、学习软件、……格式与风格、模式与规则
1. C语言的特点—函数型及其组合与调用
(1)语言简洁、紧凑,使用方便、灵活。 32个关键字、9种控制语句,程序形式自由
(2)运算符丰富。34种运算符
(3)数据类型丰富,具有现代语言的各种数据结构。
(4)具有结构化的控制语句 ,是完全模块化和结构化的语言。
(5)语法限制不太严格,程序设计自由度大。
(6)允许直接访问物理地址,能进行位操作,能实现汇编语言的大部分功能,可直接对硬件进行操作。兼有高级和低级语言的特点 。
(7)目标代码质量高,程序执行效率高。只比汇编程序生成的目标代码效率低10%-20%。
(8)程序可移植性好(与汇编语言比),基本上不做修改就能用于各种型号的计算机和各种操作系统。
C语言的基本结构—语法问题:C语言的词汇及其结构—词汇的书写顺序
2. C语言的词汇—数据类型、运算符与保留字
C语言的词汇主要有:数据类型、数组、结构体、操作符(运算符)、控制指令、内部函数(标准库函数)、用户自定义函数等
3. C语言的结构—语法
C语言的语句表达方式—词汇组合方式—(语言结构)主要有:表达式、控制结构(顺序、选择、循环)等,函数调用、复合语句(用{}标记的多个语句组合)、结构体、共用体、文件等
C语言的程序表述方式—程序结构主要是用函数。主函数中主要包含的是具有各自功能的函数的引用—调用等。当然,最简单的主函数自身也是一个普通函数。函数概念及其应用可以使得程序概念清晰、逻辑与层次分明、便于理解和交流、便于维护和扩充。
4. C语言的表述—处理对象的特点及其描述方式
a) 处理对象及其特点—数据格式
b) 控制语言与软件算法
计算机执行指令,通常是由程序指针PC按照程序的书写顺序逐行进行的。如果需要改变顺序,则通过调用指针PC的指向命令来进行。这些指向命令如:if……,for……,while……,等,通常称为控制语句。
在程序编写过程中,顺序执行是计算机程序语言的最简单、最基本、最常见的一种运行方式,C语言也是如此。对于简单的顺序执行控制,可直接用C语言符号系统编写在编译器的编译界面上。所谓的简单控制程序,一般是指程序的行数较少(语句较少),控制运行逻辑简单明了(这些都是针对人的大脑内存处理能力而言的,也就是每个语句及其执行的控制,可以在大脑中顺序执行,写过以后不需要再记住已经写过的语句)。
对于比较复杂的顺序控制,应该先用逻辑框架、伪码书写自然段的大意要求,再逐个填写“自然段”(一个阶段性的、相对完整的控制时段的指令集)的大意要求,最终填写具体详细的控制指令。
对于带有运行条件及其控制的指令集(程序组、软件),先用逻辑框架、伪码书写控制条件及其分支的要求,然后再写自然段的大意要求,再逐个填写“自然段”(一个阶段性的、相对完整的控制时段的指令集)的大意要求,最终填写每个自然段具体详细的顺序控制指令。
对于带有运行条件及其循环控制的指令集(程序组、软件),先用逻辑框架、伪码书写控制条件、循环要求及其循环终止、分支的要求框架,然后再写自然段的大意要求,尤其是循环及其终止(循环退出),再逐个填写“自然段”(一个阶段性的、相对完整的控制时段的指令集)的大意要求,最终填写每个自然段具体详细的顺序控制指令。
为了保证书写结果的正确,需要在程序编译器上进行编译验证,还要在硬件开发机上进行运行验证。当然,也可以在虚拟的软件开发产品上进行仿真运行验证。
为了通过多层验证,对于复杂、大型的控制软件,尤其是多重分支、循环等的指令集,可以先编写1~2两个分支与循环,验证无误,再逐步增加分支的复杂性、循环的多层性。避免一次调试错误与警告过多,影响开发效率、过多返工,工作心情等。经验丰富了,可以逐步根据自身的能力与条件减少不必要的环节,提高开发效率。
c) 描述框架—流程图与伪码
计算机程序除过用数据类型、算法和表达式(主要是运算符号)构成以外,还有必要的运算控制。控制的基本结构(底层结构)包括顺序结构、选择结构、循环结构,实现复杂功能的程序都是他们的各种组合。
a) 游戏 <wbr> <wbr> <wbr> <wbr> <wbr>51系列 <wbr> <wbr>c语言 <wbr> <wbr> <wbr> <wbr>proteus-keil顺序结构:顺序结构通常是用来解决那些按照步步紧连的次序可以进行计算的问题的,用计算的逻辑关系图,也就高级语言的流程图表达如图3-8所示。
b) 选择结构: 选择结构通常是用来解决那些按照某些条件来决定执行那个运算问题的。指令的运行次序由IF……THEN……或者IF……ELSE……来控制进行问题计算的,用计算的逻辑关系图,也就是计算机高级语言的流程图表达如图3-9所示。其执行的顺序是,先计算表达式得值,若表达式的值为真,执行语句1表示的指令,否则执行语句2表达的指令。
c) 游戏 <wbr> <wbr> <wbr> <wbr> <wbr>51系列 <wbr> <wbr>c语言 <wbr> <wbr> <wbr> <wbr>proteus-keil循环结构: 循环结构通常是用来解决那些需要累加重复的计算问题的,用计算的逻辑关系图,也就是计算机高级语言的流程图表达如图3-10所示,其执行的顺序是,先判断循环控制条件(表达式的值),若表达式的值为真,执行循环体表示的指令,否则执行语句2表达的指令。还有一种形式的执行的顺序是,先执行循环体表示的指令(语句),后判断循环控制条件表达式的值,若表达式的值为真,继续执行循环体表示的指令,表达式的值为假,则结束循环体。
计算机的应用就是将现实问题通过各种描述和变换,用计算机高级语言“书写”,并实际运行计算机的各种动作来实现工作。
计算机软件的基本结构,是在计算机程序结构的基础上发展演变而来的。计算机软件架构与其需求的内容、规模、功能及复杂性(人可理解的层次性、概念的大小层级等)等密切相关。为了在人的大脑可理解的前提下,将实际问题转换成计算机语言可表征的形式,需要在实际问题与计算机语言之间添加适当层级的软件模型。这些模型主要是表征计算机信息处理单元之间的逻辑关联与数据、控制关系等。
d) 语句选择
5. C语言的程序示例—故事内容与形式—想说什么?
l 例-1 信息输出—单函数(主函数也是普通函数)
#include
void main( )
{
printf ("This is a C program.\n");
}
说明: main-主函数名, void-函数类型
• 每个C程序必须有一个主函数main
• { }是函数开始和结束的标志,不可省
• 每个C语句以分号 ; 结束
• 使用标准库函数时应在程序开头一行写: #include ,称为头文件,该头文件中包含着用户需要的标准库函数。stdio.h中包含着输出函数:printf ();输入函数scanf()等。
• 表示注释。注释只是给程序编写与阅读人员看,对编译和运行不起作用,既机器不运行该信息。所以可以用汉字或英文字符表示,可以出现在一行中的最右侧,也可以单独成为一行。还可以用//表示。
• 这是一个C语言的基本格式。也是一个结构化程序设计的基本形式之一—顺序结构。
•标准库函数常用的有:
l 例-2 求两数之和—单函数(主函数也是普通函数)—故事内容与形式—想说什么?
#include
void main( )
{
int a,b,sum;
a=123; b=456; sum=a+b;
printf(″sum is %d\n″,sum);
}
l 例-3 输出3个数中较大者
—多函数(主函数引用—调用普通函数—自定义函数)(判断与选择)—故事内容与形式—想说什么?
#include
void main( ) 求3个数中较大者
{
int max(int x,int y);
int a, b, c;
scanf(″%d,%d″,&a,&b);
c=max(a,b);
printf(″max=%d\\n″,c);
}
int max(int x, int y)
{
int z;
if (x>y) z=x; /*判断与选择—结构化程序设计之分支结构
else z=y;
return (z); /*被调用的函数max用return语句将z的值返回给主调函数max
}
程序说明:
l C程序总是从main函数开始执行的,与main函数的位置无关。
l C程序书写格式自由,一行内可以写几个语句, 一个语句可以分写在多行上,C程序没有行号。
l 每个语句和数据声明的最后必须有一个分号。
l C语言本身没有输入输出语句。输入和输出的操作是由标准库函数scanf和printf等函数来完成的。使用方法是调用。C对输入输出实行“函数化”。
l 例-4 将16进制数FF赋51单片机的P1口,字节传送数据—信息
#include //预处理指令,将头文件reg51.h转换为与C语言一致的格式
void main( ) //主函数
{ //函数体开始
P1= 0xFF; //赋值语句,函数体内容 - 将16进制数FF赋P1口
} //函数体结束
l 例-5 延时函数—子程序(自定义函数—常用函数)
#include
#define uchar unsigned char //定义了DelayMS等
#define uint unsigned int //定义了x,i等
void DelayMS(uint x) //延时函数 — 非主函数,用户定义的函数,可被调用
{
while(x--) ; //条件循环语句,C语言的保留字,x每循环一次,自动减1,直至x为0,终止循环
}
void main()//主函数
{
P1=0x00; //将16进制数00H赋给P1口,字节传送,语句
DelayMS(200); //调延时函数,并传递数值x=200,语句
P1=0xff; //将16进制数FF赋给P1口,字节传送,语句
DelayMS(200); //调延时函数,并传递数值x=200,语句
}
l 例-6 扫描函数—子程序—用户定义的函数—判断与选择(逻辑运算)—条件
uchar Keys_Scan() //键盘扫描函数
{
uchar sCode,kCode,i,k;
P1=0xf0; //高4位置1,低4 位置0,令P1口状态为1111 0000B,有键按下,两位导通,则会出现高位0
文本框: //键值判断函数 bit pkey(void) { P1=0xf0; if(P1!=0xf0) { Delayt(25); if(P1!=0xf0) return 1; else return 0; } else return 0; } if((P1&0xf0)!=0xf0) //用位逻辑运算中的与&运算(遇0则0),确认高4位是否有0,有键按下,成立执行return(-1);
{ //不等的条件成立,则执行一下语句
DelayMS(2);//延时函数调用,防抖动
if((P1&0xf0)!=0xf0)//再判断有键按下否,成立执行return(-1);
{//不等的条件成立,则执行一下语句
sCode=0xfe; //行扫描码初值1111 1110B
for(k=0;k<4;k++) //对4 行分别进行扫描
{
P1=sCode; //行扫描码初值赋给P1口=1111 1110B
if((P1&0xf0)!=0xf0)//再判断1110 1110B
{//不等的条件成立,则执行一下语句,否则else
kCode=~P1;//取反后赋给列码0001 0001B—即0x11
for(i=0;i<16;i++) //查表得到按键序号并返回,i=16则再判断
if(kCode==KeyCodeTable) //扫描出16种状态
return(i); //按照列码对照表return(i),返回for(i=0;i<16;i++)
}
else
sCode=_crol_(sCode,1);//51库函数,行码左移1位补1,如:1111 1110B成为1111 1101B
}//移位以后,去执行for(k=0;k<4;k++) 行码右移1位补1,_cror_(sCode,1);
}
}
return(-1);//函数调用结尾,返回函数运行结束后的入口处。
}
程序说明:
在后续的逐级实践过程中,通过实例实践及其程序注解与程序说明,介绍C语言的基本概念、数据类型、算符及其约定、语句语法、函数构成、程序构成等。
这是一个常用程序段—子程序—标准程序—自定义函数,通过端口扫描而获得输入数据或控制输出数据,达到节省位或字节的目的—节约硬件资源。
关于扫描,可以从位及其取反实现流水灯着手来理解。可以通过移位实现流水灯—扫描。可以通过字节数据(01H,02H,04H,08H,10H,20H,40H,80H)的端口发送实现流水灯—扫描。可以通过数据表(DB 01H,02H,04H,08H,10H,20H,40H,80H)实现流水灯—扫描。可以通过循环跳转实现流水灯—扫描。
数学中的逻辑运算被用来处理判断与选择—条件控制(按照某个限制条件来执行动作)。主要有两种:
第一种:if语句,用来做两分支选择
主要有 ® if(表达式) 语句;
® if(表达式) 语句1; else 语句2;
® if(表达式1) 语句1; else if(表达式2) 语句2; else if(表达式) 语句3;else if(表达式4) 语句4;……; else 语句n;
第二种:switch语句,用来做多分支选择
® switch(表达式)
{
case 常量表达式1:语句1; case 常量表达式2:语句2; case 常量表达式3:语句3;……;default:语句n+1;
|