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

📄 新建 文本文档.txt

📁 AVR Studio下开发的CAN-232串口通信代码
💻 TXT
字号:
#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 (gPreByteReceive == 0xa5)
              {      
            // gReceivePointer = gReceiveBuf;                    
			   // *gReceivePointer = ByteReceive;
			//gReceivePointer++;
                i=0; 
			    gReceiveBuf[i]=ByteReceive;
				i++;
                gReceiveCounter = 0x08;
                gPreByteReceive = 0x00;     
                gReceiveCounter--;        
              }
              else
              { 
			   //以下是本次接收到的数据不为A5、前次接收到的数据也不为A5的情况
                  if (gReceiveCounter == 0)
                      { 
                        gPreByteReceive = 0;
                        gReceiveFlag = 0x01;
                                           
                       }
                   else
                      {
					   //*gReceivePointer = ByteReceive;
			        	//gReceivePointer++;
                      // *gReceivePointer ++ = ByteReceive;????????
                        gReceiveBuf[i]=ByteReceive;
				        i++;
					   gReceiveCounter --;      
                      }     
              }
       }         
  
}


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
while(1)
{	
	if (gReceiveFlag == 0x01)   //如果接收完成,则准备由CAN口发送
        { 
	  			//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;
     			  }
   											 //  for(i=0;i<8;i++)         //再发送8个数据字节
     										 //{
	 										   // USART0_Transmit(gReceiveBuf[i]);
    										     //PORTA =  gReceiveBuf[i];     for( j =0; j < 20; j++)   { _delay_ms(500);}   
  	 												   //}
												 ////  uint  n=1;
   											  //  MOB_send (n);            //通过邮箱1发送到CAN
                     gReceiveFlag == 0x00;
   		}  
	
	}
  }

⌨️ 快捷键说明

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