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

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管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版