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

📄 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,open_flag,ad_flag,adc_ready,usart1_flag=0,rx_counter,adc0_counter;
volatile uchar adc0_buffer[]={};
volatile uchar can_rx_data[]={};
volatile uchar can_tx_data[]={};
volatile uchar rx_buffer[]={};
uchar address;
uint rx_ID[4]={192,168,0,1};
uint tx_ID[4]={0,0,0,0};

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 = (1<<TXOK);                                      
  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));                                            //开全局中断 和 接收中断 
  CANIE2 |= (1<<IEMOB0);                                                              // 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[1])
			{
				case 0xb0: close_flag=1;               //通道关闭
				break;
				
				case 0xb8: 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)) 
  { 

    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);                   //开中断 
	
}


void can_send_data(void)                           //发送前数据整理
{
	can_tx_data[0]=0xDD; 
	can_tx_data[1]=0x00;                                   //地址
	can_tx_data[2]=0x02;
	can_tx_data[3]=0x01;                                 //ad高位
	can_tx_data[4]=0x03;                                 //ad低位 
	can_tx_data[5]=0x00;
	can_tx_data[6]=0x00;
	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); 
  can_send_data();                                   //发送前整理
  for(i = 0; i < 8; i++) 
	{
		CANMSG = can_tx_data[i]; 
	}
  CANCDMOB = 0x58;                               //帧发送  DLC=8
  CANGIE |=(1<<ENRX);                            //开接收中断
  } 
}




//---------------------串口测试相关函数------------------------------
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 + -