51单片机自学报告--实验部分

微机接口技术-自主学习笔记

PPT链接:微机接口自学--51单片机自学汇报PPT_猫猫爱吃小鱼的博客-CSDN博客

效果演示gif:

51单片机自学报告--实验部分_第1张图片

 51单片机自学报告--实验部分_第2张图片

51单片机自学报告--实验部分_第3张图片 

 51单片机自学报告--实验部分_第4张图片

 

四、Proteus仿真

仿真环境:电路仿真软件:                       Proteus

                  HEX可执行文件编写软件:    keil uVision4

keil uVision4新建项目简略步骤:

  1. new project,选择使用的芯片(例:AT89C51,AT89C52)。
  2. 创建main.c(或.asm),并添加进project。
  3. 选择生成 HEX 文件 ,因为单片机执行的时候,是通过执行 HEX 文件来执行的。
  4. 添加HEX文件,即可运行

51单片机自学报告--实验部分_第5张图片图13 步骤1

 

51单片机自学报告--实验部分_第6张图片图14 步骤2

51单片机自学报告--实验部分_第7张图片图15 步骤3

可用芯片:AT89C51,AT89C52等,它们的区别如下所示:

(1)、RAM 空间增大:AT89C51 有128 字节的内部 RAM,称之为 DATA 存储区。AT89C52 的内部 RAM 扩展为 256 字节,其中高 128 字节,位于从 80H 开始的地址空间中,称之为 IDATA 存储区,但IDATA 区的访问只能是间接寻址方式。
    (2)、内部 FLASH 变大:AT89C51 有 4K 字节的内部 FLASH PERAM,而。AT89C52 的内部 FLASH PERAM 增加1倍,达到8K。
    (3)、中断源增加:在AT89C52 中P1.0和P1.1还可分别作为定时器/计数器2的外部计数输入(P1.0/T2)和(P1.1/T2EX),也就是说,P1.0同时可作为定时器/计数器 T2 的外部计数输入,和输出占空比 50% 的时钟脉冲端口,P1.1同时可作为定时器/计数器 T2 捕获/重新装载触发和方向控制端口。故,AT89C52 除了具备 AT89C51 的定时器/计数器 T0 和定时器/计数器 T1,还额外增加了一个定时器/计数器 T2。而定时器/计数器 T2 的控制和状态位单独位于T2CON、T2MOD,定时器/计数器 T2 在 16 位捕获方式或自动重新装载方式下的捕获/重载寄存器组是(TCAO2H、RCAP2L)。

4.1 简单LED灯的控制

这是一个简单来理解51单片机定时和计数的例子。

(1)先来介绍定时功能,当作为定时使用时,配置步骤:模式设置,配置TMOD寄存器;定时器初值设置 假设10ms中断;开定时器中断;开总中断;打开定时器。流程图如下图所示:

51单片机自学报告--实验部分_第8张图片

 

图16 定时器中断方式计时流程图

仿真电路图绘制如下图所示,实现每一秒点亮LED一次:

所含电路元器件:单片机AT89C51(频率12M),LED灯,电阻,电容,电源和地等(CRYSTAL和电容组成不可编程模块,可不添加)

51单片机自学报告--实验部分_第9张图片

 图17 定时点亮LED仿真电路

LED-RED接引脚P1.0,程序中需要这样配置:

sbit led=P1^0;

采用的是定时器0,16位定时器/计数器工作模式(工作与式1),参照图 TMOD格式

 图18 TMOD格式

程序中需要这样配置:

TMOD=0X01;

 因为:1s=50ms*20,对于12M的晶振单片机,12MHz除12为1MHz,也就是说一秒=1000000次机器周期,50ms=50000次机器周期;所以计数值为50000,每中断20次,则点亮LED灯。

TH0=(65536-50000)/256;

TL0=(65536-50000)%256;

........

//中断服务子程序

void time0() interrupt 1 {

TH0=(65536-50000)/256;      //重装初值

TL0=(65536-50000)%256;

a++;

}

a每加到20,则点亮LED灯,同时置0,需要注意每次触发中断后,都需要重新装入初值。

 图19 LED点亮

(2)定时计数器作为计数器使用,配置步骤如下:

1.模式设置,配置TMOD寄存器。

2.开计数器中断

3.开总中断

4.打开计数器

注意: 计数器可以不开中断,这样溢出时只是不会进去中断服务程序。

仿真电路图绘制如下图所示,实现每按五次按键(P3.4引脚)点亮LED一次:

51单片机自学报告--实验部分_第10张图片

 

图20 计数方式点亮LED灯

LED灯接法和定时方式下一样,但是TMOD寄存器配置不一样了,本设计中TMOD的D2位C/T为设为1,选择计数功能:

sbit led=P1^0;

 sbit s=P3^4;

TMOD=0x05; //模式设置,00000101,采用的是计数器0,工作模式1

比较定时方式下的电路,在这边的P3.4/T0口接了一个简单的开关电路,对P3.4口进行下降沿的脉冲计数。因为TR0:T0充许计数控制位,为1时充许T0计数(定时),所以初始化时需要将 TR0置1。

 TR0=1;    

本次的设计是用count存储计数值,到了5次,则人为让计数器进入中断,使得TH0和TL0溢出,进行中断处理。

   count=(TH0<<8)|TL0;

        if((count*10000)==50000)//按5下按键led状态取反  

            {

                led=0;

                TH0=0XFF;

                TL0=0XFF; //人为的让计数器进入中断

            }

中断服务程序中,使LED灯亮。

 图21  LED灯点亮

4.2 流水灯控制(定时器中断控制的独立式键盘扫描)

使用定时器中断控制获得按键值,实现按下S1,D8-D1循环点亮;按下S2,D1-D8循环点亮;按下S3,全部熄灭;按下S4,D1-D8同频率闪烁。仿真电路图设计如下:

51单片机自学报告--实验部分_第11张图片

 图22 按键控制流水灯方式

D1-D8接AT89C51的P3口,按键电路接P1口。

设计要点如下:

1.考虑到实际电路中按键的不稳定性,需要对按键进行消抖设计。

2.计数初值的选择,检测按键需要迅速。

3.LED需要一定的延时,不然看不到灯亮。

4.LED点亮方式P3由口的值进行控制。

基于以上的设计要点,消抖设计的时间为20ms,每次检测到有按键按下时,都先进行消抖延时:

void delay20ms(void)

{ unsigned char i,j;

for(i=0;i<100;i++)

for(j=0;j<60;j++);

}

计数初值选择1000,检测的比较迅速。P3口直接改变值,再适当延长时间来控制LED灯的流水状况。

P3=0xfe;         //第一个灯亮

led_delay();

P3=0xfd;          //第二个灯亮

led_delay();

P3=0xfb;          //第三个灯亮

led_delay();

P3=0xf7;          //第四个灯亮

led_delay();

P3=0xef;          //第五个灯亮

led_delay();

P3=0xdf;          //第六个灯亮

led_delay();

P3=0xbf;          //第七个灯亮

led_delay();

P3=0x7f;          //第八个灯亮

led_delay();  

运行结果如下图所示(左上为S1方式,右上为S2方式,左下为S3方式,右下为S4方式):

51单片机自学报告--实验部分_第12张图片

 

图23 流水灯结果

4.3 液晶时钟设计

基于51单片机实现计时(24小时制),并显示在LCD1602屏幕上。先来简单介绍下LCD1602液晶显示屏。

LCD1602液晶显示器是广泛使用的一种字符型液晶显示模块。它是由字符型液晶显示屏(LCD)、控制驱动主电路HD44780及其扩展驱动电路HD44100,以及少量电阻、电容元件和结构件等装配在PCB板上而组成。它的引脚说明如下表所示:

表4 LCD引脚说明

编号

符号

引脚说明

标号

符号

引脚说明

1

VSS

电源地

9

D2|

数据

2

VDD

电源正极

10

D3

数据

3

VL

液晶显示偏压

11

D4

数据

4

RS

数据/命令选择

12

D5

数据

5

R/W

读/写选择

13

D6

数据

6

E

使能信号

14

D7

数据

7

D0

数据

15

BLA

背光源正极

8

D1

数据

16

BLK

背光源负极

引脚的具体功能不再进行展开,简单地介绍下我们本次设计中用到的几个指令(具体指令设计不再阐述):

表5 LCD指令

序号

指令

RS

R/W

D7

D6

D5

D4

D3

D2

D1

D0

1

清屏

0

0

0

0

0

0

0

0

0

1

2

初始化

0

0

0

0

1

1

1

0

0

0

3

开显示,无光标,不闪烁

0

0

0

0

0

0

1

1

0

0

4

光标右移,字符不移

0

0

0

0

0

0

0

1

1

0

仿真电路图设计如下图:

51单片机自学报告--实验部分_第13张图片图24 液晶时钟仿真设计图

 

LCD1602的D0-D7连接AT89C52的P0端口,将RS位,定义为P2.0引脚,将RW位定义为P2.1引脚,将E位定义为P2.2引脚,将BF(忙碌标志位)位定义为P0.7引脚。

BF是忙碌标志位,每次写数据前都需检查显示屏是否忙碌,端口为1,则是忙碌,等待。为0则空闲,直接写数据。读时需注意:RS为低电平,RW为高电平时,可以读状态,即RS=0,RW=1,E=1

才允许读写。读完BF,将E恢复低电平,使E=0;    

LCD的初始化如下:

WriteInstruction(0x38); //确保初始化成功

delay(5);

WriteInstruction(0x0c);  //显示模式设置:显示开,无光标,光标不闪烁

delay(5);

WriteInstruction(0x06);  //显示模式设置:光标右移,字符不移

delay(5);

WriteInstruction(0x01);  //清屏幕指令,将以前的显示内容清除

delay(5);

将字符写进LCD中时,需要指定字符的位置,我们需要写两个函数,先指定位置,再写数据。

指定字符的实际地址函数为:

 void WriteAddress(unsigned char x)

 {

     WriteInstruction(x|0x80); //显示位置的确定方法规定为"80H+地址码x"

 }

写数据时,RS为高电平,RW为低电平时,可以写入数据, 即RS=1,RW=0,E从0到1发生正跳变,将数据送入P0口,即将数据写入液晶模块,当E由高电平跳变成低电平时,液晶模块开始执行命令。

时间采用24小时制,控制程序就是中断服务程序,如下所示:

     count++;  //每产生1次中断,中断累计次数加1

if(count==20)  //如果中断次数计满20次

{count=0;  //中断累计次数清0

   s++;  }    //秒加1

if(s==60)   //如果计满60秒

{s=0;     //秒清0

   m++;    }    //分钟加1

if(m==60)    //如果计满60分

 { m=0;   //分钟清0

h++;    //小时加1

    }

if(h==24)  //如果计满24小时

  { h=0;   //小时清0

   }

计数器的初值:

TH0=(65536-46083)/256;   //定时器T0高8位重新赋初值

TL0=(65536-46083)%256;   //定时器T0低8位重新赋初值

因为晶振为11.059Mhz,11.0592MHz除12为921600Hz,就是一秒921600次机器周期,10ms=9216次机器周期。所以1s=20*50ms,而50ms=46083,所以计数初值为46083,可以实现比较精确的秒计时。

写时分秒分别写一个函数,时的函数如下:

void DisplayHour()

{

   unsigned char i,j;

i=h/10;                //取整运算,求得十位数字

j=h%10;                //取余运算,求得各位数字

   WriteAddress(0x44);   //写显示地址,将十位数字显示在第2行第5列

WriteData(digit[i]);  //将十位数字的字符常量写入LCD

WriteData(digit[j]);  //将个位数字的字符常量写入LCD

     

 }

分和秒的类似,只是写的地址不同(在屏幕上显示的位置不同),不在具体阐述。

结果如下图所示:

51单片机自学报告--实验部分_第14张图片

 图25 液晶时钟

和精确时钟进行对比,还是很精准的。短时间内没有任何问题。如果想改开始时间,则可以直接在源程序中改,加日期也是一样的道理。

你可能感兴趣的:(51单片机,单片机,嵌入式硬件)