您的位置:首页单片机AVR单片机
内容搜索:
阅读内容
背景:#EDF0F5 #FAFBE6 #FFF2E2 #FDE6E0 #F3FFE1 #DAFAF3 #EAEAEF 默认  

AVR教程ATmega16 简介(3)

[日期:2008-06-02 ] [来源:net 作者:佚名] [字体: (投递新闻)

ATmega16 指令执行时序

这一节介绍指令执行过程中的访问时序。AVR CPU 由系统时钟clkCPU 驱动。此时钟直接来自选定的时钟源。芯片内部不对此时钟进行分频。

Figure 6
说明了由Harvard 结构决定的并行取指和指令执行,以及可以进行快速访问的寄存器文件的概念。这是一个基本的流水线概念,性能高达1 MIPS/MHz,具有优良的性价比、功能/ 时钟比、功能/ 功耗比。

Figure 7 演示的是寄存器文件内部访问时序。在一个时钟周期里,ALU 可以同时对两个寄存器操作数进行操作,同时将结果保存到目的寄存器中去。

ATmega16 复位与中断处理

AVR有不同的中断源。每个中断和复位在程序空间都有独立的中断向量。所有的中断事件都有自己的使能位。当使能位置位,且状态寄存器的全局中断使能位I 也置位时,中断可以发生。根据程序计数器PC 的不同,在引导锁定位BLB02 BLB12 被编程的情况下,中断可能被自动禁止。这个特性提高了软件的安全性。详见 P247“ 存储器编程的描述。

程序存储区的最低地址缺省为复位向量和中断向量。完整的向量列表请参见 P43“中断。列表也决定了不同中断的优先级。向量所在的地址越低,优先级越高。RESET 具有最高的优先级,第二个为INT0 – 外部中断请求0。通过置位MCU 控制寄存器 (MCUCR) IVSEL,中断向量可以移至引导Flash的起始处。编程熔丝位BOOTRST也可以将复位向量移至引导Flash的起始处。具体参见P234“支持引导装入程序在写的同时可以读(RWW,Read-While-Write) 的自我编程能力

任一中断发生时全局中断使能位I 被清零,从而禁止了所有其他的中断。用户软件可以在中断程序里置位I 来实现中断嵌套。此时所有的中断都可以中断当前的中断服务程序。执行RETI 指令后I 自动置位。

从根本上说有两种类型的中断。第一种由事件触发并置位中断标志。对于这些中断,程序计数器跳转到实际的中断向量以执行中断处理程序,同时硬件将清除相应的中断标志。中断标志也可以通过对其写1” 的方式来清除。当中断发生后,如果相应的中断使能位为0”,则中断标志位置位,并一直保持到中断执行,或者被软件清除。类似的,如果全局中断标志被清零,则所有已发生的中断都不会被执行,直到I 置位。然后挂起的各个中断按中断优先级依次执行。

第二种类型的中断则是只要中断条件满足,就会一直触发。这些中断不需要中断标志。若中断条件在中断使能之前就消失了,中断不会被触发。

AVR
退出中断后总是回到主程序并至少执行一条指令才可以去执行其他被挂起的中断。要注意的是,进入中断服务程序时状态寄存器不会自动保存,中断返回时也不会自动恢复。这些工作必须由用户通过软件来完成。

使用CLI 指令来禁止中断时,中断禁止立即生效。没有中断可以在执行CLI 指令后发生,即使它是在执行CLI 指令的同时发生的。下面的例子说明了如何在写EEPROM 时使用这个指令来防止中断发生以避免对EEPROM 内容的可能破坏。

汇编代码例程
in r16, SREG ;
保存SREG
cli ;
禁止中断
sbi EECR, EEMWE ;
启动 EEPROM 写操作
sbi EECR, EEWE
out SREG, r16 ;
恢复SREG (I )

C 代码例程
char cSREG;
cSREG = SREG; /*
保存SREG */
/*
禁止中断*/
_CLI();
EECR |= (1<<EEMWE); /*
启动 EEPROM 写操作*/
EECR |= (1<<EEWE);
SREG = cSREG; /*
恢复SREG (I ) */

使用SEI 指令使能中断时,紧跟其后的第一条指令在执行任何中断之前一定会首先得到执行。

汇编代码例程
sei ;
置位全局中断使能标志
sleep ;
进入休眠模式,等待中断发生
;
注意: 在执行任何被挂起的中断之前MCU 将首先进入休眠模式

C
代码例程
_SEI(); /*
置位全局中断使能标志*/
_SLEEP(); /*
进入休眠模式,等待中断发生*/
/*
注意: 在执行任何被挂起的中断之前MCU 将首先进入休眠模式*/

AVR
中断响应时间最少为4 个时钟周期。4 个时钟周期后,程序跳转到实际的中断处理例程。在这4 个时钟期期间PC 自动入栈。在通常情况下,中断向量为一个跳转指令,此跳转需要3 个时钟周期。如果中断在一个多时钟周期指令执行期间发生,则在此多周期指令执行完毕后MCU 才会执行中断程序。若中断发生时MCU 处于休眠模式,中断响应时间还需增加4 个时钟周期。此外还要考虑到不同的休眠模式所需要的启动时间。这个时间不包括在前面提到的时钟周期里。

中断返回需要4 个时钟。在此期间PC( 两个字节) 将被弹出栈,堆栈指针加二,状态寄存器SREG I 置位。

ATmega16 Flash程序存储器

系统内可编程的Flash 程序存储器
ATmega16
具有16K字节的在线编程Flash,用于存放程序指令代码。因为所有的AVR指令为16 位或32 位,故而Flash 组织成8K x 16 位的形式。用户程序的安全性要根据Flash程序存储器的两个区:引导(Boot) 程序区和应用程序区,分开来考虑。

Flash
存储器至少可以擦写10,000次。ATmega16的程序计数器(PC)13位,因此可以寻址8K 字的程序存储器空间。引导程序区以及相关的软件安全锁定位请参见 P234“ 支持引导装入程序在写的同时可以读(RWW, Read-While-Write) 的自我编程能力,而 P247“存储器编程详述了用SPI JTAG 接口实现对Flash 的串行下载。

常数可以保存于整个程序存储器地址空间( 参考LPM 加载程序存储器指令的说明)。取指与执行时序图请参见 P11“ 指令执行时序

ATmega16 SRAM数据存储器

SRAM数据存储器

Figure 9
给出了ATmega16 SRAM 空间的组织结构。



1120 个数据存储器包括了寄存器文件、I/O 存储器及内部数据SRAM。起始的96 个地址为寄存器文件与64 I/O 存储器,接着是1024 字节的内部数据SRAM

数据存储器的寻址方式分为5 种:直接寻址、带偏移量的间接寻址、间接寻址、带预减量的间接寻址和带后增量的间接寻址。寄存器文件中的寄存器R26 R31 为间接寻址的指针寄存器。

直接寻址范围可达整个数据区。

带偏移量的间接寻址模式能够寻址到由寄存器Y Z 给定的基址附近的63 个地址。

在自动预减和后加的间接寻址模式中,寄存器XY Z 自动增加或减少。

ATmega16
的全部32个通用寄存器、64I/O寄存器及1024个字节的内部数据SRAM可以通过所有上述的寻址模式进行访问。寄存器文件的描述见 P9“ 通用寄存器文件

SRAM数据存储器访
本节说明访问内部存储器的时序。如Figure 10 所示,内部数据SRAM 访问时间为两个clkCPU 时钟。

ATmega16 EEPROM数据存储器

ATmega16 包含512 字节的EEPROM 数据存储器。它是作为一个独立的数据空间而存在的,可以按字节读写。EEPROM 的寿命至少为100,000 次擦除周期。EEPROM 的访问由地址寄存器、数据寄存器和控制寄存器决定。

通过SPIJTAG及并行电缆下载EEPROM数据的操作请分别参见 P260 P265P250

EEPROM / 写访问

EEPROM
/ 写访问EEPROM 的访问寄存器位于I/O 空间。

EEPROM
的写访问时间由Table 1给出。自定时功能可以让用户软件监测何时可以开始写下一字节。用户操作EEPROM 需要注意如下问题:在电源滤波时间常数比较大的电路中,上电/ 下电时VCC 上升/ 下降速度会比较慢。此时CPU 可能工作于低于晶振所要求的电源电压。请参见 P20“ 防止EEPROM 数据丢失以避免出现EEPROM 数据丢失的问题。

为了防止无意识的EEPROM 写操作,需要执行一个特定的写时序。具体参看EEPROM控制寄存器的内容。

执行EEPROM 读操作时, CPU 会停止工作4 个周期,然后再执行后续指令;执行EEPROM 写操作时, CPU 会停止工作2 个周期,然后再执行后续指令。

EEPROM 地址寄存器- EEARHEEARL

? Bits 15..9 – Res: 保留
保留位,读操作返回值为零。

? Bits 8..0 – EEAR8..0: EEPROM
地址
EEPROM
地址寄存器– EEARHEEARL指定了512字节的EEPROM空间。EEPROM地址是线性的,从0 511EEAR 的初始值没有定义。在访问EEPROM 之前必须为其赋予正确的数据。

EEPROM 数据寄存器  EEDR

? Bits 7..0 – EEDR7.0: EEPROM 数据
对于EEPROM 写操作, EEDR 是需要写到EEAR 单元的数据;对于读操作, EEDR 是从地址EEAR 读取的数据。

EEPROM 控制寄存器- EECR

? Bits 7..4 – Res: 保留
保留位,读操作返回值为零。

? Bit 3 – EERIE:
使能EEPROM 准备好中断
SREG I "1",则置位EERIE 将使能EEPROM 准备好中断。清零EERIE 则禁止此中断。当EEWE 清零时EEPROM 准备好中断即可发生。

? Bit 2 – EEMWE: EEPROM
主机写使能
EEMWE
决定了EEWE置位是否可以启动EEPROM写操作。当EEMWE"1"时,在4个时钟周期内置位EEWE 将把数据写入EEPROM 的指定地址;若EEMWE "0“,则操作EEWE 不起作用。EEMWE 置位后4 个周期,硬件对其清零。见EEPROM 写过程中对EEWE 位的描述。

? Bit 1 – EEWE: EEPROM
写使能
EEWE
EEPROM 写操作的使能信号。当EEPROM 数据和地址设置好之后,需置位EEWE以便将数据写入EEPROM。此时EEMWE必须置位,否则EEPROM写操作将不会发生。写时序如下( 3 步和第4 步的次序并不重要)
1.
等待EEWE 位变为零
2.
等待SPMCSR 中的SPMEN 位变为零
3.
将新的EEPROM 地址写入EEAR( 可选)
4.
将新的EEPROM 数据写入EEDR( 可选)
5.
EECR 寄存器的EEMWE "1",同时清零EEWE
6.
在置位EEMWE 4 个周期内,置位EEWE

CPU Flash 存储器的时候不能对EEPROM 进行编程。在启动EEPROM 写操作之前软件必须检查 Flash 写操作是否已经完成。步骤(2) 仅在软件包含引导程序并允许CPUFlash 进行编程时才有用。如果CPU 永远都不会写Flash,步骤(2) 可省略。请参见P234“支持引导装入程序在写的同时可以读(RWW, Read-While-Write)的自我编程能力

注意:如果在步骤5 6 之间发生了中断,写操作将失败。因为此时EEPROM 写使能操作将超时。如果一个操作EEPROM的中断打断了另一个EEPROM操作,EEAR EEDR寄存器可能被修改,引起EEPROM 操作失败。建议此时关闭全局中断标志I。经过写访问时间之后,EEWE 硬件清零。用户可以凭借这一位判断写时序是否已经完成。EEWE 置位后, CPU 要停止两个时钟周期才会运行下一条指令。

? Bit 0 – EERE: EEPROM
读使能
EERE
EEPROM读操作的使能信号。当EEPROM地址设置好之后,需置位EERE以便将数据读入EEAREEPROM 数据的读取只需要一条指令,且无需等待。读取EEPROMCPU 要停止4 个时钟周期才可以执行下一条指令。

用户在读取EEPROM 时应该检测EEWE。如果一个写操作正在进行,就无法读取EEPROM,也无法改变寄存器EEAR。 经过校准的片内振荡器用于EEPROM定时。

Table 1
CPU访问EEPROM的典型时间。

下面的代码分别用汇编和C 函数说明如何实现EEPROM 的写操作。在此假设中断不会在执行这些函数的过程当中发生。同时还假设软件没有Boot Loader。若Boot Loader 存在,则EEPROM 写函数还需要等待正在运行的SPM 命令的结束。

汇编代码例程
EEPROM_write:
;
等待上一次写操作结束
sbic EECR,EEWE
rjmp EEPROM_write
;
设置地址寄存器 (r18:r17)
out EEARH, r18
out EEARL, r17
;
将数据写入数据寄存器(r16)
out EEDR,r16
;
置位EEMWE
sbi EECR,EEMWE
;
置位EEWE 以启动写操作
sbi EECR,EEWE
ret
C
代码例程
void EEPROM_write(unsigned int uiAddress, unsigned char ucData)
{
/*
等待上一次写操作结束 */
while(EECR & (1<<EEWE))
;
/*
设置地址和数据寄存器*/
EEAR = uiAddress;
EEDR = ucData;
/*
置位EEMWE */
EECR |= (1<<EEMWE);
/*
置位EEWE 以启动写操作*/
EECR |= (1<<EEWE);
}

下面的例子说明如何用汇编和C 函数来读取EEPROM,在此假设中断不会在执行这些函数的过程当中发生。

汇编代码例程
EEPROM_read:
;
等待上一次写操作结束
sbic EECR,EEWE
rjmp EEPROM_read
;
设置地址寄存器 (r18:r17)
out EEARH, r18
out EEARL, r17
;
设置EERE 以启动读操作
sbi EECR,EERE
;
自数据寄存器读取数据
in r16,EEDR
ret
C
代码例程
unsigned char EEPROM_read(unsigned int uiAddress)
{
/*
等待上一次写操作结束 */
while(EECR & (1<<EEWE))
;
/*
设置地址寄存器*/
EEAR = uiAddress;
/*
设置EERE 以启动读操作*/
EECR |= (1<<EERE);
/*
自数据寄存器返回数据 */
return EEDR;
}

在掉电休眠模式下的EEPROM写操作

若程序执行掉电指令时EEPROM 的写操作正在进行, EEPROM 的写操作将继续,并在指定的写访问时间之前完成。但写操作结束后,振荡器还将继续运行,单片机并非处于完全的掉电模式。因此在执行掉电指令之前应结束EEPROM 的写操作。

防止EEPROM 数据丢失

若电源电压过低,CPU EEPROM 有可能工作不正常,造成EEPROM 数据的毁坏( 丢失)。这种情况在使用独立的EEPROM 器件时也会遇到。因而需要使用相同的保护方案。

由于电压过低造成EEPROM 数据损坏有两种可能:一是电压低于EEPROM 写操作所需要的最低电压;二是CPU 本身已经无法正常工作。

EEPROM
数据损坏的问题可以通过以下方法解决:
当电压过低时保持AVR RESET信号为低。这可以通过使能芯片的掉电检测电路BOD来实现。如果BOD 电平无法满足要求则可以使用外部复位电路。若写操作过程当中发生了复位,只要电压足够高,写操作仍将正常结束。

ATmega16 I/O存储器
ATmega16
所有的I/O及外设都被放置于I/O空间。所有的I/O位置都可以通过IN OUT指令来访问,在32 个通用工作寄存器和I/O 之间传输数据。 地址为0x00 - 0x1F I/O 寄存器还可用SBI CBI 指令直接进行位寻址,而SBIS SBIC 则用来检查某一位的值。更多内容请参见指令集。使用IN OUT 指令时地址必须在 0x00 - 0x3F 之间。如果要象SRAM 一样通过LD ST 指令访问I/O 寄存器,相应的地址要加上0x20

为了与后续产品兼容,保留未用的未应写"0",而保留的I/O 寄存器则不应进行写操作。

一些状态标志位的清除是通过写"1" 来实现的。要注意的是,与其他大多数AVR 不同,CBI SBI 指令只能对某些特定的位进行操作,因而可以用于包含这些状态标志的寄存器。CBI SBI 指令只对0x00 0x1F 的寄存器有效。

I/O
和外设控制寄存器在后续其他章节进行介绍。

阅读:
录入:JETTA

推荐 】 【 打印
本文评论
      全部评论
发表评论


点评: 字数
姓名:
赞助商广告