|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
; j% Z8 _4 g- h* Q* {7 q3 \4 Y4 Q第六讲 实验5-实验88 p) s/ F8 b) h( V
知识点:
% h$ v! J8 r& {) @; b9 H1、 学会画程序流程图" i5 f G( _; \0 r* K
2、 流程控制语句 if(){}else{}用法
; y3 W1 k( ]4 F1 y" t" O3、 操作符 ”~ ”、“!”、“&&”含义8 F8 X2 J; V( o. B [3 v( Y
4、 带参函数
; L# e/ o' R" L/ C" b, z7 p& P5、 函数调用+ S" `# X+ G( |1 `; @% t' Y
6、 理解宏定义 #define “替换”作用
: P8 @+ A7 [9 d9 G7、 循环语句 for 的用法6 @' z5 e' h) h ]$ h, g
8、 库函数 unsigned char_cror_ (unsigned char, unsigned char);
" ~! }& P, ]6 |) Kunsigned char _crol_ (unsignedchar, unsigned char);含义 e8 i8 `% ]% ]$ N7 S; U* i
9、 C51 扩展类型 code含义- Q* x) Y6 J$ P) O
10、 流程控制语句:switchcase 用法( ~/ ?- j9 L1 d S; p$ G. `
11、 数组定义、引用方式
5 K, Q+ b- G$ E! b+ g+ l% V+ j12、 延时函数, f% n6 E3 |" l
) W2 j; g- y# G* f+ L一、51单片机软件延时:/ n C: e0 l# } k
1、 几种周期介绍/ u6 n9 ?. @) S& t# @6 b$ s7 @/ F6 Z
周期名称
. c0 r+ W* a7 Z5 S9 D! M, V | 描述
/ v. K& g3 F) o4 G9 Q% b! B2 Y | 时间' b$ ^) V# w. a/ K- ?' ~! C" C% X! A
| 振荡
! ~ b4 ?& D* H% j9 m( I+ J7 V& K | 单片机提供时钟脉冲信号" z+ T5 R; M1 W7 Z
的振荡源的周期
6 ]8 Q7 J9 B6 i h0 W8 E) { | T=1/f
1 s, D3 y5 b9 a% d( }! S$ | | 状态9 t4 f: ?: ? u
| 振荡周期经二分频后得到
2 h2 O1 o5 J6 b9 T- B. H9 j 的9 O2 V% F2 u: a& z4 Z
| 2T/ N* ^' R5 S1 F
| 机器
) ^5 m% s6 I" ]6 t# U+ g | CPU 可以完成一个独立操# S9 j$ a( h& q. y7 n
作所需要的周期
% L: ^+ U7 k2 P& N, H+ B: ]2 o7 M1 ^ | 12T
' Z) F" U# x4 W# Q' t' @! Y" ` | 指令0 x" t' K: `( @$ S0 @
| 指 CPU 完成一条操作所需
' I w) N6 g P4 d, k+ ^6 P 的全部时间
: H0 i2 ?) o; n' k' I! {* F" E( Y! \ | n*12T
" k3 }) Y7 {) j | 2、指令: {" @; L6 [- S' g8 ?
1、MUL、DIV:仅有的 4 周期指令" B& S$ Z3 D/ U2 q, O9 H3 F
2、包含 DPTR 和 PC 的指令均为 2 周期指令) Z% b+ {3 P5 i/ H @
3、所有的绝对跳转和条件转移指令,均为 2 周期指令
# e. {( S y. B. c8 H4、所有包括 A 寄存器的指令,均为单周期指令( O: b o |% E" C5 S& c
5、位操作指令中,ANL 和 ORL 是 2 周期指令7 K& p7 d5 k( q; Y6 }1 U5 h0 P
6、所有包含立即地址的指令,除 INC direct 及 DEC direct 外,均为 2 周期指令
5 q) V' h5 k1 V7、剩下的均为单周期指令。如:
; ^2 I. T2 B) }2 z: M+ |voiddelay(uint z)
& G2 ^5 C9 V7 [6 l2 }{8 g8 Q4 Q0 m, T* w) e m
uinti ,j;* \1 c0 ~" ^* H
for(i = z; i> 0;i--)* ]" o& H0 x, r5 i) B. l0 P
) Q: f: n4 Y. y& u* K6 P/ N
; z: b2 z2 ` @9 j5 ~8 N% K
for(j =0; j < 921; j++)' n0 Q! e C% m/ K4 ]3 n
}
' X- N# X3 E Z4 @# d2 w4 n1 O
+ C& s! ~9 `2 x l- F5 f
}: g6 M0 T) V0 t, D, u* h分析:
1 u8 ]* E* y# p1.先计算你单片机的振荡(时钟)周期 T=1/晶振(11.0592MHZ): r8 F0 E" F: _! ]7 l! Z- @
2.一次 i--操作为 12T
# w* Z# c8 A4 @! ^" \) u' d# X- Z3.忽略变量定义,上述延时函数共需时间:921*z*12T: n* {$ K9 K% K- ^) u) j9 T
4.带入 T:921*12*T*z 约为 z us
$ S0 H! ^# d$ ]& G1 ]- l: d3、计算误差出现的原因:# d7 I8 ~( h$ n: r. `
1.软件仿真时,函数调用的时候入栈出栈操作的耗时。
/ R4 _. Y; ~2 K$ G2 ]2.指令周期随指令的不同而不同导致的误差。; S3 R7 b( G# L6 r \( }
3.中断的影响。5 z2 E6 c( h0 b* N
4.变量的范围超过,从而与预计时间不一样。( @) J! ^; p) [
* s+ M# A) F( A: v
& \/ N0 c# q3 B4 Q9 }while(i--):如果 i 为 char 型,执行一次大概为 5us 左右;如果 i 为 int 型则执行一次大概为 10us 左右。注意:软件延时通常用于时序要求较高的编程中,其它需延时较长的地方必须采用单片机内部定时器。7 s% _+ E; G( M9 |2 \1 ]! H1 H4 w
m. z8 f) E* i1 H: D二、#define与 typedef 区别
0 h9 @7 m' W0 \4 y( Z$ P6 S1、typedef 的用法) U3 c; w. B& p' ^- M: o
1 C2 L0 ]! F( W. H, z9 W+ O
在 C 语言中,typedef 常用来定义一个标识符及关键字的别名,它是语言编译过程的一部分, 但它并不实际分配内存空间,9 y& R2 ~' J0 B
如:typedef int INT;3 B/ d _& t- ?5 g9 R2 ?" z
- q0 Q, I; z8 {5 Z6 ]: x2、#define 的用法5 T: H6 S% v1 j
#define 为一宏定义语句,通常用它来定义常量(包括无参量与带参量),以及用来实现那些 “表面似和善、背后一长串”的宏,它本身并不在编译过程中进行,而是在这之前(预处理过程)就已经完成了,但也因此难以发现潜在的错误及其它代码维护问题,如:! R+ d$ @9 y0 f$ G$ {- j7 o
7 \; [( G/ l: y1 }% Z
#define INT int: \. r" R! v2 O$ c
#define TRUE 1
! X# v" l0 v2 r5 K+ q0 q#define Add(a,b) ((a)+(b));+ X- _, n" U2 Q: X1 H+ H
#define Loop_10 for (inti=0; i<10; i++)
! s2 l! B. T6 G1 A; x& t% t7 |# l3 e/ G# t1 b) f
3、typedef 与#define 的区别
2 }7 j% i6 L- ]0 ~' Y+ Y4 Y从以上的概念便也能基本清楚,typedef 只是为了增加可读性而为标识符另起的新名称(仅仅只是个别名),而#define原本在 C 中是为了定义常量,到了 C++,const、enum、 inline 的出现使它也渐渐成为了起别名的工具。有时很容易搞不清楚与 typedef 两者到 底该用哪个好,如#define INT int 这样的语句,用 typedef 一样可以完成,用哪个好 呢?我主张用 typedef,因为在早期的许多 C 编译器中这条语句是非法的,只是现今的 编译器又做了扩充。! Z. p7 @6 X8 I; T, y
9 Q( K; B7 e1 b. s& V, K) g
为了尽可能地兼容,一般都遵循#define 定义“可读”的常量以及一些宏语句的任务, 而 typedef 则常用来定义关键字、冗长的类型的别名。
, @! L9 ^/ z. l3 K
/ Y( ^7 b4 m6 ?- j宏定义只是简单的字符串代换(原地扩展),而 typedef 则不是原地扩展,它的新名字具 有一定的封装性,以致于新命名的标识符具有更易定义变量的功能。请看上面第一大点 代码的第三行:typedef (int*) pINT;以及下面这行:#define pINT2 int*效果相同?实则不同!实践中见差别:pINT a,b;的效果同 int *a;int *b;表示定 义了两个整型指针变量。而 pINT2 a,b;的效果同 int*a, b;表示定义了一个整型指针 变量 a 和整型变量 b。# o3 w+ F& M1 y9 a+ k3 O
5 D5 j. C! m+ |5 e1 o3 G
typedef 的四个用途和两个陷阱 |, X' }3 u4 g! R! P" W
用途一: 定义一种类型的别名,而不只是简单的宏替换
. {- {: {0 L3 w) Y ]: J用途二: 用在旧的 C 代码中(具体多旧没有查),帮助 struct。9 C2 b8 Q: X# @" m& U
q/ z0 W0 B, [5 W8 t; e6 Rtypedef struct tagPOINT
! J# D2 X% M" D2 }2 K{
3 B( n( H) C3 _2 {) kint x;/ v" }( z4 D; O( G+ r
int y;: M+ r0 l- l7 m- t) K: S% A
}POINT;
8 U* ~: u0 m. [
% N4 u* g, A/ w; u4 f" l7 w/ m0 LPOINT p1; // 这样就比原来的方式少写了一个 struct,比较省事,尤其在大量 使用的时候 或许,在 C++中,typedef 的这种用途二不是很大,但是理解了它,对掌握 以前的旧代码还是有帮助的,毕竟我们在项目中有可能会遇到较早些年代遗留下来的代 码。
/ |5 Y$ P! P9 i
( j, C3 |( Y: U, b4 e用途三: 用 typedef 来定义与平台无关的类型。用途四:为复杂的声明定义一个新的简单的别名。
' I. V9 v" v- u- x8 x9 V- Z* T9 p A6 u& `0 t f _8 c" g
陷阱一: 记住,typedef 是定义了一种类型的新别名,不同于宏,它不是简单的字符串替换。字符串替换就行。
5 G; N8 y7 G- b+ _# a2 M2 s3 {' D1 q. C5 e+ O3 u
& c! w3 a3 O0 N/ M- u! }, d1 T5 u陷阱二: typedef 在语法上是一个存储类的关键字(如 auto、extern、mutable、static、 register 等一样),虽然它并不真正影响对象的存储特性,如: typedef static intINT2; //不可行 编译将失败,会提示“指定了一个以上的存储类”。- u' m$ d. p" Z1 a& x
7 H& \( q. I. z. a2 g5 A$ [2 u* w3 }/ W
三、按键:
& S' r8 U+ F- A2 [! |4 a按键是单片机系统中最常用的器件。各种仪器仪表、家用电器操作面板上都离不开按键,是最基本的输入部件。因此,掌握按键输入电路设计、按键驱动程序设计是十分必要的。按键的分类:从单片机获取按键信号类型的角度来讲,可以分为模拟按键和数字按键;从按键与单片机IO 端口对应关系上来讲,可以分为独立按键和矩阵式按键。独立按键很简单,就是一个按键对应一个 IO 端口;而矩阵式按键则相对复杂一些,通过行与列的交叉组合成 i 行*j 列个 按键。
1 c l- M3 p3 q" Y, w( l: |# I5 H. ]4 F' e* \; }4 e" Q
按键的有效方式:
/ ^3 b- J% X5 q+ l1 w- a按下有效、按下松开(抬起)有效、长按 n 秒有效、连按 n 次有效、组合按键有效等。按键驱动程序设计步骤:
3 W( g$ [! N" j; a; O读取键值—按键消抖—键值处理
4 e" B# B0 C7 u% i) h4 {
/ l, ?" o3 k8 e! |: k4 A% b3 p3 x
4 E4 k {1 z. r6 u+ [9 g$ J2 Z+ B) p A四、cror 与 crol 的区别
6 U/ f- `- \3 J% e% `' p循环右移与循环左移 |
|