凌阳单片机使用中的一些问题.docx

上传人:b****8 文档编号:23914033 上传时间:2023-05-22 格式:DOCX 页数:37 大小:75.56KB
下载 相关 举报
凌阳单片机使用中的一些问题.docx_第1页
第1页 / 共37页
凌阳单片机使用中的一些问题.docx_第2页
第2页 / 共37页
凌阳单片机使用中的一些问题.docx_第3页
第3页 / 共37页
凌阳单片机使用中的一些问题.docx_第4页
第4页 / 共37页
凌阳单片机使用中的一些问题.docx_第5页
第5页 / 共37页
点击查看更多>>
下载资源
资源描述

凌阳单片机使用中的一些问题.docx

《凌阳单片机使用中的一些问题.docx》由会员分享,可在线阅读,更多相关《凌阳单片机使用中的一些问题.docx(37页珍藏版)》请在冰豆网上搜索。

凌阳单片机使用中的一些问题.docx

凌阳单片机使用中的一些问题

凌阳单片机使用中的一些问题

1.指令长度

一个指令中包含的2进制代码的位数,称为指令长度。

指令长度=操作码的长度+操作数地址的长度X操作数地址个数

2.简述时钟周期、机器周期、指令周期的概念及三者之间的关系

时钟周期

时钟周期也称为振荡周期,定义为时钟脉冲的倒数(可以这样来理解,时钟周期就是单片机外接晶振的倒数,例如12M的晶振,它的时间周期就是1/12us),是计算机中最基本的、最小的时间单位。

在一个时钟周期内,CPU仅完成一个最基本的动作。

对于某种单片机,若采用了1MHZ的时钟频率,则时钟周期为1us;若采用4MHZ的时钟频率,则时钟周期为250us。

由于时钟脉冲是计算机的基本工作脉冲,它控制着计算机的工作节奏(使计算机的每一步都统一到它的步调上来)。

显然,对同一种机型的计算机,时钟频率越高,计算机的工作速度就越快。

但是,由于不同的计算机硬件电路和器件的不完全相同,所以其所需要的时钟周频率范围也不一定相同。

我们学习的8051单片机的时钟范围是1.2MHz-12MHz。

在8051单片机中把一个时钟周期定义为一个节拍(用P表示),二个节拍定义为一个状态周期(用S表示)。

机器周期

在计算机中,为了便于管理,常把一条指令的执行过程划分为若干个阶段,每一阶段完成一项工作。

例如,取指令、存储器读、存储器写等,这每一项工作称为一个基本操作。

完成一个基本操作所需要的时间称为机器周期。

一般情况下,一个机器周期由若干个S周期(状态周期)组成。

8051系列单片机的一个机器周期同6个S周期(状态周期)组成。

前面已说过一个时钟周期定义为一个节拍(用P表示),二个节拍定义为一个状态周期(用S表示),8051单片机的机器周期由6个状态周期组成,也就是说一个机器周期=6个状态周期=12个时钟周期。

指令周期

指令周期是执行一条指令所需要的时间,一般由若干个机器周期组成。

指令不同,所需的机器周期数也不同。

对于一些简单的的单字节指令,在取指令周期中,指令取出到指令寄存器后,立即译码执行,不再需要其它的机器周期。

对于一些比较复杂的指令,例如转移指令、乘法指令,则需要两个或者两个以上的机器周期。

通常含一个机器周期的指令称为单周期指令,包含两个机器周期的指令称为双周期指令。

3、寻址方式

  寻址方式就是寻找操作数或操作数地址的方式。

8086提供了与操作数有关和与I/O端口地址有关的两类寻址方式。

与操作数有关的寻址方式有七种,分别是立即寻址,寄存器寻址,直接寻址,寄存器间接寻址,寄存器相对寻址,基址加变址寻址,相对基址加变址寻址;与I/0端口有关的寻址方式有直接端口寻址和间接端口寻址方式。

  一、与操作数有关的寻址方式

  1.立即数寻址方式

  操作数直接存放在指令中,紧跟在操作码之后的寻址方式就是立即数寻址方式。

  例如:

  MOVAX,2345H

  MOVAL,0EH

  2.寄存器寻址

  操作数存放在CPU的内存寄存器时,可在指令中指出寄存器名,这就是寄存器寻址方式。

  例如:

  MOVAX,BX

  ADDAX,BX

  3.存储器寻址方式

  8086指令系统提供了以下5种针对存储器的寻址方式。

  直接寻址、寄存器间接寻址、寄存器相对寻址、基址加变址寻址和相对基址加变址寻址。

用于说明操作数所在存储单元的地址。

由于总线接口单元BIU能根据需要自动引用段寄存器得到段值,所以这五种方式也就是确定存放操作数的存储单元有效地址EA的方法。

有效地址EA是一个16位的无符号数,在利用这五种方法计算有效地址时,所得的结果认为是一个无符号数。

  

(1).直接寻址:

  指令中给出的地址码即为操作数的有效地址,就是直接寻址方式。

  例子:

MOVAX,[2000H]

  MOVAX,2000H-->2000H为存放操作数单元号的符号地址

  上面两者是不等效的

  

(2).寄存器间接寻址方式:

  你就想成:

你已经站在你要找的"门户号(家)"的"单元号",你要找到它,必须知道它在当前"单元号"几楼.假如它在6楼,那你就上到6楼就OK了!

!

注意,最高只有16楼,因为什么呢?

那就用DEBUG的D命令看看呀,慢慢数哦,呵呵!

!

  例子:

MOVAX,[BX]

  计算公式:

物理地址=16d*(DS)+(BX)

  物理地址=16d*(DS)+(SI)

  物理地址=16d*(DS)+(DI)

  物理地址=16d*(SS)+(BP)

  (3).寄存器相对寻址方式:

  你就想成:

你要找的"门户号(家)"其实就在你家的楼上或者楼下,你要找到它,就必须知道它在你楼上几楼,或者在楼下几楼!

就OK了!

  例子:

MOVAX,COUNT[SI]

  MOVAX,[COUNT+SI]

  其中COUNT为位移量的符号地址

  计算公式:

物理地址=16d*(DS)+(BX)+8位位移量

  物理地址=16d*(SI)+(BX)+16位位移量

  物理地址=16d*(DI)+(BX)+16位位移量

  物理地址=16d*(SS)+(BP)+8位偏移量

  (4).基址变址寻址方式:

  你就想成:

你要找的"门户号(家)"是跟住在同一栋楼的不同"单元号",你要找到它,就必须知道它是该栋的哪个"单元号",并且住在几楼!

那样你就可以找到它了!

  例子:

MOVAX,[BX][DI]

  MOVAX,[BX+DI]

  计算公式:

物理地址=16d*(DS)+(BX)+(SI)

  物理地址=16d*(DS)+(BX)+(DI)

  物理地址=16d*(SS)+(BP)+(SI)

  物理地址=16d*(SS)+(BP)+(DI)

  (5).相对基址变址寻址方式:

  你就想成:

你要找的"门户号(家)"是跟住在同一栋楼的不同"单元号",它比你高几层楼或者低几层楼,然后用的你目前的楼数+/-就可以得出你要找的住在几楼了!

  例子:

MOVAX,MASK[BX][SI]

  MOVAX,MASK[BX+SI]

  MOVAX,[MASK+BX+SI]

  以上三个例子是等效的!

!

  计算公式:

物理地址=16d*(DS)+(BX)+(SI)+8位位移量

  物理地址=16d*(DS)+(BX)+(DI)+16位位移量

  物理地址=16d*(SS)+(BP)+(SI)+8位位移量

  物理地址=16d*(SS)+(BP)+(DI)+16位位移量

  上述共计七种操作数寻址方式,与80C51单片机的完全一致。

  二、与I/0端口有关的寻址方式

  8086微处理器采用独立编址的I/0端口,有专门的输入指令IN和输出指令OUT,寻址方式有以下两种。

  1.直接端口寻址

  直接端口寻址是在指令中直接给出要访问的端口地址,一般采用2位十六进制数表示,也可以是符号,访问的端口范围0~255.

  例如:

  INAL,20H

  表示从I/0端口地址为20H的端口中取数据送入AL寄存器中。

  2.间接端口寻址

  若访问的端口地址大于255时,就要用间接寻址方式。

可以访问的端口范围0~65535.

  例如:

  MOVDX,356H;将端口地址356H送入DX寄存器

  OUTDX,AL;将AL中的内容输出到DX指定的端口

一、基础实验

1、熟悉μ’nSP™IDE环境下的汇编程序的编写

2、熟悉μ’nSP™IDE环境下的C语言的编写

1、2两个实验通过观察寄存器窗口、变量窗口和内存窗口并单步运行来了解程序的执行情况。

3、使用汇编语言实现A口的输出实验

4、使用C语言实现A口的输出实验

5、使用汇编语言实现A口为输入B口为输出实验

6、使用C语言实现A口为输入B口为输出实验

3、4、5、6四个实验

方法一:

采用软件仿真的方法,观察了解程序的执行情况,注意:

DownLoad后要按下F5键才能看到仿真的结果。

方法二:

采用硬件运行的方法来验证结果,下载到实验系统中以后就使它自动运行。

方法三:

采用软硬件调试的方法来验证结果,下载到实验系统中以后通过IDE的各种调试方法(比如:

单步运行)来运行程序。

试验:

自己新建工程和源文件,把实验4中的main.c的内容复制、粘贴到新源文件中,并且要hardware.asm文件复制到新工程文件夹中,然后将hardware.asm文件加入工程的源文件中,之后编译、下载、运行,结果正确。

注意:

实验5和6时,按键的输入必须在拨码开关S28处于上面时才可以。

5、6两个实验中的key.asm修改为:

//Progarm:

Theheadfileforkey.asminassemblyview

//Arrangedby:

AndyHsu

//Lastmodifieddate:

//Functions:

//F_Key_Scan_Initial;

//F_Key_Scan_ServiceLoop;

//F_Key_DebounceCnt_Down;

//

//callF_SP_GetCh;

.INCLUDEhardware.inc;

.PUBLICF_Key_Scan_Initial;

.PUBLICF_Key_Scan_ServiceLoop;

.PUBLICF_Key_DebounceCnt_Down;

.PUBLIC_SP_GetCh;

.PUBLICF_SP_GetCh;

.PUBLICR_KeyStrobe;

//////////////////////////////////////////////////////////////////

//RAMDefineArea

//////////////////////////////////////////////////////////////////

.RAM

.VARR_DebounceReg;//forkeyboardscan每次的即时键值

.VARR_KeyStrobe;//forkeyboardscan去抖动后的最终键值

.VARR_DebounceCnt;//forkeyboardscan

.DEFINEC_DebounceCnt0x0002;

.CODE

//////////////////////////////////////////////////////////////////

//Function:

InitializationforF_Key_Scan_ServiceLoop

//////////////////////////////////////////////////////////////////

F_Key_Scan_Initial:

r1=0x0000;//

[R_DebounceReg]=r1;//

r1=C_DebounceCnt;//

[R_DebounceCnt]=r1;//resetdebouncecounter

retf;

//////////////////////////////////////////////////////////////////

//Function:

F_Key_Scan_ServiceLoop

//////////////////////////////////////////////////////////////////

F_Key_Scan_ServiceLoop:

r1=[P_IOA_Data];//getkeydatafromIOA

r1=r1and0xff;//

r2=[R_DebounceReg];//

[R_DebounceReg]=r1;//

cmpr2,[R_DebounceReg];//

jeL_KS_StableTwoSample;//

r1=C_DebounceCnt;//debouncetimesetting

[R_DebounceCnt]=r1;//

retf;//

L_KS_StableTwoSample:

r1=[R_DebounceCnt];//

jzL_KS_StableOverDebounce;//

retf;

L_KS_StableOverDebounce:

r1=[R_DebounceReg];//

[R_KeyStrobe]=r1;//savestablekeycodetoR_KeyStrobe

retf;

//////////////////////////////////////////////////////////////////

//Function:

debouncecounterdowncount

//////////////////////////////////////////////////////////////////

F_Key_DebounceCnt_Down:

r1=[R_DebounceCnt];//DebouncesubroutineforF_IO_Key_Scan:

jzL_DebounceCntZero;//stopcountifzero

r1-=0x0001;//

[R_DebounceCnt]=r1;//

L_DebounceCntZero:

//

retf;//

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

//Function:

GetKeycodeforI/OPort

//Destoryregister:

r1,r2

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

_SP_GetCh:

F_SP_GetCh:

r1=[R_KeyStrobe];//GetKeycode

r2=0x0000;//ClearKeyStrobefornextkey

[R_KeyStrobe]=r2;//

retf;

//Endofkey.asm

7、定时器TimerA/B实验

本实验的几个关键问题:

(1)溢出频率的计算

Fosc默认为24.576MHZ

time_clk=Fosc/2=12.288MHZ

情况一:

若r1=0x0000;//设定TA_TIMEOUT/16=(time_clk/65535)/16=11.7Hz

[P_TimerA_Data]=r1;

并且占空比为50%,波形和二极管的闪烁现象比较明显。

情况二:

若r1=0xff9f;//设定TA_TIMEOUT/16=(time_clk/96)/16=8kHz

[P_TimerA_Data]=r1;

并且占空比为50%,波形很好,但二极管的闪烁现象没有。

情况三:

若r1=0xc000;//设定TA_TIMEOUT/16=(time_clk/16383)/16=46.9Hz

[P_TimerA_Data]=r1;

并且占空比为50%,波形很好,但二极管的闪烁现象也没有。

(2)改变系统频率和PWM波占空比的方法

方法一:

直接改变r1的值太麻烦,因为每次必须查找书上对应的表格

r1=time_pwm或time_clk;

[P_TimerA_Ctrl]=r1;

方法二:

//选择不同的时钟源,占空比都为8/16,观察示波器中频率的变化

.definetimefosc_20x0230;//clkA选择fosc/2Hz

.definetimefosc_2560x0231;//clkA选择fosc/256Hz

.definetimeclk_327680x0232;//clkA选择32768Hz

.definetimeclk_81920x0233;//clkA选择8192Hz

.definetimeclk_40960x0234;//clkA选择4096Hz

.definetimeclk_20480x0205;//clkB选择2048Hz

.definetimeclk_10240x020d;//clkB选择1024Hz

.definetimeclk_2560x0215;//clkB选择256Hz

.definetimeclk_40x0225;//clkB选择4Hz

.definetimeclk_20x022d;//clkB选择2Hz

//频率选择fosc/2Hz,设置不同的占空比

.definetimepwm_10x0070;//脉宽选择1/16

.definetimepwm_20x00b0;//脉宽选择2/16

.definetimepwm_30x00f0;//脉宽选择3/16

.definetimepwm_40x0130;//脉宽选择4/16

.definetimepwm_50x0170;//脉宽选择5/16

.definetimepwm_60x01b0;//脉宽选择6/16

.definetimepwm_70x01f0;//脉宽选择7/16

.definetimepwm_80x0230;//脉宽选择8/16

.definetimepwm_90x0270;//脉宽选择9/16

.definetimepwm_100x02b0;//脉宽选择10/16

.definetimepwm_110x02f0;//脉宽选择11/16

.definetimepwm_120x0330;//脉宽选择12/16

.definetimepwm_130x0370;//脉宽选择13/16

.definetimepwm_140x03b0;//脉宽选择14/16

.definetime_clktimefosc_256;//占空比为50%时频率的选择

.definetime_pwmtimepwm_8;//频率为fosc/2Hz时脉宽的选择

以上方法也不好,因为频率和脉宽要求同时改变时,就非常麻烦。

方法三:

//实现功能:

1)选择不同的时钟源,同一占空比一定,观察示波器中频率的变化

//2)选择同一时钟源,改变占空比,观察示波器,比较脉冲宽度

//3)时钟源频率和占空比同时改变

//日期:

2003/6/9

//============================================================

//频率的选择

.definetimefosc_20x0030;//clkA选择fosc/2Hz

.definetimefosc_2560x0031;//clkA选择fosc/256Hz

.definetimeclk_327680x0032;//clkA选择32768Hz

.definetimeclk_81920x0033;//clkA选择8192Hz

.definetimeclk_40960x0034;//clkA选择4096Hz

.definetimeclk_20480x0005;//clkB选择2048Hz

.definetimeclk_10240x000d;//clkB选择1024Hz

.definetimeclk_2560x0015;//clkB选择256Hz

.definetimeclk_40x0025;//clkB选择4Hz

.definetimeclk_20x002d;//clkB选择2Hz

//占空比的选择

.definetimepwm_10x0040;//脉宽选择1/16

.definetimepwm_20x0080;//脉宽选择2/16

.definetimepwm_30x00c0;//脉宽选择3/16

.definetimepwm_40x0100;//脉宽选择4/16

.definetimepwm_50x0140;//脉宽选择5/16

.definetimepwm_60x0180;//脉宽选择6/16

.definetimepwm_70x01c0;//脉宽选择7/16

.definetimepwm_80x0200;//脉宽选择8/16

.definetimepwm_90x0240;//脉宽选择9/16

.definetimepwm_100x0280;//脉宽选择10/16

.definetimepwm_110x02c0;//脉宽选择11/16

.definetimepwm_120x0300;//脉宽选择12/16

.definetimepwm_130x0340;//脉宽选择13/16

.definetimepwm_140x0380;//脉宽选择14/16

.definetime_clktimefosc_2;//频率选择

.definetime_pwmtimepwm_2;//脉宽选择

.defineP_TimerA_Data0x700A;

.defineP_TimerA_Ctrl0x700B;

.defineP_IOB_DATA0x7005;

.defineP_IOB_DIR0x7007;

.defineP_IOB_ATTRI0x7008;

.defineP_Feedback0x7009;

.definep_watchdog_clear0x7012;

r1=time_clk|time_pwm;

[P_TimerA_Ctrl]=r1;

8、系统时钟实验

没有问题,能否改成跑马灯的形式。

9、FIQ中断实验

FIQ三个中断的入口地址均为FFF6H,因此产生这种中断时必须要进行判断。

FIQ_fosc/1024和IRQ0_fosc/1024类似于时基中断,也就是给定一个系统时钟频率比如24.576MHZ,中断频率就为24.576MHZ/1024,凌阳技

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 笔试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1