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

📄 xkcan_node.c

📁 CAN工业节点设计、CAN控制器为SJA1000.C源码
💻 C
字号:
#include <REGX52.h>
#include <absacc.h>

#include "xkcan.h"

//#pragma OT(4, speed)

// Frame Datas and pointers
_t_can_frame	idata rxCanFrame[2];
_t_can_frame *	idata pWriteRxCanFrame;
_t_can_frame *	idata pWriteRxCanFrameTemp;
_t_can_frame *	idata pReadRxCanFrame;
_t_can_frame *	idata pReadRxCanFrameTemp;
_t_can_frame *	idata pCanFrameTemp;
_t_can_frame *	idata pCanFrameTemp2;


_t_can_frame	idata txCanFrameTemp;
_t_can_status	idata sCanDefault;

extern ubyte *	idata pRx485Frame;
extern _t_485_tuoke_dh4	idata tx485FrameTemp;


// Flags and global variables
ubyte volatile flag_can_ir = 0;
ubyte volatile flag_can_txc = 0;
ubyte volatile flag_can_rcv = 0;

ubyte volatile flag_uart_txc = 1;
ubyte volatile flag_uart_rcv = 0;
ubyte volatile flag_485_rcv = 0;
ubyte volatile flag_485_tx = 0;

ubyte volatile flag_timer_exp_set = 0;
ubyte volatile flag_timer_exp_timeup = 0;
ubyte volatile timer_clock_pause;
ubyte volatile timer_exp_clock_pause;
uint timer_tick1, timer_tick2;

ubyte stntype;
ubyte uart_data;

ubyte NMT_Status;
ubyte EXP_Status;
ubyte NID;

ubyte cGuardingToggle = 0x80;
ubyte timer_toggle = 0;

ubyte volatile regStatus[ETN_STATUS_BANK_COUNT + 1];
//ubyte volatile StatusNum = 0;

// Function Prototypes
void InitBoard();
ubyte EnterStatus(ubyte status);
ubyte EnterExpStatus(ubyte status);
void UpdateTimeDisplay();

void pause();
void delay(uint);

void ParseCanRxData();
void StatusMachine();
void UpdateRegStatus();
//void serial_IT(void) interrupt SIO_VECTOR
//void ex1_int(void) interrupt IE1_VECTOR

void main(void)
{
	ubyte noop = 0;
	
	InitBoard();

	EnterStatus(STATUS_INITIALISING);

	timer_tick2 = TIMER_Count();

	while (1)
	{
	// Parse Received Data

		timer_tick1 = TIMER_Count();

		if ( flag_can_rcv == 1 )
		{
			flag_can_rcv = 0;
			ParseCanRxData();
		}

	// Deal with the status machine
		
		StatusMachine();
	
	// Clock Stuffs	

		if ((timer_tick_500ms & 1) == 1 ) 
		{
			timer_tick_500ms = 0;


			UpdateClock();
			UpdateTimeDisplay();

		}
 
		//P1 = ~NID;//~NMT_Status;
	}
}
	
void InitBoard()
{

	// Set default CAN parameters

	sCanDefault.btr0 = 0x01; // 250kbps at 16MHz crystal
	sCanDefault.btr1 = 0x1c;

	//sCanDefault.cobid = _GEN_COBID(0x0F, NID);
	NID = ~P1;
	sCanDefault.acr0 = ( (ubyte)NID >>3 ) & 0x0f;
	sCanDefault.acr1 = ( (ubyte)NID <<5 ) & 0xe0;
	sCanDefault.acr2 = 0;//( sCanDefault.cobid >>3 ) & 0x0f;
	sCanDefault.acr3 = 0;//( sCanDefault.cobid <<5 ) & 0xe0;

	sCanDefault.amr0 = 0xf0;
	sCanDefault.amr1 = 0x1f;
	sCanDefault.amr2 = 0xf0;
	sCanDefault.amr3 = 0x1f;
	sCanDefault.mod	= 0;


	sCanDefault.cdr = SJA1000_CDR_CLOCK_OFF|SJA1000_CDR_PELICAN_MODE|SJA1000_CDR_CBP;
	
	sCanDefault.ocr = SJA1000_OCR_MODE_NORMAL|SJA1000_OCR_TX0_PUSHPULL;
	sCanDefault.ier = SJA1000_IER_RIE|SJA1000_IER_TIE;


	pWriteRxCanFrame	= &rxCanFrame[0];
	pWriteRxCanFrameTemp	= &rxCanFrame[1];
	pReadRxCanFrame		= &rxCanFrame[0];
	pReadRxCanFrameTemp 	= &rxCanFrame[1];

 	// Device Initialization
	DIG_Init();
	TIMER_Init();
	_485_Init();
	CAN_Init(&sCanDefault);

	// Device Open
	TIMER_Reset();
	CLOCK_Set(1, 2, 3);
	CLOCK_Exp_Set(4, 5, 6);

	DIG_Open();
	TIMER_Start();
	CLOCK_Start();
	CAN_Open(&sCanDefault);

	// Enable global interrupt
	EA = 1;
	EX1 = 1;

}

ubyte EnterStatus(ubyte status)
{
	if (status == STATUS_INITIALISING)
	{
		NMT_Status = status;
	}
	else if (status == STATUS_RESET_APP)
	{
		EnterExpStatus(EXP_PRE_INIT);
		NMT_Status = status;
	}
	else if (status == STATUS_RESET_COMM)
	{
		NMT_Status = status;
	}
	else if (status == STATUS_PRE_OPERATIONAL)
	{
		// Send BootUp Frame
		cGuardingToggle = (~cGuardingToggle & 0x80);
		txCanFrameTemp.dlc = 2;
		txCanFrameTemp.cobid = _GEN_D_COBID(FC_D_NMT_EC, NID);
		txCanFrameTemp.rtr = 0;
		txCanFrameTemp.dat[0] = cGuardingToggle | NMT_Status;
		txCanFrameTemp.dat[1] = EXP_Status;
				
		CAN_Transmit( &txCanFrameTemp );

		NMT_Status = status;
	}
	else if (status == STATUS_OPERATIONAL)
	{
		NMT_Status = status;
	}
	else if (status == STATUS_STOPPED)
	{
		EnterExpStatus(EXP_STOPPED);
		NMT_Status = status;
	}
	else 
	{
		//TODO: 	Add your error handling code here
		//ERROR:	Wrong Status
		return STATUS_ERROR;
	}
	
	return status;
}

ubyte EnterExpStatus(ubyte status)
{
	if (status == EXP_PRE_INIT)
	{
		CLOCK_Exp_Reset();
		EXP_Status = status;
	}
	else if (status == EXP_INITIALISING)
	{
		CLOCK_Exp_Init();
		EXP_Status = status;
	}
	else if (status == EXP_STANDBY)
	{
		EXP_Status = status;
	}
	else if (status == EXP_RUNNING)
	{
		CLOCK_Exp_Start();
		EXP_Status = status;
	}
	else if (status == EXP_PAUSE)
	{
		CLOCK_Exp_Pause();
		EXP_Status = status;
	}
	else if (status == EXP_FAULT)
	{
		EXP_Status = status;
	}
	else if (status == EXP_STOPPED)
	{
		CLOCK_Exp_Stop();
		EXP_Status = status;
	}
	else if (status == EXP_END_REQUEST)
	{
		CLOCK_Exp_Stop();
		flag_timer_exp_set = 0;
		
		txCanFrameTemp.dlc = 1;
		txCanFrameTemp.cobid = _GEN_D_COBID(FC_D_SDO_RX, NID);
		txCanFrameTemp.rtr = 0;
		txCanFrameTemp.dat[0] = SDO_CS_EXP_END_REQUEST;
				
		CAN_Transmit( &txCanFrameTemp );

		EXP_Status = status;
	}
	else if (status == EXP_END)
	{
		CLOCK_Exp_Stop();
		EXP_Status = status;
	}
	else 
	{
		//TODO: 	Add your error handling code here
		//ERROR:	Wrong Status
		return EXP_STATUS_ERROR;
	}
	
	return status;
}

void ex1_int(void) interrupt IE1_VECTOR	 //using 3		//外部中断1
{
	EA = 0;
	
	flag_can_ir = CAN_ReadReg(SJA1000_IR);		//保持中断寄存器值
	if ( flag_can_ir & SJA1000_IR_RI != 0 )
	{
		CAN_Receive	(pWriteRxCanFrame);
		pCanFrameTemp = pWriteRxCanFrameTemp;
		pWriteRxCanFrameTemp = pWriteRxCanFrame;
		pWriteRxCanFrame = pCanFrameTemp;

		flag_can_rcv = 1;
	}
	if ( flag_can_ir & SJA1000_IR_TI != 0 )
	{ 
		flag_can_txc = 1;
	}
	
	EA = 1;
}

void serial_IT(void) interrupt SIO_VECTOR 
{
	EA = 0;
	if (RI == 1) 
	{						 /* if reception occur */
		RI = 0; 				 /* clear reception flag for next reception */
		uart_data = SBUF;	/* Read receive data */
		flag_uart_rcv = 1;
	}
	else
	{
		flag_uart_txc = 1;
		TI = 0;			/* if emission occur */
	}
	EA = 1;
	 					/* clear emission flag for next emission*/		
}


void pause(){for(;;);}
void delay(uint t)
{
	int iTemp;
	for ( iTemp = 0; iTemp < t; iTemp++ );
}


void ParseCanRxData()
{
	ubyte cTemp, i, dlc;

	ubyte csTemp, fcTemp;

	dlc = pReadRxCanFrame->dlc;
	fcTemp = _GET_FRAME_FC(pReadRxCanFrame);
	csTemp = pReadRxCanFrame->dat[0];

	if ( fcTemp == FC_NMT_MC)
	{
		if ( csTemp == NMT_MC_CS_START_REMOTE )
		{
			EnterStatus(STATUS_OPERATIONAL);
		}
		else if ( csTemp == NMT_MC_CS_STOP_REMOTE )
		{
			EnterStatus(STATUS_STOPPED);
		}
		else if ( csTemp == NMT_MC_CS_ENTER_PRE_OP )
		{
			EnterStatus(STATUS_PRE_OPERATIONAL);
		}
		else if ( csTemp == NMT_MC_CS_RESET_NODE )
		{
			EnterStatus(STATUS_RESET_APP);
		}
		else if ( csTemp == NMT_MC_CS_RESET_COMM )
		{
			EnterStatus(STATUS_RESET_COMM);
		}
		else 
		{
			//TODO: 	Add your error handling code here
			//ERROR:	Recevied undefined NMT Module Control frame
		}
		
		// Different Response of p2p frame or broadcast frame
	}
	else if ( fcTemp == FC_NMT_EC )
	{
		if ( pReadRxCanFrame->rtr == 1 )//&& _GET_FRAME_NID(pReadRxCanFrame) == NID)
		{
			cGuardingToggle = (~cGuardingToggle & 0x80);
			cTemp = cGuardingToggle | NMT_Status;

			txCanFrameTemp.dlc = 2;
			txCanFrameTemp.cobid = _GEN_D_COBID(FC_D_NMT_EC, NID);
			txCanFrameTemp.rtr = 0;
			txCanFrameTemp.dat[0] = cTemp;
			txCanFrameTemp.dat[1] = EXP_Status;
			
			CAN_Transmit( &txCanFrameTemp );
		}
		else
		{
			//TODO: 	Add your error handling code here
			//ERROR:	Recevied undefined NMT Error Control frame
		}
	}
	else if ( fcTemp == FC_SYNC )
	{
	}
	else if ( fcTemp == FC_TIME_STAMP )
	{
		CLOCK_Set(csTemp, pReadRxCanFrame->dat[1], pReadRxCanFrame->dat[2] );

		TIMER_Restart();
		CLOCK_Start();
	}
	else if ( fcTemp == FC_EMCY )
	{
	}
	else if ( NMT_Status == STATUS_OPERATIONAL )
	{
	
		if ( fcTemp == FC_PDO1_TX )
		{
			if ( csTemp == PDO1_TX_SET_SWITCH )
			{
				Switch_Write(0x10);
				for ( i = 1; i <= ETN_SWITCH_BANK_COUNT; i++ )
				{
					Switch_Write( pReadRxCanFrame->dat[i] );
				}
			}
			else if ( csTemp == PDO1_TX_SET_SPC_SWITCH )
			{			
				Switch_Write(0x1f + dlc);
				for ( i = 1; i < dlc; i++ )
				{
					Switch_Write( pReadRxCanFrame->dat[i] );
				}
			}
			else if ( csTemp == PDO1_TX_GET_STATUS )
			{
				txCanFrameTemp.dlc = 1 + ETN_STATUS_BANK_COUNT;
				txCanFrameTemp.cobid = _GEN_D_COBID(FC_D_PDO1_RX, NID);
				txCanFrameTemp.rtr = 0;
				txCanFrameTemp.dat[0] = PDO1_TX_GET_STATUS;
	
				for ( i = 1; i <= ETN_STATUS_BANK_COUNT; i++ )
				{
					txCanFrameTemp.dat[i] = regStatus[i];
				}
				
				CAN_Transmit( &txCanFrameTemp );
	
			}
			else if ( csTemp == PDO1_TX_GET_SPC_STATUS )
			{
				txCanFrameTemp.dlc = dlc;
				txCanFrameTemp.cobid = _GEN_D_COBID(FC_D_PDO1_RX, NID);
				txCanFrameTemp.rtr = 0;
				txCanFrameTemp.dat[0] = PDO1_TX_GET_SPC_STATUS;
	
				for ( i = 1; i < dlc; i++ )
				{
					cTemp = pReadRxCanFrame->dat[i];
					txCanFrameTemp.dat[i] = cTemp | ( ( ((regStatus[cTemp>>3])>>(cTemp&0x7)) & 0x01) << 7 );
					// No error handling here
				}
				
				CAN_Transmit( &txCanFrameTemp );
				// Reserved			
			}
		}
		else if ( fcTemp == FC_PDO2_TX )
		{
			if ( csTemp == PDO2_485_READ && flag_485_tx == 0 )
			{
				_485_GenerateReadFrame( pReadRxCanFrame->dat[1], pReadRxCanFrame->dat[2], &tx485FrameTemp);
				stntype = pReadRxCanFrame->dat[1];
				flag_485_tx = 1;
			}

	/*		else if ( csTemp == PDO2_485_CTRL && flag_485_tx == 0)
			{
				//Generate a full frame from CAN
				//flag_485_tx = 1;
			}
			else if ( csTemp == PDO2_485_CTRL_1 && flag_485_tx == 0)
			{
				//Generate a full frame from CAN
				//flag_485_tx = 1;
			}
			else if ( csTemp == PDO2_485_CTRL_C && flag_485_tx == 0)
			{
				//Generate a full frame from CAN
				//flag_485_tx = 1;
			}
			else if ( csTemp == PDO2_485_CTRL_C_1 && flag_485_tx == 0)
			{
				//Generate a full frame from CAN
				//flag_485_tx = 1;
			}
			else
			{
				// ERROR Handling
			}
	*/
		}
		else if ( fcTemp == FC_SDO_TX )
		{
			if ( csTemp == SDO_CS_EXP_TIME )
			{
				CLOCK_Exp_Set( pReadRxCanFrame->dat[1], pReadRxCanFrame->dat[2], pReadRxCanFrame->dat[3]);
				flag_timer_exp_set = 1;
			}
			else if ( csTemp == SDO_CS_EXP_START )
			{
				if (flag_timer_exp_set == 1)
					EnterExpStatus(EXP_RUNNING);
			}
			else if ( csTemp == SDO_CS_EXP_STOP )
			{
				EnterExpStatus(EXP_STOPPED);
			}
			else if ( csTemp == SDO_CS_EXP_PAUSE )
			{
				EnterExpStatus(EXP_PAUSE);
			}
			else if ( csTemp == SDO_CS_EXP_RESET )
			{
				EnterExpStatus(EXP_INITIALISING);
			}
			else if ( csTemp == SDO_CS_EXP_RESUME )
			{
				EnterExpStatus(EXP_RUNNING);
			}
			else if ( csTemp == SDO_CS_EXP_END )
			{
				EnterExpStatus(EXP_END);
			}
			else 
			{
				//TODO: 	Add your error handling code here
				//ERROR:	Recevied undefined NMT Module Control frame
			}		
		}
	
		else
		{
			//Error Handle
		}
	}
	
	// Data received. After all dealings, switch the ping-pong buffer

	pCanFrameTemp2 = pReadRxCanFrameTemp;
	pReadRxCanFrameTemp = pReadRxCanFrame;
	pReadRxCanFrame = pCanFrameTemp2;
}


void StatusMachine()
{
	if (NMT_Status == STATUS_INITIALISING)
	{
		//STATUS_INITIALISING
		EnterStatus (STATUS_RESET_APP); // automatically
	}
	else if (NMT_Status == STATUS_RESET_APP)
	{
		//STATUS_RESET_APP
		EnterStatus (STATUS_RESET_COMM); // automatically
	}
	else if (NMT_Status == STATUS_RESET_COMM)
	{
		//STATUS_RESET_COMM
		EnterStatus (STATUS_PRE_OPERATIONAL); // automatically
	}
	else if (NMT_Status == STATUS_PRE_OPERATIONAL)
	{
		//STATUS_PRE_OPERATIONAL
		//EnterStatus (STATUS_OPERATIONAL); // automatically
	}
	else if (NMT_Status == STATUS_OPERATIONAL)
	{
		// Check all instruments and other devices's status
		UpdateRegStatus();

		// Send Data to 485 bus
		_485_SendData(stntype);
		// Receive Data from UART, this might be 485 data
		stntype = _485_ReceiveData();

		//CRC Check
		//if ( flag_485_rcv == 1 )
		//{
		//	if ( _485_Tuoke_DH4_CRCCheck( pRx485Frame ) != 1 );
		//		flag_485_rcv = 0;
		//}

		// SEND	485 data to CAN
		if (flag_485_rcv == 1 )
		{
			txCanFrameTemp.cobid = _GEN_D_COBID(FC_D_PDO2_RX, NID);
			txCanFrameTemp.rtr = 0;
			txCanFrameTemp.dat[0] = PDO2_485_READ;
			txCanFrameTemp.dat[1] = stntype;
			
			if (stntype == INSTR_TUOKE_DH4)
			{
				txCanFrameTemp.dlc = 5;
				txCanFrameTemp.dat[2] = ((_t_485_tuoke_dh4_rx *)pRx485Frame)->stn;
				txCanFrameTemp.dat[3] = ((_t_485_tuoke_dh4_rx *)pRx485Frame)->dat_L;
				txCanFrameTemp.dat[4] = ((_t_485_tuoke_dh4_rx *)pRx485Frame)->dat_H;
			}

			CAN_Transmit( &txCanFrameTemp );
			flag_485_rcv = 0;
		}
					
		if (EXP_Status == EXP_PRE_INIT)
		{
			EnterExpStatus(EXP_INITIALISING);
		}
		else if (EXP_Status == EXP_INITIALISING)
		{
			if (flag_timer_exp_set == 1)
				EnterExpStatus(EXP_STANDBY);
		}
		else if (EXP_Status == EXP_STANDBY)
		{
			;
		}
		else if (EXP_Status == EXP_RUNNING)
		{
			if (flag_timer_exp_timeup == 1)
			{
				EnterExpStatus(EXP_END_REQUEST);
			}
		}
		else if (EXP_Status == EXP_PAUSE)
		{
			;
		}
		else if (EXP_Status == EXP_FAULT)
		{
			;
		}
		else if (EXP_Status == EXP_STOPPED)
		{
			EnterExpStatus(EXP_END_REQUEST);
		}
		else if (EXP_Status == EXP_END_REQUEST)
		{
			;
		}
		else if (EXP_Status == EXP_END)
		{
			;
		}
		else if (EXP_Status == EXP_STATUS_ERROR)
		{
			;
		}
		else
		{
			;
		}
		
	}
	else if (NMT_Status == STATUS_STOPPED)
	{
		//STATUS_STOPPED
	}
	else
	{
		//	STATUS_DEFAULT
	}

}

void UpdateRegStatus()
{
	ubyte cTemp;

	if ( timer_tick1 != timer_tick2 )
	{
		timer_tick2 = TIMER_Count();

		cTemp = Status_Read();
		if (cTemp == 0x55)
		{
			regStatus[1] = Status_Read();

		}
		else
		{
			cTemp = Status_Read();
			cTemp = Status_Read();
		}
		cTemp = Status_Read();				
	}	
}

⌨️ 快捷键说明

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