|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
/ S& b; b9 t6 g/ f7 y第六讲 实验5-实验8! q8 z: A! Q- w3 c7 E( N
知识点:
+ N$ z+ K) O4 C* h% L9 k1、 学会画程序流程图
) a H% w1 x9 G" o' M' ^7 I0 ~) c4 V2、 流程控制语句 if(){}else{}用法 Y; Y$ \ i" g7 l% k( B& {+ Z, r, i
3、 操作符 ”~ ”、“!”、“&&”含义3 {' @7 y/ n g
4、 带参函数1 k0 ]* y% A a% Z. m
5、 函数调用9 M- [# c/ R9 q9 r
6、 理解宏定义 #define “替换”作用
. m8 o$ |+ f4 b; @7、 循环语句 for 的用法
. [4 z6 O# [( R8、 库函数 unsigned char_cror_ (unsigned char, unsigned char);: A# y) o% F5 ]7 Y( F3 s/ C7 F& |
unsigned char _crol_ (unsignedchar, unsigned char);含义3 s, L H" m1 m5 u- V' U4 ?# ~$ @
9、 C51 扩展类型 code含义" n% a) U6 b" J) y
10、 流程控制语句:switchcase 用法
6 m' r: u$ J2 Y: M1 N11、 数组定义、引用方式: g" u) P/ P k, s% r, [9 O3 }
12、 延时函数
5 P& v" {% p' H6 `4 F" W0 @, |
1 f7 e' f& S6 ?9 O一、51单片机软件延时:
* U* d0 `- Q3 M- ?- w1 D0 p1、 几种周期介绍
% B% j8 @; ]6 G- a ~( l 周期名称, t4 w7 \. m* P4 n4 Q0 ~& `8 G4 e
| 描述7 _' j( Z9 g9 _4 l( `( F* b% u# a
| 时间 e9 o7 H" d" o, F3 A& P* P
| 振荡& a/ k( o& [0 ^: _5 b: H
| 单片机提供时钟脉冲信号
5 l3 b1 z+ N( i1 f 的振荡源的周期
( s6 c* n1 V5 V) C5 Y | T=1/f4 |) ^" [6 G5 a7 W& m! T
| 状态# m5 _- b! I, f( ^+ {( v2 j5 T
| 振荡周期经二分频后得到) k5 V. x0 t$ D1 w( ]
的6 F9 V/ j% v/ a# w, b% I
| 2T
9 W7 X. }5 _$ n5 k' \7 d | 机器4 R5 S( S8 f1 f5 u2 y5 h0 V8 U
| CPU 可以完成一个独立操
% w" x( D: i a8 s7 J 作所需要的周期) e( T+ ?& u- k) f5 f) h4 F
| 12T
, c" m/ k0 N2 ~% w9 j | 指令/ P4 S% F* A) W( T
| 指 CPU 完成一条操作所需2 f9 c, K. t$ ?' P6 \
的全部时间/ r! H; `2 N, u9 P: I4 q1 V; }
| n*12T
* F( _3 ]' R6 |+ G | 2、指令:& a) f6 u0 B( j8 S
1、MUL、DIV:仅有的 4 周期指令
" O; F* e0 a1 f7 x, J2、包含 DPTR 和 PC 的指令均为 2 周期指令
7 x( R( d W3 |! z3 {( y1 `3 q3、所有的绝对跳转和条件转移指令,均为 2 周期指令; y. F- }5 J2 c0 t* [- x
4、所有包括 A 寄存器的指令,均为单周期指令8 J5 l6 H& |; Z, L" M
5、位操作指令中,ANL 和 ORL 是 2 周期指令% I' ~: F6 i7 T% r6 s7 r: R: S& S
6、所有包含立即地址的指令,除 INC direct 及 DEC direct 外,均为 2 周期指令
7 I) {/ U. E! X ^) `; ]7、剩下的均为单周期指令。如:
7 E: J) c% J* r& z2 Bvoiddelay(uint z)) D3 {1 o& {2 j/ J& s& T: x7 K5 T8 L
{
. R- T2 M+ A! `1 |uinti ,j;6 H: J1 v0 H4 v6 E5 S' u
for(i = z; i> 0;i--)
; d/ S+ B Q5 B- ^9 ?7 W/ s8 [7 \& Y3 g
7 y+ \0 X# ~. Z) p3 ~+ `
for(j =0; j < 921; j++)
. @8 T" L! x" i* c' ~/ A}
]; w" V* A2 @& @2 S
0 }; |9 U4 f1 ~6 d
! T% y, \" {9 @6 L6 V分析:
7 p/ ?9 v! X% d' ]/ T( ]1.先计算你单片机的振荡(时钟)周期 T=1/晶振(11.0592MHZ)
2 V# ~- k7 \; z3 H. K2.一次 i--操作为 12T
. i# ^$ q) u" O! o; P" U p3.忽略变量定义,上述延时函数共需时间:921*z*12T
* I% V" d* p' F7 \6 @3 W, R' y4.带入 T:921*12*T*z 约为 z us
) y; M* s' j6 ]. }" \" @3、计算误差出现的原因:
; f2 j$ R7 |2 S0 ~/ X# j% G1.软件仿真时,函数调用的时候入栈出栈操作的耗时。2 _- G/ E, D- l2 t% s& N
2.指令周期随指令的不同而不同导致的误差。
# X3 C8 B0 W; ~( E: @# p3.中断的影响。$ x2 I. O# B5 A- v% j; u
4.变量的范围超过,从而与预计时间不一样。6 ?7 r+ B, l, }8 P
/ |3 S* N5 r4 t* v3 b' ]1 z3 p* U( V2 \5 H3 ^
while(i--):如果 i 为 char 型,执行一次大概为 5us 左右;如果 i 为 int 型则执行一次大概为 10us 左右。注意:软件延时通常用于时序要求较高的编程中,其它需延时较长的地方必须采用单片机内部定时器。
( Y& i9 ?$ |) g' s/ c+ z+ S7 K+ E. K7 B/ U: c' f; [
二、#define与 typedef 区别
- [* c% g8 p/ O( U1、typedef 的用法1 u$ W, _5 j+ A8 @' \
0 \4 \) V9 W }9 x
在 C 语言中,typedef 常用来定义一个标识符及关键字的别名,它是语言编译过程的一部分, 但它并不实际分配内存空间,1 y- T+ ~" Z: a
如:typedef int INT;7 g4 M' ? _* p: `# W2 `! _
/ q* k. ]) K% l1 e: |4 c3 }3 ^& w2、#define 的用法8 l. V: R1 X3 ^ E- C& P1 ` G v* |% P
#define 为一宏定义语句,通常用它来定义常量(包括无参量与带参量),以及用来实现那些 “表面似和善、背后一长串”的宏,它本身并不在编译过程中进行,而是在这之前(预处理过程)就已经完成了,但也因此难以发现潜在的错误及其它代码维护问题,如:5 A7 ~" l% ^. @+ ~, w, N
- t( Z: v# V1 x* W3 L& o
#define INT int3 L% B" X1 Q& X6 ^5 L1 Y& ?# y. ~' ]1 U, h
#define TRUE 1- e2 _' u! k9 _# Q- S X! `+ ]
#define Add(a,b) ((a)+(b));* s6 U2 [8 t0 D, F- E# i
#define Loop_10 for (inti=0; i<10; i++)
. v0 I ]2 H. I1 C% _1 ~7 Y. p; L- a @3 D5 X! ^- n4 Q4 Y
3、typedef 与#define 的区别
z- O4 H' D& \8 `3 h从以上的概念便也能基本清楚,typedef 只是为了增加可读性而为标识符另起的新名称(仅仅只是个别名),而#define原本在 C 中是为了定义常量,到了 C++,const、enum、 inline 的出现使它也渐渐成为了起别名的工具。有时很容易搞不清楚与 typedef 两者到 底该用哪个好,如#define INT int 这样的语句,用 typedef 一样可以完成,用哪个好 呢?我主张用 typedef,因为在早期的许多 C 编译器中这条语句是非法的,只是现今的 编译器又做了扩充。
% b7 M8 d& i+ z3 o) P1 K% @; J% P+ P! y4 x9 ]
为了尽可能地兼容,一般都遵循#define 定义“可读”的常量以及一些宏语句的任务, 而 typedef 则常用来定义关键字、冗长的类型的别名。
+ ]0 g! E. \6 O$ M; u5 @7 v; d7 x2 Y/ u5 y7 E' W
宏定义只是简单的字符串代换(原地扩展),而 typedef 则不是原地扩展,它的新名字具 有一定的封装性,以致于新命名的标识符具有更易定义变量的功能。请看上面第一大点 代码的第三行:typedef (int*) pINT;以及下面这行:#define pINT2 int*效果相同?实则不同!实践中见差别:pINT a,b;的效果同 int *a;int *b;表示定 义了两个整型指针变量。而 pINT2 a,b;的效果同 int*a, b;表示定义了一个整型指针 变量 a 和整型变量 b。' y. o6 f7 H5 I' I; h9 b
( V& g/ h, U& w( K x& Q- B" E" Atypedef 的四个用途和两个陷阱" a& r: ?2 S& @3 I! j" b" A1 B
用途一: 定义一种类型的别名,而不只是简单的宏替换 ]6 y' E9 a' k4 ^" [
用途二: 用在旧的 C 代码中(具体多旧没有查),帮助 struct。- i8 c* W% J9 X8 d
+ @# m0 K1 o; u2 P7 C6 ^
typedef struct tagPOINT& X, E6 T# |$ f; l, i0 b) {' h$ d9 |
{: k2 {: o1 f) F2 C# N9 h2 Z
int x;$ U8 X" u% Z$ V# J8 `- |
int y;
$ ?4 u3 S e+ n2 z! Y) x}POINT;/ G, y1 U3 t# D
$ Y& Y' a3 q& a. E6 P! L+ w4 \
POINT p1; // 这样就比原来的方式少写了一个 struct,比较省事,尤其在大量 使用的时候 或许,在 C++中,typedef 的这种用途二不是很大,但是理解了它,对掌握 以前的旧代码还是有帮助的,毕竟我们在项目中有可能会遇到较早些年代遗留下来的代 码。
; I, @ ]9 s. c) i3 |+ j2 Y* _
6 M1 u2 h# m4 n" X5 g' }3 f0 ?- @% a+ p用途三: 用 typedef 来定义与平台无关的类型。用途四:为复杂的声明定义一个新的简单的别名。
, g5 |5 i) ?6 e0 }+ v0 w* |0 ~5 r" X
陷阱一: 记住,typedef 是定义了一种类型的新别名,不同于宏,它不是简单的字符串替换。字符串替换就行。
6 i6 Z2 B4 P# d/ @- P
& o9 z7 }+ H4 V7 O0 D* {6 X g B+ P9 [5 I
陷阱二: typedef 在语法上是一个存储类的关键字(如 auto、extern、mutable、static、 register 等一样),虽然它并不真正影响对象的存储特性,如: typedef static intINT2; //不可行 编译将失败,会提示“指定了一个以上的存储类”。7 f6 g0 i3 B" X/ R
~5 Z* C/ c _, a! r
: Q! Y, A+ ^3 q, v7 C2 b+ Q三、按键:
% `$ n4 ^5 T1 ?8 n" n按键是单片机系统中最常用的器件。各种仪器仪表、家用电器操作面板上都离不开按键,是最基本的输入部件。因此,掌握按键输入电路设计、按键驱动程序设计是十分必要的。按键的分类:从单片机获取按键信号类型的角度来讲,可以分为模拟按键和数字按键;从按键与单片机IO 端口对应关系上来讲,可以分为独立按键和矩阵式按键。独立按键很简单,就是一个按键对应一个 IO 端口;而矩阵式按键则相对复杂一些,通过行与列的交叉组合成 i 行*j 列个 按键。0 s1 G) e0 V& l9 m- F: P
0 p5 D$ |3 p! B) R按键的有效方式:
) x: A$ x9 H! N% j5 i5 C/ E按下有效、按下松开(抬起)有效、长按 n 秒有效、连按 n 次有效、组合按键有效等。按键驱动程序设计步骤:' W8 z: U2 t ?$ ]; ?
读取键值—按键消抖—键值处理
- p8 t6 X: R: q5 m& M; C. k
8 p! H, F$ k% v, W* N0 x& T
4 E3 @7 E2 A4 i四、cror 与 crol 的区别# e5 ?- |0 @4 K! ~. t3 M8 `. }- [
循环右移与循环左移 |
|