单片机实验讲稿-5课时

更新时间:2023-03-09 23:46:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

单片机原理与接口

实 验 讲 稿

电子信息工程系

二零一二年九月

1

实验一 伟福仿真软件的使用

一、实验目的及要求

1、了解伟福仿真软件的特点; 2、熟悉伟福仿真软件的使用方法。 二、实验仪器和设备

PC机、WAVE软件。 三、实验内容及步骤

1、进入仿真器的操作环境,如图1。

图1 汇编环境主界面

2、熟悉主菜单及工具栏功能,其中工具栏如图2,菜单栏如图3。

图2 工具栏

2

图3 菜单栏

3、伟福仿真软件的使用方法: (1)进入伟福仿真软件的操作环境; (2)选择软件模拟仿真方式;

(3)选择要使用的仿真头和要进行仿真的单片机芯片的型号;

(4)选择编译器:单击“仿真器”菜单或工具按钮→选择“仿真器设置”选项→“语言”标签→选中“伟福汇编器”;

(5)输入需要仿真的程序进行调试:

1) 强调:输入程序和指令的格式要求、标点符号的要求、保存程序的方法(.asm或.C)。标签和断点的设置与取消;

2)标签和断点的查看(应用); 3)标签和断点的设置与取消; 4)标签和断点的查看(应用);

5)存储单元窗口的显示与查看,包括REG、SFR、DATA和XDATA、CODE窗口等 6)端口窗口的显示与查看;

7)定时/计数器初值与初始化程序的设置; 8)程序的几种模拟运行方式的区别;

9)根据程序运行后各存储单元和运行结果的指示进行调试。

3

实验二 汇编程序仿真调试

一、实验目的及要求

掌握应用WAVE软件进行单片机汇编语言的编程和编译,对语法错误的修改,对程序运行结果的跟踪等,从而在没有硬件系统的情况下,实现对所编程序的调试。 二、实验仪器和设备

PC机、WAVE软件。 三、实验内容及步骤

1、以下程序实现了把片内RAM2000H开始的10个单元中的内容送到片内RAM地址从30H开始的10个单元中。

MOV DPTR,#2000H MOV R0,#30H

START:MOVX A,@DPTR MOV @R0,A INC DPTR INC R0

CJNE R0,#3AH,START RET

打开编辑窗口,输入源程序,按“*.asm”格式保存文件。

2、调试以上程序,通过CPU 窗口观测程序的执行情况,通过存储器窗口观察并分析片外和片内RAM中各涉及到的存储器单元中的数据变化情况。

实验三 按键输入与LED指示灯控制

4

一、实验目的及要求

1)熟悉单片机对按键的控制原理,掌握通过单片机对按键信号的读取与识别; 2)掌握根据按键状态控制LED指示灯的两灭。 二、实验内容

如图1所示,监视开关K1(接在P3.0端口上),用发光二极管L1(接在单片机P1.0端口上)显示开关状态,如果开关合上,L1亮,开关打开,L1熄灭,实现模拟开关灯显示。

1、电路原理图

图1

2、程序设计内容

(1)开关状态的检测过程

单片机对开关状态的检测相对于单片机来说,是从单片机的P3.0端口输入信号,而输入的信号只有高电平和低电平两种,当拨开开关K1拨上去,即输入高电平,相当开关断开,当拨动开关K1拨下去,即输入低电平,相当开关闭合。单片机可以采用JB BIT,REL或者是JNB BIT,REL指令来完成对开关状态的检测即可。

(2)输出控制

如图1所示,当P1.0端口输出高电平,即P1.0=1时,根据发光二极管的单向导电性可知,这时发光二极管L1熄灭;当P1.0端口输出低电平,即P1.0=0时,发光二极管L1亮;我们可以使用SETB P1.0指令使P1.0端口输出高电平,使用CLR P1.0指令使P1.0端口输出低电平。

(3)程序框图

5

开始 K1开关闭合了吗? L1亮 L1灭

图2

三、参考源程序

START: LIG:

ORG 00H JB P3.0,LIG CLR P1.0 SJMP START SETB P1.0 SJMP START END

实验四 LED的定时中断控制

6

一、实验目的

1学习内部定时/计数器的使用 2学习定时中断处理程序的编程方法

二、实验内容

P1口作为输出口,接发光二极管,编写相应的程序使发光二极管点亮。发光二极管亮灭的时间间隔可以由定时中断子程序进行控制。要求0.5S中亮一个。 三、参考源程序

#include \#include \

#define uchar unsigned char #define uint unsigned int uint num=4; uchar XX=0x01;

void timer0() interrupt 1 {

num--;

TH0=0x0B;

TL0=0xDC; //重新设置初值

if(num==0) {

XX=_crol_(XX,1); //或者是 XX=XX<<1 num=4; } }

void main() {

TMOD=0x01; // set model one TH0=0x0B;

TL0=0xDC; //设置初值 EA=1; //总中断允许 ET0=1; //定时中断允许 TR0=1; //定时开始

for(;;) {

P1=XX; //计时溢出时,退出循环,跳到中断子程序 } }

实验五 A/D、D/A转换实验

7

一、实验目的及要求

通过实验进一步学习AD、D/A转换芯片的基本原理以及在单片机系统中扩展AD、D/A转换器的方法,掌握AD、D/A转换芯片的性能及编程。

二、实验内容

1.PCF8591介绍

PCF8591是一个单片集成、单独供电、低功耗、8-bit CMOS数据获取器件。PCF8591具有4个模拟输入、1个模拟输出和1个串行I2C总线接口。PCF8591的3个地址引脚A0, A1和A2可用于硬件地址编程,允许在同个I2C总线上接入8个PCF8591器件,而无需额外的硬件。在PCF8591器件上输入输出的地址、控制和数据信号都是通过双线双向

I2C

线

引脚 AIN0 AIN1 AIN2 AIN3 A0 A1 A2 VSS SDA 引脚序号 1 2 3 4 5 6 7 8 9

8

引脚功能 模拟量输入方式 模拟通道选择 负电源电压 数据信号

SCL OSC EXT AGND Vref AOUT Vdd

10 11 12 13 14 15 16 时钟信号 振荡器 振荡器输入的外部内部转换 模拟接地端 输入的参考电压 模拟量输出 正的电源电压

2.内容:通过改变学习板上的2个电位器对应的2段模拟输入,实现模拟输入,观察数码管的数字变化情况。通过改D[4]的值,实现模拟输出,观察学习板上DA处LED的亮度变化。

三、参考源程序 1.main

#include #include

#define PCF8591 0x90 //PCF8591 地址

//else IO

sbit LS138A=P2^2; sbit LS138B=P2^3; sbit LS138C=P2^4;

//此表为 LED 的字模, 共阴数码管 0-9 -

unsigned char code Disp_Tab[] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};

9

unsigned char AD_CHANNEL;

unsigned long xdata LedOut[8]; unsigned int D[32];

/******************************************************************* DAC 变换, 转化函数

*******************************************************************/ bit DACconversion(unsigned char sla,unsigned char c, unsigned char Val) {

Start_I2c(); //启动总线 SendByte(sla); //发送器件地址 if(ack==0)return(0);

SendByte(c); //发送控制字节 if(ack==0)return(0);

SendByte(Val); //发送DAC的数值 if(ack==0)return(0);

Stop_I2c(); //结束总线 return(1); }

/******************************************************************* ADC发送字节[命令]数据函数

*******************************************************************/ bit ISendByte(unsigned char sla,unsigned char c) {

Start_I2c(); //启动总线 SendByte(sla); //发送器件地址 if(ack==0)return(0);

SendByte(c); //发送数据 if(ack==0)return(0);

Stop_I2c(); //结束总线 return(1); }

/******************************************************************* ADC读字节数据函数

*******************************************************************/ unsigned char IRcvByte(unsigned char sla) { unsigned char c;

Start_I2c(); //启动总线 SendByte(sla+1); //发送器件地址 if(ack==0)return(0);

c=RcvByte(); //读取数据0

10

Ack_I2c(1); //发送非就答位 Stop_I2c(); //结束总线 return(c); }

//******************************************************************/ main()

{ char i,j;

while(1)

{/********以下AD-DA处理*************/ switch(AD_CHANNEL) {

case 0: ISendByte(PCF8591,0x41);

D[0]=IRcvByte(PCF8591)*2; //ADC0 模数转换1 放大2倍显示 break;

case 1: ISendByte(PCF8591,0x42);

D[1]=IRcvByte(PCF8591)*2; //ADC1 模数转换2 break;

case 2: ISendByte(PCF8591,0x43);

D[2]=IRcvByte(PCF8591)*2; //ADC2 模数转换3 break;

case 3: ISendByte(PCF8591,0x40);

D[3]=IRcvByte(PCF8591)*2; //ADC3 模数转换4 break;

case 4: DACconversion(PCF8591,0x40, D[4]/4); //DAC 数模转换 break; }

// D[4]=400; //数字--->>模拟输出

D[4]=D[0]; // 把模拟输入 采样的信号 通过数模转换输出 if(++AD_CHANNEL>4) AD_CHANNEL=0;

/********以下将AD的值送到LED数码管显示*************/

LedOut[0]=Disp_Tab[D[1]000/1000]; LedOut[1]=Disp_Tab[D[1]00/100]; LedOut[2]=Disp_Tab[D[1]0/10]|0x80; LedOut[3]=Disp_Tab[D[1]];

LedOut[4]=Disp_Tab[D[0]000/1000]; LedOut[5]=Disp_Tab[D[0]00/100];

11

LedOut[6]=Disp_Tab[D[0]0/10]|0x80; LedOut[7]=Disp_Tab[D[0]];

for( i=0; i<8; i++) { P0 = LedOut[i];

switch(i) //使用switch 语句控制138译码器 也可以是用查表的方式 { case 0:LS138A=0; LS138B=0; LS138C=0; break;

case 1:LS138A=1; LS138B=0; LS138C=0; break; case 2:LS138A=0; LS138B=1; LS138C=0; break; case 3:LS138A=1; LS138B=1; LS138C=0; break; case 4:LS138A=0; LS138B=0; LS138C=1; break; case 5:LS138A=1; LS138B=0; LS138C=1; break; case 6:LS138A=0; LS138B=1; LS138C=1; break; case 7:LS138A=1; LS138B=1; LS138C=1; break; }

for (j = 0 ; j<90 ;j++) { ;} //扫描间隔时间 }

P0 = 0; } } 2.i2c

/*************************此部分为I2C总线的驱动程序*************************************/

#include #include #include

#define NOP() _nop_() /* 定义空指令 */ #define _Nop() _nop_() /*定义空指令*/

sbit SCL=P2^1; //I2C 时钟 sbit SDA=P2^0; //I2C 数据 bit ack; /*应答标志位*/

/******************************************************************* 起动总线函数 函数原型: void Start_I2c();

12

功能: 启动I2C总线,即发送I2C起始条件.

********************************************************************/ void Start_I2c() {

SDA=1; /*发送起始条件的数据信号*/ _Nop(); SCL=1;

_Nop(); /*起始条件建立时间大于4.7us,延时*/ _Nop(); _Nop(); _Nop(); _Nop();

SDA=0; /*发送起始信号*/

_Nop(); /* 起始条件锁定时间大于4μs*/ _Nop(); _Nop(); _Nop();

_Nop();

SCL=0; /*钳住I2C总线,准备发送或接收数据 */ _Nop(); _Nop(); }

/******************************************************************* 结束总线函数 函数原型: void Stop_I2c();

功能: 结束I2C总线,即发送I2C结束条件.

********************************************************************/ void Stop_I2c() {

SDA=0; /*发送结束条件的数据信号*/ _Nop(); /*发送结束条件的时钟信号*/ SCL=1; /*结束条件建立时间大于4μs*/ _Nop(); _Nop(); _Nop(); _Nop(); _Nop();

SDA=1; /*发送I2C总线结束信号*/ _Nop(); _Nop(); _Nop(); _Nop(); }

/*******************************************************************

13

字节数据发送函数 函数原型: void SendByte(UCHAR c);

功能: 将数据c发送出去,可以是地址,也可以是数据,发完后等待应答,并对 此状态位进行操作.(不应答或非应答都使ack=0) 发送数据正常,ack=1; ack=0表示被控器无应答或损坏。

********************************************************************/ void SendByte(unsigned char c) {

unsigned char BitCnt;

for(BitCnt=0;BitCnt<8;BitCnt++) /*要传送的数据长度为8位*/ {

if((c<

SCL=1; /*置时钟线为高,通知被控器开始接收数据位*/ _Nop();

_Nop(); /*保证时钟高电平周期大于4μs*/ _Nop(); _Nop();

_Nop(); SCL=0; }

_Nop(); _Nop();

SDA=1; /*8位发送完后释放数据线,准备接收应答位*/ _Nop(); _Nop(); SCL=1; _Nop(); _Nop(); _Nop();

if(SDA==1)ack=0;

else ack=1; /*判断是否接收到应答信号*/ SCL=0; _Nop(); _Nop(); }

/******************************************************************* 字节数据接收函数 函数原型: UCHAR RcvByte();

功能: 用来接收从器件传来的数据,并判断总线错误(不发应答信号), 发完后请用应答函数应答从机。

********************************************************************/

14

unsigned char RcvByte() {

unsigned char retc; unsigned char BitCnt;

retc=0;

SDA=1; /*置数据线为输入方式*/ for(BitCnt=0;BitCnt<8;BitCnt++) {

_Nop();

SCL=0; /*置时钟线为低,准备接收数据位*/ _Nop();

_Nop(); /*时钟低电平周期大于4.7μs*/ _Nop(); _Nop(); _Nop();

SCL=1; /*置时钟线为高使数据线上数据有效*/ _Nop(); _Nop();

retc=retc<<1;

if(SDA==1)retc=retc+1; /*读数据位,接收的数据位放入retc中 */ _Nop(); _Nop(); }

SCL=0; _Nop(); _Nop();

return(retc); }

/******************************************************************** 应答子函数 函数原型: void Ack_I2c(bit a);

功能: 主控器进行应答信号(可以是应答或非应答信号,由位参数a决定) ********************************************************************/ void Ack_I2c(bit a) {

if(a==0)SDA=0; /*在此发出应答或非应答信号 */ else SDA=1; _Nop(); _Nop();

_Nop(); SCL=1; _Nop();

_Nop(); /*时钟低电平周期大于4μs*/

15

_Nop(); _Nop(); _Nop();

SCL=0; /*清时钟线,钳住I2C总线以便继续接收*/ _Nop(); _Nop(); }

选做实验1 单片机最小系统和常见外设硬件设计

一、实验目的及要求

1、熟悉单片机最小系统; 2、熟悉常见外设硬件设计。 二、实验仪器和设备

PC机、WAVE、protel 99se软件。 三、实验内容及步骤

1.单片机最小系统和常见外设硬件设计图

16

17

18

选做实验2 Keil C51的使用及仿真调试(汇编语言)

一 实验目的:

初步掌握Keil C51(汇编语言)和ZY15MCU12BD型综合单片机实验箱的操作和使用,能够输入和运行简单的程序。

二 实验设备:

ZY15MCU12BD型综合单片机实验箱一台、具有一个RS232串行口并安装Keil C51的计算机一台。

三 实验原理及环境:

在计算机上已安装Keil C51软件。这个软件既可以与硬件(ZY15MCU12BD型综合单片机实验箱)连接,在硬件(单片机)上运行程序;也可以不与硬件连接,仅在计算机上以虚拟仿真的方法运行程序。如果程序有对硬件的驱动,就需要与硬件连接;如果没有硬件动作,仅有软件操作,就可以使用虚拟仿真。 四 实验内容:

1.掌握软件的开发过程:

1)建立一个工程项目选择芯片确定选项。 2)加入C 源文件或汇编源文件。 3)用项目管理器生成各种应用文件。 4)检查并修改源文件中的错误。

5)编译连接通过后进行软件模拟仿真。 6)编译连接通过后进行硬件仿真。 7)I A P 编程操作

2.按以上步骤实现在P1.0输出一个频率为1Hz的方波。

3.在2的基础上,实现同时在P1.0和P1.1上各输出一个频率同为0.5Hz但电平状态相反的方波。 五 实验步骤:

以下假定你在E:\\TEST 文件夹下学习、运行Keil 1.建立一个工程项目选择芯片确定选项

如图1-1所示:①Project→②New Project→③输入工程名test→④保存工程文件(鼠标点击保存按钮)

19

图1-1 创建工程名

弹出下一界面。

如图1-2所示:①选CPU厂家(Atmel)→②选CPU型号(89C51), ③选好后确定

图1-2 选厂家,选CPU 型号

接着选晶振频率及生成HEX 文件等。

如图1-3所示:①Project→②Options for Target ‘Target 1’… →③在Target中→④更改CPU 晶振频率为12MHz→⑤在Output中→⑥选择生成HEX 格式其它采用缺省设置→⑦选好后确定。

20

图1-3 选晶振频率及生成HEX 文件等窗口

2.建立汇编源文件

如图1-4所示:①File→②New, ③弹出源文件编辑窗口。 输入以下源文件: ORG 0000H AGAIN: CPL P1.0

MOV R0,#10 ;延时0.5秒

LOOP1: MOV R1,#100 LOOP2: MOV R2,#250

DJNZ R2,$

DJNZ R1,LOOP2 DJNZ R0,LOOP1 SJMP AGAIN END

21

图1-4 进入编辑源文件窗口

源程序编写完后,①File→②Save As 将文件以test.asm保存在E:\\test 目录下,获得汇编语言源程序。

3.用项目管理器生成(编译)各种应用文件

①点击Target 1 前之+ 号→出现②Source Group1→③点击它并按鼠标右键会生弹出下拉菜单见图1-5 编译文件文件窗口→选择④Add Files to Group ‘ Source Group 1’ →⑤点击add向项目中添加Test.asm 源文件→⑥点击close关闭Add Files to Group ‘ Source Group 1’窗口→⑦在Source Group 1 前会出现一个+号→⑧点击之弹出test. asm 文件名点击该文件名→⑨主窗口中会出现该程序

图1-5 进入编译文件文件窗口

编译:Project→Build target 就会生成一系列到文件如OBJ 文件LST 文件HEX文件等。

22

4.检查并修改源文件中的错误

如果在源文件中存在错误在Output 窗口中会出现错误提示信息,你可以在源程序中进行修改,然后存盘后重新Build 观察错误提示信息。

5.编译连接通过后进行软件模拟仿真

Debug→Start/Stop Debug Session进入软件模拟的仿真窗口,可使用单步、设断点来进行调试和除错。

6.编译连接通过后进行硬件仿真

实验箱的仿真串口必须与PC 机串口连接,通电,拨位开关K10必须拨在B端,连接P10和L0,连接P11和L1,设置硬件实时仿真调试选项:Project→Options for Target ‘Targetl’→Debug.硬件实时仿真调试选项窗口,见图1-5 选硬件仿真选项,按确定按钮确定。

图1-5 硬件实时仿真调试选项窗口

进入硬件实时调试窗口后,可打开各种观察窗口,进行单步断点运行到光标连续执行等操作,无误后可连续运行观察LED发光管的显示效果。注意退出时须按单片机的复位按键SS10,在进行硬件连接前最好也先按单片机的复位按键SS10。

7.I A P 编程操作

在硬件调试正确后(实质上用户程序已写入器件了,IAP 即在应用中编程),只需使K10拨至A端,用户程序就100 年不变,实验箱的内置仿真器就可脱离PC 机工作。通电复位后,就能正确执行上次调试通过的程序。如果开机通电或复位时,K10处于B端, 则上次调试通过的程序有可能会冲掉,因为当K10处于B端时,实验箱内置仿真器器认为用户要进入仿真状态,所以对器件内存进行清理,造成程序被改写,请千万要注意K10按钮工作状态.如果用户系统用实验箱内置仿真器调试通过,可把用户程序编译通过的*.HEX文件,用万用编程器(烧录器)写到8X5X 单片机中,用8X5X 单片机取代实验箱内置仿真器的CPU工作.

8.修改以上程序,实现同时在P1.0和P1.1上各输出一个频率为1Hz但电平状态相反的方波。

重要提示:

1.指令中的“,:;”是西文字符,切不可使用中文符号;数字“0”与字符“o”不可混淆。

23

2.以上菜单操作都可以点击工具栏中的相应图标快速实现。

3.退出硬件连接可以按SS10,在进行硬件连接前最好也按一次SS10。 4.生成源文件的方法: ①从键盘上输入源文件;

②用其他编辑软件(包括Microsoft Word)编辑源文件,然后复制到Keil C51 文件窗口中,使Word 文档变为TXT 文档,这种方法最好,可方便输入中文注释;

③也可装入在其它编辑软件中编辑的源文件如: *.asm/*.a51/*.c... 等。

24

选做实验3 串行口通讯实验

2.11.1 实验目的与要求

通过实验了解实现串行通讯的硬环境、数据格式的协议、数据交换的协议,学习串口通讯中断方式的程序编写方法,掌握单片机串行口简易三线式通讯的实现方法。要求利用单片机串行口,实现两个实验台之间的串行通讯。其中一个实验台作为发送方,另一侧为接收方。发送方读入按键值,并发送给接收方,接收方收到数据后在LED上显示。

2.11.2 8051单片机串行口简介

8051单片机内部有一个可编程的全双工串行接口,它在物理上分为两个独立的发送缓冲器和接收缓冲器SBUF,这两个缓冲器占用一个特殊功能寄存器地址99H,究竟是发送缓冲器还是接收缓器工作是靠软件指令来决定的。对外有两条独立的收、发信号线RXD(P3.0)和TXD(P3.1),因此可以同时接收和发送数据,实现全双工传送,使用串行口时可以用定时器T1或T2作为波特率发生器。

8051串行口通过两个特殊功能寄存器SCON和PCON来进行控制,分别介绍如下。 串行口控制寄存器SCON(地址为98H):这个特殊功能寄存器包含有串行口的工作方式选择位,接收发送控制位及串行口的状态标志,格式如下:

D7 D6 D5 D4 D3 D2 D1 D0 SM0 SM1 SM2 REN TB8 RB8 TI RI SM0和SM1为串行口的工作方式选择位,详见表2-18。 表2-18

SM0 0 0 1 1 SM1 0 1 0 1 工作方式 方式0,移位寄存器方式(用于I/O口扩展)。 方式1,8位UART,波特率可变(T1溢出率/n)。 方式2,9位UART,波特率为fosc/64获fosc/32。 方式3,9位UART,波特率可变(T1溢出率/n)。。 表中, n为16或32, 取决于特殊功能寄存器PCON中SMOD位的值,SMOD=1时, n= 16; SMOD=0

时, n=32。UART表示通用异步收发器。

串行口有四种工作方式,说明如下。

方式0为移位寄存器输入/输出方式。串行数据从RXD线输入或输出,而TXD线专用于输出时钟脉冲给外部移位寄存器。这种方式主要用于进行I/O口的扩展,输出时将片内发送缓冲器中的内容串行地移入外部的移位寄存器,输入时将外部移位寄存器中的内容移入片内接收缓冲器,波特率固定为fosc/12。

方式1为8位异步接收发送。一帧数据有10位, 包括1位起始位(0),8位数据位和1位停止位(1)。串行口电路在发送时能自动插入起始位和停止位,在接收时,停止位进入SCON中的RB8位。方式1的传送波特率是可变的,由定时器1的溢出率决定。

方式2为9位异步接收发送。一帧数据包括有11位, 除了1位起始位、8位数据位、1位停止位之外,还可以插入第9位数据,字符格式如图2.37所示。

25

1个字符起始位00/10/10/1第9位0/10/10/10/1停止位1

图2.37 串行口方式2的9位UART数据格式

8位数据0/10/1发送时,第9位数据的值可通过SCON中的TB8指定为“0”或“1”,用一些附加的指令可使这一位作奇偶校验位。接收时,第9位数据进入特殊功能寄存器SCON中的RB8位。方式2的波特率为fosc/64或fosc/32。

方式3也是9位异步接收发送,一帧数据有11位, 工作方式与方式2相同,只是传送时的波特率受定时器1的控制,即波特率可变。

SCON寄存器中另外各位的意义如下:

SM2为允许在方式2和方式3时进行多机通讯的控制位。若允许多机通讯,则应使SM2=1,然后根据收到的第9位数据值来决定从机是否接收主机的信号,当SM2=0时禁止多机通讯。

REN为允许串行接收位。由软件置位以允许接收。由软件清“0”来禁止接收。 TB8为方式2和方式3时发送的第9位数据。需要由软件置位或复位。

RB8为方式2和方式3时接收到的第9位数据。在方式1,若SM2=0,则RB8是接收到的停止位;在方式0,不使用RB8。

TI为发送中断标志。由硬件在方式0串行发送第8位结束时置“1”,或在其他方式串行发送停止位的开始时置“1”。该位必须由软件清“0”。

RI为接收中断标志。由硬件在方式0接受到第8位结束时置“1”,或在其他方式串行接收到停止位的中间时置“1”。该位必须由软件清“0”。

特殊功能寄存器PCON(地址为87H):在PCON寄存器中,只有一位与串行口工作有关。其格式如下:

D7 D6 D5 D4 D3 D2 D1 D0

Smod 串行口工作于方式1,方式2和方式3时,数据传送的波特率与2Smod成正比,也就是说,当Smod=1时,将使串行口传送的波特率加倍。

2.16.3 实验内容

8051单片机的RXD、TXD接线柱在POD51仿真板上,通讯双方的RXD、TXD信号本应经过电平转换后再行交叉连接,本实验中为减少连线可将电平转换电路略去,而将双方的RXD、TXD直接交叉连接,如图3.38所示。

26

图3.38 双机通信连线示意图

也可以将本机的TXD接到RXD上,这样按下的键,就会在本机LED上显示出来。若想与标准的RS232设备通信,就要做电平转换,输出时要将TTL电平换成RS232电平,输入时要将RS232电平换成TTL电平。可以将仿真板上的RXD、TXD信号接到实验板上的“用户串口接线”的相应RXD和TXD端,经过电平转换,通过“用户串口”接到外部的RS232设备。

按表2-19连线,执行如下程序,按下一台实验系统的按键,注意观察另一台实验系统上数码管的显示值。

表2-19 连线 1 2 3 4 连接孔1 甲方TXD 甲方RXD 甲方GND KEY/LED_CS 连接孔2 乙方RXD 乙方TXD 乙方GND CS0

实验程序清单如下。

OUTBIT EQU 08002H ; 数码管位控制口 OUTSEG EQU 08004H ; 数码管段控制口 IN EQU 08001H ; 键盘读入口

HASRCV EQU 20H.0 ; 接收标志位 LEDBUF EQU 40H ; 显示缓冲 RCVBUF EQU 50H ; 接收缓冲

ORG 0000H ; 复位入口 LJMP START

ORG 0023H ; 串行口中断入口 LJMP SINT

LEDMAP: ; 数码管显示代码

DB 3FH, 06H, 5BH, 4FH, 66H, 6DH, 7DH, 07H DB 7FH, 6FH, 77H, 7CH, 39H, 5EH, 79H, 71H

DELAY: MOV R7, #0 ; 延时子程序 DELAYLOOP:

DJNZ R7, DELAYLOOP DJNZ R6, DELAYLOOP RET

DISPLAYLED:

MOV R0, #LEDBUF

MOV R1, #6 ; 共6个数码管 MOV R2, #00100000B ; 从左边开始显示 LOOP: MOV DPTR, #OUTBIT MOV A, #0

27

MOVX @DPTR, A ; 关所有数码管 MOV A, @R0

MOV DPTR, #OUTSEG MOVX @DPTR,A

MOV DPTR, #OUTBIT MOV A, R2

MOVX @DPTR, A ; 显示一位数码管 MOV R6, #1 CALL DELAY

MOV A, R2 ; RR A MOV R2, A INC R0

DJNZ R1, LOOP RET

TESTKEY:

MOV DPTR, #OUTBIT MOV A, #0

MOVX @DPTR, A ; MOV DPTR, #IN

MOVX A, @DPTR ; CPL A

ANL A, #0FH ; RET

KEYTABLE: ; DB 16H, 15H, 14H, 0FFH DB 13H, 12H, 11H, 10H DB 0DH, 0CH, 0BH, 0AH DB 0EH, 03H, 06H, 09H DB 0FH, 02H, 05H, 08H DB 00H, 01H, 04H, 07H

GETKEY:MOV DPTR, #OUTBIT MOV P2, DPH

MOV R0, #LOW(IN) MOV R1, #00100000B MOV R2, #6

KLOOP: MOV A, R1 ; CPL A

MOVX @DPTR, A CPL A RR A

显示下一位 输出线置为0 读入键状态 高四位不用 键码定义 找出键所在列 28

MOV R1, A ; 下一列 MOVX A, @R0 CPL A

ANL A, #0FH

JNZ GOON1 ; 该列有键入 DJNZ R2, KLOOP

MOV R2, #0FFH ; 没有键按下, 返回 0FFH SJMP EXIT

GOON1: MOV R1, A ; 键值 = 列 X 4 + 行 MOV A, R2 DEC A RL A RL A

MOV R2, A ; R2 = (R2-1)*4 MOV A, R1 ; R1中为读入的行值 MOV R1, #4

LOOPC: RRC A ; 移位找出所在行 JC EXIT

INC R2 ; R2 = R2+ 行值 DJNZ R1, LOOPC

EXIT: MOV A, R2 ; 取出键码 MOV DPTR, #KEYTABLE MOVC A, @A+DPTR MOV R2, A WAITRELEASE:

MOV DPTR, #OUTBIT ; 等键释放 CLR A

MOVX @DPTR, A MOV R6, #10 CALL DELAY CALL TESTKEY JNZ WAITRELEASE MOV A, R2 RET

START: MOV SP, #60H ; 主程序

MOV IE, #0 ; DISABLE ALL INTERRUPT

MOV TMOD,#020H ; 定时器1工作于方式2 (8位重装) MOV TH1, #0F3H ; 波特率=2400BPS @ 12MHZ MOV TL1, #0F3H

ANL PCON,#07FH ; SMOD 位清零 ORL PCON,#80H

MOV SCON,#050H ; 串行口工作方式设置 MOV LEDBUF, #0FFH ; 显示 8.8.8.8.

29

MOV LEDBUF+1, #0FFH MOV LEDBUF+2, #0FFH MOV LEDBUF+3, #0FFH MOV LEDBUF+4, #0 MOV LEDBUF+5, #0 SETB TR1 SETB ES SETB EA

;MOV SBUF,A ;JNB TI,$

MLOOP: JB HASRCV, RCVDATA ; 收到数据? CALL DISPLAYLED ; 显示 CALL TESTKEY ; 有键入?

JZ MLOOP ; 无键入, 继续显示 CALL GETKEY ; 读入键码

ANL A, #0FH ; 通讯口输出键码 MOV SBUF,A LJMP MLOOP RCVDATA:

CLR HASRCV ; 是

MOV A, RCVBUF ; 显示数据 MOV B,A

ANL A,#0FH ; 显示低位 MOV DPTR, #LEDMAP MOVC A, @A+DPTR MOV LEDBUF+5, A MOV A,B

SWAP A ; 显示高位 ANL A,#0FH

MOV DPTR, #LEDMAP MOVC A, @A+DPTR MOV LEDBUF+4, A LJMP MLOOP

SINT: JNB TI,S0_R ; 串行口中断服务程序 CLR TI NOP

SJMP S0_RET

S0_R: CLR RI ; 接收数据 MOV RCVBUF,SBUF ; 保存数据 SETB HASRCV ; 提示收到数据 NOP S0_RET: RETI END

30

复习思考题

1. 复习实验过程,加深对串行工作原理的理解。

2. 修改实验程序实现下位机8051与上位机PC之间的串行通信。

31

本文来源:https://www.bwwdw.com/article/rr8a.html

Top