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

📄 can.c

📁 Pic18F458的Can通信模块代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 * Note:            Care is not taken if buffer is full
 ********************************************************************/
void CANGetMessage(void);

/*********************************************************************
 * Function:        char CANPutMessage(void)
 *
 * PreCondition:    <WIN2:WIN0> in the CANCON register has to set
 *                  to reflect the desired TXB registers
 *
 * Input:           None
 *
 * Output:          0 -> A new message has been put in the transmit queue
 *                  1 -> There was no messages in the TX buffer to send
 *
 * Side Effects:    Will modify the TX buffer磗 Read pointer (TXRPtr)
 *
 * Overview:        Checks if there is any messages to transmit and if so
 *                  place it in the registers reflected by <WIN2:WIN0> 
 *
 * Note:            None
 ********************************************************************/
 char CANPutMessage(void);

/*********************************************************************
 * Function:        char CANOpen(void)
 *
 * PreCondition:    None
 *
 * Input:           Values to be written into BRGCON1 -> BRGCON3
 *
 * Output:          0 -> Initialasation succeeded
 *
 * Side Effects:    None
 *
 * Overview:        Sets up the appropriate register for the device to act
 *                  as a CAN node
 *
 * Note:            Input values 0x03, 0xAA, 0x05 at Fosc = 16MHz works with 
 *                  the default firmware at nodeB on the CAN I/O expander board.
 ********************************************************************/
char CANOpen(unsigned char CONFIG1, unsigned char CONFIG2, unsigned char CONFIG3)
{
	TRISB2 = 0;
	TRISB3 = 1;
	PIE3 = 0;										//Disable all CAN interrupts
	PIR3 = 0;										//and clear all CAN interrupt flags
	CANCON = (CONFIG_MODE & MODE_MASK) | (CANCON & 0x3F);	//Set configuration mode//进入配制模式
	while((CANSTAT & MODE_MASK) != (CONFIG_MODE & MODE_MASK));	//Wait until config mode is set

	BRGCON1 = CONFIG1;     //TQ=2*4/16=0.5us |___________ 一比特位____________________| sync=1TQ
	BRGCON2 = CONFIG2;     //                |sync | propagation |  phase1  |   phase2|
	BRGCON3 = CONFIG3;     // Tbit=16*TQ=8us | 1TQ |    3TQ      |  6TQ     |  6TQ    |=16TQ
	                       //波特率=125k
	//RXB0CON = 0x04;	   //Receive all valid messages receive buffer overflow 接收所有正确的消息并准许溢出到(buff0)->buffer1
	RXB0CON = 0x24;        //rxf1 接收标准格式的消息 	
    //RXB1CON = 0x00;		   //writes to RXB1 接收缓冲1接收所有消息并用RXF0过滤
	RXB1CON = 0x24;        //rxf4 接收标准格式的消息

	//Set the acceptance filters for all the filters
#ifdef ACCEPT_STANDARD_FILTER_0  //11BIT标准格式 ACCEPTANCE_FILTER_0= int 型
	RXF0SIDL = (unsigned char)(ACCEPTANCE_FILTER_0 << 5);//EXIDEN=0 标准ID=BIT(2--0) EXIDEN=1 扩展ID(20-16) 只取低3位装入bit(7-5) 
	RXF0SIDH = (unsigned char)(ACCEPTANCE_FILTER_0 >> 3);//EXIDEN=0 标准ID=BIT(10-3) EXIDEN=1 扩展ID(28-21) 
#else                           //29比特扩展格式 
	RXF0EIDL = (unsigned char)(ACCEPTANCE_FILTER_0 & 0xFF);	         //扩展ID(7-0)
	RXF0EIDH = (unsigned char)((ACCEPTANCE_FILTER_0 >> 8) & 0xFF);   //扩展ID(15-8)
	RXF0SIDL = (unsigned char)((ACCEPTANCE_FILTER_0 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_FILTER_0 >> 13) & 0xE0) | 0x08;
	RXF0SIDH = (unsigned char)((ACCEPTANCE_FILTER_0 >> 21) & 0xFF);
#endif
#ifdef ACCEPT_STANDARD_FILTER_1
	RXF1SIDL = (unsigned char)(ACCEPTANCE_FILTER_1 << 5);
	RXF1SIDH = (unsigned char)(ACCEPTANCE_FILTER_1 >> 3);
#else
	RXF1EIDL = (unsigned char)(ACCEPTANCE_FILTER_1 & 0xFF);	
	RXF1EIDH = (unsigned char)((ACCEPTANCE_FILTER_1 >> 8) & 0xFF);
	RXF1SIDL = (unsigned char)((ACCEPTANCE_FILTER_1 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_FILTER_1 >> 13) & 0xE0) | 0x08;
	RXF1SIDH = (unsigned char)((ACCEPTANCE_FILTER_1 >> 21) & 0xFF);
#endif

#ifdef ACCEPT_STANDARD_FILTER_2
	RXF2SIDL = (unsigned char)(ACCEPTANCE_FILTER_2 << 5);
	RXF2SIDH = (unsigned char)(ACCEPTANCE_FILTER_2 >> 3);
#else
	RXF2EIDL = (unsigned char)(ACCEPTANCE_FILTER_2 & 0xFF);	
	RXF2EIDH = (unsigned char)((ACCEPTANCE_FILTER_2 >> 8) & 0xFF);
	RXF2SIDL = (unsigned char)((ACCEPTANCE_FILTER_2 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_FILTER_2 >> 13) & 0xE0) | 0x08;
	RXF2SIDH = (unsigned char)((ACCEPTANCE_FILTER_2 >> 21) & 0xFF);
#endif

#ifdef ACCEPT_STANDARD_FILTER_3
	RXF3SIDL = (unsigned char)(ACCEPTANCE_FILTER_3 << 5);
	RXF3SIDH = (unsigned char)(ACCEPTANCE_FILTER_3 >> 3);
#else
	RXF3EIDL = (unsigned char)(ACCEPTANCE_FILTER_3 & 0xFF);	
	RXF3EIDH = (unsigned char)((ACCEPTANCE_FILTER_3 >> 8) & 0xFF);
	RXF3SIDL = (unsigned char)((ACCEPTANCE_FILTER_3 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_FILTER_3 >> 13) & 0xE0) | 0x08;
	RXF3SIDH = (unsigned char)((ACCEPTANCE_FILTER_3 >> 21) & 0xFF);
#endif

#ifdef ACCEPT_STANDARD_FILTER_4
	RXF4SIDL = (unsigned char)(ACCEPTANCE_FILTER_4 << 5);
	RXF4SIDH = (unsigned char)(ACCEPTANCE_FILTER_4 >> 3);
#else
	RXF4EIDL = (unsigned char)(ACCEPTANCE_FILTER_4 & 0xFF);	
	RXF4EIDH = (unsigned char)((ACCEPTANCE_FILTER_4 >> 8) & 0xFF);
	RXF4SIDL = (unsigned char)((ACCEPTANCE_FILTER_4 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_FILTER_4 >> 13) & 0xE0) | 0x08;
	RXF4SIDH = (unsigned char)((ACCEPTANCE_FILTER_4 >> 21) & 0xFF);
#endif

#ifdef ACCEPT_STANDARD_FILTER_5
	RXF5SIDL = (unsigned char)(ACCEPTANCE_FILTER_5 << 5);
	RXF5SIDH = (unsigned char)(ACCEPTANCE_FILTER_5 >> 3);
#else
	RXF5EIDL = (unsigned char)(ACCEPTANCE_FILTER_5 & 0xFF);	
	RXF5EIDH = (unsigned char)((ACCEPTANCE_FILTER_5 >> 8) & 0xFF);
	RXF5SIDL = (unsigned char)((ACCEPTANCE_FILTER_5 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_FILTER_4 >> 13) & 0xE0) | 0x08;
	RXF5SIDH = (unsigned char)((ACCEPTANCE_FILTER_5 >> 21) & 0xFF);
#endif

//Set the acceptance masks
#ifdef MY_ADDRESS_IS_STANDARD //接收标准格式的掩码	
	RXM0SIDL = (unsigned char)(ACCEPTANCE_MASK_0_1 <<5); // 标准ID=BIT(2--0)   扩展ID(20-16)
	RXM0SIDH = (unsigned char)((ACCEPTANCE_MASK_0_1 >>3) & 0xFF); 
	RXM1SIDL = (unsigned char)(ACCEPTANCE_MASK_2_5 <<5);
	RXM1SIDH = (unsigned char)((ACCEPTANCE_MASK_2_5 >> 3) & 0xFF);
    RXM0EIDL =0xff;
    RXM0EIDH =0xff;
    RXM1EIDL =0xff; 
    RXM1EIDH =0xff;
#else                        //接收扩展格式的掩码
    RXM0EIDL = (unsigned char)(ACCEPTANCE_MASK_0_1 & 0xFF);	      //mark0  扩展ID(7--0)
	RXM0EIDH = (unsigned char)((ACCEPTANCE_MASK_0_1 >> 8) & 0xFF);//mark0  扩展ID(15-8)
	RXM0SIDL = (unsigned char)((ACCEPTANCE_MASK_0_1 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_MASK_0_1 >> 13) & 0xE0) | 0x08;//mark0 标准ID=BIT(2--0)   扩展ID(20-16)
	RXM0SIDH = (unsigned char)((ACCEPTANCE_MASK_0_1 >> 21) & 0xFF); //mark0 标准ID=BIT(10--3) 扩展ID(28-21)
	RXM1EIDL = (unsigned char)(ACCEPTANCE_MASK_2_5 & 0xFF);	      //mark1  扩展ID(7--0)
	RXM1EIDH = (unsigned char)((ACCEPTANCE_MASK_2_5 >> 8) & 0xFF);//mark1  扩展ID(15-8)
	RXM1SIDL = (unsigned char)((ACCEPTANCE_MASK_2_5 >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_MASK_2_5 >> 13) & 0xE0) | 0x08;
	RXM1SIDH = (unsigned char)((ACCEPTANCE_MASK_2_5 >> 21) & 0xFF); //mark1 标准ID=BIT(10--3) 扩展ID(28-21)
#endif
	CIOCON = 0x20;						//Drive TX pin Vdd when recessive, disable capture//使隐性时输出=vdd 接收禁止

#ifdef CAN_LOW_INT   //设置can中断优先级
	IPR3 = 0x00;
#else
	IPR3 = 0xFF;    //高优先级
#endif

#ifdef USE_LOOPBACK_MODE  //设置工作模式和接收buf
	CANCON = (LOOPBACK_MODE & MODE_MASK) | (CANCON & (MODE_MASK ^ 0xFF));//Set loopback mode for debug purposes only
	while((CANSTAT & MODE_MASK) != (LOOPBACK_MODE & MODE_MASK));	//Wait until loopback mode is set
#else
	CANCON = (NORMAL_MODE & MODE_MASK) | (CANCON & (MODE_MASK ^ 0xFF));					//Set normal mode
    while((CANSTAT & MODE_MASK) != (NORMAL_MODE & MODE_MASK));		//Wait until normal mode is set
    //CANCON=0x60;
    //while(CANSTAT !=0x60);
#endif
	PIE3 = CAN_INT_BITS & 0xE3;			//Enable CAN interrupts except TX interrupts //始能can接收
	PIR3 = 0x18;						//Set TXB1 & TXB2 int flags //设置发送but1,2 为空的中断

//Send my address to notify our presence
#ifdef MY_ADDRESS_IS_STANDARD //标准格式 非中断方式发送数据
	TXB0SIDL = (unsigned char)(MY_ADDRESS_IDENTIFIER << 5);     //装载1d指示位
	TXB0SIDH = (unsigned char)(MY_ADDRESS_IDENTIFIER >> 3);		//Load address with MY_ADDRESS_IDENTIFIER standard identifier
	TXB0DLC = 0x06;//0x00;												//0 data bytes to send  //数据长度=0
	TXB0D0='C';
    TXB0D1='A';
    TXB0D2='N';
	TXB0D3='2';
    TXB0D4='.';
    TXB0D5='0';
    TXB0CON = 0x00;												//Initiate transmission //发送
	TXB0REQ = 1;  //设置此bit后说明发送准备就绪如bus可用将发送高优先级的消息传送完成后设置TXBn(0)IF=1, TXB0REQ=0,
#else                        //扩展格式
	TXB0EIDL = (unsigned char)(MY_ADDRESS_IDENTIFIER & 0xFF);	//Load address with MY_ADDRESS_IDENTIFIER extended identifier
	TXB0EIDH = (unsigned char)((MY_ADDRESS_IDENTIFIER >> 8) & 0xFF);
	TXB0SIDL = (unsigned char)((MY_ADDRESS_IDENTIFIER >> 16) & 0x03) | (unsigned char)((ACCEPTANCE_FILTER_2 >> 13) & 0xE0) | 0x08;
	TXB0SIDH = (unsigned char)((MY_ADDRESS_IDENTIFIER >> 21) & 0xFF);
	TXB0DLC = 0x00;												//0 data bytes to send
	TXB0CON = 0x00;												//Initiate transmission
	TXB0REQ = 1;   //TXB0CON。3
#endif
	
	return 0;
}


/*********************************************************************
 * Function:        void CANISR(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    Will modify the RX/TX interrupt flags 
 *                  and interrupt enable bits
 *
 * Overview:        Checks if a CAN reception/transmission was complete 
 *                  and if so write/read to the CAN RX/TX FIFO buffers
 *
 * Note:            This function is supposed to be called from the ISR
 ********************************************************************/
void CANISR(void)
{
	unsigned char TempCANCON;

	if(PIR3 & PIE3) // 有tx--rx中断请求 & tx-rx使能
	{
		TempCANCON = CANCON;
		
		if(RXB0IF && RXB0IE)      //接收buf0
		{
			RXB0IF = 0;		      //Clear interrupt flag
			CANCON = CANCON & 0xF0 | RXB0Interrupt;  //1100 RXbuf0->可访区
			CANGetMessage();      //从寄存器读数据到缓存区  
		}
		else if(RXB1IF && RXB1IE) //接收buf1
		{
			RXB1IF = 0;		//Clear interrupt flag
			CANCON = CANCON & 0xF0 | RXB1Interrupt; //1010 RXbuf1->可访区
			CANGetMessage();
		}
		else if(TXB0IF && TXB0IE) //发送buf0 缓存有数据时,TXB0IE=1
		{
			CANCON = CANCON & 0xF0 | TXB0Interrupt; //1000 TXbuf0->可访区
			if(CANPutMessage())   //缓存数据写寄存器
				TXB0IE = 0;       //写入不成功(无数据可写)禁中断
			else
				TXB0IF = 0;       //写入成功
		}
		else if(TXB1IF && TXB1IE) //发送buf1
		{
			CANCON = CANCON & 0xF0 | TXB1Interrupt; //0100 TXbuf1->可访区
			if(CANPutMessage())
				TXB1IE = 0;
			else
				TXB1IF = 0;
		}
		else if(TXB2IF && TXB2IE) //发送buf2      
		{
			CANCON = CANCON & 0xF0 | TXB2Interrupt; //0100 TXbuf2->可访区
			if(CANPutMessage())			//if there wasn't any more messages to send
				TXB2IE = 0;				//disable interrupts for TXB2 and leave TXB2IF 
			else						//still on so PutCAN() can reenable the interrupt and instantly vector to ISR
				TXB2IF = 0;				//message was sent, just clear the interrupt flag.
		}
		else if(ERRIF && ERRIE)
		{
			ERRIF = 0;			 //Clear interrupt flag
#ifdef CAN_ERROR_HANDLER_ENABLE
			CANErrorHandler();
#endif			
								//No error handler implemented!!!
		}
		else if(WAKIF && WAKIE)
		{
			WAKIF = 0;			//Clear interrupt flag
		}

		CANCON = TempCANCON;
	}
}


/*********************************************************************
 * Function:        void CANGetMessage(void)
 *
 * PreCondition:    <WIN2:WIN0> in the CANCON register has to set
 *                  to reflect the desired RXB registers
 *                  //通过 <WIN2:WIN0> 设置可访问的寄存器
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    Will modify the RX FIFO Write pointer (RXWPtr)
 *
 * Overview:        Gets the registers for a RXB and puts them in the
 *                  CAN Receive buffer
 *
 * Note:            Care is not taken if buffer is full

⌨️ 快捷键说明

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