你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM8L152R8T6定时器中断异常

[复制链接]
zxdsccd 提问时间:2018-4-10 21:27 /


void TIM2_Init(void)
{
CLK_PCKENR1_PCKEN10=1;//开启定时器2外设时钟
TIM2_PSCR=0x0f;//不分频
TIM2_ARRH = 0x27; // 自动重载寄存器,10000
TIM2_ARRL = 0x10; // 计数达到该值即重头开始计数,(更新)
TIM2_CNTRH =0x00;//设定计数器起始值(出现异常后增加了这段程序)
TIM2_CNTRL =0x00;
TIM2_IER = 0x01; // 允许更新中断
TIM2_SR1_UIF=0;//清除中断标志 (出现异常后才加的这代码,异常照旧)
TIM2_CR1 = 0x85; // 允许溢出中断,开始计数
}

//下面是定时器2中断程序
//TIM2溢出中断,采样时间进行定时
#pragma vector = TIM2_OVR_UIF_vector
__interrupt void EXIT_TIM2_OVR(void)     //中断服务函数
{         
TIM2_SR1_UIF=0;//清除中断标志      
TIM2_CR1 = 0x00; //停止计数器2      
TIM2_CNTRH =0x13;//设定计数器起始值,5000(出现异常后增加了这段程序)      
TIM2_CNTRL =0x88;      
TIM2_CR1 = 0x85;//// 允许溢出中断,开始计数
}

#include <iostm8l152r8.h>
//主函数
int main( void )               
{                  
asm("rim");                  
TIM2_Init();                     
while(1);                 
}
照上面的程序运行,在计数到10000时能够进入中断,但是问题在于定时器一起动就先进入中断(从5000开始计数),然后才正常计数到10000后再次进入中断。换成定时器3,定时器4,定时器5,都一样的情况,不管是先请中断标志再启动定时器,还是启动定时器立即清除中断标志都一样的效果,初始化顺序来回调整都一样的效果,折腾一晚上了,还没搞定。

收藏 1 评论3 发布时间:2018-4-10 21:27

举报

3个回答
zxdsccd 回答时间:2018-4-10 21:28:06
#include <iostm8l152r8.h>
#include <math.h>
void TIM2_Init(void)
{
CLK_PCKENR1_PCKEN10=1;//开启定时器2外设时钟
TIM2_PSCR  = 0x07;//使用内部时钟,4分频
//TIM2_CNTRH = 0x00;
//TIM2_CNTRL = 0x00;
TIM2_ARRH  = 0x23;//自动重载值9000,计数到此值计数器从0开始重新计数
TIM2_ARRL  = 0x28;
TIM2_CNTRH = 0x00;
TIM2_CNTRL = 0x00;
TIM2_CCR1H = 0xff;
TIM2_CCR1L = 0xff;
TIM2_CCR2H = 0xff;
TIM2_CCR2L = 0xff;
//TIM2_ARRH  = 0xC0; // 自动重载寄存器,复位默认值为0xff,所以不用设置
//TIM2_ARRL  = 0x00; // 计数达到该值即重头开始计数,(更新)
TIM2_IER   = 0x01; // 允许更新中断

TIM2_SR1_UIF  = 0;
//TIM2_CR1   = 0x81; // 开始计数

}
void LCD_Init(void)
              {
               CLK_PCKENR2_PCKEN22=1;//打开RTC时钟,LCD刷新频率与此时钟有关

               CLK_PCKENR2_PCKEN23=1;//打开LCD时钟,读写LCD寄存器用到此时钟
               
               LCD_CR1=0x06;//闪烁关 //8分频,//1/4duty,1/3bias
      
               LCD_CR2=0xFE;//每像素暂停时间7clk,高驱动,高电压,内部电压
               LCD_FRQ=0x08;//分频系数
               LCD_PM0=0xFF;//直接向LCD_PM0寄存器的地址写入数据

               LCD_PM1=0xFF;//直接向LCD_PM1寄存器的地址写入数据

               LCD_PM2=0x1f;//直接向LCD_PM2寄存器的地址写入数据
               LCD_CR4=0x02;//LCD_RAM页面切换,1/8duty,1/4bias
               LCD_CR3=0x41;//使能LCD功能
              }

void fuhaoxianshi(unsigned char number,unsigned char value)
     {
       switch(number)
       {
       case 1:
         LCD_CR4&=0xFB;//切换寄存器0123
         LCD_RAM7_S202=value;//S1 MMHG
         break;
         
       case 2:
         LCD_CR4|=0x04;//切换寄存器4567
         LCD_RAM0_S004=value; //S2心率百位
         break;
         
       case 3:
         LCD_CR4|=0x04;//切换寄存器4567
         LCD_RAM4_S104=value;//S3心跳符号
         break;
       case 4:
         LCD_CR4&=0xFB;//切换寄存器0123
         LCD_RAM7_S205 =value;//S4心率不齐
         break;
       case 5:
         LCD_CR4&=0xFB;//切换寄存器0123
         LCD_RAM11_S309=value;//S5声音符号
         break;
       case 6:
         LCD_CR4|=0x04;//切换寄存器4567
         LCD_RAM1_S009=value;//S6电量
         break;
         
       case 7:
         LCD_CR4|=0x04;//切换寄存器4567
         LCD_RAM4_S109=value;// S7电池
        break;

       case 8:
         LCD_CR4|=0x04;//切换寄存器4567
         LCD_RAM2_S019=value;//90
         break;

       case 9:
         LCD_CR4&=0xFB;//切换寄存器0123
         LCD_RAM12_S319=value;//120
         break;

       case 10:
         LCD_CR4&=0xFB;//切换寄存器0123
         LCD_RAM9_S219=value;//150
         break;
      
       case 11:
         LCD_CR4&=0xFB;//切换寄存器0123
         LCD_RAM9_S218=value;//记忆
         break;
         
       case 12:
         LCD_CR4&=0xFB;//切换寄存器0123
         LCD_RAM5_S118=value;//双人2
         break;
         
       case 13:
         LCD_CR4&=0xFB;//切换寄存器0123
         LCD_RAM2_S018=value;//双人1
         break;
         
       case 14:
         LCD_CR4|=0x04;//切换寄存器4567
         LCD_RAM5_S119=value;//
         break;
         
       case 15:
         LCD_CR4|=0x04;//切换寄存器4567
         LCD_RAM2_S020=value;
         break;
         
       case 16:
         LCD_CR4&=0xFB;//切换寄存器0123
         LCD_RAM13_S320=value;
         break;
         
       case 17:
         LCD_CR4&=0xFB;//切换寄存器0123
         LCD_RAM9_S220=value;
         break;
         
       case 18:
         LCD_CR4&=0xFB;//切换寄存器0123
         LCD_RAM6_S120=value;
         break;
         
       case 19:
         LCD_CR4&=0xFB;//切换寄存器0123
         LCD_RAM2_S020=value;
         break;
         
       case 20://COL
         LCD_CR4|=0x04;//切换寄存器4567
         LCD_RAM6_S120=value;
         break;
         
       case 21:
         LCD_CR4&=0xFB;//切换寄存器0123
         LCD_RAM8_S214=value;
         break;
         
       case 22:
         LCD_CR4&=0xFB;//切换寄存器0123
         LCD_RAM5_S114=value;
         break;
         
       case 23:
         LCD_CR4|=0x04;//切换寄存器4567
         LCD_RAM5_S113=value;
         break;
         
       case 24:
         LCD_CR4&=0xFB;//切换寄存器0123
         LCD_RAM1_S014=value;
         break;
         
       case 25:
         LCD_CR4&=0xFB;//切换寄存器0123
         LCD_RAM12_S316=value;
         break;
         
       case 26:
         LCD_CR4&=0xFB;//切换寄存器0123
         LCD_RAM12_S318=value;
         break;
         
       case 27:
         LCD_CR4&=0xFB;//切换寄存器0123
         LCD_RAM2_S019=value;
         break;
         
       case 28:
         LCD_CR4&=0xFB;//切换寄存器0123
         LCD_RAM5_S119=value;
         break;
         
       case 29:
         LCD_CR4&=0xFB;//切换寄存器0123
         LCD_RAM7_S203=value;
         break;
       }
     }



void shuzixianshi(unsigned char number,unsigned char value)
         {
         unsigned char A=0;   //              A
         unsigned char B=0;  //           F   G   B
         unsigned char C=0;  //           E       C
         unsigned char D=0;  //               D
         unsigned char E=0;
         unsigned char F=0;
         unsigned char G=0;
         switch(value)
                 {
                case 0:
                   A=1;
                   B=1;
                   C=1;
                   D=1;
                   E=1;
                   F=1;
                   break;
          case 1:
          B=1;
          C=1;
          break;
         
          case 2:
          A=1;
          B=1;
          D=1;
          E=1;
          G=1;
          break;
         
          case 3:
          A=1;
          B=1;
          C=1;
          D=1;
          G=1;
          break;
         
          case 4:
          B=1;
          C=1;
          F=1;
          G=1;
          break;
         
          case 5:
           A=1;
          C=1;
          D=1;
          F=1;
          G=1;
          break;
         
          case 6:
           A=1;
          C=1;
          D=1;
          E=1;
          F=1;
          G=1;
          break;
         
          case 7:
           A=1;
          B=1;
          C=1;
          break;
         
          case 8:
          A=1;
          B=1;
          C=1;
          D=1;
          E=1;
          F=1;
          G=1;
          break;
         
          case 9:
          A=1;
          B=1;
          C=1;
          D=1;
          F=1;
          G=1;
          break;
         
         case 10:
          A=1;
          D=1;
          E=1;
          F=1;
          G=1;
          break;
        }
         
  switch(number)
         {
           
         case 1:
              LCD_CR4&=0xFB;//切换寄存器0123
              LCD_RAM7_S200=A;
              LCD_RAM10_S300=B;
              LCD_RAM10_S301=F;
              LCD_CR4|=0x04;//切换寄存器4567
              LCD_RAM0_S000=C;
              LCD_RAM3_S100=D;
              LCD_RAM3_S101=E;
              LCD_RAM0_S001=G;
              break;
         
         
         case 2:
              LCD_CR4&=0xFB;//切换寄存器0123
              LCD_RAM10_S303=A;
              LCD_RAM10_S302=B;
              LCD_RAM11_S304=F;
              LCD_CR4|=0x04;//切换寄存器4567
              LCD_RAM0_S002=C;
              LCD_RAM3_S102=D;
              LCD_RAM3_S103=E;
              LCD_RAM0_S003=G;
             break;
         case 3:
              LCD_CR4&=0xFB;//切换寄存器0123
              LCD_RAM7_S206=A;
              LCD_RAM11_S305=B;
              LCD_RAM11_S306=F;
              LCD_CR4|=0x04;//切换寄存器4567
              LCD_RAM4_S105=C;
              LCD_RAM4_S106=D;
              LCD_RAM0_S006=E;
              LCD_RAM0_S005=G;
             break;
         case 4:
              LCD_CR4&=0xFB;//切换寄存器0123
              LCD_RAM7_S207=A;
              LCD_RAM11_S307=B;
              LCD_RAM11_S308=F;
              LCD_CR4|=0x04;//切换寄存器4567
              LCD_RAM0_S007=C;
              LCD_RAM4_S107 =D;
              LCD_RAM4_S108=E;
              LCD_RAM1_S008=G;
             break;
         
         
         case 5:
              LCD_CR4&=0xFB;//切换寄存器0123
              LCD_RAM0_S001=A;
              LCD_RAM0_S000=B;
              LCD_RAM3_S100=C;
              LCD_RAM7_S201=D;
              LCD_RAM3_S102=E;
              LCD_RAM0_S002=F;
              LCD_RAM3_S101=G;
             break;
         
         case 6:
              LCD_CR4&=0xFB;//切换寄存器0123
              LCD_RAM0_S004=A;
              LCD_RAM0_S003=B;
              LCD_RAM3_S103=C;
              LCD_RAM7_S204=D;
              LCD_RAM4_S105=E;
              LCD_RAM0_S005=F;
              LCD_RAM4_S104=G;
             break;
         
         case 7:
              LCD_CR4&=0xFB;//切换寄存器0123
              LCD_RAM0_S006=A;
              LCD_RAM4_S106=B;
              LCD_RAM4_S107=C;
              LCD_RAM8_S208=D;
              LCD_RAM4_S108=E;
              LCD_RAM1_S008=F;
              LCD_RAM0_S007=G;
             break;
         case 8:
              LCD_CR4&=0xFB;//切换寄存器0123
              LCD_RAM11_S311=A;
              LCD_CR4|=0x04;//切换寄存器4567
              LCD_RAM1_S010=B;
              LCD_RAM4_S110=C;
              LCD_RAM4_S111=D;
              LCD_RAM5_S112=E;
              LCD_RAM1_S012=F;
              LCD_RAM1_S011=G;
             break;
         
         case 9:
              LCD_CR4&=0xFB;//切换寄存器0123
              LCD_RAM12_S314=A;
              LCD_RAM12_S313=B;
              LCD_CR4|=0x04;//切换寄存器4567
              LCD_RAM1_S013=C;
              LCD_RAM5_S114=D;
              LCD_RAM5_S115=E;
              LCD_RAM1_S015=F;
              LCD_RAM1_S014=G;
             break;
         
         case 10:
              LCD_CR4&=0xFB;//切换寄存器0123
              LCD_RAM12_S317=A;
              LCD_CR4|=0x04;//切换寄存器4567
              LCD_RAM2_S016=B;
              LCD_RAM5_S116=C;
              LCD_RAM5_S117=D;
              LCD_RAM5_S118=E;
              LCD_RAM2_S018=F;
              LCD_RAM2_S017=G;
             break;
         
         case 11:
              LCD_CR4&=0xFB;//切换寄存器0123
              LCD_RAM1_S010=A;
              LCD_RAM4_S110=B;
              LCD_RAM8_S210=C;
              LCD_RAM11_S310=D;
              LCD_RAM8_S211=E;
              LCD_RAM1_S011=F;
              LCD_RAM4_S111=G;
             break;
         
         case 12:
              LCD_CR4&=0xFB;//切换寄存器0123
              LCD_RAM1_S012=A;
              LCD_RAM5_S112=B;
              LCD_RAM8_S212=C;
              LCD_RAM12_S312=D;
              LCD_RAM8_S213=E;
              LCD_RAM1_S013=F;
              LCD_RAM5_S113=G;
             break;
         case 13:
              LCD_CR4&=0xFB;//切换寄存器0123
              LCD_RAM1_S015=A;
              LCD_RAM5_S115=B;
              LCD_RAM8_S215=C;
              LCD_RAM12_S315=D;
              LCD_RAM9_S216=E;
              LCD_RAM2_S016=F;
              LCD_RAM5_S116=G;
             break;
         case 14:
              LCD_CR4&=0xFB;//切换寄存器0123
              LCD_RAM5_S117=A;
              LCD_RAM2_S017=B;
              LCD_RAM9_S217=C;
             break;

         }
}
void port_init(void)
        {
        PC_DDR=0x00;//引脚全为输入,带32k管脚和I2C,PC2双人控制,PC3 ON/OFF,PC4记忆,PC7设置
        PC_CR1=0xff;//输入上拉
        PC_CR2=0x08;//PC3电平中断允许,ON/OFF
        
        PD_ODR=0x00;//数据输出寄存器,对应输出端口电平
        PD_DDR=0x80;//PD7位电机驱动,其他引脚全为输入,PD4,PD5为COM4,COM5,其他引脚悬空
        PD_CR1=0xff;//推挽输出,输入上拉
        PD_CR2=0x00;//禁止外部中断
        
        PE_ODR=0x00;//数据输出寄存器,对应输出端口电平
        PE_DDR=0x40;//PE6为输出驱动电磁阀,其他引脚全为输入
        PE_CR1=0xff;//推挽输出,输入上拉
        PE_CR2=0x00;//输出模式最大2MHZ
        
        PF_DDR=0x00;//输引脚全为输入,PD4,PD5为COM4,COM5,其他引脚悬空
        PF_CR1=0xff;//输入上拉
        PF_CR2=0x00;//禁止外部中断
        
        
        PG_DDR=0x00;//输引脚全为输入,PD4,PD5为COM4,COM5,其他引脚悬空
        PG_CR1=0xff;//输入上拉
        PG_CR1=0x00;//禁止外部中断
        
        }
void CLOCK_Init(unsigned char i)
{
   if(i==1)//高频运行
          {
          CLK_ICKCR|=0x04;//开启内部低速时钟
          CLK_CRTCR=0x10;//RTC时钟,采用外部低速时钟,不分频
  
          CLK_SWR=0x04;//选择外部高速晶振为主时钟
   
          CLK_SWCR|=0x02;//切换时钟源
          CLK_CKDIVR=0x00; //12MHZ不分频
          }
   else  //低频运行
         {
          CLK_ICKCR|=0x04;//开启内部低速时钟
          CLK_CRTCR=0x04;//RTC时钟,采用内部低速时钟,不分频
  
          CLK_SWR=0x08;//选择外部低速振荡器为主时钟
   
          CLK_SWCR|=0x02;//切换时钟源
          CLK_CKDIVR=0x00; //32k不分频
         }

}

#pragma vector = TIM2_OVR_UIF_vector
__interrupt void EXIT_TIM2_OVR(void)     //中断服务函数  
            {  
            TIM2_SR1_UIF =0;//清除中断标志
            TIM2_CR1 = 0x00; //停止计数器1
            TIM2_CNTRH =0x11;//计数器赋值4500,从4500开始计数
            TIM2_CNTRL =0x94;
            TIM2_CR1 = 0x81;//开始计数
            PD_ODR^=0x80;//外部电机驱动端口,高电平驱动
            }

void main(void)
          {
           unsigned int j=0;
           asm("sim");//关全局中断
           CLOCK_Init(0);//低频,内部低速时钟
           port_init();//初始化IO口
           LCD_Init();//初始化LCD
           TIM2_Init();//初始化tim2
           j=TIM2_SR1&0xC7;//读TIM2中断标志寄存器
           shuzixianshi(10,1);//显示序号1
           shuzixianshi(3,j/100);//显示TIM中断寄存器值
           shuzixianshi(2,j%100/10);
           shuzixianshi(1,j%10);
           
           j=TIM2_CNTRH;//读TIM计数器值
           j=(j<<8)+TIM2_CNTRL;
           shuzixianshi(8,j%10000/1000);//显示计数器值
           shuzixianshi(7,j%1000/100);
           shuzixianshi(6,j%100/10);
           shuzixianshi(5,j%10);
                  
           asm("rim");//开全局中断
           shuzixianshi(10,2);//显示序号2
           j=TIM2_SR1&0xC7;//读TIM2中断标志寄存器
           shuzixianshi(3,j/100);//显示中断标志寄存器值
           shuzixianshi(2,j%100/10);
           shuzixianshi(1,j%10);
           j=TIM2_CNTRH;//读计数器值
           j=(j<<8)+TIM2_CNTRL;
           shuzixianshi(8,j%10000/1000);//显示计数器值
           shuzixianshi(7,j%1000/100);
           shuzixianshi(6,j%100/10);
           shuzixianshi(5,j%10);
           
           
           TIM2_CR1   = 0x81; // 开始计数
           while(1)//循环读取计数器中断标志寄存器和计数值并显示
                  {
                   shuzixianshi(10,3);
                   j=TIM2_SR1&0xC7;
                   shuzixianshi(3,j/100);
                   shuzixianshi(2,j%100/10);
                   shuzixianshi(1,j%10);
                  
                   j=TIM2_CNTRH;
                   j=(j<<8)+TIM2_CNTRL;
                   shuzixianshi(8,j%10000/1000);
                   shuzixianshi(7,j%1000/100);
                   shuzixianshi(6,j%100/10);
                   shuzixianshi(5,j%10);
                  
                  
                  }
}

上面是完整程序
单步调试,序号1,2,3段都正常,计数器从0开始计数,计数到9000,产生溢出中断(更新),
PD7口输出高电平,电机运转。
分段调试也运行正常,
但是如果让单片机自己运行,计数器到序号3段时中断寄存器的值就是0x07,表明两个比较中断和溢出中断标志都置位了,计数器进入中断程序,然后计数器从4500开始计数,PD7直接输出高电平,电机运转,计数到9000后电机停止,然后从4500再开始计数,再次计数到9000,电机停止,从现象开,程序在定时器溢出时能正常进入中断,但是还是老问题,为啥一起动定时器即进入定时器溢出中断,然后后续才能正常运行,调整了开始计数命令和全局中断命令位置也是同样的情况,
zxdsccd 回答时间:2018-4-10 22:17:42
找到为啥出现已启动即进入定时器中断了,经过反复验证,并不是一启动就进入定时器中断,而是经过非常短的时间即进入定时器中断,大约0.3秒左右,这段时间定时器在计数,速度非常快,并不是设定的速度,溢出后进入中断,然后定时器才开始按照设定的频率进行计数,我以为是时钟设置问题,上面的程序设置的是内部低速时钟,我直接采用默认的内部高速时钟,但存在同样的问题,为啥出现这种现象,目前还不清楚
zxdsccd 回答时间:2018-4-10 22:39:23
根本原因找到了,问题出在预装载寄存器上,下面这段程序并没有把值写入对应的寄存器,而是写在预装载寄存器里面,在发生更新(溢出)时才会写入对应的寄存器里面,
void TIM2_Init(void)
{
CLK_PCKENR1_PCKEN10=1;//开启定时器2外设时钟
TIM2_PSCR  = 0x07;//使用内部时钟,4分频
//TIM2_CNTRH = 0x00;
//TIM2_CNTRL = 0x00;
TIM2_ARRH  = 0x23;//自动重载值9000,计数到此值计数器从0开始重新计数
TIM2_ARRL  = 0x28;
TIM2_CNTRH = 0x00;
TIM2_CNTRL = 0x00;
TIM2_CCR1H = 0xff;
TIM2_CCR1L = 0xff;
TIM2_CCR2H = 0xff;
TIM2_CCR2L = 0xff;
//TIM2_ARRH  = 0xC0; // 自动重载寄存器,复位默认值为0xff,所以不用设置
//TIM2_ARRL  = 0x00; // 计数达到该值即重头开始计数,(更新)
TIM2_IER   = 0x01; // 允许更新中断

TIM2_SR1_UIF  = 0;
//TIM2_CR1   = 0x81; // 开始计数

}

在这段程序的末尾加一个强制更新命令即可,
TIM2_EGR_UG   =1;
到这程序运行就全部正常了。

意法的定时器功能太多了,以前用AVR、PIC、合泰的设置都没这么复杂,这个问题折腾了我一周时间。希望刚开始用意法的同行引以为戒

评分

参与人数 1蝴蝶豆 +3 收起 理由
zero99 + 3 结贴奖励

查看全部评分

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版