📄 hard_can.c
字号:
/*========================================================*
* 程序修改记录(最新的放在最前面):
1. 2005.08.02.lejianxin modify
*/
#include "Macro.h"
#include "Variable.h"
#include "Function.h"
#include "CPU_S3C44B0x.h"
#include "CAN_SJA1000.h"
#include "Mon_Can.h"
#if( !CN_HAVE_CAN ) // 本装置上不存在CAN 硬件
#error 本装置无CAN 硬件,无法使用ISA-CAN规约!
#endif
BYTE g_byCANMode[CN_NUM_PORT_CAN]; // CAN芯片运行模式,初始化时赋值,中断处调用
/*======================================*
* Initialize the SJA1000 chip
* bIsHardRst:TRUE 为硬启动,FALSE 为软启动*/
BOOLEAN Hard_Can_Init( BYTE byPortNo ,BOOLEAN bIsHardRst)
{
tagPPortSet ptPortSet;
tagPPortVal ptPortVal;
tagPCanCtrl ptCanCtrl;
BYTE byIndex, byCanIP, byBTR0, byBTR1, byTemp;
LPSTR pAddr;
byIndex = byPortNo - CN_PORT_BASE_CAN;
if( byIndex >=CN_NUM_PORT_CAN ) return FALSE;
if( FALSE==Fun_GetPortVariable(byPortNo, &ptPortVal) ) return FALSE;
ptPortSet = ptPortVal->ptPortSet;
g_tPortVal[byPortNo].wResetTimes++;
byCanIP = ((tagPParamCan)(ptPortSet->dwParam))->byCanIP;
pAddr = (LPSTR)(ptPortSet->dwAddBase);
switch( ptPortSet->byBaudRate )
{
case EN_CAN_BAUD_5K : byBTR0 = 0xBF; byBTR1 = 0x7F; break; // 5k
case EN_CAN_BAUD_10K : byBTR0 = 0xB1; byBTR1 = 0x2B; break; // 10k
case EN_CAN_BAUD_20K : byBTR0 = 0x98; byBTR1 = 0x2B; break; // 20k
case EN_CAN_BAUD_40K : byBTR0 = 0x89; byBTR1 = 0X5C; break; // 40k
case EN_CAN_BAUD_80K : byBTR0 = 0x84; byBTR1 = 0X5C; break; // 80k
case EN_CAN_BAUD_200K : byBTR0 = 0x81; byBTR1 = 0X5C; break; // 200k
case EN_CAN_BAUD_400K : byBTR0 = 0x80; byBTR1 = 0x2F; break; // 400k
case EN_CAN_BAUD_800K : byBTR0 = 0x80; byBTR1 = 0x25; break; // 800k
case EN_CAN_BAUD_1000K: byBTR0 = 0x80; byBTR1 = 0x14; break; // 1000k
default : byBTR0 = 0x84; byBTR1 = 0x2F; break; // 80k
}
g_byCANMode[byIndex] = ptPortSet->byRunMode; // CAN芯片运行模式
if( EN_MODE_BASIC_CAN ==ptPortSet->byRunMode )
{
byTemp = *( pAddr + CN_BCAN_SR ); // Clear Status Register
byTemp = *( pAddr + CN_BCAN_IIR ); // Clear Interrupt Identify Register
*( pAddr + CN_BCAN_CR ) = 0x21; // 0010-0001: reset mode
*( pAddr + CN_BCAN_CDR ) = 0x05; // BasicCAN mode & Clock driver: 0000-0101
*( pAddr + CN_BCAN_CMR ) = 0x0E; // Command
*( pAddr + CN_BCAN_ACR ) = byCanIP; //
*( pAddr + CN_BCAN_AMR ) = 0x00; // 0000-0000
*( pAddr + CN_BCAN_BTR0 ) = byBTR0; // Bus timing register 0
*( pAddr + CN_BCAN_BTR1 ) = byBTR1; // Bus timing register 1
*( pAddr + CN_BCAN_OCR ) = 0xDA; // 1101-1010:
*( pAddr + CN_BCAN_CR ) = 0x3E; // Operating mode & Interrupt enabled: 0011-1110
}else // PeliCAN mode ( EN_MODE_PELI_CAN )
{
byTemp = *( pAddr + CN_PCAN_SR ); // Clear Status Register
byTemp = *( pAddr + CN_PCAN_IIR ); // Clear Interrupt Identify Register
*( pAddr + CN_PCAN_MODE ) = 0x21; // Reset mode
*( pAddr + CN_PCAN_CDR ) = 0x85; // PeliCAN mode & Clock driver:1000-0101
*( pAddr + CN_PCAN_CMR ) = 0x0E; // Command Register
*( pAddr + CN_PCAN_IER ) = 0x00; // Interruption disabled
*( pAddr + CN_PCAN_BTR0 ) = byBTR0; // Bus timeing register 0
*( pAddr + CN_PCAN_BTR1 ) = byBTR1; // Bus timeing register 1
*( pAddr + CN_PCAN_OCR ) = 0xDA; // Output Control:110-110-10
*( pAddr + CN_PCAN_RXERR )= 0x00; // RX Error counter
*( pAddr + CN_PCAN_TXERR )= 0x00; // TX Error counter
*( pAddr + CN_PCAN_RBSA ) = 0x00; // RX Buffer Start Address
*( pAddr + CN_PCAN_ACR0 ) = byCanIP; //
*( pAddr + CN_PCAN_ACR1 ) = 0x00; //
*( pAddr + CN_PCAN_ACR2 ) = 0x00; //广播地址
*( pAddr + CN_PCAN_ACR3 ) = 0x00; //
*( pAddr + CN_PCAN_AMR0 ) = 0x00; //
*( pAddr + CN_PCAN_AMR1 ) = 0xFF; //
*( pAddr + CN_PCAN_AMR2 ) = 0x00; //
*( pAddr + CN_PCAN_AMR3 ) = 0xFF; //
*( pAddr + CN_PCAN_IER ) = 0x7F; // Interrupt enabled
*( pAddr + CN_PCAN_MODE ) = 0x20; // Normal Operating mode
}
ptCanCtrl = (tagPCanCtrl)ptPortVal->dwRes;
if(bIsHardRst==TRUE)
ptCanCtrl->bStopByAddrConflict = FALSE;
return TRUE;
}
/*=======================================================*
* Read only ONE frame from can buffer each times
*/
BYTE Hard_Can_Message_Read( BYTE byIndex )
{
tagPRecvCtrl ptRecvCtrl;
tagPPortSet ptPortSet;
WORD wWrite, wRead;
BYTE byPortNo, *pbyRecvBuf, bySR, byLen, byLoop;
LPSTR pAddr;
if( byIndex >=CN_NUM_PORT_CAN ) return 0;
byPortNo = CN_PORT_BASE_CAN + byIndex;
ptPortSet = g_ptPortSet[byPortNo];
pAddr = (LPSTR)(ptPortSet->dwAddBase);
ptRecvCtrl = &g_tPortVal[byPortNo].tRecvCtrl;
if( ptRecvCtrl->wRecvWrite >=CN_NUM_CAN_FRAME )
{
ptRecvCtrl->wRecvWrite = 0;
ptRecvCtrl->wRecvRead = 0;
}
byLen = 0;
wRead = ptRecvCtrl->wRecvRead; // 保存的是帧指针
//for( wCounter=0; wCounter<1; wCounter++ )
{
wWrite = ptRecvCtrl->wRecvWrite;
pbyRecvBuf = &(ptRecvCtrl->byRecvQue[ wWrite*11] );
bySR = *( pAddr + CN_CAN_SR ); // CN_BCAN_SR=CN_PCAN_SR
if( 0 ==(bySR & 0x01) ) return( byLen ); // RBS is empty
//Time_TimerBReset( &ptRecvCtrl->tTimerRecv ); // clear the timer
if( g_byCANMode[byIndex] == EN_MODE_BASIC_CAN )
{
byLen = ((*( pAddr + CN_BCAN_RX_LEN )) & 0x0F) + 2;
if( 10 <byLen ) byLen = 10;
for( byLoop=0; byLoop<byLen; byLoop++)
{
pbyRecvBuf[byLoop] = *( pAddr + CN_BCAN_RXD+byLoop ) ;
}
*( pAddr + CN_BCAN_CMR ) = 0xEC; // 1110-1100
}else // EN_MODE_PELI_CAN
{
byLen = ((*( pAddr + CN_PCAN_RX_LEN )) & 0x0F) + 3;
if( 11 <byLen ) byLen = 11;
for( byLoop=0; byLoop<byLen; byLoop++ )
{
pbyRecvBuf[byLoop] = *( pAddr + CN_PCAN_RXD+byLoop );
}
*( pAddr + CN_PCAN_CMR ) = 0xEC; // 1110-1100
}
wWrite++; // 保存的是帧指针
if( wWrite >=CN_NUM_CAN_FRAME ) wWrite = 0;
ptRecvCtrl->wRecvWrite = wWrite;
if( wWrite ==wRead ) // receive buffer overflow!!!
{
wRead++; // 保存的是帧指针
if( wRead >=CN_NUM_CAN_FRAME ) wRead = 0;
ptRecvCtrl->wRecvRead = wRead;
}
// message-watching
if( M_Dbg_RawDataRecv( byPortNo ))
{
Dbg_SavePortMsg( byPortNo, EN_DBG_DATA_RECV, byLen, pbyRecvBuf );
}
}
return( byLen );
}
/*========================================*
* Write ONE frame to SJA1000 */
BYTE Hard_Can_Message_Write( BYTE byIndex )
{
tagPSendCtrl ptSendCtrl;
tagPPortSet ptPortSet;
LPSTR pAddr;
BYTE byPortNo, *pbySendBuf;
BYTE byUnitNo, byFrameNo, bySR, byLen, byLoop;
WORD wRead;
if( byIndex >=CN_NUM_PORT_CAN ) return 0;
byPortNo = CN_PORT_BASE_CAN + byIndex;
ptPortSet = g_ptPortSet[byPortNo];
pAddr = (LPSTR)(ptPortSet->dwAddBase);
bySR = *( pAddr + CN_CAN_SR );
if( 0 ==(bySR & 0x04) ) return 0; // TBS not empty
ptSendCtrl = &g_tPortVal[byPortNo].tSendCtrl;
if( ptSendCtrl->wSendFlag !=CN_STATUS_SEND_BUSY ) return 0;
wRead = ptSendCtrl->wSendRead;
if( (wRead >=CN_VOL_BUF_SEND) || (wRead >=ptSendCtrl->wSendLen) ) // ERROR
{
ptSendCtrl->wSendLen = 0;
ptSendCtrl->wSendRead = 0;
ptSendCtrl->wSendFlag = CN_STATUS_SEND_IDLE;
Time_TimerBStop ( &ptSendCtrl->tTimerAbandon );
Time_TimerBStart( &ptSendCtrl->tTimerLineIdle, CN_INTERVAL_BUS_IDLE, EN_TIMERB_TYPE_MS);
return 0;
}
byUnitNo = ptSendCtrl->wUnitAddr; // 发送函数中必须注明该参数
pbySendBuf = &ptSendCtrl->bySendBuf[wRead]; // the start position to be sent
if( g_byCANMode[byIndex] == EN_MODE_BASIC_CAN )
{
byFrameNo = wRead / 7;
if( (wRead+7) >=ptSendCtrl->wSendLen )
{
byLen = ptSendCtrl->wSendLen - wRead;
ptSendCtrl->wSendLen = 0;
ptSendCtrl->wSendRead = 0;
ptSendCtrl->wSendFlag = CN_STATUS_SEND_IDLE;
//Time_TimerBStop ( &ptSendCtrl->tTimerAbandon );
//Time_TimerBStart( &ptSendCtrl->TimerLineIdle, CN_INTERVAL_BUS_IDLE, EN_TIMERB_TYPE_MS);
*( pAddr + CN_BCAN_DSCR0 ) = byUnitNo;
*( pAddr + CN_BCAN_DSCR1 ) = (0x60 | (byLen+1));
*( pAddr + CN_BCAN_FRAMENO ) = byFrameNo;
}else
{
byLen = 7;
ptSendCtrl->wSendRead = wRead + 7;
//Time_TimerBRestart( &ptSendCtrl->tTimerAbandon );
*( pAddr + CN_BCAN_DSCR0 ) = byUnitNo;
*( pAddr + CN_BCAN_DSCR1 ) = 0x48;
*( pAddr + CN_BCAN_FRAMENO ) = byFrameNo;
}
for( byLoop=0; byLoop<byLen; byLoop++ )
*( pAddr + (CN_BCAN_TXD+byLoop) ) = pbySendBuf[byLoop];
*( pAddr + CN_BCAN_CMR ) = 0x01; // sending request
}else // EN_MODE_PELI_CAN
{
byFrameNo = wRead / 7; // max 7 Byte per frame
if( (wRead+7) >=ptSendCtrl->wSendLen )
{
byLen = ptSendCtrl->wSendLen - wRead;
ptSendCtrl->wSendLen = 0;
ptSendCtrl->wSendRead = 0;
ptSendCtrl->wSendFlag = CN_STATUS_SEND_IDLE;
//Time_TimerBStop ( &ptSendCtrl->tTimerAbandon );
//Time_TimerBStart( &ptSendCtrl->TimerLineIdle, CN_INTERVAL_BUS_IDLE, EN_TIMERB_TYPE_MS);
*( pAddr + CN_PCAN_DSCR0 ) = (byLen+1);
*( pAddr + CN_PCAN_DSCR1 ) = byUnitNo;
*( pAddr + CN_PCAN_DSCR2 ) = 0x20;
*( pAddr + CN_PCAN_FRAMENO ) = byFrameNo;
}else
{
byLen = 7;
ptSendCtrl->wSendRead = wRead + 7;
//Time_TimerBRestart( &ptSendCtrl->tTimerAbandon );
*( pAddr + CN_PCAN_DSCR0 ) = 0x08;
*( pAddr + CN_PCAN_DSCR1 ) = byUnitNo;
*( pAddr + CN_PCAN_DSCR2 ) = 0x00;
*( pAddr + CN_PCAN_FRAMENO ) = byFrameNo;
}
for( byLoop=0; byLoop<byLen; byLoop++ )
*( pAddr + (CN_PCAN_TXD+byLoop) ) = pbySendBuf[byLoop];
*( pAddr + CN_PCAN_CMR ) = 0x01; // sending request
}
// message-watching
if( M_Dbg_RawDataSend( byPortNo) )
{
Dbg_SavePortMsg( byPortNo, EN_DBG_DATA_SEND, byLen, pbySendBuf );
}
return byLen;
}
/*==================================================*
* Start the CAN Transmit */
BOOLEAN Hard_Can_TxStartup( BYTE byPortNo ,BOOLEAN bIsReSend)
{
tagPSendCtrl ptSendCtrl;
BYTE byIndex, byLenSend;
WORD wMsgLen;
byIndex = byPortNo - CN_PORT_BASE_CAN;
if( byIndex >=CN_NUM_PORT_CAN ) return FALSE;
ptSendCtrl = &g_tPortVal[byPortNo].tSendCtrl;
if( ptSendCtrl->wSendRead !=0 ) return FALSE;
wMsgLen = ptSendCtrl->wSendLen;
// intDisable( CN_CPU_INT_LVL_EINT0 ); // INT CAN-0
// intDisable( CN_CPU_INT_LVL_EINT1 ); // INT CAN-1
byLenSend = Hard_Can_Message_Write( byIndex );
// intEnable( CN_CPU_INT_LVL_EINT0 ); // INT CAN-0
// intEnable( CN_CPU_INT_LVL_EINT1 ); // INT CAN-1
if(( M_Dbg_MsgDataSend( byPortNo ) ) && (!bIsReSend))
{ // message-watching
ptSendCtrl = &g_tPortVal[byPortNo].tSendCtrl;
Dbg_SavePortMsg( byPortNo, EN_DBG_MSG_SEND, wMsgLen, ptSendCtrl->bySendBuf );
}// 重发的报文可能显示两次
return TRUE;
}
//void Hard_Can_IntProcess( BYTE byIndex )
void ISR_Can( BYTE byIndex )
{
BYTE byIIR, byPortNo, byINTSource, byTemp;
tagPPortSet ptPortSet;
LPSTR pAddr;
if( byIndex >=CN_NUM_PORT_CAN ) return ;
byPortNo = CN_PORT_BASE_CAN + byIndex;
ptPortSet = g_ptPortSet[byPortNo];
pAddr = (LPSTR)(ptPortSet->dwAddBase);
if( g_byCANMode[byIndex] == EN_MODE_BASIC_CAN ) // CAN芯片运行模式
byINTSource = 0x1C; // Error: 0001-1100
else // EN_MODE_PELI_CAN
byINTSource = 0x7C; // Error: 0111-1100
byIIR = *( pAddr + CN_CAN_IIR );
// printf("\nbyIIR: %d",byIIR);
if( byIIR & byINTSource )
{
byTemp = *( pAddr + CN_CAN_SR );
Hard_Can_Init( byPortNo , FALSE);
}else
{
if( byIIR & 0x02 ) // TI
Hard_Can_Message_Write( byIndex );
if( byIIR & 0x01 ) // RI
Hard_Can_Message_Read( byIndex );
}
// Clear the INT pending flag
// *(PUI32)(CN_CPU_I_ISPC) = *(PUI32)(CN_CPU_I_ISPR);
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -