第七集:定时器
时钟能产生周期性电平变动的信号源,用于不同设备之间的信号同步、计数、计时等。时钟可以通过硬件晶振产生,也可以通过另一个时钟源分频或者PLL技术产生。
AI8051U中存在不同的时钟,有些仅仅作为另一个时钟的上游,有些则是专门给某些设备使用,有些则两者兼备。
- 内部高速IRC,22~44MHz
- 内部低速IRC,32K
- 内部48M高速IRC,主要给USB高速传输使用。为了传输稳定性,在UCAP引脚要求连一个去耦电容。
- 主时钟MCLK,可以从内部高低速IRC,内部PLL,外部晶振生成,常作为系统运行的主要时钟信号源。
- 系统时钟SYSCLK,通过主时钟分频得到
- 内部PLL,从内部高速IRC/外部高速晶振通过PLL技术产生
- 外部高速晶振,芯片外部输入时钟信号
- 外部32768,为RTC时钟提供时钟源
- 外设时钟,指SPI,I2C,I2S,PWM,TFPU等外设的时钟信号,可以从主时钟或PLL时钟产生,每个外设时钟的分频数可以不同。
- RTC时钟,独立于系统运行的一个时钟,可以在系统休眠时继续工作,维持一些状态
定时器
时钟源/分频数(1或12) = 定时器时钟频率
时钟频率/(时钟分频+1)/时钟数 = 定时触发频率
1/定时触发频率 = 定时触发周期,每个周期会触发一次定时中断信号。
所谓多少位定时器,指可以设置的一个周期内的最大时钟数。8位定时器,一个周期最长 = 输入时钟周期*0x100。
相关设置寄存器:

- 1T/12T模式,对时钟源不分频/12分频
- 定时器开关,(!GATE | INT0) & TR0。GATE是使能(允许)外部INT0引脚触发计数,可实现脉宽测量。
- T1_C/T:控制计数器输入源,对定时器时钟计数 or 对T引脚信号计数
- T1_M1/T1_M0: 计数重载模式,会影响计数器重载的周期,也就是影响一个周期(两次重载间隔)内的tick数。对16位计数器,如果设定重载值为0xe000,则每次溢出时计数器重载位0xe000,然后开始+1+1的计数,直到再次溢出,一共计数0x1000次,也就是两次溢出时间间隔是0x1000个时钟周期。这里0x1000就是上面说的时钟数。
- 自动重载,可控制溢出频率
- 不自动重载,不可控制溢出频率,相当于重载值为0
- 溢出频率 = 输入频率/(多少位 - 重载值)
- 不可中断意味着全局中断关闭也不能停止计时器的中断。且该中断具有高优先级
- TM0PS: 8位预分频,作用与1T/12T差不多。感觉没啥用。
- TF0: 溢出时设置位1,需要程序重置。
- T0CLKO: 输出信号开关,将溢出作为一种信号输出,每次溢出电平反转。
中断号
函数通过指定中断号来响应对应的中断。在文档中列有中断号,0~73,每个中断号对应一种中断类型。官方头文件里也已经将中断号定义成宏,方便从名称识别。
#define INT0_VECTOR 0 //0003H
#define TMR0_VECTOR 1 //000BH
#define INT1_VECTOR 2 //0013H
#define TMR1_VECTOR 3 //001BH
#define UART1_VECTOR 4 //0023H
#define ADC_VECTOR 5 //002BH
#define LVD_VECTOR 6 //0033H
#define PCA_VECTOR 7 //003BH
#define UART2_VECTOR 8 //0043H
#define SPI_VECTOR 9 //004BH
#define INT2_VECTOR 10 //0053H
#define INT3_VECTOR 11 //005BH
#define TMR2_VECTOR 12 //0063H
#define USER_VECTOR 13 //006BH
#define INT4_VECTOR 16 //0083H
#define UART3_VECTOR 17 //008BH
#define UART4_VECTOR 18 //0093H
#define TMR3_VECTOR 19 //009BH
#define TMR4_VECTOR 20 //00A3H
#define CMP_VECTOR 21 //00ABH
#define I2C_VECTOR 24 //00C3H
#define USB_VECTOR 25 //00CBH
#define PWMA_VECTOR 26 //00D3H
#define PWMB_VECTOR 27 //00DBH
#define RTC_VECTOR 36 //0123H
#define P0INT_VECTOR 37 //012BH
#define P1INT_VECTOR 38 //0133H
#define P2INT_VECTOR 39 //013BH
#define P3INT_VECTOR 40 //0143H
#define P4INT_VECTOR 41 //014BH
#define P5INT_VECTOR 42 //0153H
#define P6INT_VECTOR 43 //015BH
#define P7INT_VECTOR 44 //0163H
#define DMA_M2M_VECTOR 47 //017BH
#define DMA_ADC_VECTOR 48 //0183H
#define DMA_SPI_VECTOR 49 //018BH
#define DMA_UR1T_VECTOR 50 //0193H
#define DMA_UR1R_VECTOR 51 //019BH
#define DMA_UR2T_VECTOR 52 //01A3H
#define DMA_UR2R_VECTOR 53 //01ABH
#define DMA_UR3T_VECTOR 54 //01B3H
#define DMA_UR3R_VECTOR 55 //01BBH
#define DMA_UR4T_VECTOR 56 //01C3H
#define DMA_UR4R_VECTOR 57 //01CBH
#define DMA_LCM_VECTOR 58 //01D3H
#define LCM_VECTOR 59 //01DBH
#define DMA_I2CT_VECTOR 60 //01E3H
#define DMA_I2CR_VECTOR 61 //01EBH
#define I2S_VECTOR 62 //01F3H
#define DMA_I2ST_VECTOR 63 //01FBH
#define DMA_I2SR_VECTOR 64 //0203H
#define DMA_QSPI_VECTOR 65 //020BH
#define QSPI_VECTOR 66 //0213H
#define TMR11_VECTOR 67 //021BH
#define DMA_PWMAT_VECTOR 72 //0243H
#define DMA_PWMAR_VECTOR 73 //024BH
诡异的0xfd问题,在带有0xfd的汉字后面,需要加上\xfd才能正常显示。