|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
; @" a _: R0 p第六讲 实验5-实验8
% g9 t+ F1 B, S) b: F1 k; d知识点:) T+ {# }% f- i2 _0 z* y0 q+ [. v7 v
1、 学会画程序流程图4 R9 e, c( `4 f3 v# Z, T3 u
2、 流程控制语句 if(){}else{}用法3 ~8 ~7 R2 m9 r: R& x# K$ l( {
3、 操作符 ”~ ”、“!”、“&&”含义& x: W; z/ k% }/ b5 q. x$ s X& T+ q
4、 带参函数 n' ]8 u( t% o) y
5、 函数调用" e& q" h& F2 r
6、 理解宏定义 #define “替换”作用
( e8 p& d) T) q& ~$ D2 B7、 循环语句 for 的用法0 k z f2 y$ v: O
8、 库函数 unsigned char_cror_ (unsigned char, unsigned char);" |& R, ]& y3 }8 T; C P# U
unsigned char _crol_ (unsignedchar, unsigned char);含义
$ {5 P1 o7 z8 X1 j9、 C51 扩展类型 code含义
6 ^) g( ?/ G5 A2 k i$ d10、 流程控制语句:switchcase 用法% N) S* w( |+ z( u6 G( [) T1 O
11、 数组定义、引用方式 j* U9 N. T* k: c
12、 延时函数
$ i$ t5 M8 g& S) T' ?# D1 t4 p5 O5 _5 V* D/ e N
一、51单片机软件延时:
. j; R+ ~9 w1 X1 p1 Y# e0 w0 O1、 几种周期介绍$ s% `1 t. c* h6 S
周期名称
/ C: `% _2 r* G/ v/ k ^8 g | 描述2 y0 V" P: \- z ^7 r
| 时间
, G) n- }( \- T. Q& F0 Z* \8 i | 振荡
k% J# |: r- K, b | 单片机提供时钟脉冲信号
: c8 R* n ?: v) X/ O d 的振荡源的周期
+ h- g$ C1 T4 W$ C! z. W9 e5 T | T=1/f
- r' u$ h! k0 O1 B5 L | 状态
8 C( l6 q9 e. w2 v! r$ ? | 振荡周期经二分频后得到
) L, Z+ E: ~; S; _: _ i+ M+ J 的
/ g. N# u: c% f3 v$ U+ ~3 Q | 2T- X6 W9 E% D' j2 h- s9 r! ], _0 |
| 机器
( X) V* S( ]7 E7 U( u | CPU 可以完成一个独立操7 q* ?9 ]/ p$ q5 c0 R: A6 e( f
作所需要的周期
4 F+ }- {1 g/ J/ W0 D% y/ F! @8 P | 12T
3 U' A' c+ F2 H! q0 P5 _ | 指令
9 q: V; M3 d# ?' J# ?7 c, `' @2 L | 指 CPU 完成一条操作所需
3 q" `& j2 z! A/ B4 e0 {: j 的全部时间* @0 e" p0 }5 I% L; w
| n*12T8 i7 L9 W% H: |# D% |3 w
| 2、指令:
$ y# u: J1 K* ~% _* ^6 L1、MUL、DIV:仅有的 4 周期指令
) E: B8 f W! z, d* |! Q8 m2、包含 DPTR 和 PC 的指令均为 2 周期指令# `8 Z" t6 n0 q9 ?3 M
3、所有的绝对跳转和条件转移指令,均为 2 周期指令
9 s# _* C( h* f8 _: J% P4、所有包括 A 寄存器的指令,均为单周期指令9 T! L, e2 J% b
5、位操作指令中,ANL 和 ORL 是 2 周期指令$ X+ z7 S+ C# h3 p: V8 L
6、所有包含立即地址的指令,除 INC direct 及 DEC direct 外,均为 2 周期指令
5 B) b0 n# } H/ V$ t0 g' B7、剩下的均为单周期指令。如:
+ E. L; h9 ~1 q5 M" ?0 w* Ovoiddelay(uint z)+ K5 G/ O% z" b
{/ p* \" d% @: g" J# @0 A& }) G4 O
uinti ,j;. F5 H6 P% z9 ?9 I8 V- y5 U
for(i = z; i> 0;i--)/ C' m7 l( y5 |4 C0 z
4 Q( d" L( y$ B+ J: r
! M8 |* ?: _# U/ C; U
for(j =0; j < 921; j++)
; H" l( D2 p* H6 @) Z- }}
; P6 D+ C$ r8 G5 x, ?) Z \; I' J g
( q( F/ w1 T* [* x1 O- C+ _% D9 z! T" t
分析: ]+ C, e; W# S
1.先计算你单片机的振荡(时钟)周期 T=1/晶振(11.0592MHZ)
5 j, o v1 B' T& X$ `2.一次 i--操作为 12T. U; W" D$ `5 j2 u1 `. e% }" x
3.忽略变量定义,上述延时函数共需时间:921*z*12T7 u m0 F% }9 O& F
4.带入 T:921*12*T*z 约为 z us; o1 F" d, Q" H2 x4 Z" g6 T1 U
3、计算误差出现的原因:6 Y1 _% i" }( X" _$ C5 u
1.软件仿真时,函数调用的时候入栈出栈操作的耗时。
8 Q& W% N5 ^' Z# ^. s* f$ G8 E$ d* r2.指令周期随指令的不同而不同导致的误差。0 w4 Q0 n' t, A! n5 b$ H+ c6 \
3.中断的影响。 U! p( O( ?. v7 a0 { n
4.变量的范围超过,从而与预计时间不一样。
. H7 d' v% n" I( M! A l3 C" h- ~( b& I- S1 W: n% O
4 W: _2 _ J6 c' I$ U- Bwhile(i--):如果 i 为 char 型,执行一次大概为 5us 左右;如果 i 为 int 型则执行一次大概为 10us 左右。注意:软件延时通常用于时序要求较高的编程中,其它需延时较长的地方必须采用单片机内部定时器。2 H" V6 G# p8 I, `% `
9 T b- o: J4 ]; ?二、#define与 typedef 区别3 ?% B( w. ^& b% k
1、typedef 的用法8 q0 q6 O* `' t. E2 t
; w, H8 a& M1 o" H$ ~在 C 语言中,typedef 常用来定义一个标识符及关键字的别名,它是语言编译过程的一部分, 但它并不实际分配内存空间,+ n: V8 B( ^9 } d8 O
如:typedef int INT;' h% G* F @2 Y
8 [* z) Z' H' [& u
2、#define 的用法 _0 L& Y, E @0 l: _
#define 为一宏定义语句,通常用它来定义常量(包括无参量与带参量),以及用来实现那些 “表面似和善、背后一长串”的宏,它本身并不在编译过程中进行,而是在这之前(预处理过程)就已经完成了,但也因此难以发现潜在的错误及其它代码维护问题,如:
: ?" L+ u9 R! T* w$ B6 J9 a& r+ N% \/ ~' z/ G I
#define INT int
) m; j. m! K! S7 t#define TRUE 1
1 z* d r( [, s0 O: |#define Add(a,b) ((a)+(b));
: A9 j; @5 Z y+ @' F3 y#define Loop_10 for (inti=0; i<10; i++)
, e! Z# u2 @: g7 `4 r# A' f. P1 g- b/ Z5 e: g- T/ ?/ k* p: O7 e
3、typedef 与#define 的区别
! N: r/ ?) ]8 T( U: {从以上的概念便也能基本清楚,typedef 只是为了增加可读性而为标识符另起的新名称(仅仅只是个别名),而#define原本在 C 中是为了定义常量,到了 C++,const、enum、 inline 的出现使它也渐渐成为了起别名的工具。有时很容易搞不清楚与 typedef 两者到 底该用哪个好,如#define INT int 这样的语句,用 typedef 一样可以完成,用哪个好 呢?我主张用 typedef,因为在早期的许多 C 编译器中这条语句是非法的,只是现今的 编译器又做了扩充。3 f; u1 O/ H+ O' Z
3 S- `4 A2 \2 _" U" c
为了尽可能地兼容,一般都遵循#define 定义“可读”的常量以及一些宏语句的任务, 而 typedef 则常用来定义关键字、冗长的类型的别名。' D) ?1 k0 r) C
& n0 `1 ]$ {5 z$ k* H6 u* J% N
宏定义只是简单的字符串代换(原地扩展),而 typedef 则不是原地扩展,它的新名字具 有一定的封装性,以致于新命名的标识符具有更易定义变量的功能。请看上面第一大点 代码的第三行:typedef (int*) pINT;以及下面这行:#define pINT2 int*效果相同?实则不同!实践中见差别:pINT a,b;的效果同 int *a;int *b;表示定 义了两个整型指针变量。而 pINT2 a,b;的效果同 int*a, b;表示定义了一个整型指针 变量 a 和整型变量 b。
8 D. i( B9 r9 q" n) O8 L% M& B" ] Y4 U, R8 U. N( K; g) t, z# s
typedef 的四个用途和两个陷阱) N. \( c3 W: Z( Z0 S+ v
用途一: 定义一种类型的别名,而不只是简单的宏替换
& q. m1 @3 Z7 `+ l用途二: 用在旧的 C 代码中(具体多旧没有查),帮助 struct。. C. b+ W& t8 k0 ]
1 \7 y$ v3 Y; N8 U
typedef struct tagPOINT
) }. |! l& N. k4 j{$ A# _4 ~8 |, I9 t$ `2 \% _
int x;% K. s; S; K7 `7 ?
int y;
J& w: M; N9 q! l5 x}POINT;. c& s4 L0 f8 I' c. X
/ S& @5 d8 `7 @5 c, h) b2 V+ ]5 w0 gPOINT p1; // 这样就比原来的方式少写了一个 struct,比较省事,尤其在大量 使用的时候 或许,在 C++中,typedef 的这种用途二不是很大,但是理解了它,对掌握 以前的旧代码还是有帮助的,毕竟我们在项目中有可能会遇到较早些年代遗留下来的代 码。
6 Z; z: m' ^1 g. \3 s- I; Q4 ^2 A9 V# R& G1 Z
用途三: 用 typedef 来定义与平台无关的类型。用途四:为复杂的声明定义一个新的简单的别名。
2 _( [7 t4 i7 p2 i
# t" ^) ~/ a" M" [$ h陷阱一: 记住,typedef 是定义了一种类型的新别名,不同于宏,它不是简单的字符串替换。字符串替换就行。3 s6 n0 i) W A, e3 j9 C
8 P/ ~/ s4 b& K6 A! e+ s1 E! B
h; M4 r& q$ q$ w陷阱二: typedef 在语法上是一个存储类的关键字(如 auto、extern、mutable、static、 register 等一样),虽然它并不真正影响对象的存储特性,如: typedef static intINT2; //不可行 编译将失败,会提示“指定了一个以上的存储类”。
$ B* |$ o. S4 X- {" E
; X$ \. |: p( v o: o. z% b# e/ Q, ?+ G5 o2 V( u
三、按键:
& T" t! P$ z- M' i6 ^按键是单片机系统中最常用的器件。各种仪器仪表、家用电器操作面板上都离不开按键,是最基本的输入部件。因此,掌握按键输入电路设计、按键驱动程序设计是十分必要的。按键的分类:从单片机获取按键信号类型的角度来讲,可以分为模拟按键和数字按键;从按键与单片机IO 端口对应关系上来讲,可以分为独立按键和矩阵式按键。独立按键很简单,就是一个按键对应一个 IO 端口;而矩阵式按键则相对复杂一些,通过行与列的交叉组合成 i 行*j 列个 按键。
+ F8 ~* F; L" K) h4 a# U) v) w/ o8 B- l$ ~' d
按键的有效方式:/ Y0 t6 w, `( C
按下有效、按下松开(抬起)有效、长按 n 秒有效、连按 n 次有效、组合按键有效等。按键驱动程序设计步骤:; U0 V! B$ f. E" J a
读取键值—按键消抖—键值处理
. \" `% H4 _, H9 K
5 ^) T5 T( r3 ]! B9 t; {3 I- c' I' l% \
四、cror 与 crol 的区别
- C/ w0 _) d# Q G$ B循环右移与循环左移 |
|