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

📄 can.c

📁 AT90CAN128的CAN通信源码测试成功
💻 C
字号:
#include <avr/io.h>	
#include <avr/iocan32.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define uchar unsigned char
#define uint  unsigned int


volatile uchar close_flag=0,open_flag=0,ad_flag=0,adc_ready=0,usart1_flag=0,rx_counter=0,adc0_counter=0;
volatile uchar adc0_buffer[]={};
volatile uchar adc0_ch[]={};
volatile uchar can_rx_data[]={};
volatile uchar can_tx_data[]={};
volatile uchar rx_buffer[]={};
uchar address;
uint rx_ID[4]={192,168,1,1};
uint tx_ID[4]={192,168,0,1};

void USART_Transmit(uchar);


void read_address(void)                              //读取本机地址
{
    uchar read_add;
	DDRC = 0X00;           //C口输入上拉
	PORTC = 0XFF;
	read_add = PINC;
	address=read_add;
}


void can_baudrate(void)               //设置波特率250K 
{
		
	uchar	i;
	int	n;
	uchar	PH[8] = {20,16,15,12,10,8,25,18};
	uchar	CTSYNC,CBRP,CSJW,CPRS,CPHS2,CPHS1,CSMP;
	
	//20,16,15,12,10,8,18

	n = 48 ;                       // 12M/250K; 

	for(i=0;i<8;i++)
	{
		if( n%PH[i] == 0 )
		{
			 break;
		}
	}

	CPHS2 = PH[i]/3;
	CPHS1 = PH[i]/3;

	CTSYNC 	= 1;
	CSJW	= 0;
	CSMP 	= 1;
	CBRP 	= n/PH[i];                  
	CPRS 	= PH[i]- CPHS2 - CPHS1 - CTSYNC;
	
	
	CANBT1 	=	(CBRP-1)<<1;
	CANBT2 	= 	((CSJW)<<5) | ((CPRS-1)<<1);
	CANBT3 	=	((CPHS2-1)<<4) | ((CPHS1-1)<<1) | CSMP;

}

void init_CAN(void)
{

  CANGCON |= (1<<SWRES);                                                        //CAN控制器软复位 
  can_baudrate();
  CANTCON = 0x00; 

//--------------can_MOB INITIAL------------------- 
//MOB0=RX[CMD]   接收设置      主机格式:192.168.0.0   从机192.168.0.1          
  CANPAGE  = 0x00;                                                              //MOB0 接收,自动增量,初值为0 
  CANSTMOB = 0; 
  CANCDMOB = 0x18;                                                              //can2B,DLC=8 
  CANIDT4 = rx_ID[3]<<3;                                                        // 接收ID设置  
  CANIDT3 = rx_ID[2];                                                              
  CANIDT2 = rx_ID[1];                                                              
  CANIDT1 = rx_ID[0];                                                              

  CANIDM4  = 0xff;                                                              //校验寄存器设置                           
  CANIDM3  = 0xff;                                                                                          
  CANIDM2  = 0xff;                                                                                          
  CANIDM1  = 0xff;                                                              

//MOB4=TX[CMD]     发送设置     主机格式:192.168.0.1    从机192.168.0.0    
  CANPAGE = 0x40;                                                                 //MOB4 发送,自动增量,初值为0  
  CANSTMOB = 0;                                      
  CANCDMOB = 0x18;                                                               //can2B,DLC=8 
  CANIDT4 = tx_ID[3]<<3;                                                        //发送ID设置     
  CANIDT3 = tx_ID[2];                                                                 
  CANIDT2 = tx_ID[1];                                                                 
  CANIDT1 = tx_ID[0];                                                                


 
  CANGIE |= ((1<<ENIT) + (1<<ENRX)+(1<<ENTX));                                            //开全局中断 和 接收中断 
  CANIE2 |= (1<<IEMOB0)|(1<<IEMOB4);                                                              // MOB0信箱接收中断(接收邮箱) 
  CANPAGE  = 0x00; 
  CANCDMOB |=(1<<CONMOB1);                                                             // CONMOB1,CONMOB0=10是接收使能 
 
  CANGCON |=  (1<<ENASTB);                                                              //CAN控制器启动 

}


// FET控制 CC     00     01    00 00 00 00    FF
//     开头   地址   指令      数据       结尾  

// 开路电压DD     00     01    00 00 00 00    FF
//     开头   地址   指令      数据       结尾  

void can_rx_deal(void)                                     //接收数据处理   
{
	
	if(can_rx_data[0]==0Xcc)   //FET控制
	{
		//if(can_rx_data[1]==0xb0)   
		{
			switch(can_rx_data[2])
			{
				case 0x01: close_flag=1;               //通道关闭
				break;
				
				case 0x02: open_flag=1;                 //通道开启
				break;
				
				case 0xa0: ad_flag=1;                  //AD采集启动
				break;
				
				default:
				break;
			}
		}
		 
	}
	else if(can_rx_data[0]==0XDD)  //太阳能方阵开路电压采集
	     {
			if(can_rx_data[1]==address)
			{
				switch(can_rx_data[2])
				{
					case 0x02:               //电压采集需向上传送
					break;
					
					default:
					break;
				}
			}
		 }
	
}


ISR(CANIT_vect)                     //CAN接收中断处理函数
{
	
	
  uchar i , num_i; 
  CANGIE &= ~(1<<ENRX);                  //关接收中断**** 
  num_i = CANSIT2; 
  

//----------------------------------------------------- 
    if (num_i & (1<<SIT0)) 
	  { 
		  if (CANSTMOB & (1<<RXOK)) 
		  { 

			i=0; 
			CANPAGE = i<<4; 
			for(num_i = 0; num_i < 8; num_i++) 
			{ 
			  can_rx_data[num_i]=CANMSG;           //取得8个字节的数据 
			} 
				   
			can_rx_deal() ;                           //处理接收指令
				
			CANPAGE = 0x00; 
			CANSTMOB &= ~(1<<RXOK);                //清中断标志**** 
			CANCDMOB = 0x98;                      //接收使能  2.0B DLC=8
			//CANGIE |= (1<<ENRX);                   //开中断 
		   }
		   else
		   {
		   }
		   CANSTMOB &= ~(1<<RXOK);                //清中断标志**** 
		}
       
   else if (num_i & (1<<SIT4))
		  {
			  if (CANSTMOB & (1<<TXOK)) 
			   {
					
					i=4; 
					CANPAGE = i<<4; 
					for(num_i = 0; num_i < 8; num_i++) 
					{ 
					  CANMSG=can_tx_data[num_i];           //发送8个字节的数据 
					} 
					CANPAGE = 0x40; 
					CANSTMOB &= ~(1<<TXOK);                //清中断标志**** 
					CANCDMOB = 0x58;                      //接收使能  2.0B DLC=8
					//CANGIE |= (1<<ENRX);                   //开中断 
			   }
			   else
			   {
			   }
			  CANSTMOB &= ~(1<<TXOK);                //清中断标志****  
	       }
	CANGIE |= (1<<ENRX);                   //开中断 	   
}


void can_send_data(void)                           //发送前数据整理
{
	can_tx_data[0]=0xcc; 
	can_tx_data[1]=0x00;                                   //地址
	can_tx_data[2]=0x01;
	can_tx_data[3]=0x01;                                 //ad高位
	can_tx_data[4]=0x00;                                 //ad低位 
	can_tx_data[5]=0x02;
	can_tx_data[6]=0x01;
	can_tx_data[7]=0xff;
}


/*void MOB_send (void)                       //CAN发送函数
{ 
  CANGIE &= ~(1<<ENRX);                   //关接收中断
  uint i,n=4; 

  CANPAGE = (n<<4);                      //MOB_n, auto increment, index 0 
  if (CANSTMOB & (1<<TXOK)) 
  { 
 // CANCDMOB= 0x18; 
  CANSTMOB &= ~(1<<TXOK); 
                                    //发送前整理
  for(i = 0; i < 8; i++) 
	{
		CANMSG = can_tx_data[i]; 
	}
  CANCDMOB = 0x58;                               //帧发送  DLC=8
  CANGIE |=(1<<ENRX);                            //开接收中断
  } 
}*/
void can_tx_init(void)
{
	CANPAGE = 0x40;
	if( (CANCDMOB & 0xc0) == 0x00 )
	{
		CANSTMOB |= (1<<TXOK);
	}
	
}



//---------------------串口测试相关函数------------------------------
void USART_Transmit(uchar data)
{
	while(!(UCSR1A&_BV(UDRE1)));
	
	UDR1=data;
	
	
}
ISR(USART1_RX_vect)
{
	uchar status,data;
	status=UCSR1A;
	data=UDR1;
	
	if((status&(_BV(FE1)|_BV(UPE1)|_BV(DOR1)))==0)
	
		{
	
	        rx_buffer[rx_counter]=data;
			
			rx_counter++;
			
			switch(rx_counter)
			{
				case 1:
						if(data!=0XBB)
						rx_counter=0;
					break;
				
				case 5:
						if(data==0XFF)
						{
							rx_counter=0;
							usart1_flag=1;
						}	
					break;
			}
		}
}
void USART_init(void)
{	
	                                        
	
	UCSR1A= 0X00 ;                                        
	UCSR1B= _BV(RXCIE1)|_BV(RXEN1)|_BV(TXEN1)|_BV(TXCIE1);          //发送允许,接收允许 发送中断使能,接收中断使能
	UCSR1C= _BV(UCSZ11)|_BV(UCSZ10);                                //异步通信模式;通信参数 8位数据位1位停止位,无校验
	UBRR1H= 0x00;
	UBRR1L= 0x4D;
}



/**********************AD采集相关函数*****************************/
void adc_init(void)                 //初始化函数
{	
	DDRF=0X00;
	PORTF=0X00;                    //输入禁止上拉
	ADCSRA=0x00;                 //暂时关闭AD

⌨️ 快捷键说明

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