📄 can.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 + -