Download presentation
Presentation is loading. Please wait.
1
项目三 闪烁的LED 任务一 一只LED的闪烁 任务二 跑马灯 任务三 任意变化的彩灯控制
2
知识目标: Keil uVision2 软件的使用和调试方法。 掌握汇编语言与C语言的编写方法和技巧。 技能目标: 能根据实际电路要求编写闪烁LED程序。 学习目标
3
任务一 一只LED的闪烁 一、课题目标 本课题就是以发光二极管为例,用单片机控制8只发光二极管,实现逐个点亮、全亮、闪烁等花样显示。
为了便于理解,采用从简单的单只发光二极管的点亮和熄灭控制开始,到实现八只发光二极管组成的各种样式闪亮彩灯控制。
4
二、电路原理 图3-1 LED显示电路原理图
5
图 八路发光二极管控制实物图
6
三、程序设计 P1.0端口的LED闪亮 AT89S51 P1.0 +Vcc 单片机的I/O端口 图3-3 单片机驱动一只发光二极管的原理电路
7
1、端口的定义 C51使用sfr命令来对单片机这些端口进行定义,如: sfr P1 = 0x90; 这条命令的作用就是定义了P1这个名称(也可叫变量)代表了地址为90H的特殊功能寄存器。 汇编程序直接使用P1就可以,并且不分大小写。例:MOV P1,#0FFH;MOV P1,#00H。
8
在程序命令中使用命令“sfr P1 = 0x90;”这样定义后,P1就代表了P1口,程序中就可以对单片机的P1口进行读写操作了,如使用“Y=P1;”的命令将单片机P1口的状态读入并存入变量Y中,而“P1=0x02”则是P1口的P1.1置1。 同样的方式,也可以定义其他端口。为了方便,C51将各个厂商生产的单片机的各个特殊功能寄存器的定义放在一个特殊的文件中,如AT89S51、AT89C51对应的文件是AT89X51.H。作为通用的MCS-51系列单片机,在编写C程序,首先调用这些通用的REG51.H头文件。
9
2、位定义 针对特殊功能寄存器的某一位进行操作,则需要使用sbit命令定义特殊功能寄存器中的可寻址位。如要对AT89S51端口P1的P1.0进行操作,则可以使用下面的命令进行定义: sbit P10=P1^0; 然后就能使用“P10=1;”控制P1.0输出高电平,“P10=0;”控制P1.0输出低电平。
10
图3-4 1Hz的闪烁程序设计框图 输出低电平 输出高电平 程序开始 延时0.5秒 3、程序设计分析 在本任务的程序设计框图就是图3-4。从框图中可看出两点,一是程序是一个循环结构,即程序开始后就反复地循环执行,二是程序包含了端口输出控制和0.5秒的延时程序。
11
在本任务中的引脚定义使用如下命令: sbit light=P1^0; 命令定义了light表示P1口的P1.0端。 让LED点亮,需要在引脚上输出低电平,就是在P1.0引脚上输出0,应使用的命令是: light=0;(汇编:CLR P1.0) 同理,让LED熄灭,应使用的命令是: light=1; (汇编:SETB P1.0)
12
4、延时程序的编写 单片机执行一条指令的执行时间,称为指令周期。指令周期是以机器周期为单位的,为1~4个机器周期,多数指令都是单周期指令,也就是执行一条指令的时间为一个机器周期。在MCS-51单片机规定一个机器周期为单片机振荡器的12个振荡周期。如果晶振频率为12MHz,则一个机器周期为1μs。 单片机的指令运行是很快的,要在端口获得一定时间长度的脉冲信号,就要通过编写程序,使单片运行设计程序产生时间延迟,实现从单片机输出端口上获得需要频率的电脉冲信号。
13
任务中要求获得0. 5s的时间长度,当单片机的指令周期是1μs时,可计算出0
任务中要求获得0.5s的时间长度,当单片机的指令周期是1μs时,可计算出0.5s是1μs的500000倍,在程序编写中常用循环语句来完成计数和时间延迟,从而获得需要的延时时间。 为了便于计算和控制,常采用无符号变量的循环来实现。因为程序执行时,对应的每次循环所需要的时间是两个机器周期,当单片机所使用的晶振为12MHz,每次循环就延时2μs。 无符号数最大值为255,也就是说,使用无符号类型的变量的单个的循环最多为255次,即用一个循环不能完成所需要的0.5s延时。为了达到0.5s延时,可采用多重循环的方式完成。为了方便,将其中的每重循环的循环次数取为0.5s/2μs=250000的因数200、250和5。
14
下面就是一个完成0.5秒延时的程序。 void delay05s(void) { unsigned char i,j,k; for(i=5;i>0;i--) for(j=200;j>0;j--) for(k=250;k>0;k--) {;} } 整个子程序延时为:2μs×250×200×5=500000μs=0.5s。
15
0.5秒延时的汇编程序: MOV R6,#5 SS:MOV R7, #200 LOOP:MOV R5, #249 DJNZ R5, $ DJNZ R7,LOOP DJNZ R6,SS 整个子程序延时为:{[2μs×249+3]×200+2}×5=501010μs
16
按图3-5所对应的主程序: void main(void) { while(1) light=0; delay05s(); light=1;
} 图3-5 1Hz的闪烁程序设计框图 输出低电平 输出高电平 程序开始 延时0.5秒
17
5、(1)C语言程序: #include <reg51.H> sbit light=P1^0;
void delay05s(void) { unsigned char i,j,k; for(i=5;i>0;i--) { for(j=200;j>0;j--) { for(k=250;k>0;k--) {;} } } } void main(void) { while(1) { light=0; delay05s(); light=1; }
18
(2)、汇编语言程序: org 00h LS:setb p1.0 Lcall delay clr P1.0 Lcall delay
sjmp lS delay:mov R6,#5 SS:MOV R7, #200 loop:mov R1,#245 SD:DJNZ R1, SD DJNZ R7,loop DJNZ R6,SS ret end
19
工具栏 菜单栏 源文件编辑窗口 工程窗口 输出窗口
(一)keil C51 windows集成开发平台的使用 1.keil C51 windows集成开发平台介绍 工具栏 菜单栏 源文件编辑窗口 工程窗口 输出窗口 图 软件窗口介绍
20
KEIL 软件开发平台 2.导入需要仿真的程序 建立一个工程项目 芯片选择 属性设置 建立源程序文件 添加文件到当前项目组中 编译文件
21
KEIL 软件开发平台 图 新建工程窗口
22
KEIL 软件开发平台 图 新建工程窗口
23
KEIL 软件开发平台 图 单片机选择窗口
24
KEIL 软件开发平台 图 目标1属性设置窗口
25
KEIL 软件开发平台 图 目标1输出窗口设置
26
KEIL 软件开发平台 图 调试窗口设置
27
KEIL 软件开发平台 图 软件输入窗口
28
KEIL 软件开发平台 图 目标1添加窗口
29
KEIL 软件开发平台 图 目标1添加文件窗口
30
KEIL 软件开发平台 (二) Keil 程序调试 1.程序调试时的常用窗口 编译文件界面 图 编辑文件界面
31
KEIL 软件开发平台 调试程序窗口 字母C:代码存储空间 D:直接寻址的片内存储空间 I:间接寻址的片内存储空间 X:扩展的外部RAM空间
“数字”:想要查看的地址。 图 代码查询窗口
32
KEIL 软件开发平台 工程窗口寄存器页 图 工程寄存器窗口
33
KEIL 软件开发平台 2.各种窗口在程序调试中的用途 程序调试界面 图 程序调试窗口
34
KEIL 软件开发平台 I/O端口界面 图 硬件查询窗口
35
KEIL 软件开发平台 I/O口全部打开界面 图 硬件I/0口查询窗口
36
KEIL 软件开发平台 打开后的Interrupt窗口 图 P3口查询窗口
37
KEIL 软件开发平台 串口设置 图 串口查询窗口
38
KEIL 软件开发平台 打开后的串口窗口 图 串口窗口
39
KEIL 软件开发平台 定时器设置 图 定时器窗口
40
KEIL 软件开发平台 打开后的定时器1窗口 图 硬件I/0口查询窗口
41
停止全速运行 全速运行 KEIL 软件开发平台 常用的调试按钮 进入循环并单步执行 跳出单步执行过程 执行到断点处 跳过循环并单步执行
复位按钮,按下后,所有的系统状态将变成初始状态。 全速运行 停止全速运行 进入循环并单步执行 跳出单步执行过程 跳过循环并单步执行 执行到断点处 图 调试按钮
42
二、ISP软件的使用 打开下载软件,双击目录下的文件ISPgm.exe,打开软件进入软件使用界面
KEIL 软件开发平台 二、ISP软件的使用 打开下载软件,双击目录下的文件ISPgm.exe,打开软件进入软件使用界面 1.芯片选择:左击界面右面芯片选择窗口的下拉箭标,选择编程芯片的型号。 2.导入hex文件到缓冲区:左击界面上的“Open File”按钮,选择本目录下的hex文件。 3.向芯片写入文件:左击界面上的“Write”按钮,开始编程向芯片写入程序。 4.完成写入编程。 5.退出程序:左击界面右上角的“x”按钮,退出此程序。
44
任务二 跑马灯 本任务让图3-28中的LED依次循环点亮。 图 LED硬件图
45
程序设计分析 为了让图3-28所示的LED依次点亮,就是要求从P1口从P1.0至P1.7依次输出低电平,其余引脚都输出高电平,就能让被接在端口的彩灯依次点亮。 从输出的具体的数据来看,第一个LED点亮需要的输出数据,是对应于P1.0的位为0,其余位为1,组合为一个字节时对应的二进制位从高到低为: ,即十六进制数0xFE;同理,第二个LED点亮对应的数为: ,化为十六进制数为0xFD。 依次类推,逐次点亮LED所对应的数据为: 、 、 、 、 、 、 、 。
46
从这些数据上,可以看出一个规律,就是这些数据中的二进制数0的位置依次往左移动了一位。在C51中,要直接实现数据的这种计算是不容易的。
根据前面的分析,实现任务的思路是:程序开始时,给某一变量赋初始值0xFE,然后每次将数据左移后送入P1口直到所有循环次数输出完毕,再次重复整个过程。根据思路得出的程序框图如图3-29所示。
47
图 程序流程图
48
{ for(k=250;k>0;k--) {;} } } } void main()
(1)C语言程序: #include "reg51.h" #include "intrins.h" void delay05s(void) { unsigned char i,j,k; for(i=5;i>0;i--) { for(j=200;j>0;j--) { for(k=250;k>0;k--) {;} } } } void main() { unsigned char OutData=0xfe; for(;;) {P1=OutData; OutData=_crol_(OutData,1); //循环左移 delay05s(); }
49
(2)汇编语言 START: MOV A,#0FEH LOOP: MOV P1,A LCALL DELAY RL A SJMP loop
ORG 00H START: MOV A,#0FEH LOOP: MOV P1,A LCALL DELAY RL A SJMP loop delay:mov R6,#5 SS:MOV R7, #200 lp:mov R1,#245 SD:DJNZ R1, SD DJNZ R7,lp DJNZ R6,SS RET END
50
思考题: 1、编写程序实现8个LED指示灯从左到右,从右到左依次循环点亮。 2、编写程序实现8个LED指示灯闪亮3次并且从左到右,从右到左依次循环点亮。
51
1、#include "reg51.h" #include "intrins.h" #define uchar unsigned char #define uint unsigned int uchar j,k; void mDelay(unsigned int Delay) { unsigned int i; for(;Delay>0;Delay--) { for(i=0;i<124;i++) {;}}} void main() { unsigned char OutData=0xfe; while(1){ for(j=0;j<7;j++) {P1=OutData; OutData=_crol_(OutData,1); //循环左移 mDelay(1000); /*延时1000 毫秒*/} for(k=0;k<7;k++) OutData=_cror_(OutData,1); //循环左移 mDelay(1000); /*延时1000 毫秒*/}}}
52
2、#include "reg51.h" #include "intrins.h" #define uchar unsigned char #define uint unsigned int uchar j,k,OutData=0xfe; void mDelay(unsigned int Delay) { unsigned int i; for(;Delay>0;Delay--) { for(i=0;i<124;i++) {;}}} void FLASH() {uchar l; for(l=3;l>0;l--) { P1=OutData; mDelay(1000); P1=0xff; mDelay(1000); }}
53
void main() { OutData=0xfe; while(1){ for(j=0;j<7;j++) { OutData=_crol_(OutData,1); FLASH(); } for(k=0;k<7;k++) { OutData=_cror_(OutData,1); FLASH(); }}}
54
本任务实现让彩灯显示出规定的任意的花样。
任务三 任意变化的彩灯控制 本任务实现让彩灯显示出规定的任意的花样。
55
程序设计要求: 要求LED灯从右至左依次循环点亮2轮,然 后从右至左依次循环点亮2轮,全亮全灭2次。 LED灯按这规律依次循环。
56
程序设计分析 由于本任务中是按时间变化依次控制彩灯亮、灭,可以采用跑马灯类似的思路来完成程序框图,但显示花样所对应的数据的变化不一定有规律,不能采用变量直接计算的方式实现前后数据的变化,这里介绍一种很重要的程序设计方法——查表法。 将彩灯显示的图案所对应的端口输出数据依次编写为一张数据表,表中每个数据中为0的位表示对应的彩灯亮,数据为1的位表示对应的彩灯熄。将这张数据表放在程序中,以数组的形式存储,在使用时依次读出数组中的元素就得到了需要的数据,实现了数据的无规律变化,并且数组存储的数据可以较多,能实现的花样变化也可以做到比较繁复。在C51中要进行复杂的计算,也可以采用数组的方式来实现,比如:一个周期正弦值的计算,可以先将这些列在表中,需要时查表读出,这就是查表法。
57
将用于点亮彩灯的数据放在数组中,让程序依次读这数组中的数据,并将数据送到端口,控制彩灯的点亮,就实现了任意规律变化彩灯控制。假设有N个数据,当程序读完N个数据后,又从头开始读数。具体的程序框图如图3-30所示。 图3-30 采用数组的彩灯控制程序框图
58
C语言程序: #include <AT89X51.H> unsigned char code table[]={0xfe,0xfd,0xfb,0xf7, 0xef,0xdf,0xbf,0x7f, 0xfe,0xfd,0xfb,0xf7, 0x7f,0xbf,0xdf,0xef, 0xf7,0xfb,0xfd,0xfe, 0x00,0xff,0x00,0xff, 0x01};
59
unsigned char i; void delay(void) {unsigned char m,n,s; for(m=20;m>0;m--) for(n=20;n>0;n--) for(s=248;s>0;s--);} void main(void) {while(1) {if(table[i]!=0x01) {P1=table[i]; i++; delay();} else {i=0;} }
60
汇编语言程序 ORG 00h START: MOV DPTR,#TABLE LOOP: CLR A MOVC A, @A+DPTR
CJNE A,#01H,LOOP1 LJMP START LOOP1: MOV P1, A MOV R3, #20 LCALL DELAY INC DPTR LJMP LOOP DELAY: MOV R4,#20 D1: MOV R5,#248 DJNZ R5,$ DJNZ R4,D1 DJNZ R3,DELAY RET
61
TABLE: DB 0FEH,0FDH,0FBH,0F7H DB 0EFH,0DFH,0BFH,07FH DB 0FEH,0FDH,0FBH,0F7H DB 07FH,0BFH,0DFH,0EFH DB 0F7H,0FBH,0FDH,0FEH DB 00H, 0FFH,00H, 0FFH DB 01H END
62
作业题 1、第一个发光二极管以间隔500ms闪烁。 2、8个由左至右间隔1s流动,其中每个管亮500ms, 灭500ms,一直重复下去。
3、8个发光二极管演示出8位二进制数累加过程。 间隔300ms第一次一个管点亮,第二次2个,以此 点亮8个。然后重复循环。
63
习题 1、 #include "reg51.h" sbit d1=P1^0; void delay05s(void)
{ unsigned char i,j,k; for(i=5;i>0;i--) { for(j=200;j>0;j--) { for(k=250;k>0;k--) {;} } } } void main() { for(;;) {d1=!d1; delay05s(); }
64
#define uchar unsigned char #define uint unsigned int
2、 #include "reg51.h" #include "intrins.h" #define uchar unsigned char #define uint unsigned int uchar j,k,OutData=0xfe; void mDelay(unsigned int Delay) { unsigned int i; for(;Delay>0;Delay--) { for(i=0;i<124;i++) {;}}}
65
void FLASH() { P1=OutData; mDelay(1000); P1=0xff; mDelay(1000); } void main() { OutData=0xfe; while(1){ { OutData=_crol_(OutData,1); FLASH(); } }}
66
3、 #include "reg51.h" #define uchar unsigned char uchar a=0;
void delay03s(void) { unsigned char i,j,k; for(i=3;i>0;i--) { for(j=200;j>0;j--) { for(k=250;k>0;k--) {;} } } } void main() {while(1) {a++; delay03s(); P1=~a; }
Similar presentations