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

📄 can.c

📁 Atmel 89C51cc01 CAN BUS driver
💻 C
字号:
/*================================================================================
                                                                               
Module Name:  can.c

          General Description:

==================================================================================
                     Honeywell Confidential Proprietary
               ACS - Security (Asia Pacific) R&D Software Operations
               (c) Copyright Honeywell 2005, All Rights Reserved
 
Revision History:
                            Modification     Tracking
Author                 Date        Ver Number     Description of Changes
----------------   ------------    ----------   -------------------------
Lake Hu            02/22/2006      ver0.0.1     Initial draft

Portability: This in not portable for non-Atmel 89C51CC0X MCU, because it utilize
              this MCU's config head file.

==================================================================================
                                 INCLUDE FILES
================================================================================*/

#include "Venus.h"
#include "..\canprotocol\canprotocol.h"
#include "can.h"
#include "flash_api.h"

#define DELAY_TIME_CAN_ID  (1200) 
/*================================================================================
                                GLOBAL VARIABLES
================================================================================*/


unsigned char data num_channel;
unsigned char data num_data;


can_msg_t idata can_tx_buf; /* CAN message Tx buffer */
can_msg_t xdata can_rx_buf;  /* received CAN message */
unsigned char idata  can_tx_fail_counter; /* CAN tx fail counter */
bit can_tx_busy;		      /* one CAN message Tx is ongoing */
bit can_tx_ok; 

unsigned short data can_rx_buf_pending;

/* 
 *bit decalaration used by FindFirstChIt
 *-------------------------------------------------------
 */
bdata unsigned char bit_var;
Sbit( bit_7, bit_var, 7);
Sbit( bit_6, bit_var, 6);
Sbit( bit_5, bit_var, 5);
Sbit( bit_4, bit_var, 4);
Sbit( bit_3, bit_var, 3);
Sbit( bit_2, bit_var, 2);
Sbit( bit_1, bit_var, 1);
Sbit( bit_0, bit_var, 0);


void check_start_firmware_update()
{
	if ((UPGRADE_HIGH == 0x55)&&(UPGRADE_LOW == 0x55))
	{
		//   UPGRADE_HIGH = 0xaa;
		//   UPGRADE_LOW = 0xaa;
	  	  __api_start_bootloader();
		return;
	 }
}


void prepare_firmware_update()
{
	if(Dailling_module_expand)
		 send_mcu_reboot_message();

	draw_upgrade_msg_dlg();		//display upgrading gui on LCD

	UPGRADE_HIGH = 0x55;					//set upgrade flag
	UPGRADE_LOW = 0x55;
	ResetWatchdog();
	(*(void(*)( ))0)( );	
}

/**
* FUNCTION_PURPOSE: This will fill CAN reveived buffer with one CAN message
* 
* FUNCTION_INPUTS:  received buffer address, if zero, the global variable is used.
* FUNCTION_OUTPUTS: void
*/
void CanDrivertoProtocolRx(STR_CAN_GENERAL_MSG_S xdata *  pOutstrRxdata)
{
	unsigned char i;
	can_rx_buf.ucDLC = CANCONCH; /* get flag and  DLC */	
	
	/* receive one CAN message */
	for (i=0; i<can_rx_buf.ucDLC&MSK_CANCONCH_DLC; i++) can_rx_buf.aucData[i] = CANMSG; /* save receive data */

	can_rx_buf.strCanID.can_id[0] =(CANIDT4>>3)|(CANIDT3<<5); /* CAN ID bit 00~07*/				
	can_rx_buf.strCanID.can_id[1] =(CANIDT3>>3)|(CANIDT2<<5); /* CAN ID bit 08~15*/				
	can_rx_buf.strCanID.can_id[3] =(CANIDT2>>3)|(CANIDT1<<5); /* CAN ID bit 16~23*/				
	can_rx_buf.strCanID.can_id[2] =CANIDT1>>3;			      /* CAN ID bit 24~28*/

	if(((unsigned char xdata *)0)==pOutstrRxdata)
		return ;
	*pOutstrRxdata = can_rx_buf;
}

/**
* FUNCTION_PURPOSE: This will transfer one CAN message to CAN buffer
* 
* FUNCTION_INPUTS:  transfer buffer address
* FUNCTION_OUTPUTS: void
*/
void CanProtocoltoDriverTx(STR_CAN_GENERAL_MSG_S xdata *  pInstrTxData)
{
	
	 *pInstrTxData = can_tx_buf;	
}


/**
* FUNCTION_PURPOSE: This will reset on receiving channel
* 
* FUNCTION_INPUTS:  channel index
* FUNCTION_OUTPUTS: void
*/
void reset_rx_channel(unsigned char num_channel)
{
	unsigned short bit_channel;
	bit_channel = (1<<num_channel);
	CANPAGE = (num_channel << 4); /* point to the current channel */	
	/*CAN id and data are saved, so enable this channel again */
	
	CANSTCH = 0x00; /* reset channel staus */
	CANCONCH = CH_DISABLE; /* reset control and dlc register */
	CANCONCH |= MSK_CANCONCH_IDE; /* receive 2.0B only */
	/*filter */					
	CANIDT1 = 0xff;
	CANIDT2 = 0xff;
	CANIDT3 = 0xff;
	CANIDT4 = 0xff;
	
	/* Channel mask = 29bits */
	CANIDM1 = 0x00;
	CANIDM2 = 0x00;
	CANIDM3 = 0x00;
	CANIDM4 = 0x01;  /* force comparision*/
	CANIDT4 &=~0x04; /* clear bit rtr in CANIDT4. */
	
	CANCONCH |= DLC_MAX; /* expect to receive 8 bytes */					 
	CANCONCH |= CH_RxBENA; /* Reception enabled with buffer.*/		
	
	/* enable channel again */
	if(num_channel < CHANNEL_8)  CANEN2 |= bit_channel;
	else	CANEN1 |= (bit_channel >> 8) ;

	can_rx_buf_pending &= (~bit_channel);	 /* clear pending flag */ 
}


/**
* FUNCTION_PURPOSE: This file set up Can at 500Kbauds with channel 0 id 0x123
* in reception
* and channel 1 id 0x001 in emission.
* FUNCTION_INPUTS: void
* FUNCTION_OUTPUTS: void
*/
void can_rx(void)
{
	unsigned short bit_channel;
	int resp;

	
	//while(1)
	{
		if(can_rx_buf_pending)
		{
			  /** proces the incoming message **/
		  	for (num_channel = RX_CHANNEL_FIRST; num_channel < RX_CHANNEL_LAST; num_channel++)
			{
				bit_channel = (1<<num_channel);
			    	if(!(can_rx_buf_pending & bit_channel))
			    	{
			    		//num_channel--;
					continue;
			    	}
			
				
				CANPAGE = (num_channel << 4); /* point to the current channel */
				resp =can_protocol_proc(); 
		//		if(resp == -2)
		//			return;
				reset_rx_channel(num_channel);			
				break;	   
             		}/*end for (num_channel =*/
 		}/* if(can_rx_buf_pending) */

		 
	 } /* end while(1) */
}

void init_can()		 
{
	can_tx_busy = 0;
	can_tx_ok = 0;
    can_tx_fail_counter = 0;


	CANGCON |= MSK_CANGCON_GRES;/* reset CAN */
	/* reset all mailboxes */
	for (num_channel = 0; num_channel < MAX_CHANNEL_NUM+1 ; num_channel++)
	{
		CANPAGE = num_channel << 4;
		CANCONCH = CH_DISABLE;
		CANSTCH = 0;
		CANIDT1 = 0;
		CANIDT2 = 0;
		CANIDT3 = 0;
		CANIDT4 = 0;
		CANIDM1 = 0;
		CANIDM2 = 0;
		CANIDM3 = 0;
		CANIDM4 = 0;
		for (num_data = 0; num_data < 8; num_data++) CANMSG = 0;
	}
	/* setup bit timing */
	CANBT1 = BRP_20k << 1; /* BRP=0x00; */
	CANBT2 &= ~0x60; /* reset SJW */
	CANBT2 |= SJW_20k << 5; /* SJW=0x00; */
	CANBT2 &= ~0x0E; /* reset PRS */
	CANBT2 |= PRS_20k << 1; /* PRS=0x02; */
	CANBT3 &= ~0x70; /* reset PHS2 */
	CANBT3 |= PHS2_20k << 4; /* PHS2=0x03;*/
	CANBT3 &= ~0x0E; /* reset PHS1 */
	CANBT3 |= PHS1_20k << 1; /* PHS1=0x03 */
	CANGCON |= MSK_CANGCON_ENA; /* start CAN */
	
	for (num_channel = RX_CHANNEL_FIRST; num_channel < RX_CHANNEL_LAST; num_channel++)
	{
		/* Channel 0 init */
		CANPAGE = (num_channel << 4); /* CHNB=0x00; select channel 0 */
		CANSTCH = 0x00; /* reset channel staus */
		CANCONCH = CH_DISABLE; /* reset control and dlc register */
		CANCONCH |= MSK_CANCONCH_IDE; /* receive 2.0B only */
		/* Channel 0: identifier = 29bits.  */
		CANIDT1 = 0xff;
		CANIDT2 = 0xff;
		//CANIDT2 |= 0x00;
		/* Channel 0: mask = 11bits. 0x7F0 */
		CANIDM1 = 0x00;
		CANIDM2 = 0x00;
		CANIDM4 = 0x01;  /* force comparision*/
		/* Channel 0 configuration */
		CANIDT4 &=~0x04; /* clear bit rtr in CANIDT4. */
		CANCONCH |= DLC_MAX; /* Reception 8 bytes.*/
		//CANCONCH |= CH_RxENA; /* Reception enabled without buffer.*/
		CANCONCH |= CH_RxBENA; /* Reception enabled with buffer.*/
	}

	//CANEN2 |= 0x01 ; /* channel 0 enable */

		
	/* Channel Tx init */
	CANPAGE = (TX_CHANNEL_NUM << 4); /* CHNB=0x00; select channel 0 as Tx Channel */
	CANSTCH = 0x00; /* reset channel staus */
	CANCONCH = CH_DISABLE; /* reset control and dlc register */
    CANCONCH|= MSK_CANCONCH_IDE; /* set ide bit in CANCONCH. */
	/* Channel Tx: identifier = 29bits. CANIDT=0x10000000 */
	CANIDT1 = 0x00;
	CANIDT2 = 0x00;
	CANIDT3 = 0x00;
	CANIDT4 = 0x00;

    /* Enable all channels 0~14 */
	CANEN2 |= 0xFF ;
	CANEN1 |= 0x3F ;

	/* interrupt configuration */
	CANIE2|=0xFF; /* enable message object 0~7 interrupts  */
	CANIE1|=0x7F; /* enable message object 8~13 and 14 interrupts  */
	///CANIE2|=0x03; /* enable channel 0 (TX) interrupt and channel 1 (Rx) interrupt*/ 
	CANGIE |= MSK_CANGIE_ENTX; /* Can_Tx IT enable */
	CANGIE |= MSK_CANGIE_ENRX; /* can_rx_buf IT enable */
	CANGIE |= MSK_CANGIE_ENERCH; /* Enable Message object error enable */

//	CANSIT2|=0x01;
	
	can_rx_buf_pending = 0;
	AUXR |= RAM_EX; // external ram
	local_can_add = 0;
	while(1)
	{
	
	//local_can_add = (*(unsigned char xdata *)ZNE_ADDR);	
	local_can_add = *(unsigned char xdata *)MODE_REG;

	if((local_can_add&0x7f)!=0) 
		break; 	
	for(num_channel=DELAY_TIME_CAN_ID;num_channel;num_channel--);	 
	local_can_add = 0;
	} 

	AUXR &= ~RAM_EX; // external ram
	ECAN = 1; /* CAN IT enable */

}

/**
* FUNCTION_PURPOSE: can interrupt.
* FUNCTION_INPUTS: P4.1(RxDC) can input
* FUNCTION_OUTPUTS: P4.0(TxDC) can output
*/
void can_it(void) interrupt 7
{
	char save_canpage;
 	unsigned char channel;

	if(bit_radio_receiving) 
	    goto end_can_it;
	save_canpage = CANPAGE; /* save current context */

	channel = FindFirstChIt();
	if(channel == TX_CHANNEL_NUM)   /* Tx interrupt */
	{
 
		CANPAGE = (TX_CHANNEL_NUM << 4); /* CHNB=0x0F; select channel 14 */
		if(CANSTCH != 0)
		{
			if((CANSTCH&MSK_CANSTCH_TxOk)==MSK_CANSTCH_TxOk)
			{
			    can_tx_ok = 1;
				can_tx_busy = 0;
			}
			else  /* Tx error */
			{
			 	can_tx_ok = 0;
				can_tx_busy = 0;
                		can_tx_fail_counter ++;
				if(can_tx_fail_counter==0)
				   can_tx_fail_counter = 0xff;
			}
			CANCONCH = CH_DISABLE; /* emission disabled */
			CANEN2 &= ~0x01; /* channel Tx disable */
			CANSTCH=0x00; /* reset channel Tx status */
			CANGIE &= ~MSK_CANGIE_ENTX; /* Can_Tx IT disabled */
			CANGIE &= ~MSK_CANGIE_ENERCH; /* Disable Message object error  */


		}	     
	}
	else  /* Rx interrupt */
	{
		CANPAGE = (channel << 4); /* CHNB=0x00; select channel 0 */
		if(CANSTCH != 0)
		{
		/* receive one CAN message */
			if((CANSTCH&(~MSK_CANSTCH_DLCW))==MSK_CANSTCH_RxOk)
			{
//				if(CAN_FAIL_FLAG)
//					CAN_get_single = 1;
				can_tx_fail_counter = 0;
				CANCONCH &= (CH_DISABLE|MSK_CANCONCH_DLC); /* reset control and hold the data */

				CANSTCH=0x00; /* reset channel Rx status */
				can_rx_buf_pending |= (1<<channel);
				
			}
			else /* Rx error */
			{
				  CANCONCH &= ~MSK_CANCONCH_DLC;/* reset channel configuration */
				  CANCONCH |= DLC_MAX; /* expect to receive 8 bytes */
				  CANSTCH=0x00; /* reset channel Rx status */	
			}

		}
	}
	CANPAGE= save_canpage; /* restore saved context */
	end_can_it:
	CANGIT = 0x00; /* reset all flags */
}





/*F***************************************************************************
* FUNCTION_NAME:  FindFirstChIt                                              
*----------------------------------------------------------------------------
* FUNCTION_PURPOSE: This function return the first channel with an interrupt
*                   request. The big priority start with the lowest channel 
*                   value (CHANNEL_0). 
* FUNCTION_INPUTS : void                 
* FUNCTION_OUTPUTS: unsigned char num_channel: return the channel number of the first 
*                   it find in CANSIT registers.                                                         
*****************************************************************************
* NOTE: Tx interrupt (i.e CHANNEL_0) will have high priority sinec there are only one buffer to 
        hold Rx message for all Rx channels                                                                     
******************************************************************************/
unsigned char FindFirstChIt (void)
{
  unsigned char num_channel = NO_CHANNEL;

  if (CANSIT2)
  {
    bit_var = CANSIT2;
    if(bit_0)
    {
      num_channel = CHANNEL_0;
    }
    else if (bit_1)
    {
      num_channel = CHANNEL_1;
    }
    else if (bit_2)
    {
      num_channel = CHANNEL_2;
    }
    else if (bit_3)
    {
      num_channel = CHANNEL_3;
    }
    else if (bit_4)
    {
      num_channel = CHANNEL_4;
    }
    else if (bit_5)
    {
      num_channel = CHANNEL_5;
    }
    else if (bit_6)
    {
      num_channel = CHANNEL_6;
    }
    else 
    {
      num_channel = CHANNEL_7;
    }
    
  }
  else if (CANSIT1)
  {
    bit_var = CANSIT1;
    if(bit_0)
    {
      num_channel = CHANNEL_8;
    }
    else if (bit_1)
    {
      num_channel = CHANNEL_9;
    }
    else if (bit_2)
    {
      num_channel = CHANNEL_10;
    }
    else if (bit_3)
    {
      num_channel = CHANNEL_11;
    }
    else if (bit_4)
    {
      num_channel = CHANNEL_12;
    }
    else if (bit_5)
    {
      num_channel = CHANNEL_13;
    }
    else if (bit_6)
    {
      num_channel = CHANNEL_14;
    }
  }

  return(num_channel);
}

void send_can_msg()
{
	unsigned char i;

	can_tx_busy = 1;
	can_tx_ok = 0;
	CANPAGE = (TX_CHANNEL_NUM << 4); /* CHNB=0x0F; select channel Tx */
	CANCONCH = CH_DISABLE; /* reset channel Tx configuration */
     	CANGIE |= MSK_CANGIE_ENTX; /* Can_Tx IT enable */
	CANGIE |= MSK_CANGIE_ENERCH; /* Enable Message object error enable */

	/* For VRP, since it is big indian, the high byte must be exchanged with 
   the low byte
	*/    
    i = can_tx_buf.strCanID.can_id[2];
    can_tx_buf.strCanID.can_id[2]= can_tx_buf.strCanID.can_id[3];
    can_tx_buf.strCanID.can_id[3]= i;

	CANIDT4 = can_tx_buf.strCanID.can_id[0]<<3;										/* CAN ID bit 00~04*/
	CANIDT3 = (can_tx_buf.strCanID.can_id[1]<<3)|(can_tx_buf.strCanID.can_id[0]>>5);/* CAN ID bit 05~12*/		
	CANIDT2	= (can_tx_buf.strCanID.can_id[2]<<3)|(can_tx_buf.strCanID.can_id[1]>>5);/* CAN ID bit 13~20*/				
	CANIDT1	= (can_tx_buf.strCanID.can_id[3]<<3)|(can_tx_buf.strCanID.can_id[2]>>5);/* CAN ID bit 21~28*/	
	
	
	CANCONCH|= MSK_CANCONCH_IDE;  /* set ide bit in CANCONCH. */
 
	CANCONCH|= can_tx_buf.ucDLC&MSK_CANCONCH_DLC;	  /* set DLC in CANCONCH. */


	for (i=0; i<DLC_MAX; i++) 
	{
		
		CANMSG = can_tx_buf.aucData[i]; /* load saved data */

	}
	
	CANCONCH |= CH_TxENA; /* emission enabled */
	CANEN2 |= 0x01; /* channel Tx enable */
	CANSTCH=0x00; /* reset channel Tx status */

}

⌨️ 快捷键说明

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