怎么访问l6位寄存器
发表:2023-08-29 12:02:09 阅读:85

怎么访问l6位寄存器

TCNTn、OCRnA/B/C与ICRn是AVR CPU通过8位数据总线可以访问的1 6位寄存器。读/写l6位寄存器需要两次操作。每个16位计数器都有一个8位临时寄存器用来存放其高8位数据。每个l 6位定时器所属的1 6位寄存器共用相同的临时寄存器。访问低字节会触发16位读或写操作。当CPU写数据到l 6位寄存器的低字节时,写入的8位数据与存放在临时寄存器中的高8位数据组成一个16位数据,同步写入到1 6位寄存器中。当CPU读取l 6位寄存器的低字节时,高字节内容在读低字节操作的同时被放置于临时辅助寄存器中。

并非所有的l 6位访问都涉及临时寄存器.对OCRnA/B/C寄存器的读操作就不涉及临时寄存器。

写l6位寄存器时,应先写入该寄存器的高位字节;而读l 6位寄存器时,应先读取该寄存器的低位字节。

下面的例程说明了如何访问16位定时器寄存器.前提是假设不会发生更新临时寄存器内容的中断。同样的原则也适用于对0CRnA/B/C与ICRn寄存器的访问。使用C语言时,编译器会自动处理l6位操作。

汇编代码例程:

.....

设置TCNTn为0x01FF

idi rl7.0xol

idi rl6,0xFF

out TCNTnH,rl7

out TCNTnL,rl6

;将TCNTn读入7:rl6

in rl6,TCNTnL

in rl7,TCNTnH

.....

C代码例程(1):

unsigned int i;

/*设置TCNTD为OxOIFF*/

姗n=OxlFFl

/*将TCNTn读人i*/

i=TCNTn;

注:本代码假定已经包含了合适的头文件。当I/O寄存器为扩展I/O寄存器时,必须用诸如LDS、STS、SBRS、SBRC、SBR与CBR等可访问扩展I/O寄存器的指令代替IN、OUT、SBIS、SBIC、CBI与SBI指令。

汇编代码例程中TCNTn的返回值在r17:r16寄存器对中。

16位寄存器的访问是一个基本操作,认识这一点是非常重要的。在对16位寄存器操作时,最好首先屏蔽中断响应,防止在主程序读/写16位寄存器的两条指令之间发生这样的中断-它也访问同样的寄存器或其他的16位寄存器,从而改了临时寄存器。如果这种情况发生,那么中断返回后临时寄存器中的内容已经改变,造成主程序对l 6位寄存器的读/写错误。

下面的例程给出了读取TCNTn寄存器内容的基本操作。对0CRnA/B/C或ICRn的读操作可以使用相同的方法。

汇编代码例程:

TIMl 6一ReadTCNTn:

;保存全局中断标志

in rl8,SREG

;禁用中断

cli

;将TCNTn读入rl7:rl6

in rl6,TCNTnL

in rl7,TCNTnH

;恢复全局中断标志

out SREG,rl8

ret

C代码例程注:

uns igned int TIMl 6——ReadTCNTn(void)

uns igned char sreg

unsigned int i;

/*保存全局中断标志*/

sreg=SREG;

/*禁用中断*/

-CLI();

/*将TCNTn读入i*/

i=TCNTn;

/*恢复全局中断标志*/

SREG=sre9;

return i:

)

注:本代码假定已经包含了合适的头文件。当I/O寄存器为扩展I/O寄存器时.必须用诸如LDS、STS、SBRS、SBRC、SBR与CBR等可访问扩展I/O寄存器的指令代替IN、OUT、SBIS、SBIC、CBl与SBl指令。汇编代码例程中r17:rl6寄存器对保存的是TCNTn的写人数据。

如果对不止一个16位寄存器写入数据而且所有的寄存器高字节相同,则只须写一次高字节。前面讲到的基本操作在这种情况下同样适用。

 

【电子街】推荐阅读:

16位定时器/计数器的特点

16位足时器/计数器的组成结构

16位定时器/计数器的计数单元

T/CD的输入捕捉单元