MC9S08DZ60单片机测量时间的问题

1.    问题描述

用DZ60的计时器测周期时发现,TPM(计时器)在初始化后,需要等待500多ms才能勉强测到。

TPM产生的波形如下图,蓝色波形上升沿为初始化指令执行完成时间点,用一个IO口输出高电平并延时100ms作为示波器触发源,黄色波形为TPM的PWM方式输出波形。


2.    问题分析

         在DZ60DATASHEET中文版第313页找到这段话。

大概意思是TPM的通道控制寄存器的更新时机由clksb:clksa控制。而clksb:clksa的功能如表16-3所示。

        合起来就是说,对通道控制寄存器的写入,不是直接写到寄存器里面,而是先写到寄存器对应的缓冲器。当TPM计数器关闭时,写入的数据从缓冲器写入完成后立即更新到寄存器;而当TPM有时钟在运行时,写入的数据更新则需要等到,计时器从0xfffe变成0xffff才开始进行。

        由此想到,产生问题的TPM初始化是128分频(16MHZ总线时钟下,周期为8us)。16位TPM计数器从0开始计数,则有更新设置需等待时间为65535×8us=524ms。与所见波形符合。



3.    问题解决

         无论TPM用作输入捕捉,还是PWM或者比较输出,所有TPM控制寄存器初始化时,都要先把时钟关掉,即clksb:clksa=0b00。问题解决后得到波形如下:


4.      正确实例

  

//初始化时必须先关掉时钟,否则以下两个寄存器要到将要溢出即(0xfffe->0xffff)时才会更新。
    //--如果设置128分频,则初始化时间需要 16MHz/128*65535=524ms
//关掉时钟初始化,则寄存器在写入完成后立即更新,无需等待。
//TPM2产生中央对齐PWM输出
    TPM_CSTR(TPM_NUM_2) =0b001<span style="color:#ff0000;">00</span>111;
    //                      |||||||
    //                      ||||||+-----PS0\
    //                      |||||+------PS1 ----128倍分频
    //                      ||||+-------PS2/
    //                      |||+--------CLKSA\
    //                      ||+---------CLKSB/--关时钟
    //                      |+----------CPWMS---所有通道以中央对齐PWM模式运行
    //                      +-----------TOIE----禁止溢出中断
//TPM1设置为输入捕捉
    TPM_CSTR(TPM_NUM_1) =0b000<span style="color:#ff0000;">00</span>111;
    //                      |||||||
    //                      ||||||+-----PS0\
    //                      |||||+------PS1 ----128倍分频
    //                      ||||+-------PS2/
    //                      |||+--------CLKSA\
    //                      ||+---------CLKSB/--关时钟
    //                      |+----------CPWMS---所有通道以输入捕捉运行
    //                      +-----------TOIE----禁止溢出中断
//TPM2通道设置
    TPM2_CHSCSTR(TPM_CHNo)=0b00101000;
    //                        |||||
    //                        ||||+-----ELSA\
    //                        |||+------ELSB/---High-true 脉冲(清除向上比较输出)
    //                        ||+-------MSA\
    //                        |+--------MSB/----CPWMS=1时,此设置无效
    //                        +---------CHIE----禁止中断
    tmp = Period * (125) / 2;
    TPM2MOD = tmp;     //周期Period以ms为单位
    TPM2C0V = tmp / 10 * Duty / 10;   //占空比Duty为0~100整数
    TPM2SC_CLKSB = 0;
    TPM2SC_CLKSA = 1;  <span style="color:#ff0000;">//寄存器设置完成,再打开总线时钟,避免长时间的寄存器更新。</span>
//TPM2通道设置
    TPM1SC_CLKSB = 0;
    TPM1SC_CLKSA = 1;  <span style="color:#ff0000;">//寄存器设置完成,再打开总线时钟,避免长时间的寄存器更新。</span>
    TPM1SC_TOIE = 1;   //使能输入捕捉中断
EnableTPM1ChInt(G_TMUch_Start);

中断程序的写法如下
interrupt void isrT1Ch0In(void)
{
   DisableInterrupt();          //禁止总中断

   if(TPM1C0SC_CH0F == 1)   //判断是否发生输入捕捉中断
   {
       TPM1C0SC_CH0F = 0;     //清除标志位
       switch(g_trigged)
       {
       case 0:
           //第一次触发,保存数据
           g_start_data = TPM1C0V;
           g_trigged++;
           //设置第二次触发边沿方式
           <span style="color:#ff0000;">TPM_CSTR(TPM_NUM_1) =0b00000111;//重新初始化,避免长时间的寄存器更新。</span>
           switch(G_Edge_Stop) 
           {
             case POS_EDGE:
                 TPM1_CHSCSTR(G_TMUch_Stop)=0b00000100;
                 //                              |||||
                 //                              ||||+-----ELSA\
                 //                              |||+------ELSB/---上升边沿捕捉
                 //                              ||+-------MSA\
                 //                              |+--------MSB/----输入捕捉模式
                 //                              +---------CHIE----禁止通道中断
                 break;
             case NEG_EDGE:
                 TPM1_CHSCSTR(G_TMUch_Stop)=0b00001000;//下降边沿捕捉
                 break;
             default:
                 TPM1_CHSCSTR(G_TMUch_Stop)=0b00000100;//默认为上升边沿捕捉
                 break;
           }           
          <span style="color:#ff0000;"> //寄存器设置完成,再打开总线时钟,避免长时间的寄存器更新。
           TPM1SC_CLKSB = 0;
           TPM1SC_CLKSA = 1; 
           TPM1SC_TOIE = 1;</span>
           EnableTPM1ChInt(G_TMUch_Stop);
           break;
       case 1:
           //第二次触发,保存数据
           g_stop_data = TPM1C0V;
           g_trigged++;
           //时间采集完毕,恢复成IO功能
           TPM1_CHSCSTR(G_TMUch_Start)=0b00000000; 
           TPM1_CHSCSTR(G_TMUch_Stop)=0b00000000;  //恢复成IO功能
           break;
       default:
           break;
       } 
   }
   
   EnableInterrupt();           //开放总中断
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值