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

📄 can-rs232.c

📁 AVR Studio下开发的CAN-232串口通信代码
💻 C
字号:
#include <avr/wdt.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#define uchar unsigned char
#define uint unsigned int
#include <avr/delay.h>
uchar can_data[2][8];
uchar cReceiveBuf[8];

//减1数据接收计数器的初始值
#define          RECEIVE_COUNTER_INIV       0x08
//接收状态标志,gReceiveFlag=0x01表示一帧数据接收完成
uchar  gReceiveFlag;
//接收缓冲区的指针
uchar      *gReceivePointer;
//串口接收缓冲区
uchar       gReceiveBuf[8];
//接收计数器,用于判断一帧数据是否接收完
uchar       gReceiveCounter;
//用于存放前一次中断发生时接收到的数据。如果前次接收到的数据为A5,则该变量的值
//为A5,否则为0
uchar       gPreByteReceive;

void usart_init(void)
{
  /* set baud rate 4800*/
   UBRR0H=0;
   UBRR0L=103;

   UCSR0B=(1<<RXEN0)|(1<<TXEN0)|(1<<RXCIE0);
   /* set frame format:8 data,2 stop bit*/
   UCSR0C=(1<<USBS0)|(3<<UCSZ0);
}

  void mcu_init(void) 
{ 
 // WDTCR = (1<<WDCE) | (1<<WDE);                        //2行看门狗初始化 
 //WDTCR = 0x0f;                                       //0x1c=0.25s    0x1d=0.5s 
 //// __watchdog_reset();                                 //喂狗 
  //wdt_reset();


//-------------------prot init---------
 //ORTA = 0xfe; 
  DDRA  = 0xFF;                                       //端口设置:PA设置为输出 

//---------------- MCU interrupt ------- 
  SREG = 0x00;                                      //关全局中断; 0x80开全局中断 

  CANGCON |= (1<<SWRES);                           //CAN控制器软复位 
  CANBT1 = 0x06;       ///设置系统时钟          //设置波特率分频因子16MHz,16TQ,250k,=4=3+1,3 
  CANBT2 = 0x0c;    //补偿不同CAN控制器之间的相位差和物理延时 //同步段为1“0x0n”传播段=7=6+1 
  CANBT3 = 0x37;                                //相位缓冲PH2=4=3+1,PH1=4=3+1 
  CANTCON = 0xff; //预比例因子

//--------------can_MOB INITIAL---------------
 
//MOB0=RX[CMD]    接收上位机发来的指令       格式:3,0,0,177,239,33 
  CANPAGE  = 0x00;   //选择邮箱和增长方式     //选择邮箱0,自动增量,初值为0 
  CANSTMOB = 0;     //CAN Mob状态寄存器,控制.DLC寄存器需要初始化
  CANCDMOB = 0x08;         //can2A,DLC=8 

  CANIDT4 = 0x00;         
  CANIDT3 = 0x00;          
  CANIDT2 = 0x80;          // 100 000000
  CANIDT1 = 0x00;          // 000 000000 该节点ID为4   
 
  CANIDM4  = 0x00;       
  CANIDM3  = 0x00;        
  CANIDM2  = 0x00;       
  CANIDM1  = 0x00;



//MOB1=TX[STA1]  向上位机报告状态组1          6,0,0,178,239,33 
  CANPAGE = 0x10; //选择邮箱1,自动增长,初值为0
  CANSTMOB = (1<<TXOK); 

  CANCDMOB = 0x08; 
  CANIDT4 = 0x00;       // 
  CANIDT3 = 0x00;       //
  CANIDT2 = 0x20;       // 001 000000             1
  CANIDT1 = 0x01;       // 000 0000 1   该节点ID为9   
 

  CANGIE |= ((1<<ENIT) + (1<<ENRX));  //开全局中断和接收中断 

  CANIE2 |= 0x01;            //开MOB0信箱接收中断(接收邮箱) 
 
  CANPAGE  = 0x00; 
  CANCDMOB |= 0x80;     //MOB0接收使能 
  
  CANGCON |= 0x02;      //CAN控制器启动,连续的11个电平之后进入读取数据状态 

  SREG = 0x80;            //开全局中断 
} 

void USART0_Transmit (unsigned char data)

{
  /*wait for empty transmit buffer*/
   while ( ! (UCSR0A&(1<<UDRE0)));
  /*Put data into buffer ,sends the data*/
   UDR0= data;
}

void MOB_send (uchar n)
//void MOB_send(void)
{ 
  CANGIE &= ~(1<<ENRX); 
  uint i,j; 

  CANPAGE = (n<<4);                     //MOB_n, auto increment, index 0 
  if (CANSTMOB & (1<<TXOK)) 
  { 
  CANCDMOB= 0x08; //设置协议类型和数据长度
  CANSTMOB &= ~(1<<TXOK);   //禁止TXOK,开始发送数据

  for(i =0; i < 8; i++)     //发送8个数据字节
  {
   CANMSG = gReceiveBuf[i]; 
   PORTA = gReceiveBuf[i];    //  每发送完一个字节即通过A口显示
   for( j =0; j < 40; j++)   { _delay_ms(500);} 
  }	
   CANCDMOB = 0x48;   //帧发送
                               
   CANGIE |=(1<<ENRX); 
  } 
} 


ISR(USART0_RX_vect)
{  uint i,j;
   //UCSR0B=(0<<RXEN0)|(1<<TXEN0);//关串口接收中断
    unsigned char ByteReceive;
       ByteReceive = UDR0;
       //以下判断接收到的一个字节的数据是否为0xa5
       if (ByteReceive == 0xa5)      
       
	   {
              // gPreByteReceive = 0xa5;                    
                gReceivePointer = gReceiveBuf;            
            
       }
       else 
	   {	   if (ByteReceive==0x5a)
             {      
            
	  		//uint i,j;
      			 PORTA =0xaa;   for( j =0; j < 20; j++)   { _delay_ms(500);}   //准备发送信号 1010 1010
				 PORTA =0x55;   for( j =0; j < 20; j++)   { _delay_ms(500);}   //准备发送信号 0101 0101
	  
	 			  for( i =0; i < 8; i++) 
     			   {
					 PORTA = gReceiveBuf[i]; //先显示要发送的8个数据字节      
         				 for( j =0; j < 20; j++)   { _delay_ms(500);}  
                     //gReceiveBuf[i]=0;
     			    }
   				  
            }
			  
			 else 
			 {
		        // gReceivePointer = gReceiveBuf;  
			 		*gReceivePointer = ByteReceive;
			        gReceivePointer++;
				// *gReceivePointer ++ = ByteReceive;  //????????
			  }
			  
		}	  
  
  
}


ISR(CANIT_vect)
{ 
  uchar i = 1, num_i,j; 
  
  CANGIE &= ~(1<<ENRX);                         //关接收中断**** 
 
  CANSIT2=0x01;
  num_i = CANSIT2;                              ///中断的邮箱号 
    i=0;                                        ///零号邮箱中断
    TCNT1 = 0x0000;                              //重启定时监视器,计数器清零
    CANPAGE = i<<4; 
                          	                     //////对应0#接受邮箱////////
    for(num_i = 0; num_i < 8; num_i++) 
    { 
      cReceiveBuf[num_i]=CANMSG;           //取得8个字节的数据 

    } 

    CANPAGE = 0x00; 
    CANSTMOB &= ~(1<<RXOK);                //清中断标志**** 
    CANCDMOB = 0x88;                      //接收使能   
 
      //准备发送
       PORTA =0xaa;   for( j =0; j < 20; j++)   { _delay_ms(500);}   //准备发送信号 1010 1010
	   PORTA =0x55;  for( j =0; j < 20; j++)   { _delay_ms(500);}   //准备发送信号 0101 0101
	     for( num_i = 0; num_i < 8; num_i++) 
        {
		 PORTA = cReceiveBuf[num_i]; //先显示要发送的8个数据字节      
        _delay_ms(500);
        }
      
      //取得字节后由串口发送
      for(num_i=0;num_i<2;num_i++)        //先发送起始2个字节“A5”  
	  { 
	     USART0_Transmit(0xa5);
         PORTA = 0xa5; for( j =0; j < 20; j++)   { _delay_ms(500);}   
	  }

	
	  for(num_i=0;num_i<8;num_i++)         //再发送8个数据字节
      {
	     USART0_Transmit(cReceiveBuf[num_i]);
         PORTA =  cReceiveBuf[num_i];     for( j =0; j < 20; j++)   { _delay_ms(500);}   
      }

    CANGIE |= (1<<ENRX);                   //开中断 ,允许接收
} 


void main()
{ 
    
	mcu_init();
    usart_init( );

       gPreByteReceive=0x00;
	   gReceiveFlag=0x00;
       

	   uint i=0,j;
      
	   PORTA =0xaa;   for( j =0; j < 20; j++)   { _delay_ms(500);}   //准备发送信号 1010 1010
	   PORTA =0x55;   for( j =0; j < 20; j++)   { _delay_ms(500);}   //准备发送信号 0101 010
   
         for(i=0;i<8;i++)  
		 { cReceiveBuf[i]=i+1;}
     
	  for(i=0;i<8;i++)         //再发送8个数据字节
      {
	     USART0_Transmit(cReceiveBuf[i]);
         PORTA =  cReceiveBuf[i];     for( j =0; j < 20; j++)   { _delay_ms(500);}   
      }


}

⌨️ 快捷键说明

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