MC9S12G128 Timer(定时器,计数器)

Introduction:

The basic scalable timer consists of a 16-bit, software-programmable counter driven by a flexible
programmable prescaler.
This timer can be used for many purposes, including input waveform measurements while simultaneously
generating an output waveform. Pulse widths can vary from microseconds to many seconds.
This timer could contain up to 8 input capture/output compare channels with one pulse accumulator
available only on channel 7. The input capture function is used to detect a selected transition edge and
record the time. The output compare function is used for generating output signals or for timer software
delays. The 16-bit pulse accumulator is used to operate as a simple event counter or a gated time
accumulator. The pulse accumulator shares timer channel 7 when the channel is available and when in
event mode.
A full access for the counter registers or the input capture/output compare registers should take place in
one clock cycle. Accessing high byte and low byte separately for all of these registers may not yield the
same result as accessing them in one word.

Features:

  • Up to 8 channels available. (refer to device specification for exact
    number).
  • All channels have same input capture/output compare functionality.
  • Clock prescaling.
  • 16-bit counter.
  • 16-bit pulse accumulator on channel 7.

Block Diagrams:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Register Descriptions:

在这里插入图片描述
在这里插入图片描述

TIOS:

输入捕获/输出比较选择:

  • IOSx=0, 输入捕获;
  • IOSx=1, 输出比较;
  • 寄存器TIOS, TIOS_IOS[0-7];
    在这里插入图片描述

CFORC:

CFFORC 定时器比较强制寄存器:

  • FOCx=1将导致相应通道上立即产生一个输出比较动作,这个状态和正常状态下输出比较发生后标志位未被置位后的情况相同;

在这里插入图片描述

OC7M:

输出比较7屏蔽寄存器:

在这里插入图片描述
在这里插入图片描述

OC7D:

在这里插入图片描述

TCNT:

定时器核心计数寄存器:
在这里插入图片描述
在这里插入图片描述

TSCR1:

定时器系统控制寄存器1:

  • TEN 定时器使能位,0:定时器/计数器被禁止,有利于降低功耗。1:定时器/计数器使能,正常工作。
  • TFFCA 定时器快速清除所有标志控制位,0:关闭定时器快速清除所有标志,1:使能定时器快速清除所有标志;
  • TSWAI 等待模式下计数器关闭控制位,0:在中断等待模式下允许MCU继续运行,1:当MCU进入中断等待模式时,禁止计时器;
  • TSFRZ 在冻结模式下计时器和计数器停止位,0:冻结模式下允许计时器和计数器继续运行,1:冻结模式下禁止计时器和计数器,用于仿真调试;

在这里插入图片描述
在这里插入图片描述

TTOV:

触发比较溢出选择:

  • 0:触发输出比较溢出禁止;
  • 1:触发输出比较溢出使能;

在这里插入图片描述

TCTL1/TCTL2:

输出比较pin脚设置,OMx OLx分别设定输出方式和输出电平:

  • 00:定时器与引脚断开;
  • 01:OCx输出反转;
  • 10:OCx输出0;
  • 11:OCx输出1;
OMx OLx Action
0 0 引脚断开
0 1 OCx输出反转
1 0 OCx输出0
1 1 OCx输出1

在这里插入图片描述
在这里插入图片描述

TCTL3/TCTL4:

输入捕获边沿控制 EDGxB,EDGxA :

  • 00:禁止捕获;
  • 01:捕获上升沿;
  • 10:捕获下降沿;
  • 11:捕获上升沿下降沿均捕获;
EDGxB EDGxA 捕获边沿
0 0 禁止
0 1 上升沿
1 0 下降沿
1 1 上升沿/下降沿

在这里插入图片描述
在这里插入图片描述

TIE:

定时器中断使能:

  • 0:IC/OC相应通道中断禁止;
  • 1:IC/OC相应通道中断使能;
    IC输入捕获,OC输出比较
    在这里插入图片描述

TSCR2:

定时器溢出中断使能:

  • 0:关闭溢出中断;
  • 1:使能溢出中断;

在这里插入图片描述

TFLG1:

中断标志寄存器1:

  • CxF输入捕获/输出比较中断标志,需要清除某个标志位,只需向该位写1即可,写0无效不影响改位状态值;

在这里插入图片描述

TFLG2:

中断标志寄存器2:

  • TOF 核心计数器溢出中断标志,TFLG2 只有1位TOF,TOF=1说明核心计数器溢出;

在这里插入图片描述
在这里插入图片描述

TCxH/TCxL:

在这里插入图片描述

PACTL:

在这里插入图片描述
在这里插入图片描述

PAFLG:

在这里插入图片描述
在这里插入图片描述

PACNT:

在这里插入图片描述

OCPD:

在这里插入图片描述

PTPSR:

精确定时器预分频寄存器:

  • TSCR1_PRNT = 1,PTPSR中的所有位都作为预分频选择;
  • PRNT=1,分频系数=PTPSR[7:0]+1, 值域(1~256);

在这里插入图片描述
在这里插入图片描述

示例代码:

Timer溢出模式:

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


#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#define D_BUSCLK_FREQ   (16000000) // 总线频率 16MHz
#define D_SCI_BAUDRATE  (9600)     // 串口波特率  


/**
* @brief  串口发送函数
* @param  data@串口发送的字符
* @return none
*/
void csi_send(unsigned char data) 
{
    
    
  while(!SCI0SR1_TDRE);         //等待发送数据寄存器(缓冲器)为空
  SCI0DRL = data;
}


/**
* @brief  串口接收函数
* @param none
* @return 串口接收到的字符
*/
unsigned char csi_receive(void) 
{
    
    
  while(!SCI0SR1_RDRF);          //等待发送数据寄存器满
  return(SCI0DRL);
}

/*************************************************************/
/**   定义了这个两个接口就可以使用printf函数格式化输出      **/
/**   TERMIO_PutChar                                        **/
/**   TERMIO_GetChar                                        **/
/*************************************************************/
void TERMIO_PutChar(char ch){
    
    
  csi_send((unsigned char)ch);
}

char TERMIO_GetChar(void){
    
    
  return (char)csi_receive();
}

/**
* @brief  串口初始化函数
* @param none
* @return none
*/
void sci_init(void) {
    
    
  SCI0BD = D_BUSCLK_FREQ/16/D_SCI_BAUDRATE;    // 设置SCI0波特率 busCLK/16/BAUDRATE;
  SCI0CR1 = 0x00;    //设置SCI0为正常模式,八位数据位,无奇偶校验  7:LOOPS 6:SCISWAI 5:RSRC 4:M     3:WAKE 2:ILT  1:PE   0:PT
  SCI0CR2 = 0x0C;    //允许收发数据,允许收发中断功能              7:TIE,  6:TCIE,   5:RIE, 4:ILIE, 3:TE,  2:RE,  1:RWU, 0:SBK
}


/**
* @brief 锁相环 初始化
* @param none
* @return none
*/
void pll_init(void) {
    
    
  CPMUPROT = 0x26;              //保护时钟配置寄存器
  
  CPMUCLKS_PSTP = 0;            //禁用PLL
  CPMUCLKS_PLLSEL = 1;          //选择PLL作为系统时钟源
  
  CPMUOSC_OSCE = 1;             //外部晶振使能
  while(CPMUOSC_OSCPINS_EN==0); //等待外部晶振使能

  // BUSCLK = (PLLCLK / 2)   总线频率=(锁相环频率/2)
  
  
  #if 1
  //fVOC= 2*fOSC*(SYNDIV + 1)/(REFDIV + 1) 
  CPMUSYNR = 0x07;                                                  
  //CPMUREFDIV = 0x0F; // PLLCLK:16M  BUSCLK:8M   
  CPMUREFDIV = 0x07; // PLLCLK:32M  BUSCLK:16M   
  //CPMUREFDIV = 0x03; // PLLCLK:64M  BUSCLK:32M        
  #endif
  
  #if 0
  //fVOC配置 fVOC = 2*fREF*(SYNDIV +1)
  //CPMUSYNR = 0x45; // PLLCLK:48M     BUSCLK:24M
  //CPMUSYNR = 0x44; // PLLCLK:40M     BUSCLK:20M
  //CPMUSYNR = 0x43; // PLLCLK:32M     BUSCLK:16M
  //CPMUSYNR = 0x42; // PLLCLK:24M     BUSCLK:12M
  CPMUSYNR = 0x01; // PLLCLK:16M    BUSCLK:8M
  CPMUREFDIV = 0x81;//REFDIV基准分频器配置
  #endif
    
  CPMUPOSTDIV = 0x00;           // PLL CLOCK = VCO CLOCK / (POSTDIV + 1) 
                              
  _asm(nop);
  _asm(nop);
  
  CPMUPLL=0x10;               //锁相环调频启用,用以减少噪音
    
  while(CPMUFLG_LOCK == 0);	  //等待PLL稳定
  
  	  
  CPMUPROT = 0x00;            //关闭保护时钟
  CPMUCLKS_PLLSEL = 1;        //使能PLL
}

/************************************************************/
/*                    初始化TIM模块                         */
/************************************************************/

/**
* @brief 定时器/计数器 初始化
* @param none
* @return none
*/
void tim_init(void){
    
    

  // 定时器使能控制,0:关闭主定时器,包括计数器; 1:允许定时器正常工作;
  TSCR1_TEN = 1;
  
  // 定时器快速清除所有标志:
  // 0:关闭定时器快速清除所有标志(需要手动清除标志中断标志写1,TFLG2_TOF = 1);
  // 1:使能定时器快速清除所有标志;
  // 注意:如果TSCR1_TFFCA=1,中断函数需要操作一次TCNT寄存器使触发清除TOF,TCNT=0~65535(手动装载计数器初始值); 
  TSCR1_TFFCA = 1;
  
  // 定时器溢出中断使能, 0:关闭溢出中断,1:使能溢出中断
  TSCR2_TOI = 1; // 定时器溢出触发TFLG2_TOF中断,中断处理函数TFLG2_TOF=1清除TOF中断;
  
  
  /**
  定时器 时钟分频设置
  TSCR2_PR
   --------------------------------------------
  | TSCR2_PR[PR2:PR1:PR0] |     Timer Clock    |          
  |--------------------------------------------|
  |       0x0             |   Bus clock        |
  |--------------------------------------------|
  |       0x1             |   Bus clock/2      |
  |--------------------------------------------|
  |       0x2             |   Bus clock/4      |
  |--------------------------------------------|
  |       0x3             |   Bus clock/8      |
  |--------------------------------------------| 
  |       0x4             |   Bus clock/16     |
  |--------------------------------------------| 
  |       0x5             |   Bus clock/32     |
  |--------------------------------------------| 
  |       0x6             |   Bus clock/64     |
  |--------------------------------------------| 
  |       0x7             |   Bus clock/128    |
   -------------------------------------------- 
  **/
  TSCR2_PR = 4;
  

  //精确定时器选择
  TSCR1_PRNT = 0; //精确定时器选择,0:使用传统定时器(TSCR2[2:0]作为预分频), 1:使用精确定时器,PTPSR中的所有位都作为预分频选择;
  PTPSR = 0x00;   //PTPS[7:0]+1
   
   
  TSCR2_TCRE = 0; // 0:计数器复位禁止,计数器自由计数。1:OV7成功输出比较后计数器将被复位;


  TIE = 0x00; // 定时器中断使能, 0:IC/OC相应通道中断禁止,1:IC/OC相应通道中断使能;
   
  
  // 等待模式下计数器关闭控制位,0:在中断等待模式下允许MCU继续运行,1:当MCU进入中断等待模式时,禁止计时器;
  TSCR1_TSWAI = 0;
  
  // 在冻结模式下计时器和计数器停止位,0:冻结模式下允许计时器和计数器继续运行,1:冻结模式下禁止计时器和计数器,用于仿真调试;
  TSCR1_TSFRZ = 0; 
  
  
  // 输出比较pin脚设置
  //TCTL1/TCTL2 // OMx OLx分别设定输出方式和输出电平,00:定时器与引脚断开,01:OCx输出反转,10:OCx输出0,11:OCx输出1;
  TCTL1 = 0x00;
  TCTL2 = 0x00;
  
  // 输入捕获边沿控制
  // TCTL3/TCTL4  EDGxB,EDGxA 输入捕获边沿控制,00:禁止捕获,01:捕获上升沿,10:捕获下降沿,11:捕获上升沿下降沿均捕获?
  TCTL3 = 0x00;
  TCTL4 = 0x00;
  
  //TFLG1/TFLG2中断标志寄存器,需要清除某个标志位,只需向该位写1即可,写0无效不影响改位状态值;
  //TFLG2 只有1位TOF,TOF=1说明核心计数器溢出。
  TFLG1 = 0xFF;
  TFLG2 = 0xFF; 
  

#if 0
  TSCR1_TFFCA = 1;  // 定时器标志位快速清除
  TSCR1_TEN = 1;    // 定时器使能位. 1=允许定时器正常工作; 0=使主定时器不起作用(包括计数器)
  TIOS  = 0xff;     // 指定所有通道为输出比较方式
  TCTL1 = 0x00;	    // 后四个通道设置为定时器与输出引脚断开
  TCTL2 = 0x00;     // 前四个通道设置为定时器与输出引脚断开
  TIE   = 0x00;     // 禁止所有通道定时中断
  TSCR2 = 0x86;	    // 预分频系数pr2-pr0:110,时钟周期为4us,使能定时器溢出中断
  TFLG1 = 0xff;	    // 清除各IC/OC中断标志位
  TFLG2 = 0xff;     // 清除自由定时器中断标志位
#endif
}


//unsigned int temp = 0;
unsigned int count = 0;
unsigned int tt = 0;
/*************************************************************/
/*                      定时器溢出中断                       */
/*************************************************************/
#pragma CODE_SEG __NEAR_SEG NON_BANKED
interrupt VectorNumber_Vtimovf void overflow(void)
{
    
    
  if(TFLG2_TOF ==1)
  {
    
    
    //TFLG2_TOF = 1; //清除TOF标志 
    TCNT = 0;         
    count += 1;
  }
}
#pragma CODE_SEG DEFAULT


void main(void) {
    
    
  /* put your own code here */
  
  DisableInterrupts;
  pll_init();
  sci_init();
  tim_init();
  DDRD_DDRD3 = 1;
	EnableInterrupts;

  (void)printf("**************** Timer overflow mode *******************\n");
  for(;;) {
    
    
     if (tt != count) {
    
    
        tt = count;
        (void)printf("count:%d\n",count);
        PORTD_PD3 = !PORTD_PD3;
     }
     
    _FEED_COP(); /* feeds the dog */
  } /* loop forever */
  /* please make sure that you never leave main */
}

Timer脉冲累加:

IOC7脉冲输入

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


unsigned int data1,data2;
unsigned int pulsenum;

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#define D_BUSCLK_FREQ   (16000000) // 总线频率 16MHz
#define D_SCI_BAUDRATE  (9600)     // 串口波特率  


/**
* @brief  串口发送函数
* @param  data@串口发送的字符
* @return none
*/
void csi_send(unsigned char data) 
{
    
    
  while(!SCI0SR1_TDRE);         //等待发送数据寄存器(缓冲器)为空
  SCI0DRL = data;
}


/**
* @brief  串口接收函数
* @param none
* @return 串口接收到的字符
*/
unsigned char csi_receive(void) 
{
    
    
  while(!SCI0SR1_RDRF);          //等待发送数据寄存器满
  return(SCI0DRL);
}

/*************************************************************/
/**   定义了这个两个接口就可以使用printf函数格式化输出      **/
/**   TERMIO_PutChar                                        **/
/**   TERMIO_GetChar                                        **/
/*************************************************************/
void TERMIO_PutChar(char ch){
    
    
  csi_send((unsigned char)ch);
}

char TERMIO_GetChar(void){
    
    
  return (char)csi_receive();
}

/**
* @brief  串口初始化函数
* @param none
* @return none
*/
void sci_init(void) {
    
    
  SCI0BD = D_BUSCLK_FREQ/16/D_SCI_BAUDRATE;    // 设置SCI0波特率 busCLK/16/BAUDRATE;
  SCI0CR1 = 0x00;    //设置SCI0为正常模式,八位数据位,无奇偶校验  7:LOOPS 6:SCISWAI 5:RSRC 4:M     3:WAKE 2:ILT  1:PE   0:PT
  SCI0CR2 = 0x0C;    //允许收发数据,允许收发中断功能              7:TIE,  6:TCIE,   5:RIE, 4:ILIE, 3:TE,  2:RE,  1:RWU, 0:SBK
}


/**
* @brief 锁相环 初始化
* @param none
* @return none
*/
void pll_init(void) {
    
    
  CPMUPROT = 0x26;              //保护时钟配置寄存器
  
  CPMUCLKS_PSTP = 0;            //禁用PLL
  CPMUCLKS_PLLSEL = 1;          //选择PLL作为系统时钟源
  
  CPMUOSC_OSCE = 1;             //外部晶振使能
  while(CPMUOSC_OSCPINS_EN==0); //等待外部晶振使能

  // BUSCLK = (PLLCLK / 2)   总线频率=(锁相环频率/2)
  
  
  #if 1
  //fVOC= 2*fOSC*(SYNDIV + 1)/(REFDIV + 1) 
  CPMUSYNR = 0x07;                                                  
  //CPMUREFDIV = 0x0F; // PLLCLK:16M  BUSCLK:8M   
  CPMUREFDIV = 0x07; // PLLCLK:32M  BUSCLK:16M   
  //CPMUREFDIV = 0x03; // PLLCLK:64M  BUSCLK:32M        
  #endif
  
  #if 0
  //fVOC配置 fVOC = 2*fREF*(SYNDIV +1)
  //CPMUSYNR = 0x45; // PLLCLK:48M     BUSCLK:24M
  //CPMUSYNR = 0x44; // PLLCLK:40M     BUSCLK:20M
  //CPMUSYNR = 0x43; // PLLCLK:32M     BUSCLK:16M
  //CPMUSYNR = 0x42; // PLLCLK:24M     BUSCLK:12M
  CPMUSYNR = 0x01; // PLLCLK:16M    BUSCLK:8M
  CPMUREFDIV = 0x81;//REFDIV基准分频器配置
  #endif
    
  CPMUPOSTDIV = 0x00;           // PLL CLOCK = VCO CLOCK / (POSTDIV + 1) 
                              
  _asm(nop);
  _asm(nop);
  
  CPMUPLL=0x10;               //锁相环调频启用,用以减少噪音
    
  while(CPMUFLG_LOCK == 0);	  //等待PLL稳定
  
  	  
  CPMUPROT = 0x00;            //关闭保护时钟
  CPMUCLKS_PLLSEL = 1;        //使能PLL
}


void tim_init(void)
{
    
    

  //PACTL = 0x50;      
  PACTL_PAEN  = 1; //0:关闭脉冲累加器,1:使能脉冲累加器(依赖于TEN=1);
  
 
  /***********************************
  PAMOD 脉冲模式 0:边沿触发,     1:电平触发;
  PEDGE 脉冲边沿 0:下降沿/高电平,1:上升沿/低电平
   -------------------------------
  |  PAMOD  | PEDGE |   Pin Action|
  |-------------------------------|
  |    0    |   0   |   下降沿    |
  |-------------------------------|
  |    0    |   1   |   上升沿    |
  |-------------------------------|
  |    1    |   0   |   高电平    |
  |-------------------------------|
  |    1    |   1   |   低电平    |
   -------------------------------
  ************************************/  
  PACTL_PAMOD = 0;
  PACTL_PEDGE = 1; // 脉冲累加上升沿触发


  /*******************************************
   CLK1,CLK1 定时器时钟选择
   ---------------------------------------- 
  |  CLK1   | CLK1  |   Timer Clock        |
  |----------------------------------------|
  |    0    |   0   | 使用定时器预分频时钟 |
  |----------------------------------------|
  |    0    |   1   | 使用PACLK            |
  |----------------------------------------|
  |    1    |   0   | 使用PACLK/256        |
  |----------------------------------------|
  |    1    |   1   | 使用PACLK/512        |
   ----------------------------------------
  ********************************************/  
  PACTL_CLK1 = 0;
  PACTL_CLK0 = 0;
  
  PACTL_PAOVI = 1; // 脉冲累加溢出中断使能,0:关闭,1:使能;脉冲累加溢出中断PAFLG_PAOVF
  PACTL_PAI = 1;   // 脉冲累加输入中断使能,0:关闭,1:使能;脉冲累加输入中断PAFLG_PAIF
  
  //PACNT 脉冲累加计数 当 PACNT 下溢出 0xFFFF to 0x0000  PAOVF中断标志置位;
 
 
  
  // 定时器快速清除所有标志:
  // 0:关闭定时器快速清除所有标志(需要手动清除标志中断标志写1,TFLG2_TOF = 1);
  // 1:使能定时器快速清除所有标志;
  // 注意:如果TSCR1_TFFCA=1,中断函数需要操作一次TCNT寄存器使触发清除TOF,TCNT=0~65535(手动装载计数器初始值); 
  TSCR1_TFFCA = 0;
  
  // 定时器溢出中断使能, 0:关闭溢出中断,1:使能溢出中断
  TSCR2_TOI = 1; // 定时器溢出触发TFLG2_TOF中断,中断处理函数TFLG2_TOF=1清除TOF中断;
  
  TIE = 0x00; // 定时器中断使能, 0:IC/OC相应通道中断禁止,1:IC/OC相应通道中断使能;
  
  TIOS_IOS7 = 0; // IOC7脉冲累加输入脚, 输入捕获/输出比较选择OSx=0, 输入捕获;IOSx=1, 输出比较;
  
   
  // 输出比较pin脚设置
  //TCTL1/TCTL2 // OMx OLx分别设定输出方式和输出电平,00:定时器与引脚断开,01:OCx输出反转,10:OCx输出0,11:OCx输出1;
  TCTL1 = 0x00;
  TCTL2 = 0x00;
  
  //TFLG1/TFLG2中断标志寄存器,需要清除某个标志位,只需向该位写1即可,写0无效不影响改位状态值;
  //TFLG2 只有1位TOF,TOF=1说明核心计数器溢出。
  TFLG1 = 0xFF;
  TFLG2 = 0xFF; 
  
  
  /**
  定时器 时钟分频设置
  TSCR2_PR
   --------------------------------------------
  | TSCR2_PR[PR2:PR1:PR0] |     Timer Clock    |          
  |--------------------------------------------|
  |       0x0             |   Bus clock        |
  |--------------------------------------------|
  |       0x1             |   Bus clock/2      |
  |--------------------------------------------|
  |       0x2             |   Bus clock/4      |
  |--------------------------------------------|
  |       0x3             |   Bus clock/8      |
  |--------------------------------------------| 
  |       0x4             |   Bus clock/16     |
  |--------------------------------------------| 
  |       0x5             |   Bus clock/32     |
  |--------------------------------------------| 
  |       0x6             |   Bus clock/64     |
  |--------------------------------------------| 
  |       0x7             |   Bus clock/128    |
   -------------------------------------------- 
  **/
  TSCR2_PR = 0x5;  //32分频 16000000/32=500000;一个时钟周期2us
  
   // 定时器使能控制,0:关闭主定时器,包括计数器; 1:允许定时器正常工作;
  TSCR1_TEN = 1;
}

/**
* @brief 脉冲累加 计数溢出中断
*/
#pragma CODE_SEG __NEAR_SEG NON_BANKED
interrupt VectorNumber_Vtimpaaovf void timpaaovf_irq(void)
{
    
    
  if (PAFLG_PAOVF == 1) {
    
    
    PAFLG_PAOVF = 1;

    (void)printf("PAFLG_PAOVF IRQ\n");
  }
  
}
#pragma CODE_SEG DEFAULT


/**
* @brief 脉冲累加输入中断
*/
#pragma CODE_SEG __NEAR_SEG NON_BANKED
interrupt VectorNumber_Vtimpaie void timpaie_irq(void) 
{
    
    
  if (PAFLG_PAIF == 1) {
    
    
    PAFLG_PAIF = 1;
    //(void)printf("PAFLG_PAIF IRQ\n");
  }
}
#pragma CODE_SEG DEFAULT


/**
* @brief 定时器计数溢出中断
*/
#pragma CODE_SEG __NEAR_SEG NON_BANKED
interrupt VectorNumber_Vtimovf void timovf_irq(void)
{
    
    
  if(TFLG2_TOF ==1)
  {
    
    
    TFLG2_TOF = 1; //清除TOF标志 
    TCNT = 15535;  //100ms定时时间 (65535-50000) 
    
    data2 = PACNT; // 100ms定时时间内采集到的脉冲个数
    //(void)printf("time ovf data2:%u\n",data2); 
    PACNT = 0;      
   
  }  
}
#pragma CODE_SEG DEFAULT  
  


void main(void) {
    
    
  /* put your own code here */
  
  DisableInterrupts;
  pll_init();
  sci_init();
  tim_init();
	EnableInterrupts;

  PACNT = 0;

  (void)printf("************** Timer pulse accumulator *************\n");
  
  for(;;) {
    
    
    
    (void)printf("time ovf data2:%u\n",data2); 
   
    _FEED_COP(); /* feeds the dog */
  } /* loop forever */
  
  /* please make sure that you never leave main */
}

Timer输入捕获:

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define D_BUSCLK_FREQ   (16000000) // 总线频率 16MHz
#define D_SCI_BAUDRATE  (9600)     // 串口波特率  


/**
* @brief  串口发送函数
* @param  data@串口发送的字符
* @return none
*/
void csi_send(unsigned char data) 
{
    
    
  while(!SCI0SR1_TDRE);         //等待发送数据寄存器(缓冲器)为空
  SCI0DRL = data;
}


/**
* @brief  串口接收函数
* @param none
* @return 串口接收到的字符
*/
unsigned char csi_receive(void) 
{
    
    
  while(!SCI0SR1_RDRF);          //等待发送数据寄存器满
  return(SCI0DRL);
}

/*************************************************************/
/**   定义了这个两个接口就可以使用printf函数格式化输出      **/
/**   TERMIO_PutChar                                        **/
/**   TERMIO_GetChar                                        **/
/*************************************************************/
void TERMIO_PutChar(char ch){
    
    
  csi_send((unsigned char)ch);
}

char TERMIO_GetChar(void){
    
    
  return (char)csi_receive();
}

/**
* @brief  串口初始化函数
* @param none
* @return none
*/
void sci_init(void) {
    
    
  SCI0BD = D_BUSCLK_FREQ/16/D_SCI_BAUDRATE;    // 设置SCI0波特率 busCLK/16/BAUDRATE;
  SCI0CR1 = 0x00;    //设置SCI0为正常模式,八位数据位,无奇偶校验  7:LOOPS 6:SCISWAI 5:RSRC 4:M     3:WAKE 2:ILT  1:PE   0:PT
  SCI0CR2 = 0x0C;    //允许收发数据,允许收发中断功能              7:TIE,  6:TCIE,   5:RIE, 4:ILIE, 3:TE,  2:RE,  1:RWU, 0:SBK
}


/**
* @brief 锁相环 初始化
* @param none
* @return none
*/
void pll_init(void) {
    
    
  CPMUPROT = 0x26;              //保护时钟配置寄存器
  
  CPMUCLKS_PSTP = 0;            //禁用PLL
  CPMUCLKS_PLLSEL = 1;          //选择PLL作为系统时钟源
  
  CPMUOSC_OSCE = 1;             //外部晶振使能
  while(CPMUOSC_OSCPINS_EN==0); //等待外部晶振使能

  // BUSCLK = (PLLCLK / 2)   总线频率=(锁相环频率/2)
  
  
  #if 1
  //fVOC= 2*fOSC*(SYNDIV + 1)/(REFDIV + 1) 
  CPMUSYNR = 0x07;                                                  
  //CPMUREFDIV = 0x0F; // PLLCLK:16M  BUSCLK:8M   
  CPMUREFDIV = 0x07; // PLLCLK:32M  BUSCLK:16M   
  //CPMUREFDIV = 0x03; // PLLCLK:64M  BUSCLK:32M        
  #endif
  
  #if 0
  //fVOC配置 fVOC = 2*fREF*(SYNDIV +1)
  //CPMUSYNR = 0x45; // PLLCLK:48M     BUSCLK:24M
  //CPMUSYNR = 0x44; // PLLCLK:40M     BUSCLK:20M
  //CPMUSYNR = 0x43; // PLLCLK:32M     BUSCLK:16M
  //CPMUSYNR = 0x42; // PLLCLK:24M     BUSCLK:12M
  CPMUSYNR = 0x01; // PLLCLK:16M    BUSCLK:8M
  CPMUREFDIV = 0x81;//REFDIV基准分频器配置
  #endif
    
  CPMUPOSTDIV = 0x00;           // PLL CLOCK = VCO CLOCK / (POSTDIV + 1) 
                              
  _asm(nop);
  _asm(nop);
  
  CPMUPLL=0x10;               //锁相环调频启用,用以减少噪音
    
  while(CPMUFLG_LOCK == 0);	  //等待PLL稳定
  
  	  
  CPMUPROT = 0x00;            //关闭保护时钟
  CPMUCLKS_PLLSEL = 1;        //使能PLL
}

void tim_init(void) 
{
    
    

  // PT0-PT4设为输入捕获
  
  // 输入捕获/输出比较选择  IOSx=0, 输入捕获,IOSx=1, 输出比较;
  TIOS = 0xf0;  
  TIOS_IOS0 = 0;

  // 定时器使能控制,0:关闭主定时器,包括计数器; 1:允许定时器正常工作;
  TSCR1_TEN = 1;
  
  // 定时器快速清除所有标志:
  // 0:关闭定时器快速清除所有标志(需要手动清除标志中断标志写1,TFLG2_TOF = 1);
  // 1:使能定时器快速清除所有标志;
  // 注意:如果TSCR1_TFFCA=1,中断函数需要操作一次TCNT寄存器使触发清除TOF,TCNT=0~65535(手动装载计数器初始值); 
  TSCR1_TFFCA = 1;
  

  // 定时器溢出中断使能, 0:关闭溢出中断,1:使能溢出中断
  TSCR2_TOI = 0; // 定时器溢出触发TFLG2_TOF中断,中断处理函数TFLG2_TOF=1清除TOF中断;  


  // 定时器中断使能, 0:IC/OC相应通道中断禁止, 1:IC/OC相应通道中断使能。IC输入捕获,OC输出比较;
  // TIE[C7I|C6I|C5I|C4I|C3I|C2I|C1I|C0I]
  TIE = 0x0f;
  
  
  // 输入捕获边沿控制
  // TCTL3/TCTL4  EDGxB,EDGxA 输入捕获边沿控制,00:禁止捕获,01:捕获上升沿,10:捕获下降沿,11:捕获上升沿下降沿均捕获?
  TCTL3 = 0x00;
  TCTL4 = 0x55; // 上升沿捕获
  /*****************************************
  TCTL3[EDG7B|EDG7A|EDG6B|EDG6A|EDG5B|EDG5A|EDG4B|EDG4A]
  TCTL4[EDG3B|EDG3A|EDG2B|EDG2A|EDG1B|EDG1A|EDG0B|EDG0A]
  EDGnB,EDGnA  输入捕获边沿控制
   ---------------------------------------- 
  |  EDGnB  | EDGnA |  边沿检测电路配置    |
  |----------------------------------------|
  |    0    |   0   |  禁止捕获            |
  |----------------------------------------|
  |    0    |   1   |  上升沿              |
  |----------------------------------------|
  |    1    |   0   |  下降沿              |
  |----------------------------------------|
  |    1    |   1   |  上升沿/下降沿       |
   ----------------------------------------
  ********************************************/  
  
  
  //TFLG1/TFLG2中断标志寄存器,需要清除某个标志位,只需向该位写1即可,写0无效不影响改位状态值;
  //TFLG2 只有1位TOF,TOF=1说明核心计数器溢出。
  TFLG1 = 0xFF;
  TFLG2 = 0xFF; 

  /**
  定时器 时钟分频设置
  TSCR2_PR
   --------------------------------------------
  | TSCR2_PR[PR2:PR1:PR0] |     Timer Clock    |          
  |--------------------------------------------|
  |       0x0             |   Bus clock        |
  |--------------------------------------------|
  |       0x1             |   Bus clock/2      |
  |--------------------------------------------|
  |       0x2             |   Bus clock/4      |
  |--------------------------------------------|
  |       0x3             |   Bus clock/8      |
  |--------------------------------------------| 
  |       0x4             |   Bus clock/16     |
  |--------------------------------------------| 
  |       0x5             |   Bus clock/32     |
  |--------------------------------------------| 
  |       0x6             |   Bus clock/64     |
  |--------------------------------------------| 
  |       0x7             |   Bus clock/128    |
   -------------------------------------------- 
  **/
  TSCR2_PR = 4;


}


unsigned int time1=0;
unsigned int time2=0;
unsigned int delaytime=0;


#pragma CODE_SEG __NEAR_SEG NON_BANKED   //将中断ISR放在MCU未分页存储器(P-Flash)中
interrupt VectorNumber_Vtimch0 void capture0_isr(void) 
{
    
     
   if (TFLG1_C0F == 1) {
    
    
     TFLG1_C0F = 1; // 清除输入通道0中断
     time1 = time2;
     time2 = TC0;
     delaytime = time2 -time1;
     (void)printf("TFLG1_C0F %u\n",time2);
   }
}
#pragma CODE_SEG DEFAULT


void main(void) {
    
    
  /* put your own code here */
  
  DisableInterrupts;
  pll_init();
  sci_init();
  tim_init();
	EnableInterrupts;

  (void)printf("************ TIM input capture ***********\n");
  for(;;) {
    
    
    _FEED_COP(); /* feeds the dog */
  } /* loop forever */
  /* please make sure that you never leave main */
}

Timer输出比较:

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



#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define D_BUSCLK_FREQ   (16000000) // 总线频率 16MHz
#define D_SCI_BAUDRATE  (9600)     // 串口波特率  


/**
* @brief  串口发送函数
* @param  data@串口发送的字符
* @return none
*/
void csi_send(unsigned char data) 
{
    
    
  while(!SCI0SR1_TDRE);         //等待发送数据寄存器(缓冲器)为空
  SCI0DRL = data;
}


/**
* @brief  串口接收函数
* @param none
* @return 串口接收到的字符
*/
unsigned char csi_receive(void) 
{
    
    
  while(!SCI0SR1_RDRF);          //等待发送数据寄存器满
  return(SCI0DRL);
}

/*************************************************************/
/**   定义了这个两个接口就可以使用printf函数格式化输出      **/
/**   TERMIO_PutChar                                        **/
/**   TERMIO_GetChar                                        **/
/*************************************************************/
void TERMIO_PutChar(char ch){
    
    
  csi_send((unsigned char)ch);
}

char TERMIO_GetChar(void){
    
    
  return (char)csi_receive();
}

/**
* @brief  串口初始化函数
* @param none
* @return none
*/
void sci_init(void) {
    
    
  SCI0BD = D_BUSCLK_FREQ/16/D_SCI_BAUDRATE;    // 设置SCI0波特率 busCLK/16/BAUDRATE;
  SCI0CR1 = 0x00;    //设置SCI0为正常模式,八位数据位,无奇偶校验  7:LOOPS 6:SCISWAI 5:RSRC 4:M     3:WAKE 2:ILT  1:PE   0:PT
  SCI0CR2 = 0x0C;    //允许收发数据,允许收发中断功能              7:TIE,  6:TCIE,   5:RIE, 4:ILIE, 3:TE,  2:RE,  1:RWU, 0:SBK
}


/**
* @brief 锁相环 初始化
* @param none
* @return none
*/
void pll_init(void) {
    
    
  CPMUPROT = 0x26;              //保护时钟配置寄存器
  
  CPMUCLKS_PSTP = 0;            //禁用PLL
  CPMUCLKS_PLLSEL = 1;          //选择PLL作为系统时钟源
  
  CPMUOSC_OSCE = 1;             //外部晶振使能
  while(CPMUOSC_OSCPINS_EN==0); //等待外部晶振使能

  // BUSCLK = (PLLCLK / 2)   总线频率=(锁相环频率/2)
  
  
  #if 1
  //fVOC= 2*fOSC*(SYNDIV + 1)/(REFDIV + 1) 
  CPMUSYNR = 0x07;                                                  
  //CPMUREFDIV = 0x0F; // PLLCLK:16M  BUSCLK:8M   
  CPMUREFDIV = 0x07; // PLLCLK:32M  BUSCLK:16M   
  //CPMUREFDIV = 0x03; // PLLCLK:64M  BUSCLK:32M        
  #endif
  
  #if 0
  //fVOC配置 fVOC = 2*fREF*(SYNDIV +1)
  //CPMUSYNR = 0x45; // PLLCLK:48M     BUSCLK:24M
  //CPMUSYNR = 0x44; // PLLCLK:40M     BUSCLK:20M
  //CPMUSYNR = 0x43; // PLLCLK:32M     BUSCLK:16M
  //CPMUSYNR = 0x42; // PLLCLK:24M     BUSCLK:12M
  CPMUSYNR = 0x01; // PLLCLK:16M    BUSCLK:8M
  CPMUREFDIV = 0x81;//REFDIV基准分频器配置
  #endif
    
  CPMUPOSTDIV = 0x00;           // PLL CLOCK = VCO CLOCK / (POSTDIV + 1) 
                              
  _asm(nop);
  _asm(nop);
  
  CPMUPLL=0x10;               //锁相环调频启用,用以减少噪音
    
  while(CPMUFLG_LOCK == 0);	  //等待PLL稳定
  
  	  
  CPMUPROT = 0x00;            //关闭保护时钟
  CPMUCLKS_PLLSEL = 1;        //使能PLL
}


void tim_init(void) {
    
    
  // PT0-PT7设为输入捕获
  
  // 输入捕获/输出比较选择  IOSx=0, 输入捕获,IOSx=1, 输出比较;
  TIOS = 0xff;  // 设置通道x TIOS_IOSx=1;

  // CFORC 定时器比较强制寄存器,FOCx=1将导致相应通道上立即产生一个输出比较动作,
  //       这个状态和正常状态下输出比较发生后标志位未被置位后的情况相同;
  // CFORC[FOC7|FOC6|FOC5|FOC4|FOC3|FOC2|FOC1|FOC0]
  CFORC = 0xff;
  
  // TTOV = 0xff;//触发比较溢出选择,0:触发输出比较溢出禁止,1:触发输出比较溢出使能;
  // TTOV[TOV7|TOV6|TOV5|TOV4|TOV3|TOV2|TOV1|TOV0]
  TTOV = 0xff; 
     

  // OC7M输出比较7屏蔽寄存器,
  // OC7M[OC7M7|OC7M6|OC7M5|OC7M4|OC7M3|OC7M2|OC7M1|OC7M0]
  OC7M = 0x00;
  
  // OC7D 输出比较7数据寄存器,0:输出低电平,1:输出高电平
  // OC7D[OC7D7|OC7D6|OC7D5|OC7D4|OC7D3|OC7D2|OC7D1|OC7D0]
  OC7D = 0xff;
  
  // OCPD 输出比较引引脚断开寄存器,0:连接OC引脚输出,1:断开OC引脚输出;
  // OCPD[OCPD7|OCPD6|OCPD5|OCPD4|OCPD3|OCPD2|OCPD1|OCPD0]
  OCPD = 0x00;
  

  // 输出比较pin脚设置
  // TCTL1/TCTL2  OMx OLx分别设定输出方式和输出电平,00:定时器与引脚断开,01:OCx输出反转,10:OCx输出0,11:OCx输出1;
  /**********************************************
  TCTL1[OM7|OL7|OM6|OL6|OM5|OL5|OM4|OL4]
  TCTL2[OM3|OL3|OM2|OL2|OM1|OL1|OM0|OL0]
   -------------------------------------
  |    OMx   |   OLx   |    Action      |
  |-------------------------------------|
  |     0    |    0    |   引脚断开     |
  |-------------------------------------| 
  |     0    |    1    |  OCx输出反转   |
  |-------------------------------------| 
  |     1    |    0    |  OCx输出低电平 |
  |-------------------------------------| 
  |     1    |    1    |  OCx输出高电平 |
   -------------------------------------  
  ***********************************************/
  TCTL1 = 0x55;
  TCTL2 = 0xff;
     
  
  // 定时器快速清除所有标志:
  // 0:关闭定时器快速清除所有标志(需要手动清除标志中断标志写1,TFLG2_TOF = 1);
  // 1:使能定时器快速清除所有标志;
  // 注意:如果TSCR1_TFFCA=1,中断函数需要操作一次TCNT寄存器使触发清除TOF,TCNT=0~65535(手动装载计数器初始值); 
  TSCR1_TFFCA = 1;
 
  TSCR1_TSWAI = 0; //等待模式下计数器关闭控制位,0:在中断等待模式下允许MCU继续运行,1:当MCU进入中断等待模式时,禁止计时器;
 
  TSCR1_TSFRZ = 0; //在冻结模式下计时器和计数器停止位,0:冻结模式下允许计时器和计数器继续运行,1:冻结模式下禁止计时器和计数器,用于仿真调试;
 
  // 定时器中断使能, 0:IC/OC相应通道中断禁止, 1:IC/OC相应通道中断使能。IC输入捕获,OC输出比较;
  // TIE[C7I|C6I|C5I|C4I|C3I|C2I|C1I|C0I]
  TIE = 0x00;
  
  //TFLG1/TFLG2中断标志寄存器,需要清除某个标志位,只需向该位写1即可,写0无效不影响改位状态值;
  //TFLG1[C7F|C6F|C5F|C4F|C3F|C2F|C1F|C0F]  输入捕获/输出比较 通道x中断标志位
  TFLG1 = 0xFF; // 清除各IC/OC中断标志位
  
  //TFLG2 只有1位TOF,TOF=1说明核心计数器溢出。
  TFLG2 = 0xFF; // 清除自由定时器中断标志位


  /**
  定时器 时钟分频设置
  TSCR2_PR
   --------------------------------------------
  | TSCR2_PR[PR2:PR1:PR0] |     Timer Clock    |          
  |--------------------------------------------|
  |       0x0             |   Bus clock        |
  |--------------------------------------------|
  |       0x1             |   Bus clock/2      |
  |--------------------------------------------|
  |       0x2             |   Bus clock/4      |
  |--------------------------------------------|
  |       0x3             |   Bus clock/8      |
  |--------------------------------------------| 
  |       0x4             |   Bus clock/16     |
  |--------------------------------------------| 
  |       0x5             |   Bus clock/32     |
  |--------------------------------------------| 
  |       0x6             |   Bus clock/64     |
  |--------------------------------------------| 
  |       0x7             |   Bus clock/128    |
   -------------------------------------------- 
  **/
  TSCR2_PR = 0;
 
 
  //TCx[TCxH|TCxL] 16bit寄存器,填入不同的初始值可以改变输出波形时序。
  TC0 = 0;
  TC1 = 500;
  TC2 = 1000;  
  TC3 = 1500;
  TC4 = 50000;
  TC5 = 2500;
  TC6 = 3000;
  TC7 = 3500;
  
     
  // 定时器使能控制,0:关闭主定时器,包括计数器; 1:允许定时器正常工作;
  TSCR1_TEN = 1;    
    
}

void main(void) {
    
    
  /* put your own code here */
  
  DisableInterrupts;
  pll_init();
  sci_init();
  tim_init();
	EnableInterrupts;

  (void)printf("******* Timer Output Compare *******\n");
  for(;;) {
    
    
    _FEED_COP(); /* feeds the dog */
  } /* loop forever */
  /* please make sure that you never leave main */
}

猜你喜欢

转载自blog.csdn.net/u013420428/article/details/113122516