所谓输出比较功能就是根据需要设置输出比较寄存器的值,自由运行计数器的值与输出比较寄存器的值每隔4个总线周期比较一次,当两者相等时,会在规定的通道引脚上输出预定的电平。如果允许中断,会产生一次输出比较中断。
相应需要操作的寄存器有如下几个:
总共8个16位寄存器,分别对应8个输出比较通道。当 TCx = TCNT 时满足输出比较条件,这时根据程序设置在对应输出管腿输出特定的电平(具体方法见TCTL1/TCTL2 寄存器的功能设置)或者产生对应的中断事件。
用来设定某一通道是输入捕捉功能还是输出比较功能。IOSx = 1 对应位为输出比较功能,IOSx = 0 对应位为输入捕捉功能。
图 7 TIOS寄存器
其中某一位置 1 后则使能相应的通道的中断,这里控制的中断既包括输出比较中断也包括后面要介绍的输入捕捉中断。
图 8 TIE寄存器
用来决定输出比较时的输出模式和输出电平。具体参见表格 1。
表格 1 输出比较动作
OMx |
OLx |
动作 |
---|---|---|
0 | 0 | 不输出 |
0 | 1 | 每次翻转OCx 的电平 |
1 | 0 | OCx = 0 |
1 | 1 | OCx = 1 |
图 9 TCTL1/TCTL2 寄存器
用来标识中断条件发生了,对某一位写1则清除对应位。
图 10 TFLG1寄存器
有了这些就可以开始第二个例子了。第二个例子利用通道0和通道1的输出比较功能。在 TCNT = TC0 时将对应的PT0 管腿的输出电平翻转,并且产生相应中断。在 TCNT = TC1时将对应的PT1 管腿的输出电平翻转,并且产生相应中断。这样,PT0和PT1 就会输出两个具有恒定相位差的同频方波信号了。
#include <hidef.h> /* common defines and macros */ #include "derivative.h" /* derivative-specific definitions */ #include "sci.h" void ECTInit(void) { //TSCR2_PR = 7; //prescale factor is 8, bus clock/128=8Mhz/8 TSCR2_TOI = 1; //timer overflow interrupt enable TSCR1_TEN = 1; //timer enable TIOS_IOS0 = 1; // channel 0 as output compare TIOS_IOS1 = 1; // channel 1 as output compare TC0 = 10000; TC1 = 20000; TIE_C0I = 1; // 使能 channel 0 中断 TIE_C1I = 1; // 使能 channel 1 中断 TCTL2_OL0 = 1; TCTL2_OM0 = 0; TCTL2_OL1 = 1; TCTL2_OM1 = 0; } void main(void) { SCIInit(); SCISetBaudRate (SCI0, 9600, 8192000L); ECTInit(); DDRM_DDRM0 = 1; DDRM_DDRM1 = 1; DDRM_DDRM2 = 1; EnableInterrupts; for(;;) { _FEED_COP(); /* feeds the dog */ } /* loop forever */ } interrupt VectorNumber_Vtimovf void ECT_TimerOverflow_ISR(void) { TFLG2 = TFLG2_TOF_MASK; //clear timer overflow interrupt flag PTM_PTM0 = ~ PTM_PTM0; } interrupt VectorNumber_Vtimch0 void ECT_0_ISR(void) { unsigned int value; TFLG1 = TFLG1_C0F_MASK; //clear channel 0 interrupt flag PTM_PTM1 = ~ PTM_PTM1; } interrupt VectorNumber_Vtimch1 void ECT_1_ISR(void) { TFLG1 = TFLG1_C1F_MASK; //clear channel 1 interrupt flag PTM_PTM2 = ~ PTM_PTM2; } interrupt VectorNumber_Vtimch7 void ECT_7_ISR(void) { TFLG1 = TFLG1_C7F_MASK; //clear channel 7 interrupt flag }
下面是用 USBee 抓下来的波形图。Port M 0 是在溢出中断中翻转的。PT0 、PT1分别对应两个输出比较通道,两个上升沿的时间间隔为 1/8192=1.22ms,测量结果与理论值完全相同。
下面将程序做一个很小的修改。将 TC0 和 TC1 的值改成相同的。
void ECTInit(void) { //TSCR2_PR = 7; //prescale factor is 8, bus clock/128=8Mhz/8 TSCR2_TOI = 1; //timer overflow interrupt enable TSCR1_TEN = 1; //timer enable TIOS_IOS0 = 1; // channel 0 as output compare TIOS_IOS1 = 1; // channel 1 as output compare TC0 = 10000; TC1 = 10000; TIE_C0I = 1; // 使能 channel 0 中断 TIE_C1I = 1; // 使能 channel 1 中断 TCTL2_OL0 = 1; TCTL2_OM0 = 0; TCTL2_OL1 = 1; TCTL2_OM1 = 0; }
从波形图中可以看出,输出是正常的。但是有些低版本的 ECT 模块有些问题,在这种情况下只有 通道 0 的中断能够响应,通道1的中断无法响应。