PIC18F25k80不断重启

2019-03-25 19:16发布

最近做了个CAN总线取件纠错的系统,开机LED灯闪烁一次。但是程序运行的时候LED一直闪,就是在init()函数初始化LED闪烁一次后程序不断复位,实在找不出原因了,烦请各位大神帮忙分析下原因。
#include <pic18f25k80.h>
#define uchar unsigned char
#define uint  unsigned int
#define LED PORTBbits.RB4
void init();//初始化函数
void caninit();//CAN初始化
void cansend();//发送函数
void interrupt canrec();//can总线接收中断函数
void delay(uint time);//延时函数
void run();//上位机操作码判断函数
uchar addr;//地址
uchar sidh;//发送标识符高位
uchar sidl;//发送标识符低位
uchar sidh1;//接收标识符高位
uchar sidl1;//接收标识符低位
uchar opcode;//操作码
uchar fucode;//功能码
uchar takenum;//取件数量
uchar opnum;//操作数量
uchar stcation;//指示状态
#pragma config INTOSCSEL=LOW//休眠期间LF-INTOSC处于低功耗模式
#pragma config SOSCSEL=DIG //数字模式使能RC0,RC1端口功能
#pragma config XINST=OFF  //不使用扩展指令集
#pragma config RETEN=OFF  //禁止超低功耗稳压器
#pragma config IESO=OFF    // 禁止双速启动
#pragma config FOSC=HS1   //振荡器4-16MHZ
#pragma config FCMEN=OFF //禁止故障保护时钟
#pragma config PLLCFG=OFF  //直接试用晶振
#pragma config BOREN=OFF   //关闭欠压复位
#pragma config BORPWR=LOW  //低功耗级别
#pragma config BORV=3    //欠压复位电压1.8V
#pragma config PWRTEN=OFF //禁止上电延时复位
#pragma config WDTPS=256   //WDT后分频比为1:256约为1.024S
#pragma config WDTEN=OFF   //关闭看门狗
#pragma config CANMX=PORTB  //CAN TX RX为RB2 RB3
#pragma config MSSPMSK=MSK7  //7位地址掩码
#pragma config MCLRE=ON      // 使能MCLR复位引脚,禁止RE3IO功能
#pragma config STVREN=OFF     //堆栈下溢、满不会导致复位
#pragma config BBSIZ=BB2K   //引导区为2K
#pragma config CP0=OFF      //代码保护关闭
#pragma config CP1=OFF
#pragma config CP2=OFF
#pragma config CP3=OFF
#pragma config CPD=OFF
#pragma config CPB=OFF
#pragma config WRT0=OFF    //不写保护
#pragma config WRT1=OFF
#pragma config WRT2=OFF
#pragma config WRT3=OFF
#pragma config WRTB=OFF
#pragma config WRTC=OFF
#pragma config WRTD=OFF
#pragma config EBTR0=OFF
#pragma config EBTR1=OFF
#pragma config EBTR2=OFF
#pragma config EBTR3=OFF   //允许表读
#pragma config EBTRB=OFF
void main()
{
INTCON=0x00;//关中断
init();//初始化
caninit();//CAN初始化
INTCON=0XC0;//开中断
    while(1)
{
    if(PORTBbits.RB0==0)//发送数据判断
    {
      delay(10);
      if(PORTBbits.RB0==0)//消抖
      {
  while(PORTBbits.RB0==1);//检测开关是否释放
  LED=1;//如果释放LED灯闪烁2次
  delay(50);
  LED=0;
  delay(50);
  LED=1;
  delay(50);
  LED=0;
  delay(50);
        stcation=0;//更新指示状态
        opnum=opnum++;//操作数量加1
        if(opnum>takenum)
         {
          fucode=0x06;//如果取件错误,设置错误码
         }
        cansend();//CAN总线发送数据
      }
     }
     run();//上位机命令判断
}
        
}
void init()
{   
TRISC=0xff;//设置RC口为输入
    TRISB=0x09;//设置RB0为输入,CANTX为输出,CANRX为输入,RB4为输出
//INTCON2bits.nRBPU=1;//开RB上拉
LED=1;//开机LED闪烁1次
delay(50);
LED=0;
delay(50);
    addr=PORTC;//读取取件器设置地址值
sidh=(addr>>3)&0x20;//CAN发送高位标识符
sidl=(addr<<5)&0x00;//CAN发送低位标识符
sidh1=(addr>>3)&0x00;//can接收高位标识符
sidl1=(addr<<5)&0x00;//can接收低位标识符
opcode=1;//初始化操作码
    fucode=1;//初始化功能码
    takenum=0;//初始化取件数量
    opnum=0;//初始化操作数量
    stcation=0;//初始化指示状态
}
void caninit()
{
    CANCON=0x80;//请求进入CAN配置模式
    while(CANSTAT&0x80==0);//等待进入CAN配置模式
    BRGCON1=0X01;//设置SJW和BRP,SJW=1TQ,BRP=01H
    BRGCON2=0X90;//设置Phase_Seg1=3TQ和Prog _Seg=1TQ
    BRGCON3=0X42;//设置Phase_Seg2=3TQ
    TXB0CON=0X03;//设置发送优先级为最高
    TXB0SIDH=sidh;//高位标识符
    TXB0SIDL=sidl;//低位标识符
    TXB0DLC=0x05;//设置数据长度为5字节
RXB0SIDH=sidh1;//接收缓冲区0高位标识符
    RXB0SIDL=sidl1;//接收缓冲区0低位标识符
    RXB0CON=0X20;//接收标准标识符
    RXB0DLC=0X05;//设置接收缓冲区0数据长度为5字节
RXF0SIDH=sidh1;//过滤器
    RXF0SIDL=sidl1;//过滤器
RXM0SIDH=0XFF;//屏蔽与过滤器标识符不同的数据
    RXM0SIDL=0XFF;//屏蔽与过滤器标识符不同的数据
    RXB1SIDH=0X00;//接收广播
    RXB1SIDL=0X00;//接收广播
    RXB1CON=0X22;//接收标准标识符和过滤器为RXF2
    RXB0DLC=0X05;//设置接收缓冲区1数据长度为5字节
RXF2SIDH=0X00;//过滤器
RXF2SIDL=0X00;//过滤器
RXM1SIDH=0XFF;//接收与过滤器2相同标识符的数据
RXM1SIDL=0XFF;//接收与过滤器2相同标识符的数据
    CIOCON=0x31;//CAN IO初始化 使用振荡器作为时钟
    CANCON=0X00;//正常工作模式
    while(CANSTAT&0XE0!=0);//检测CAN总线是否正常工作
    PIR5=0X00;//清所有CAN中断
    PIE5=0X0c;//开CAN接收中断
    IPR5=0X0c;//CAN接收中断最高优先级
}
void interrupt canrec()//CAN总线接收中断函数
{
    if((PIR5bits.RXB0IF==1)&&(opcode!=0x06))//缓冲区0接收中断
  {
PIR5bits.RXB0IF=0;//清中断标志位
RXB0CONbits.RXFUL=0;//打开接收缓冲器0接收数据
while(RXB0CONbits.RXFUL==0);
opcode=RXB0D0;//接收操作码
fucode=RXB0D1;//接收功能码
takenum=RXB0D2;//取件数量
  }
if((PIR5bits.RXB1IF==1)&&(opcode!=0x06))//CAN总线缓冲区1接收中断
  {
PIR5bits.RXB1IF=0;//清中断标志位
RXB1CONbits.RXFUL=0;//打开接收缓冲区1接收数据
while(RXB1CONbits.RXFUL==1);//等待接收完成
opcode=RXB1D0;//接收操作码
fucode=RXB1D1;//接收功能码
takenum=RXB1D2;//接收取件数量
  }
   if((PIR5bits.RXB1IF==1)&&(opcode==6)) //误码率测试
  {
    PIR5bits.RXB1IF=0;//清中断标志位
RXB1CONbits.RXFUL=0;//打开接收缓冲区1接收数据
while(RXB1CONbits.RXFUL==1);//等待接收完成
TXB0D0=RXB1D0;
TXB0D1=RXB1D1;
TXB0D2=RXB1D2;
TXB0D3=RXB1D3;
TXB0D4=RXB1D4;
cansend();
  }
if((PIR5bits.RXB0IF==1)&&(opcode==6))  //误码率测试
  {
    PIR5bits.RXB0IF=0;//清中断标志位
RXB0CONbits.RXFUL=0;//打开接收缓冲区0接收数据
while(RXB0CONbits.RXFUL==1);//等待接收完成
TXB0D0=RXB0D0;
TXB0D1=RXB0D1;
TXB0D2=RXB0D2;
TXB0D3=RXB0D3;
TXB0D4=RXB0D4;
cansend();
  }
}
void cansend()//CAN发送数据函数
{
if(opcode!=0x06)
   {
    TXB0D0=opcode;//写发送缓冲区
    TXB0D1=fucode;//写发送缓冲区
    TXB0D2=takenum;//写发送缓冲区
    TXB0D3=opnum;//写发送缓冲区
    TXB0D4=stcation;//写发送缓冲区
    TXB0CONbits.TXREQ=1;//开始发送
    while(PIR5bits.TXB0IF);//检测是否发送完毕
TXB0CONbits.TXREQ=0;//禁止发送
   }
   if(opcode==0x06)
   {
    TXB0CONbits.TXREQ=1;//开始发送
    while(PIR5bits.TXB0IF);//检测是否发送完毕
TXB0CONbits.TXREQ=0;//禁止发送
   }
}
void  run()//上位机命令判断函数
{
    switch(opcode)//操作码判断
  {
    case 0:
    {
   cansend();//状态查询
   opcode=1;
      break;
    }
    case 1:
    {
      if(fucode==0)//复位
       {
  LED=0;
  opcode=1;
        fucode=1;
        takenum=0;
        opnum=0;
        stcation=0;
       }
       if(fucode==1)//取件
        {
         if(takenum!=0)
         {
         LED=1;
         fucode=1;
         stcation=1;
         }
         if(takenum==0)
         {
          LED=0;
         }
        }
        break;
    }
    case 2://进入测试流程
     {
        stcation=0x02;
  LED=1;
        delay(50);
  LED=0;
        delay(50);
  LED=1;
        delay(50);
  LED=0;
        delay(50);
  LED=1;
        delay(50);
  LED=0;
        delay(50);
  LED=1;
        delay(50);
  LED=0;
        delay(50);
  LED=1;
        delay(50);
        LED=0;
        opcode=0;
        stcation=0;
      break;
    }
     case 3://设置取件指示灯
      {
        if(fucode==0x03)
        {
         LED=0;
         stcation=0;
        }
        if(fucode==0x04)
        {
         LED=1;
         stcation=1;
        }
        if(fucode==0x05)
        {
         do
         {
    LED=1;
          delay(50);
          LED=0;
          delay(50);
          stcation=0x03;
         }
         while((fucode!=0x05)||(opcode!=0x03));
         stcation=0;
        }
        break;
      }
     case 5://重启
     {
       WDTCON=1;//开狗
       while(1);//等待看门狗重启程序
     }
  }
}
void delay(uint time)//延时函数
   {
     uint a,b;
     for(a=time;a>0;a--)
     for(b=110;b>0;b--);
   }
     
            
      
         
   
   
   
   

此帖出自小平头技术问答
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
3条回答
forbbzmt
2019-03-26 12:15
kevin.wang 发表于 2013-12-23 19:21
:cry2::cry2::cry2:求大神,没人懂么?

用 C 对PIC18Fxx时,要注意对变量的定义一定要用#pragma udata(idata) 为变量分配地址,否则容易出错。
第二、子函数的形参和局部变量越少越好。这两点是我用教训换来的。我没仔细看你的程序,你说的“复位“现象可以通过仿真看看RCON的值,确定复位源。一般的,如果不开WATCHDOG的话,软件写成什么样都不会引起复位的

一周热门 更多>