简介:
PIC23H的CPU为带增强指令的哈弗结构,24位指令宽度,可寻址存储空间达4M*24bits。
除了改变程序流的指令外,其他的指令都是单周期指令。
寄存器:
带16个工作寄存器,每一个寄存器都可以用作数据地址和地址偏移。W15用来存储中断时候的堆栈指针。W14用来作为LNK和UNLK的堆栈帧指针。(?)
数据空间可以寻址64KB,或者32个字。高达32KB的数据空间可以映射到程序空间,在PSVPAG中设置,详细内容可以参考程序存储器中的内容。
寻址模式:
- 自寻址,无需操作
- 相对寻址
- 立即数寻
- 存储器直接寻址
- 寄存器直接寻址
- 寄存器间接寻址
下面的操作可以单指令完成:
- 数据或者程序诗句存储器读
- 工作寄存器读
- 数据存储器写
- 程序存储器读
因此,如果要操作A+B=C则三条指令就可以搞定。
算术逻辑单元:
乘法:17*17位的数据可以单指令周期完成,并且支持各种不同类型的数据,16*16,8*8均在单指令周期完成。
除法:支持迭代算法,32/16,16/16通过19个指令周期完成,计算过程中可以产生中断。
CPU方框图:
编程模块:
下面是可以被指令直接操作的模块,其中:
- W0~W15为工作寄存器阵列
- PC为23位指针
- SR为CPU的状态寄存器
- SPLIM:堆栈最大值
- TBLPAG:编程空间页地址
- PSVPAG:程序空间可见页地址
- RCOUNT:重复计数寄存器
- CORCON:CPU控制寄存器
工作寄存器:
16个工作寄存器可以用于存储数据,地址或者是偏置值,具体功能取决于指令,PIC24H的指令集分为两种:
- 寄存器指令:直接操作W寄存器,比如MOV W0 ,W1,和相加等。
- 文件寄存器指令,只有W0可以作为文件寄存器,名称为WREG,里面可以存放数据和直接存储到存储单元中,比如:
MOV WREG,0X0100
ADD 0X0100,WREG
W寄存器的映射:既然W寄存器是一个映射,也可以直接给出地址,比如
MOV 0X0004,W10,这里0X0004就是W2
也可以,将W寄存器中的作为一个地址指针直接操作,如
MOV W1,[W2++]
W寄存器和字节模式的指令:字节指令,只会影响到目标寄存器的最低有效位,如果经过映射,则LSB和MSB都可以操作。
SHADOW寄存器:
影子寄存器,这个寄存器主要是用于在压栈和解压的时候,快速的备份起来。
主要有一下的东西在程序跳转和中断服务程序之前要保存:
这里要注意的是,影子寄存器只有一级,如果要使用多个任务的时候,要记得保存其他的备份。
未初始化的W寄存器复位
所有的复位将清零W寄存器,在写之前都是未进行初始化的,试图使用一个未初始化的寄存器将引发器件复位。写W寄存器就是一个初始化过程,写字节不影响初始化检测逻辑。
软堆栈指针
W15作为一个专用的SSP自动被意外处理,调用和返回读写。同时也可以作为一个通用寄存器。这样简化了对堆栈指针的读写操作。
初始化W15为0X8000,如下,也就是SFR后,紧跟着开辟堆栈:
软堆栈通过PUSH和POP指令来实现,如下:
PUSH W0,就是将W0的数据保存到W15++的位置,也就是栈顶的位置。
POP W0,就是将--W15的内容解压出来,赋值给W0
还有一个要注意的地方:
PUSH W0
PUSH W1
POP W3
此时,W3为W1的内容,也就是说,解压出来赋值,而不是只能操作POP W2和POP W1,并且要注意顺序。
W14,软件堆栈帧指针。
这个是作为子程序的堆栈使用的,用于LNK和UNLK两条指令,具体的例子可以参考DS70157的编程手册。
堆栈指针溢出:
在中断的时候里面讲到过,如果堆栈的指针超出了限制的值,将产生一个复位。
堆栈指针错误:
如果指针指向0X0800更低的地址,堆栈出错产生。
CPU的寄存器描述:
- 状态寄存器分为两部分
- SRL:包括CPU的中断优先级,以及重复上一条指令的状态REPEAT。
- SRH:只有一位:DC,半溢出。
- 控制寄存器,只有两位,PSV和IPL3
- TBLPAG指针,在读写时HOLD住程序存储器地址的高8为,具体看程序存储器的内容。
- PSVPAG指针,映射可见页的指针, 具体看程序存储器的内容。
- DISICNT:关掉多久的中断使能,见中断内容
算术逻辑单元:
ALU影响:C,N,OV,DC位,具体指令影响的位,可以在编程参考手册中找到。
乘法和除法支持:
支持如下的乘除法运算:
乘法器支持多种数据类型的运算,运算的结果有些可以指定存储位置,有些是有默认位置的,而有些位置是不能存放的(W14和W15).
类型不同,指令也是不同的,如下:
除法指令支持两种除法模式,商和余数存储在W0和W1中,且以为每一位除数占用一条指令,所以两种算法的时间是一样的,这里要注意的是,除法占用的时间内,不能进行其他操作,所以必须用REPEAT的指令,并且由用户来添加。
还有一点需要注意的是,除法是可以由中断来打断的,并且除数为0时候,将进入陷阱复位。
编译器友好结构
为了产生高效的C码,结构有如下的设计
- 每条指令都可以进行数据存储器读,工作寄存器读,和数据存储器写,程序存储器读的操作,所以A+B=C的操作单指令就可以完成
- 指令的地址模式非常灵活,适用于编译器需求
- 工作寄存器以及W15用于堆栈的设计
- 数据空间线性间接寻址
- 部分数据空间映射到程序空间,允许常数的存储,加快了数据的读写。
支持多位位移
指令如下:
指令流的类型:
大部分都是单指令周期,但是也有如下的类型不止单周期,PIC24HJ的指令流类型有如下7种:
- 单指令字,单周期,大部分都是这种,也就是一个指令周期取,一个指令周期执行
- 单指令字,双周期,这种用于那种需要取两次操作数的时候
- 单指令字,两到三指令周期,主要用于跳转,取第一个,执行,第二个,需要丢掉,但是此时第三个也已经取了,还要丢掉一次,同时取第四个数,才开始执行第四个数。
- 还有一种是需要丢掉两个数据的情况,类似上面的问题。
- 有些指令需要三条周期,如RETFIE,RETURN,RETLW指令
- TABLE读写
- 两指令字,两指令周期
- 跟地址寄存器拥堵有关,比如两个X_DATA空间的读写操作
编程流的循环控制:
重复:可以设置重复的次数,紧跟在REPEAT指令后面。也可以设置RCOUNT里面。
同时这个循环还有一个标志位,在上面介绍过。
在循环的时候,同样可以中断。并且,这个指令也可以在中断内部使用,当同时使用的时候要注意堆栈。
也可以软件清RCCUNT。
有些指令后面是不能立刻跟一条循环指令的,如:
- 程序流控制指令
- REPEAT指令
- DISI,ULNK,LNK,PWRSAV,RESET指令
- MOV.D指令
地址寄存器的操作:
看下表:
指令拥堵的时候,有两个问题要考虑:时间和在中断情况下的使用。
文章评论(0条评论)
登录后参与讨论