|
|
本帖最后由 luozewei 于 2025-2-18 14:48 编辑
T5L芯片内还有鲜为人知的外设,是资料上没有公开的,CCR是比较器模块,和T2定时器计数寄存器比较,有3种模式,1、比较模式,当T2计数值和CCRx值相等时会输出CCxpin=1; 2、外部引脚触发捕捉模式,当CCxpin脚上升沿,CCRx记录T2计数值。 3、CCRL写触发捕捉模式, 当CCRxL写时,CCRx记录T2计数值,由于CCxpin脚没有引出,那么第3中模式我们可以利于做时间戳,比如做精确的us级延时,Delay_us(); us级的测量一段代码运行时间。下面是代码实现方法: 用一个定时器T2,实现了秒信号输出,精确us级延时,精确ms级延时,ms级Timerout超时功能,测量代码运行精确计时。5大功能。 原本需要5个定时器实现的功能现在1个定时器解决了。以下代码在实际中已经验证过了。
//---------------------------CCR 寄存器位置
sfr CCR3H = 0xC7; //Compare/Capture Register 3, high byte
sfr CCR3L = 0xC6; //Compare/Capture Register 3, low byte
sfr16 CCR3 = 0xC6;
sfr CCR2H = 0xC5; //Compare/Capture Register 2, low byte
sfr CCR2L = 0xC4; //Compare/Capture Register 2, low byte
sfr16 CCR2 = 0xC4;
sfr CCR1H = 0xC3; //Compare/Capture Register 1, high byte
sfr CCR1L = 0xC2; //Compare/Capture Register 1, low byte
sfr16 CCR1 = 0xC2;
sfr CCEN = 0xC1; //Compare/Capture .0-.1 CCR0模式;.2-.3 CCR1模式;.4-.5 CCR2模式;.6-.7 CCR3模式
#define FOSC 206438400UL //11059200*56/3
#define T2_5MS (65536 - FOSC/4800) //定时器2, 5ms时基信号计数, 5ms计时对于11.0592M晶振刚好是整数,没有时间计算误差。
//T2定时器计数
xdata uint16_t runTick;
xdata int16_t timerMs[4] = {-1,-1,-1,-1,};
void T2_Init(void)
{
T2CON = 0xF0; //24分频
T2 = T2_5MS;
TRL2 = T2_5MS;
ET2 = 1; //中断开启
TR2 = 1;
CCEN = 0xFC; //开启CCR1,CCR2,CCR3捕捉模式
}
void T2_T2EX_ISR(void) interrupt 5
{
static uint8_t sysTick = 200;
if(TF2)
{
uint8_t i;
TF2 = 0;
runTick++; //测量代码运行时间5ms递增
for(i=0; i<4; i++)
if(timerMs > 0) timerMs--;
sysTick--;
if(sysTick == 0){
sysTick = 200;
isr_send_signal(1); //RTX51 操作系统代码,用于秒信号发送
} } }
void Put_Timerout(uint8_t timeid, uint16_t nTime)
{
if(timeid >= 4) return;
timerMs[timeid] = nTime / 5;
}
bit Get_Timeout(uint8_t timeid)
{
if(timerMs[timeid] == 0)
{
timerMs[timeid] = -1;
return 1;
}
return 0;
}
//------------------------------精确ms级延时
void Delay_ms(uint16_t ms)
{
timerMs[3] = ms / 5;
while(1){
if(timerMs[3] == 0) break;
}
timerMs[3] = -1;
}
//------------------------------精确us级延时
void Delay_us(uint8_t us)
{
CCR3L = 0; //记录T2时间到CCR3寄存器
EX6 = 0; //IEN1^5;
CCEN &= ~0x40; //设置CCR3位比较模式,
CCR3 = (FOSC / 2400 * us / 10000) + CCR3;
if(CCR3 < T2_5MS) CCR3 += T2_5MS;
while(!IEX6); //IRCON^5
IEX6 = 0;
CCEN |= 0x40; //设置CCR3位捕捉模式,不改会影响UART5 RX中断无法接收了。
EX6 = 1;
}
//----------------------------------------测量代码运行时间开始记录函数。
void RunTick_reset(void)
{
CCR1L = 0; //记录T2时间到CCR1寄存器
runTick = 0; //清空定时器的CNT */
}
//----------------------------------------测量代码运行时间结束记录函数。
uint32_t Get_RunTick(void)
{
uint32_t runTime;
CCR2L = 0; //记录T2时间到CCR2寄存器
runTime = runTick;
runTime *= (FOSC/4800);
runTime += CCR2;
runTime -= CCR1;
runTime *= 625; //*625/21/256 系数是平衡计算精度和最大延时时间溢出问题
runTime /= 21;
runTime >>= 8;
return runTime; //返回计数值 单位us
}
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|