|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
% H3 q4 U, t9 l" o! s( c1 }" n: i5 K- {第六讲 实验5-实验8
I3 z/ Z. Z0 g: L5 B7 J8 c知识点:
, C% R6 J1 K7 ]7 s* n1、 学会画程序流程图
3 M0 P2 u: \- b% T: O6 I. v9 a" f7 `2、 流程控制语句 if(){}else{}用法
, O P. `' t+ `5 Y3、 操作符 ”~ ”、“!”、“&&”含义
" J- O" c, ~2 l7 \ T# b+ o! a: g4、 带参函数$ Y- U+ C% s" e$ b
5、 函数调用* W0 `, f, Q! S! {
6、 理解宏定义 #define “替换”作用
1 m0 c) M: K8 W1 K8 o4 t7、 循环语句 for 的用法
' {6 Q, F E; U9 ^, ~2 {* M H Q8、 库函数 unsigned char_cror_ (unsigned char, unsigned char);8 L1 k' |: H, N: @# H
unsigned char _crol_ (unsignedchar, unsigned char);含义* x( K3 |4 H6 X' g0 D) g( D( o
9、 C51 扩展类型 code含义: V, s2 ]3 z, w; T: z4 t) _# C
10、 流程控制语句:switchcase 用法6 B3 F y C+ N
11、 数组定义、引用方式0 b( Q/ w3 x$ w h. ?+ a# I) c
12、 延时函数+ a1 r% \8 F5 u: Z; f
5 X9 h2 |- n: z/ j0 u一、51单片机软件延时:
7 u) I6 H/ F) U! F' `! s6 o1、 几种周期介绍
6 ]# p# U( b* `! E: e; D 周期名称
) @, Y* c$ y6 d% ?! x7 w! ^' @0 M6 Z# A( ? | 描述3 R, n1 W8 E; L* h: }
| 时间: r0 U4 S p* h" P9 I! @! r& ~
| 振荡: l1 \2 l6 N+ q3 G
| 单片机提供时钟脉冲信号3 A- R- h7 C' z% u
的振荡源的周期7 M* m$ g5 I/ G/ \
| T=1/f ~- q3 s0 }( k; G, e8 e8 ~
| 状态! n* L3 _7 I8 S3 \5 m5 c |" ]
| 振荡周期经二分频后得到1 o8 M) {# G, y$ T* t1 \/ G/ `7 B
的4 j( x8 Z: R! v" P
| 2T
6 t5 g. G3 N9 B1 i: n | 机器
2 a, J% Y1 Z6 H1 x6 O | CPU 可以完成一个独立操
: \# S' ?: A" R1 ?: G: ~: O* n 作所需要的周期: e) o. u; l: P5 H& }# d' V
| 12T
. n: m) t! O& \7 Y# g- ^ | 指令, P4 Q3 T/ N3 @* T" L
| 指 CPU 完成一条操作所需
* {2 t j! n( M' ~1 i( E" O 的全部时间6 g2 `5 S$ H, h$ X j
| n*12T! J) W" r1 [) h L8 }6 G! |0 M2 l
| 2、指令:
. p! h0 {" }& g! B0 r" o1、MUL、DIV:仅有的 4 周期指令( X6 j: L" f/ r; k- w
2、包含 DPTR 和 PC 的指令均为 2 周期指令& g% w* X1 v1 l& C0 v
3、所有的绝对跳转和条件转移指令,均为 2 周期指令
# O) N! X9 V! M! e' f; M% U4、所有包括 A 寄存器的指令,均为单周期指令
% q3 d3 q: G/ |, e. v5、位操作指令中,ANL 和 ORL 是 2 周期指令. @" r+ i& l0 E' M% j1 J
6、所有包含立即地址的指令,除 INC direct 及 DEC direct 外,均为 2 周期指令8 g# J& j9 i& M& x
7、剩下的均为单周期指令。如:
1 k4 b0 c9 D. ^! V) q/ jvoiddelay(uint z)+ p" J3 s# Z3 b
{+ y/ j1 N" ]9 x4 @/ [
uinti ,j;; a1 Q: O0 w8 l& D6 M. j/ @
for(i = z; i> 0;i--)6 I- R& k! p3 q; j5 H
8 ?: T) s8 _8 t/ }; m
: A& T, F% u' s* H
for(j =0; j < 921; j++)3 f7 `- }# [+ F5 r2 W4 y
}
$ I) ~; [" g2 H z. y7 N! k7 E2 L4 G9 c0 A
: Z$ s! A' G0 A' R2 R' |% m
分析:, ?. x. i9 n' d; t9 I- {; s/ ?; w
1.先计算你单片机的振荡(时钟)周期 T=1/晶振(11.0592MHZ)0 W- B( {6 b$ A! W8 J
2.一次 i--操作为 12T [! u J4 i4 Z! B
3.忽略变量定义,上述延时函数共需时间:921*z*12T) F# K9 D) d: i4 W
4.带入 T:921*12*T*z 约为 z us! r5 V) f% P5 `; Z; f+ c0 ?
3、计算误差出现的原因:
0 |6 t7 E7 `$ O0 S" Z+ w1.软件仿真时,函数调用的时候入栈出栈操作的耗时。, @) b: M+ e r5 ^9 Z9 W% Y/ O
2.指令周期随指令的不同而不同导致的误差。
* O, T( S# k# C4 Z2 x! T- B7 c( T* }3.中断的影响。
3 n! e: @+ H' Z" e: J% p: c, `) d4.变量的范围超过,从而与预计时间不一样。# Z( H: c; K' n9 ~
0 V/ z7 U* R0 C6 u: X9 @, o0 T. r5 H3 \! S; y
while(i--):如果 i 为 char 型,执行一次大概为 5us 左右;如果 i 为 int 型则执行一次大概为 10us 左右。注意:软件延时通常用于时序要求较高的编程中,其它需延时较长的地方必须采用单片机内部定时器。9 W$ N+ Z; P- }" F, y4 Q! w& I
- I# U7 Y4 l7 \" ]% C6 g# D二、#define与 typedef 区别, I) Q8 D+ V. F- R2 g
1、typedef 的用法- ^6 h$ Q& D/ I+ v \/ ]8 h
2 t+ ?3 Q" ~; x) g$ S8 |4 g" L
在 C 语言中,typedef 常用来定义一个标识符及关键字的别名,它是语言编译过程的一部分, 但它并不实际分配内存空间,, r7 t9 p4 V2 H( m$ V' A
如:typedef int INT;
; q( C; |+ t7 o1 a, L! w
0 y2 a8 C0 g; R+ t" ?: {1 L' X, n( o2、#define 的用法+ @, k8 t% h0 _& G& f9 I# E) j
#define 为一宏定义语句,通常用它来定义常量(包括无参量与带参量),以及用来实现那些 “表面似和善、背后一长串”的宏,它本身并不在编译过程中进行,而是在这之前(预处理过程)就已经完成了,但也因此难以发现潜在的错误及其它代码维护问题,如:
) [+ T/ U" h" A0 r3 w: T) b& \* M$ i) l
#define INT int+ C7 U F, G7 }3 D. d
#define TRUE 1, y# W; c4 L1 K9 n( l
#define Add(a,b) ((a)+(b));6 S5 l2 E: s2 K$ A( [
#define Loop_10 for (inti=0; i<10; i++)
1 {: v# d0 X6 D4 Z" { Z
, w1 c1 v$ V% O& O0 y' Y3、typedef 与#define 的区别
9 J1 F; m* r* A9 l |, n6 L从以上的概念便也能基本清楚,typedef 只是为了增加可读性而为标识符另起的新名称(仅仅只是个别名),而#define原本在 C 中是为了定义常量,到了 C++,const、enum、 inline 的出现使它也渐渐成为了起别名的工具。有时很容易搞不清楚与 typedef 两者到 底该用哪个好,如#define INT int 这样的语句,用 typedef 一样可以完成,用哪个好 呢?我主张用 typedef,因为在早期的许多 C 编译器中这条语句是非法的,只是现今的 编译器又做了扩充。% }" m5 P9 O! e9 N9 Q
1 y4 I# y* `7 }9 w& o为了尽可能地兼容,一般都遵循#define 定义“可读”的常量以及一些宏语句的任务, 而 typedef 则常用来定义关键字、冗长的类型的别名。/ f$ i/ D# D( O- Y; x
8 G6 W. `& O2 h% I( X宏定义只是简单的字符串代换(原地扩展),而 typedef 则不是原地扩展,它的新名字具 有一定的封装性,以致于新命名的标识符具有更易定义变量的功能。请看上面第一大点 代码的第三行:typedef (int*) pINT;以及下面这行:#define pINT2 int*效果相同?实则不同!实践中见差别:pINT a,b;的效果同 int *a;int *b;表示定 义了两个整型指针变量。而 pINT2 a,b;的效果同 int*a, b;表示定义了一个整型指针 变量 a 和整型变量 b。
1 @) v# y) [6 g6 @" E8 @
7 s- r" i/ u2 _ T- u3 Ntypedef 的四个用途和两个陷阱
) u2 c; |% K9 ]% L# D用途一: 定义一种类型的别名,而不只是简单的宏替换
' N% D" B" U& X$ D, H1 e6 R用途二: 用在旧的 C 代码中(具体多旧没有查),帮助 struct。
9 h2 L' T$ p, h: J/ E
3 f% O0 C, f# M% _typedef struct tagPOINT- p# W0 E8 p3 x d" v
{' u2 b$ Q' W9 t" z
int x;
3 \, z1 D1 G+ _- y+ Mint y;
& J( X* z# s4 Q+ u4 q, A}POINT; E6 Z* h. c2 }+ a0 }! G1 Z+ K
! ], I; N: T( C" t0 d8 x7 D2 hPOINT p1; // 这样就比原来的方式少写了一个 struct,比较省事,尤其在大量 使用的时候 或许,在 C++中,typedef 的这种用途二不是很大,但是理解了它,对掌握 以前的旧代码还是有帮助的,毕竟我们在项目中有可能会遇到较早些年代遗留下来的代 码。+ J2 X* a. V: K; T/ R( O. r2 B
$ P2 t$ {/ P( e+ n7 G' q3 l3 ] _
用途三: 用 typedef 来定义与平台无关的类型。用途四:为复杂的声明定义一个新的简单的别名。
6 z8 B5 K9 p L" z. w0 @4 r" C! V' r7 y: B- `- g. I
陷阱一: 记住,typedef 是定义了一种类型的新别名,不同于宏,它不是简单的字符串替换。字符串替换就行。
) g5 ^" B* G9 I5 q' d7 J7 e$ ]7 Y. L4 ]$ I w
1 _7 }* _5 t- R' E7 a- _ M! o陷阱二: typedef 在语法上是一个存储类的关键字(如 auto、extern、mutable、static、 register 等一样),虽然它并不真正影响对象的存储特性,如: typedef static intINT2; //不可行 编译将失败,会提示“指定了一个以上的存储类”。
7 f/ B; M- L8 b: C2 k/ v
$ @; s) b3 \: C) U# l$ {9 S. k/ Y4 U6 `# d
三、按键:
" T0 x0 W X9 C7 u& {$ t按键是单片机系统中最常用的器件。各种仪器仪表、家用电器操作面板上都离不开按键,是最基本的输入部件。因此,掌握按键输入电路设计、按键驱动程序设计是十分必要的。按键的分类:从单片机获取按键信号类型的角度来讲,可以分为模拟按键和数字按键;从按键与单片机IO 端口对应关系上来讲,可以分为独立按键和矩阵式按键。独立按键很简单,就是一个按键对应一个 IO 端口;而矩阵式按键则相对复杂一些,通过行与列的交叉组合成 i 行*j 列个 按键。4 x! R, x. r( c: h" K- Z8 n' h
; g2 d9 t2 @! K9 }按键的有效方式:
( H( X) X A/ d3 N6 p% S3 `! |4 S& b+ T按下有效、按下松开(抬起)有效、长按 n 秒有效、连按 n 次有效、组合按键有效等。按键驱动程序设计步骤:
1 u' k" c6 Y. O: `读取键值—按键消抖—键值处理! U: p! |9 J6 G' O: ~* c! `
+ y5 c- O! h6 G9 _. d8 Z
& A3 J; ~5 c4 M+ {3 F8 W2 Z
四、cror 与 crol 的区别& ^+ L, x k. l5 ]$ M/ x
循环右移与循环左移 |
|