dsPIC30F系列TIMER1模块详解:16位定时器与计数器模式

需积分: 7 37 下载量 52 浏览量 更新于2024-08-10 收藏 3.37MB PDF 举报
"TIMER1模块-chroma language_manual" 这篇文档详细介绍了dsPIC30F系列微控制器中的16位通用TIMER1模块及其工作模式。TIMER1模块可以作为一个实时时钟的时间计数器,或者自由运行的时段定时器/计数器。它支持三种主要的工作模式:16位定时器模式、16位同步计数器模式和16位异步计数器模式。 1. **16位定时器模式**:在此模式下,定时器在每个指令周期内自动递增,直到计数值与预设在16位周期寄存器PR1中的值匹配,然后自动复位回0,继续计数。当CPU进入空闲模式时,若TSIDL位(T1CON寄存器的第13位)为0,定时器会停止递增;若TSIDL位为1,定时器则在空闲模式下继续工作。 2. **16位同步计数器模式**:在这个模式下,定时器依赖外部时钟信号的上升沿进行递增,且外部时钟与内部相位时钟同步。当计数值达到PR1中的预设值时,定时器同样复位并重新开始计数。在CPU空闲模式下,定时器的行为与定时器模式相同,取决于TSIDL位的状态。 3. **16位异步计数器模式**:在这种模式下,定时器的递增由外部时钟信号的上升沿触发,而不管CPU的状态。即使CPU进入空闲模式,只要TSIDL位为1,定时器也会持续工作。但若配置为异步工作模式,且TSIDL = 1,CPU进入空闲模式时,定时器将停止递增。 TIMER1模块的配置可以通过设置16位特殊功能寄存器(SFR)T1CON的相应位来实现。此外,它还支持定时器门控操作、可选的预分频比设置,以及在CPU空闲和休眠模式下的定时器操作。当周期寄存器匹配或外部门控信号下降沿发生时,可以触发中断。 需要注意的是,dsPIC30F系列的数据手册虽然概述了该系列器件的功能,但不应视作全面的参考手册。用户需要参考《dsPIC30F系列参考手册》和《16位MCU和DSC程序员参考手册》获取更详细的信息。TIMER1被标记为“A类”定时器,具体规格可以在电气特性章节找到。 最后,文档中提到了Microchip Technology Inc.对产品性能、应用信息和使用情况的免责声明,强调用户需根据技术规范自行负责应用设计,并且使用Microchip器件在生命维持和/或生命安全应用中风险自负。此外,文档中的商标信息表明Microchip对这些商标拥有知识产权,并禁止未经授权的使用。

int itcs_timer_irq(int idx, void *arg) { timer_priv_t *timer_priv = (timer_priv_t *)arg; uint32_t tempregisr = 0; switch (timer_priv->timeridx) { case 1: tempregisr = readl(timer_priv->base + TIMER_ISR_C1); // printf("BEFORE READ COUNT1 ISR STAT RET :%08x\n",tempregisr); if (GET_BIT(tempregisr, 4) == 1) { // printf("OVERFLOW INTERRUPT OCCUR\n"); timer_priv->enum_interrupt = TIMER_OVERFLOW_INTERRUPT; } if (GET_BIT(tempregisr, 0) == 1) { g_endtime = get_timer(0); // printf("INTERVAL INTERRUPT OCCUR\n"); timer_priv->enum_interrupt = TIMER_INTERVAL_INTERRUPT; } if (GET_BIT(tempregisr, 1) == 1) { g_endtimematch1 = get_timer(0); // printf("MATCH1 INTERRUPT OCCUR\n"); timer_priv->enum_interrupt = TIMER_MATCH1_INTERRUPT; } if (GET_BIT(tempregisr, 2) == 1) { g_endtimematch2 = get_timer(0); // printf("MATCH2 INTERRUPT OCCUR\n"); timer_priv->enum_interrupt = TIMER_MATCH2_INTERRUPT; } if (GET_BIT(tempregisr, 3) == 1) { g_endtimematch3 = get_timer(0); // printf("MATCH3 INTERRUPT OCCUR\n"); timer_priv->enum_interrupt = TIMER_MATCH3_INTERRUPT; } tempregisr = readl(timer_priv->base + TIMER_ISR_C1); // printf("AFTER READ COUNT1 ISR STAT RET :%08x\n",tempregisr); break; case 2: tempregisr = readl(timer_priv->base + TIMER_ISR_C2); // printf("BEFORE READ COUNT2 ISR STAT RET :%08x\n",tempregisr); if (GET_BIT(tempregisr, 4) == 1) { // printf("OVERFLOW INTERRUPT OCCUR\n"); timer_priv->enum_interrupt = TIMER_OVERFLOW_INTERRUPT; } if (GET_BIT(tempregisr, 0) == 1) { g_endtime = get_timer(0); // printf("INTERVAL INTERRUPT OCCUR\n"); timer_priv->enum_interrupt = TIMER_INTERVAL_INTERRUPT; } if (GET_BIT(tempregisr, 1) == 1) { // printf("MATCH1 INTERRUPT OCCUR\n"); g_endtimematch1 = get_timer(0); timer_priv->enum_interrupt = TIMER_MATCH1_INTERRUPT; } if (GET_BIT(tempregisr, 2) == 1) { g_endtimematch2 = get_timer(0); // printf("MATCH2 INTERRUPT OCCUR\n"); timer_priv->enum_interrupt = TIMER_MATCH2_INTERRUPT; } if (GET_BIT(tempregisr, 3) == 1) { g_endtimematch3 = get_timer(0); // printf("MATCH3 INTERRUPT OCCUR\n"); timer_priv->enum_interrupt = TIMER_MATCH3_INTERRUPT; } tempregisr = readl(timer_priv->base + TIMER_ISR_C2); // printf("AFTER READ COUNT2 ISR STAT RET :%08x\n",tempregisr); break; case 3: tempregisr = readl(timer_priv->base + TIMER_ISR_C3); // printf("BEFORE READ COUNT3 ISR STAT RET :%08x\n",tempregisr); if (GET_BIT(tempregisr, 4) == 1) { // printf("OVERFLOW INTERRUPT OCCUR\n"); timer_priv->enum_interrupt = TIMER_OVERFLOW_INTERRUPT; } if (GET_BIT(tempregisr, 0) == 1) { g_endtime = get_timer(0); // printf("INTERVAL INTERRUPT OCCUR\n"); timer_priv->enum_interrupt = TIMER_INTERVAL_INTERRUPT; } if (GET_BIT(tempregisr, 1) == 1) { g_endtimematch1 = get_timer(0); // printf("MATCH1 INTERRUPT OCCUR\n"); timer_priv->enum_interrupt = TIMER_MATCH1_INTERRUPT; } if (GET_BIT(tempregisr, 2) == 1) { g_endtimematch2 = get_timer(0); // printf("MATCH2 INTERRUPT OCCUR\n"); timer_priv->enum_interrupt = TIMER_MATCH2_INTERRUPT; } if (GET_BIT(tempregisr, 3) == 1) { g_endtimematch3 = get_timer(0); // printf("MATCH3 INTERRUPT OCCUR\n"); timer_priv->enum_interrupt = TIMER_MATCH3_INTERRUPT; } tempregisr = readl(timer_priv->base + TIMER_ISR_C3); // printf("AFTER READED COUNT3 ISR STAT RET :%08x\n",readregisr); break; default: break; } if (timer_priv->cb_event) { timer_priv->cb_event(timer_priv); } return 0; }

2023-02-17 上传

重写下面代码;timer_handle_t itcs_timer_init(timer_handle_t handle, timer_event_cb_t cb_event) { timer_priv_t *timer_priv = handle; if (timer_priv->idx < 0 || timer_priv->idx >= CONFIG_TIMER_NUM) { return NULL; } set_clock_type("cpu-pclk"); // printf("enter timer init fun in driver\n"); uint32_t tempreg = 0; switch (timer_priv->idx) { case 0: timer_priv->base = ITCS_TIMER0_BASE; break; case 1: timer_priv->base = ITCS_TIMER1_BASE; break; default: break; } // printf("unit %d ,timeridx %d, base addr // %08x\n",timer_priv->idx,timer_priv->timeridx,timer_priv->base); switch (timer_priv->timeridx) { case 1: tempreg = readl(timer_priv->base + TIMER_CCR_CONTROL_C1); tempreg |= CCR_RST_ENABLE; writel(tempreg, timer_priv->base + TIMER_CCR_CONTROL_C1); tempreg = readl(timer_priv->base + TIMER_IER_C1); tempreg &= ~(IER_EVNT_ENABLE | IER_ITRV_ENABLE | IER_M1_ENABLE | IER_M2_ENABLE | IER_M3_ENABLE); writel(tempreg, timer_priv->base + TIMER_IER_C1); if (timer_priv->idx == 0) { timer_priv->irq = TTC0_TIMER1_IRQn; request_irq(TTC0_TIMER1_IRQn, itcs_timer_irq, "itcs_timer_irq01", timer_priv); } else { timer_priv->irq = TTC1_TIMER1_IRQn; request_irq(TTC1_TIMER1_IRQn, itcs_timer_irq, "itcs_timer_irq11", timer_priv); } break; case 2: tempreg = readl(timer_priv->base + TIMER_CCR_CONTROL_C2); tempreg |= CCR_RST_ENABLE; writel(tempreg, timer_priv->base + TIMER_CCR_CONTROL_C2); tempreg = readl(timer_priv->base + TIMER_IER_C2); tempreg &= ~(IER_EVNT_ENABLE | IER_ITRV_ENABLE | IER_M1_ENABLE | IER_M2_ENABLE | IER_M3_ENABLE); writel(tempreg, timer_priv->base + TIMER_IER_C2); if (timer_priv->idx == 0) { timer_priv->irq = TTC0_TIMER2_IRQn; request_irq(TTC0_TIMER2_IRQn, itcs_timer_irq, "itcs_timer_irq02", timer_priv); } else { timer_priv->irq = TTC1_TIMER2_IRQn; request_irq(TTC1_TIMER2_IRQn, itcs_timer_irq, "itcs_timer_irq12", timer_priv); } break; case 3: tempreg = readl(timer_priv->base + TIMER_CCR_CONTROL_C3); tempreg |= CCR_RST_ENABLE; writel(tempreg, timer_priv->base + TIMER_CCR_CONTROL_C3); tempreg = readl(timer_priv->base + TIMER_IER_C3); tempreg &= ~(IER_EVNT_ENABLE | IER_ITRV_ENABLE | IER_M1_ENABLE | IER_M2_ENABLE | IER_M3_ENABLE); writel(tempreg, timer_priv->base + TIMER_IER_C3); if (timer_priv->idx == 0) { timer_priv->irq = TTC0_TIMER3_IRQn; request_irq(TTC0_TIMER3_IRQn, itcs_timer_irq, "itcs_timer_irq03", timer_priv); // printf("unit timer1 ret=%08x , request irq3 success!\n",ret); } else { timer_priv->irq = TTC1_TIMER3_IRQn; request_irq(TTC1_TIMER3_IRQn, itcs_timer_irq, "itcs_timer_irq13", timer_priv); // printf("unit timer1 ret=%08x , request irq3 success!\n",ret); } break; default: return NULL; } timer_priv->cb_event = cb_event; // printf("init status irq id num:%d\n",timer_priv->irq); // printf("INIT TIMER %d Timer Count No %d SUCCESS\n", timer_priv->idx, // timer_priv->timeridx); return (timer_handle_t)timer_priv; }

2023-02-17 上传
2023-02-18 上传