Arduino CH552 定时器2的使用
CH552总共有3个定时器(0,1,2),其中定时器0被延时函数占用。
- 📍Arduino CH55x固件支持包安装地址:
https://cos.thinkcreate.us/package_ch55xduino_mcs51_newest_cloudflare_index.json
📗定时器 Timer寄存器简介
- Timer 0/1
Timer0/1 是 2 个 16 位定时/计数器,通过TCON
和TMOD
来配置Timer0
和Timer1
,TCON
用于定时/计数器 T0 和 T1 的启动控制与溢出中断以及外部中断控制。每个定时器都是由 2 个 8 位寄存器组成的 16 位定时单元。定时器 0 的高字节计数器是 TH0,低字节是 TL0;定时器 1 的高字节计数器是TH1,低字节是 TL1。定时器 1 还可以作为 UART0 的波特率发生器。
- Timer2
Timer2 是 16 位自动重载定时/计数器,通过T2CON
和T2MOD
寄存器进行配置,定时器 2 的高字
节计数器是 TH2,低字节是 TL2。Timer2 可以作为 UART0 的波特率发生器,还具有 2 路信号电平捕捉功能,捕捉计数存储于 RCAP2 和 T2CAP1 寄存器中。
📘定时器不同模式配置
- Timer 0/1/2 不同分频系数下的时钟配置:(参考官方资源包定时器例程)
//CH554 Timer0时钟选择
//bTMR_CLK同时影响Timer0&1&2,使用时要注意 (除定时使用标准时钟)
#define mTimer0Clk12DivFsys( ) (T2MOD &= ~bT0_CLK) //定时器,时钟=Fsys/12 T0标准时钟
#define mTimer0ClkFsys( ) (T2MOD |= bTMR_CLK | bT0_CLK) //定时器,时钟=Fsys
#define mTimer0Clk4DivFsys( ) (T2MOD &= ~bTMR_CLK;T2MOD |= bT0_CLK) //定时器,时钟=Fsys/4
#define mTimer0CountClk( ) (TMOD |= bT0_CT) //计数器,T0引脚的下降沿有效
#define mTimer1Clk12DivFsys( ) (T2MOD &= ~bT1_CLK) //定时器,时钟=Fsys/12 T1标准时钟
#define mTimer1ClkFsys( ) (T2MOD |= bTMR_CLK | bT1_CLK) //定时器,时钟=Fsys
#define mTimer1Clk4DivFsys( ) (T2MOD &= ~bTMR_CLK;T2MOD |= bT1_CLK) //定时器,时钟=Fsys/4
#define mTimer1CountClk( ) (TMOD |= bT1_CT) //计数器,T0引脚的下降沿有效
#define mTimer2Clk12DivFsys( ) {T2MOD &= ~ bT2_CLK;C_T2 = 0;} //定时器,时钟=Fsys/12 T2标准时钟
#define mTimer2ClkFsys( ) {T2MOD |= (bTMR_CLK | bT2_CLK);C_T2=0;} //定时器,时钟=Fsys
#define mTimer2Clk4DivFsys( ) {T2MOD &= ~bTMR_CLK;T2MOD |= bT2_CLK;C_T2 = 0;}//定时器,时钟=Fsys/4
#define mTimer2CountClk( ) {C_T2 = 1;} //计数器,T2引脚的下降沿有效
📑定时器1、2测试例程
- 使用定时器1,需要在固件:
C:\Users\Administrator\AppData\Local\Arduino15\packages\CH55xDuino\hardware\mcs51\0.0.23\cores\ch55xduino\main.c
文件中,将定时器1的中断函数添加进去:void Timer1Interrupt(void) __interrupt(INT_NO_TMR1);
/*
This example code is in the public domain.
https://github.com/DeqingSun/ch55xduino
https://docs.arduino.cc/built-in-examples/basics/Blink/
*/
#define LED_BUILTIN 11
// 定义LED引脚
#define LED_PIN 17
#define INTERRUPT_MS 1 // 定时器中断周期(ms)
volatile uint16_t count = 0; // 中断计数器(必须为volatile)
volatile uint16_t count2 = 0;
#define INTERRUPT_US 1000 // 定时器中断周期(1ms = 1000μs)
const uint16_t target = 500; // 500次中断(每次1ms)
const uint16_t target2 = 500;
static bool LED_FLAG = 0;
static bool LED2_FLAG = 0;
// 定时器1中断服务函数
void Timer1Interrupt(void) __interrupt(INT_NO_TMR1) __using(2)
{
TH1 = (65536 - 2000) >> 8; // 重新装载
TL1 = (65536 - 2000) & 0xFF;
count2++;
if (count2 >= target2) {
count2 = 0;
LED2_FLAG = !LED2_FLAG;
digitalWrite(LED_PIN, LED2_FLAG); // 翻转LED
}
}
void Timer1_init()
{
// TMOD = (TMOD &(~0xf0)) |0x20;// mode 2 for 8 位重载 autoreload
// TMOD = (TMOD & 0x0F) | 0x20; // 设置T1为模式2(8位自动重装),不影响T0配置
// T2MOD &= ~bT1_CLK;//定时器,时钟=Fsys/12
// T2MOD &= ~bT1_CLK //定时器,时钟=Fsys/12 T1标准时钟
// T2MOD |= bTMR_CLK | bT1_CLK //定时器,时钟=Fsys
TMOD = (TMOD & 0x0F) | 0x10; // 设置T1为模式1(16位)
TH1 = (65536 - 2000) >> 8; // 1ms定时高字节(2000×0.5μs)
TL1 = (65536 - 2000) & 0xFF; // 1ms定时低字节
TF1 = 0;
// 使能中断
ET1 = 1; // 使能定时器1中断
TR1 = 1;// 启动定时器1
EA = 1; // 使能全局中断
}
// 定时器2中断服务函数
void Timer2Interrupt(void) __interrupt(INT_NO_TMR2) __using(3)
{
if (TF2) {
TF2 = 0; // 清除定时器2溢出标志
count++;
if (count >= target) {
count = 0;
LED_FLAG = !LED_FLAG;
// 执行500ms任务
digitalWrite(LED_BUILTIN, LED_FLAG); // 翻转LED
}
}
}
void Timer2_init()
{
// 配置定时器2
T2CON = 0x00; // 清除T2CON,设置为16位自动重载模式
T2MOD = 0x00; // 时钟=Fsys(24MHz)
// 计算定时器初值(24MHz时钟,1ms中断)
uint16_t timerValue = 65536 - 1000;//1ms
RCAP2L = timerValue & 0xFF; // 低8位
RCAP2H = (timerValue >> 8); // 高8位
// 装载初值
TL2 = RCAP2L;
TH2 = RCAP2H;
// 使能定时器2中断
ET2 = 1; // 使能定时器2中断
EA = 1; // 使能全局中断
// 启动定时器2
TR2 = 1;
}
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
digitalWrite(LED_PIN, HIGH); // 初始化为低电平(LED熄灭)
Timer1_init();
Timer2_init();
}
// the loop function runs over and over again forever
void loop() {
// USBSerial_println("Hello World123!");
// USBSerial_flush();
// delay(1000); // wait for a second
// USBSerial_println("perseverance51");// wait for a second
// USBSerial_flush();//等待串口数据发送结束(串口数据发送必不可少)
}