⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 基于SJA1000和STC89C54的CAN转RS232透明数据传输
💻 C
字号:
#include "stc89c51.h"
#include "main.h"
#include "SJA1000_Peli_REG.h"
#include <intrins.h>

unsigned char  error;
unsigned char  RX_Total_NUM;
unsigned char  TX_Total_NUM;
unsigned char  RX_Total_NUM_COM;
unsigned char  TX_Total_NUM_COM;



void mcu_init(void);
void sja_init(void);

void main()
{
  /*初始化*/ 
  mcu_init(); 
  sja_init();
  while(1)
     {
              WDT_CONTR = 0X34 ;  //喂狗
              if ( uart_buf_num >= 8 ) 
			   //如果已接受了8个字节,则打包转发到CAN总线上
               {
                  unsigned char pdata * ptr ;
                  unsigned char i ; 
                  while ( ( Peli_SR & 0x04 ) == 0 ) ; //等待发送缓冲区释放                             
                  Peli_TXFMINFO  =  0x08 ;  //标准数据帧,数据字节数为1
                  Peli_TXBUF1    =  0x00 ;  //标识符  
			      Peli_TXBUF2    =  0x20 ; 
                  ptr            =  &Peli_TXBUF3  ;
                  for ( i = 0 ; i<8 ; i++)
				     {
                        *ptr++   =  UART_BUF[uart_s_ptr] ;
                        TX_Total_NUM ++ ; 
					//	SBUF   =  UART_BUF[uart_s_ptr] ;
                    //    while  (   TI     ==  0 );
					//	TI   =      0 ;
						if ( ++uart_s_ptr == UART_BUF_NUM )
						       uart_s_ptr = 0 ;
					 }
				  uart_buf_num -= 8 ;
                  while ( ( Peli_SR & 0x30 ) != 0 ) ;  
			      Peli_CMR    |=  0x01 ;    //启动发送
                  LED0= !LED0;
  			   }
              else if ( ( uart_r_time >= 20 ) &&  ( uart_buf_num >0 )  )
               // 如果超过一定时间未继续接受到数据,则将已接受到的数据打包发到CAN总线上 
               {
			      unsigned char pdata * ptr ;
                //  unsigned char i ; 
                  while ( ( Peli_SR & 0x04 ) == 0 ) ; //等待发送缓冲区释放  
                  Peli_TXFMINFO  =  ( uart_buf_num  & 0x0f   );  //标准数据帧,数据字节数为uart_buf_num
                  Peli_TXBUF1    =  0x00 ;    //标识符  
			      Peli_TXBUF2    =  0x20 ; 
                  ptr            =  &Peli_TXBUF3  ;				  
                  for (  ; uart_buf_num > 0  ; uart_buf_num-- )
				     {
                        *ptr++   =  UART_BUF[uart_s_ptr] ;
						TX_Total_NUM ++ ; 
					//	SBUF   =  UART_BUF[uart_s_ptr] ;
                    //    while  (   TI     ==  0 );
					//       	TI   =      0 ;
						if ( ++uart_s_ptr == UART_BUF_NUM )
						       uart_s_ptr = 0 ;   
					 }
                  while ( ( Peli_SR & 0x30 ) != 0   ) ;  
			      Peli_CMR    |=  0x01 ;    //启动发送 
                  LED1= !LED1;
   			  }
		 }
}

void mcu_init(void)
{
    AUXR   =   0X03 ;      //禁止使用片内扩展的外部RAM,常态下禁止ALE输出,提高EMI
    WDT_CONTR  =  0X34 ;   //启用看门狗
//IO口初始化
//定时器初始化
	TMOD  = 0X10 ; //定时器0、1分别工作于方式0、1   
//串口初始化
    SCON  = 0X50 ; //串口工作于方式1,数据位8位,波特率可变,允许接受   
    TCLK  =  1   ; //定时器2用作波特率发生器
	RCLK  =  1   ; 
	//晶振 22.1184 , 6T ,波特率9600
    RCAP2H  =  0xff ;
    RCAP2L  =  0X70 ;
//外部中断初始化
    IT0 = 1; //INT0由下降沿触发,其中断标志IE0在响应中断之后由硬件自动清零

//中断初始化 
    ET0  =  1 ;  //允许T0中断
	EX0  =  1 ;  //允许外部中断INT0中断
	ES   =  1 ;  //允许串口中断
    EA   =  1 ;  
    TR0  =  1 ;  //启动定时器
	TR2  =  1 ;
}

/*
*/

void sja_init( void )
{
//  unsigned char i;
//  unsigned char pdata * ptr ;
  EA     =  0 ;  //先禁止SJA1000中断
  SJA_CS  =  0 ;  //选中SJA1000
  SJA_RST =  0 ;  //硬件复位SJA1000
  _nop_()  ;    
  _nop_()  ;    
  _nop_()  ;    
  _nop_()  ;
  SJA_RST =  1 ;
  _nop_()  ;    
  _nop_()  ; 
  _nop_()  ;    
  _nop_()  ;
  // 确保SJA进入复位模式
  while ( ( Peli_MOD & RM_RR_BIT ) == 0 )
       Peli_MOD  =  0X01 ;
  // 设置时钟分频寄存器 REG_CAN_CDR 
  Peli_CDR	=	CLKOff_BIT|CBP_BIT|CANMode_BIT  ;
  // 设置时序寄存器
  Peli_BTR0 =   0XCA ;  
  Peli_BTR1 =   0X39  ;  
  // 设置输出控制寄存器
  Peli_OCR  =   0X1A  ;  //   正常输出模式 、推挽是输出方式, 0:低  1:悬空
  // 设置中断寄存器
  Peli_IER  =   0X07  ;  //   允许发送、接受、错误中断
  // 设置验收屏蔽寄存器
  Peli_AMR0 =   0XFF  ;
  Peli_AMR1 =   0XFF  ;
  Peli_AMR2 =   0XFF  ;
  Peli_AMR3 =   0XFF  ;
  // 设置验收代码寄存器

  // 进入操作模式
  Peli_MOD &=  ~RM_RR_BIT ;
  while ( ( Peli_MOD & RM_RR_BIT ) != 0 )
          Peli_MOD &=  ~RM_RR_BIT ;
  EA     =  1 ;
//  LED0   =  0 ; 
}

void time0_isr ( void ) interrupt 1
{
      if ( uart_r_time <100 )
         uart_r_time++ ; 
}


void uart_isr ( void ) interrupt 4
{
//   LED0 = !LED0 ;
   if ( RI  ==  1 )
       {
/*	     if ( SBUF == 1)
		   {

		      Peli_TXFMINFO  =  0x01 ;  //标准数据帧,数据字节数为1
              Peli_TXBUF1  =  0x00 ;    //标识符  
			  Peli_TXBUF2  =  0x20 ;
              Peli_TXBUF3  =  0x88 ;    //数据
			  Peli_CMR    |=  0x01 ;    //启动发送
		   }
*/         
          RI = 0 ;
          if ( SBUF == 0XFF)
		      {
                 ES = 0 ;
				 TI = 0 ;
				 SBUF = Peli_SR  ;
				 while ( TI == 0 ) ;
				 TI = 0 ;
				 ES = 1 ;
                 return ;
			  }     
           if ( SBUF == 0XFE)
		      {
                 ES = 0 ;
				 TI = 0 ;
				 SBUF = TX_Total_NUM ;
				 while ( TI == 0 ) ;
				 TI = 0 ;
				 SBUF = RX_Total_NUM  ;
				 while ( TI == 0 ) ;
				 TI = 0 ;
				 SBUF = RX_Total_NUM_COM   ;
				 while ( TI == 0 ) ;
				 TI = 0 ;
				 SBUF = TX_Total_NUM_COM   ;
				 while ( TI == 0 ) ;
				 TI = 0 ;
				 ES = 1 ;                  
                 return ;
			  }     
           if ( SBUF == 0XFD)
		      {
                 TX_Total_NUM  =  0  ;
				 RX_Total_NUM  =  0  ;
		         RX_Total_NUM_COM =  0 ;
                 TX_Total_NUM_COM =  0 ;  
                 return ;
			  }  
		  uart_r_time  =  0 ;                    // 接收计时清零 
          if ( ++uart_buf_num > UART_BUF_NUM )   // 判断串口接受缓冲区是否溢出,溢出则不接收数据
		         return ;
          UART_BUF[ uart_r_ptr ] =  SBUF ;
		  RX_Total_NUM_COM++ ;
          if( ++uart_r_ptr ==  UART_BUF_NUM  )     // 接受指针是否需要归零
  		         uart_r_ptr = 0 ; 
		  LED3 = !LED3 ;
	   }
   if (  TI == 1 ) 
       {
	      TI = 0 ;
	      if ( can_buf_num > 0 )  //CAN缓冲区中是否有数据待发送到RS232上 
            {
              SBUF = CAN_BUF[can_s_ptr] ;     
              if ( ++can_s_ptr == CAN_BUF_NUM )
			       can_s_ptr  =  0 ;
			  can_buf_num-- ;
	  		  TX_Total_NUM_COM++ ;
			  send_going  =  1;
            }
		  else
		      send_going  =  0;
	   }
}

void sja_isr ( void ) interrupt 0
{
   Peli_IR_buf = Peli_IR  ;  
   if ( ( Peli_IR_buf & TI_BIT ) != 0 )  //判断是否发送中断
        {
//        LED1 = ! LED1;
          return ;
		}
   if ( ( Peli_IR_buf & RI_BIT ) != 0 )  //判断是否接受中断
        {
          /*
          if ( (Peli_RXFMINFO == 0X01 ) && ( Peli_RXBUF1 == 0x00 ) && ( Peli_RXBUF2  ==  0x20 ) &&  ( Peli_RXBUF3 ==  0x88 ) )
          */
          if ( ( Peli_RXFMINFO & 0xf0 ) == 0   ) //暂时只接受标准数据帧 
             {
                unsigned char len ;
				unsigned char pdata * ptr ;
				len = Peli_RXFMINFO ;
				ptr = &Peli_RXBUF3 ;
                LED2 = !LED2 ; 
                while ( ( len > 0 ) && ( can_buf_num  <  CAN_BUF_NUM )  )
				  {
				    if ( send_going == 0 ) //如果前面没有正在往串口发送数据,则置位TI使得CAN数据能够转发到RS232上
 				         TI  =  1 ;//如果当前已经正在发送数据,置位TI反而可能引起错误
				    CAN_BUF[can_r_ptr] = *ptr++ ;
					RX_Total_NUM ++ ; 
	                if ( ++can_r_ptr == CAN_BUF_NUM )
					     can_r_ptr = 0 ;
                    can_buf_num ++ ;
					len--  ;
				  }
    		 }
     	  Peli_CMR    |=   0X04 ;       //释放缓冲区
    	}    
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -