GBA multiBoot时的AVR TIME设置~

来源:互联网 发布:李维嘉暴瘦 知乎 编辑:程序博客网 时间:2024/04/30 06:34

写这个是为了以后哪天要是忘记了,好让自己找到底。。。。

首先会用到下面几个寄存器。

T/C中断屏蔽寄存器-TIMSK0(Timer/Counter Interrupt Mask Register 0)


OCIE0B(Output Compare Match Interrupt Enabled 0 B):当OCIE0B 和状态寄存器的全局中断使能位I 都为”1” 时,T/C 的输出比较匹配B 中断使能。当T/C 的比较匹配发生,即TIFR0 中的OCF0B 置位时,中断服务程序得以执行。
OICE0A(Output Compare Match Interrupt Enabled 0 A):当OCIE0A 和状态寄存器的全局中断使能位I 都为”1” 时, T/C0 的输出比较匹配A 中断使能。当T/C0 的比较匹配发生,即TIFR0 中的OCF0A 置位时,中断服务程序得以执行。
TOIE0(T/C0 Overflow Interrupt Enable):当TOIE0 和状态寄存器的全局中断使能位I 都为”1” 时,T/C0 的溢出中断使能。当T/C0发生溢出,即TIFR0 中的TOV0 位置位时,中断服务程序得以执行。

这次的程序里没有用到中断函数,所以嘛我会设为全0。

OCR0B(Output Compare Register 0B):
输出比较寄存器B 包含一个8 位的数据,不间断地与计数器数值TCNT0 进行比较。匹配事件可以用来产生输出比较中断,或者用来在OC0B 引脚上产生波形。
OCR0A(Output Compare Register 0A):

输出比较寄存器A 包含一个8 位的数据,不间断地与计数器数值TCNT0 进行比较。匹配事件可以用来产生输出比较中断,或者用来在OC0A 引脚上产生波形。
TCNT0(T/C0 Timer/Counter Register):

通过T/C 寄存器可以直接对计数器的8 位数据进行读写访问。对TCNT0 寄存器的写访问将在下一个时钟阻止比较匹配。在计数器运行的过程中修改TCNT0 的数值有可能丢失一次TCNT0 和OCR0x 的比较匹配。

TIFR0(Timer/Counter Interrupt Flag Register 0):

OCF0B(Output Compare Flag B):当T/C 与OCR0B( 输出比较寄存器0B) 的值匹配时, OCF0B 置位。此位在中断服务程序里硬件清零,也可以对其写1 来清零。当SREG 中的位I、OCIE0B(T/C 比较B 匹配中断使能) 和OCF0B 都置位时,中断服务程序得到执行。

OCF0A(Output Compare Flag A):当T/C0 与OCR0A( 输出比较寄存器0A) 的值匹配时, OCF0A 置位。此位在中断服务程序里硬件清零,也可以对其写1 来清零。当SREG 中的位I、OCIE0A(T/C0 比较匹配中断使能) 和OCF0A 都置位时,中断服务程序得到执行。

TOV0(Timer/Counter Overflow Flag 0):T/C0 溢出时TOV0 置位。执行相应的中断服务程序时此位硬件清零。此外,TOV0 也可以通过写1 来清零。当SREG 中的位I、TOIE0(T/C0 溢出中断使能) 和TOV0 都置位时,

中断服务程序得到执行。

TCCR0B(Timer/Counter Control Register 0B):T/C0控制寄存器。


FOC0A(Force Output Compare 0A):强制输出比较位A。FOC0A 仅在WGM 指明非PWM 模式时才有效。但是,为了保证与未来器件的兼容性,在使用PWM 时,写TCCR0B 要对其清零。对其写1 后,波形发生器将立即进行比较操作。比较匹配输出引脚 OC0A 将按照COM0A1:0的设置输出相应的电平。要注意FOC0A 类似一个锁存信号,真正对强制输出比较起作用的是COM0A1:0 的设置。FOC0A不会引发任何中断,也不会在利用OCR0A作为TOP的CTC模式下对定时器进行清零的操作。

FOC0B(Force Output Compare 0B):强制输出比较位B。FOC0B 仅在WGM 指明非PWM 模式时才有效。但是,为了保证与未来器件的兼容性,在使用PWM 时,写TCCR0B 要对其清零。对其写1 后,波形发生器将立即进行比较操作。比较匹配输出引脚 OC0B 将按照COM0B1:0的设置输出相应的电平。要注意FOC0B 类似一个锁存信号,真正对强制输出比较起作用的是COM0B1:0 的设置。FOC0B不会引发任何中断,也不会在利用OCR0B作为TOP的CTC模式下对定时器进行清零的操作。

WGM02(Waveform Generation Mode 02):后面结合WGM00跟01一起说。

CS02:0(Clock Select02~00):为时钟选择位,其设置如下:

CS02CS01CS00说明000无时钟, T/C 不工作001clkI/O/1 ( 没有预分频)010clkI/O/8 ( 来自预分频器)011clkI/O/64 ( 来自预分频器)100clkI/O/256 ( 来自预分频器)101clkI/O/1024 ( 来自预分频器)110时钟由T0 引脚输入,下降沿触发111时钟由T0 引脚输入,上升沿触发当频率比较低的时候可以使用分频。比如8分频的意思就是8个CPU时钟周期计数器才+1,这样可以用一个小一点的数值成计数。毕竟Timer0的计数器只有8位。

TCCR0A(Timer/Counter Control Register 0A):T/C0控制寄存器


WGM01:0(Waveform Generation Mode 01/00): 波形产生模式

这几位与TCCR0B 寄存器的WGM02 结合起来控制计数器的计数序列,计数器的最大值TOP,以及产生何种波形。T/C 支持的模式有:普通模式,比较匹配发生时清除计数器模式(CTC),以及两种PWM 模式。

波形产生模式的位定义:模式WGM02WGM01WGM00T/C 的工作模式TOPOCRx 的更新时间TOV 的置位时刻0000普通0xFF立即更新MAX1011PWM,相位修正0xFFTOPBOTTOM2010CTCOCRA立即更新MAX3011快速 PWM0xFFTOPMAX4100保留---5101PWM,相位修正OCRATOPBOTTOM6110保留---7111快速PWMOCRATOPTOP
COM01:0(Compare Match Output Mode 01/00):比较匹配输出模式位

这个就不详细说了,在不同的WGM模式下COM的组全定义都不一样,太多了。用来设置相对应的针脚的高低电平切换。我是用不到这东西的。详细设置参阅AVR的官方手册。

相关函数:

这程序用了Timer0,所以对应该的寄存器是0CR0A、TCCR0A、TCCR0B、TCNT0

初始化函数有两个,InitTmr32是用于GBA 32位NORMAL模式的时钟,InitTmr16是用于GBA的16位Multi-player模式的时钟设置。WGM设置为111快速PWM模式。我试过设置成CTC模式,要每次到TOP的时候重设OCR0A才能正常工作,于是就用快速PWM模式。由于频率快,所以CS设置为001,也就是不分频。这程序用不着中断,所以TIMSK0把所有时钟中断清零。

ResetTmr()是重置时钟,没啥说的就是把TCNT0清零,然后往TIFR0的OCF0A写1来重置请求。。。好奇怪的方式,往OCF0A写1,他就会变0。

WaitTmr()是等待时钟到达TOP。一般会用while来写这个阻塞,但是ECLIPSE的格式化会变成两行,我特别不喜欢,怎么设置都不行,只好用伟大的GOTO了。当计数器也就是TCNT0到达OCR0A的值时,TIFR0的OCF0A位会变成1。一直阻塞循环判断这个值直到为1时继续执行。如果你需要这时候执行别的东西的话,那就用中断来判断更好。但我这水平玩不来中断,还是阻塞吧。接着就是奇怪的往OCF0A写1来把这个位清0。因为TCNT0到达TOP后会重置又从0开始计数,所以不用对TCNT0进行清零操作。如果你这么做了,时序肯定不正常,因为执行代码时已经过了几个CPU周期了再清0反而不准了。

这几个函数弄好了,时序就果断OK了。

原创粉丝点击