实验四 TIM定时器、中断处理

2024年重庆大学通信工程大二课程:《MCU原理及应用——基于恩智浦S12X的嵌入式系统开发》实验课程记录。(错误在所难免,请多斧正!🙏)

见下前言

实验二 并行I/O接口、IRQ中断-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/m0_73918454/article/details/139250471?spm=1001.2014.3001.5501


一、实验目的

掌握C语言综合编程方法,掌握并行I/O接口TIM(Timer定时器中断等功能部件的使用规则和应用方法,熟悉中断处理程序的安排。

并行I/O接口

并行:数据传输方式之一。在并行接口中,数据作为一个数据组(通常是8位、16位或更多位组成的字节或字)同时通过多条线路进行传输。

TIM:定时器

TIM实际上是一个可编程计数器,也是高速I/O通道。

其核心为一个16位自由运行计数器TCNT,Timer Counter),原始时钟来自MCU总线时钟,通过预分频生成不同频率的时钟,再对该时钟进行递增计数。可作为定时时间基准、产生波形输出、测量输入波形、统计脉冲或边沿个数和产生脉宽调制输出。

对于本实验使用的MCU,为增强型捕捉定时器(ECT,Enhanced Capture Timer)。需要在寄存器名称前加 “ECT_”。

中断 Interrupt

重要事件发生或异常产生并提出处理请求(中断源)时,CPU暂时停止执行当前程序,转向中断服务程序,中断处理完后返回原来程序地址继续运行。

二、实验内容

2.1 实现1s精确定时

每定时时间到,使开发板上接B口8位LED灯变化以对应表达(输出一个递增数),观察是否进入中断。调试时,可在中断服务程序中设置断点,以方便观察是否进入中断。

MCU为8MHz总线频率,利用MCU的ECT定时器通道0、中断功能部件。(教材P165)

输出比较 OCOutput Compare。通过预置的数值与TCNT的值相比,确定动作。用于精确定时,定时时间的计算公式:

定时时间 = TCx预置常数 × 总线周期 × 预分频因子

总线周期  T\displaystyle \displaystyle _{BUS} =  1 / 8 MHz = 125 ns

 预分频因子 (教材P159)

PR[2:0]

000

001010011100101110111
预分频因子1248163264128

TCx预置常数 :16位二进制数,最大为 2^{16} = 65535。实际所需写入的TCx值,应为 TCNT当前值+ 预置常数(因为定时器OC中的16位定时器计数器TCNT是自由运行的)

代码实现

#include <hidef.h>      /* common defines and macros */
#include "derivative.h"      /* derivative-specific definitions */

static word outValue=0;

void main(void) {
  /* put your own code here */
  DisableInterrupts;
  
  DDRB=0xFF;
  PORTB=0xFF;
  
  ECT_TSCR2=0x07;
  ECT_TIOS=0x01;
  ECT_TCTL2=0x00;
  ECT_TFLG1=0x01;
  ECT_TIE=0x01;
  ECT_TC0=(word)(ECT_TCNT+62500);
  
  ECT_TSCR1=0x80;
  
  EnableInterrupts;
  
  for(;;) {
    _FEED_COP(); /* feeds the dog */
  } /* loop forever */
  /* please make sure that you never leave main */
}


#pragma CODE_SEG NON_BANKED
interrupt 8 void Timer0_ISR(){
  ECT_TFLG1=0x01;
  ECT_TC0=(word)(ECT_TCNT+62500);
  
  outValue++;
  if(outValue>255)outValue=0;
  PORTB=~outValue;
}

硬件显示

实验四 2.1 实现1s精确定时

2.2 单位周期内统计脉冲次数

统计每 5s 时间内IOC6脉冲事件次数,结果送 B口 LED灯进行二进制表达。

  1. ECT通道7输出比较以定时 1s,时间到时 IOC7 引脚电平自动翻转(驱动开发板上 LED9);
  2. ECT通道6输入捕捉以检测脉冲(须设置内部上拉电阻),按键 SW6 每按动一次形成一个下降沿脉冲,由IOC6响应。通道6每1个中断中计数值递增;
  3. 通道0每5个中断后(即成5s定时)送结果。
  4. 每1s时间到LED9亮出x/熄灭,每5s时间到 LED1~7灯显示统计到的按键次数。

引脚复用:IOC0~7与T口的PT0~7引脚复用。复用使能时,DDRx寄存器作用无效。

代码实现

#include <hidef.h>      /* common defines and macros */
#include "derivative.h"      /* derivative-specific definitions */

void delay_ms(unsigned int ms){
  int i,j;
  for(i=0;i<ms;i++){
    for(j=0;j<1333;j++);
  }
}

byte nPulseNums = 0;   //脉冲数
byte time = 0;         //时间计数
void main(void) {
  /* put your own code here */
  DisableInterrupts;
  
  DDRB = 0xFF;       //设B口(LED1~8)为输出
  PORTB = 0x00;      //LED全亮
  nPulseNums = 0;    //计数脉冲数为0
  
  //TCNT设置
  ECT_TSCR2 = 0x07;  //溢出中断禁止;计数器自由运行;预分频因子:128
  ECT_TIOS = 0x81;   //通道7、0为输出比较,通道6为输入比较
  ECT_TIE = 0xC1;    //通道7、6、0中断使能
  
  //通道7定时1s,IOC7引脚电平自动翻转
  ECT_TCTL1 = 0x40;  //通道7比较成功,电平翻转
  ECT_TFLG1 = 0x80;  //写1清除TIM通道7中断标志
  ECT_TC7 = (word) (ECT_TCNT+62500);  //通道7定时1s
  
  //通道6输入捕捉脉冲
  PERT = 0xFF;       //T口内部拉电阻使能
  PPST = 0x00;       //T口上拉
  ECT_TCTL3 = 0x20;  //IC6下降沿捕捉
  ECT_TFLG1 = 0x40;  //写1清除IC6中断标志

  //通道0送结果
  ECT_TCTL3 = 0x02;  //捕捉下降沿
  ECT_TFLG1 = 0x01;  //写1清除IC0中断标志
  
  ECT_TSCR1 = 0x80;  //TIM使能;中断标志普通清除
  
  EnableInterrupts;


  for(;;) {
    //_FEED_COP(); /* feeds the dog */
  } /* loop forever */
  /* please make sure that you never leave main */
}

//通道6中断服务函数
# pragma CODE_SEG NON_BANKED
interrupt 14 void Timer6_ISR(){
  DisableInterrupts;
  ECT_TFLG1 = 0x40;      //写1清除IC6中断标志
  nPulseNums++;          //脉冲数加1
  EnableInterrupts;
}

//通道7中断服务函数
# pragma CODE_SEG NON_BANKED
interrupt 15 void Timer7_ISR(){
  ECT_TFLG1 = 0x80;                  //写1清除通道7中断标志
  ECT_TC7 = (word)(ECT_TCNT+62500);  //重置预置数TC7
  PTT = 0xFE;                        //给IC0送0触发中断 
}

//通道0中断服务函数
# pragma CODE_SEG NON_BANKED
interrupt 8 void Timer0_ISR(){
  time++;                            //1s定时成功
  if(time == 5){
    PORTB = ~nPulseNums;
    delay_ms(200);
    time = 0;
    nPulseNums = 0;
  }
}

失败了,LED1~8没有显示。 

硬件显示

实验四 2.2 单位周期内统计脉冲计数

2.3 控制周期信号的生成

利用ECT定时器(TCNT)通道7定时(f_{BUS}=8MHz)的专有中断标志自动清除,及自动复位计数器特性,同时检查:

PT0
1IOC7引脚自动输出翻转(输出周期为100ms的方波信号,LED9会闪烁)

0(按键按下)

信号保持为0电平

代码实现

#include <hidef.h>      /* common defines and macros */
#include "derivative.h"      /* derivative-specific definitions */
  
static word preScale = 25000;

void main(void) {
  /* put your own code here */
  DisableInterrupts;
  
  //DDRT &= 0xFE;       //有无该句效果一样?
  ECT_TSCR2 = 0x0C;     //预分频因子:16;TCNT溢出中断禁止;OC7比较成功复位计算器
  ECT_TIOS = 0x80;      //定时器通道7 设为输出比较
  ECT_TCTL1 = 0x40;     //比较成功后,输出电平翻转
  ECT_TFLG1 = 0x80;     //中断标志清零
  ECT_TIE = 0x80;       //中断使能,输出比较成功时申请中断
  ECT_TC7 = preScale;   //输出比较寄存器预置数
  ECT_TSCR1 = 0x90;     //定时器模块使能,中断标志快速自动清除使能

	EnableInterrupts;

  for(;;) {
      if ((PTT & 0x01) == 0x01){
        ECT_TCTL1 = 0x40;
      } else ECT_TCTL1 = 0x80;
              
    //_FEED_COP(); /* feeds the dog */
  } /* loop forever */
  /* please make sure that you never leave main */
}

#pragma CODE_SEG NON_BANKED
interrupt 15 void Timer7_ISR(){
  ECT_TC7 = preScale;
}

硬件显示

实验四 2.3 控制周期信号生成


总结

知识点很琐碎。尤其第二个...做得很累

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Qiming_Peng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值