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

📄 can.c

📁 Pic18F458的Can通信模块代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 ********************************************************************/
void CANGetMessage(void)        //从buf0读消息到接收缓存
{
	unsigned char i;
	if(++RXWPtr >= RXBUF)		//If pointer overflowed
		RXWPtr = 0;				//Clear it
	
	for(i=0;i<14;i++)
	{
		RXMessage[RXWPtr].Data[i] = *(unsigned char *)(0xF60+i);
	}
	RXB0FUL = 0;
}


/*********************************************************************
 * Function:        char CANPutMessage(void)
 *
 * PreCondition:    <WIN2:WIN0> in the CANCON register has to set
 *                  to reflect the desired TXB registers
 *                  //通过 <WIN2:WIN0> 设置可访问的寄存器
 * 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:            把缓冲区的消息写入发送寄存器 成功返回0 无可发消息返回1
 ********************************************************************/
char CANPutMessage(void) 
{
	unsigned char i;
	if(TXWPtr != TXRPtr)						//If there are any more data to send
	{
		if(++TXRPtr >= TXBUF)					//then increment the TX read pointer
			TXRPtr = 0;
//---------------old---code-------------------------------	 
    //	for(i=0;i<14;i++)
	//		*(unsigned char *)(0xF60+i) = TXMessage[TXRPtr].Data[i];  //地址 0xf60??? 是收
	//	RXB0RTRRO = 1;	
//-------------zhy 2006--04---------------------
    	for(i=0;i<14;i++)
			*(unsigned char *)(0xF40+i) = TXMessage[TXRPtr].Data[i];  //地址 0xf60??? 是收
	    TXB0REQ =1;   					//TXREQ = 1;   //zhy ????? 地址到可访区的比特映射
//-----------------------------------------------	
        return 0;
	}
	else
		return 1;
}


/*********************************************************************
 * Function:        char CANPut(struct CANMessage Message)
 *
 * PreCondition:    None
 *
 * Input:           A CAN message
 *
 * Output:          1 -> Failed to put a CAN on the buffer, buffer is full
 *                  0 -> The CAN message is put on the buffer and will be 
 *                       transmitted eventually 
 *
 * Side Effects:    Will modify the TX Buffer register磗 Write pointer
 *
 * Overview:        Initially checks if at least one buffer slot is available
 *                  and if so push the requested message in the buffer.
 *                  Checks if the TX modules are idle and if they are, reactivate one.
 *
 * Note:            把消息写入发送缓冲区  始能TXB  TXBnIE中断 成功返回0
 ********************************************************************/
char CANPut(struct CANMessage Message)
{
	unsigned char TempPtr, i;
	if(TXWPtr == TXRPtr-1 || (TXWPtr == TXBUF-1 && TXRPtr == 0))	//if all transmit buffers are full return 1
		return 1;  //发送缓冲区满
		
	//Do not modify the TX pointer until the message has been successfully copied so the CANISR don't
	//send a message that isn't ready
	if(TXWPtr >= TXBUF-1)					//防止写指针溢出
	{
		TempPtr = 0;						//and post clear write pointer
	}
	else
	{
		TempPtr = TXWPtr+1;					//and postincrement write pointer
	}
	
	if(Message.NoOfBytes > 8)				//确保消息长度不大于8Ensure we don't handle more than 8 bytes
		Message.NoOfBytes = 8;	
		
	TXMessage[TempPtr].Specific.TXBDLC.Byte = Message.NoOfBytes; //设置消息长度Set the data count

	if(!Message.Remote)			            //数据桢处理 If dataframe
	{
		TXMessage[TempPtr].Specific.TXBDLC.Bits.TXRTR = 0;				//Clear the Remote Transfer Request bit
		
		for(i = 0; i < Message.NoOfBytes; i++)	//Load data registers
		{
			TXMessage[TempPtr].Specific.TXBD.Array[i] = Message.Data[i];
		}
	}
	else									//远程桢处理 Remote frame
	{
		TXMessage[TempPtr].Specific.TXBDLC.Bits.TXRTR = 1;				//设置远程传送bit Set TXRTR bit
	}
   //设置地址信息	
   if(Message.Ext)					    	//29位扩展格式 Extended identifier
	{
		TXMessage[TempPtr].Specific.TXBEIDL.Byte = (unsigned char)(Message.Address & 0xFF);			// Put address <7:0> in EIDL
		TXMessage[TempPtr].Specific.TXBEIDH.Byte = (unsigned char)((Message.Address >> 8) & 0xFF);	// Put address <15:8> in EIDH
		TXMessage[TempPtr].Specific.TXBSIDL.Byte = (unsigned char)((Message.Address >> 16) & 0x03) | (unsigned char)((Message.Address >> 13) & 0xE0);
		TXMessage[TempPtr].Specific.TXBSIDH.Byte = (unsigned char)((Message.Address >> 21) & 0xFF);
		TXMessage[TempPtr].Specific.TXBSIDL.Bits.EXIDE = 1; //设置扩展格式控制bit
	}
	else									//11位标准格式 Standard identifier
	{
		TXMessage[TempPtr].Specific.TXBSIDL.Byte = (unsigned char)((Message.Address << 5) & 0xFF);	//Put address <2:0> in SIDL
		TXMessage[TempPtr].Specific.TXBSIDH.Byte = (unsigned char)((Message.Address >> 3) & 0xFF);	//Put address <10:3> in SIDH
		TXMessage[TempPtr].Specific.TXBSIDL.Bits.EXIDE = 0;
	}
    //设置优先级00--03	
    TXMessage[TempPtr].Specific.TXBCON.Byte = Message.Priority & 0x03;//Set the internal priority of the data frame
	TXWPtr = TempPtr;  //修改写指针

	//Reenable an interrupt if it is idle, it doesn't matter if another TX source caught the pending message
	//before the source that is enabled here does since the interrupt CHECKS if there are any messages pending
	//and if the buffer is empty, it will disable itself again.
	if(!TXB0IE)			//TXB0 is idle
		TXB0IE = 1;		// 始能TXB0中断 enable TXB0 to fire an interrupt to send the pending message
	else if(!TXB1IE)	//else if TXB1 is idle
		TXB1IE = 1;		//始能TXB1中断 same procedure
	else if(!TXB2IE)	//finally try TXB2
		TXB2IE = 1;	

	return 0;
}


/*********************************************************************
 * Function:        char CANRXMessageIsPending(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          1 -> At least one received message is pending in the RX buffer
 *                  0 -> No received messages are pending
 *
 * Side Effects:    None
 *
 * Overview:        Checks if the RX Write pointer is equal to RX Read pointer and
 *                  if so returns 0, else returns 1
 *
 * Note:            Since no care is taken if the buffer overflow
 *                  this function has to be polled frequently to
 *                  prevent a software receive buffer overflow
 ********************************************************************/
char CANRXMessageIsPending(void)
{
	if(RXWPtr != RXRPtr)
		return 1;
	else
		return 0;
}



/*********************************************************************
 * Function:        struct CANMessage CANGet(void)
 *
 * PreCondition:    An unread message has to be in the buffer
 *                  use RXCANMessageIsPending(void) prior to 
 *                  calling this function in order to determine
 *                  if an unread message is pending.
 *
 * Input:           None
 *
 * Output:          The received message
 *
 * Side Effects:    Will modify the RX Buffer register磗 Read pointer
 *
 * Overview:        Pops the the first message of the RX buffer
 *
 * Note:            None
 ********************************************************************/
struct CANMessage CANGet(void)  //从接收缓冲区提取消息
{
	struct CANMessage ReturnMessage;
	unsigned char TempPtr, i;

	/*Do not modify the RX pointer until the message has been successfully
	  copied to prevent ISR to overwrite it (Note. this is not implemented in the ISR yet)*/
	if(RXRPtr >= RXBUF-1)		//防止接收缓冲溢出Check if pointer will overflow
	{
		TempPtr = 0;
	}
	else
	{
		TempPtr = RXRPtr+1;
	}
	
	ReturnMessage.NoOfBytes = RXMessage[TempPtr].Specific.RXBDLC.Byte & 0x0F;	//桢数据长度copy data count
	if(RXMessage[TempPtr].Specific.RXBCON.Bits.RXRTRRO)	   //远程桢请求
	{
		ReturnMessage.Remote = 1;
	}
	else				                                   //数据桢处理 
	{
		ReturnMessage.Remote = 0;									//Clear remote flag
		for(i = 0; i < ReturnMessage.NoOfBytes; i++)				//copy data content
			ReturnMessage.Data[i] = RXMessage[TempPtr].Specific.RXBD.Array[i];
	}
	CANCON = CANCON & 0xF0; //buf0到可访区
	//获得标准地址信息
	ReturnMessage.Address = (unsigned int)(RXMessage[TempPtr].Specific.RXBSIDH.Byte) << 3;			//Load the standard identifier into the address
	ReturnMessage.Address |= (RXMessage[TempPtr].Specific.RXBSIDL.Byte >> 5);
    //获得扩展地址信息
	if(RXMessage[TempPtr].Specific.RXBSIDL.Bits.EXID)				//Extended identifier
	{
		ReturnMessage.Ext = 1;										//Set the extended identifier flag
		ReturnMessage.Address = (ReturnMessage.Address << 2) | (RXMessage[TempPtr].Specific.RXBSIDL.Byte & 0x03);
		ReturnMessage.Address = ReturnMessage.Address << 16;		//and copy the extended address 
		ReturnMessage.Address |= (unsigned int)(RXMessage[TempPtr].Specific.RXBEIDH.Byte) << 8;
		ReturnMessage.Address |= RXMessage[TempPtr].Specific.RXBEIDL.Byte;		
	}
	else								//Standard identifier
	{
		ReturnMessage.Ext = 0;		//clear the extended identifier flag
	}
	
	RXRPtr = TempPtr;
	return ReturnMessage; //返回消息		
}


/*********************************************************************
 * Function:        void CANSetMode(unsigned char Mode)
 *
 * PreCondition:    None
 *
 * Input:           Desired CAN Mode
 *                  (CAN_LISTEN_MODE, CAN_LOOPBACK_MODE
 *                   CAN_DISABLE_MODE, CAN_NORMAL_MODE)
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Requests to set the desired mode and waits until
 *                  the mode has been set.
 *
 * Note:            If USE_LOOPBACK_MODE is defined the requested
 *                  mode will be loopback mode if the input is
 *                  Normal mode 
 *                 设置can工作模式
 ********************************************************************/
void CANSetMode(unsigned char Mode)
{
#ifdef USE_LOOPBACK_MODE
	if(Mode == NORMAL_MODE)
	{
		CANCON = (LOOPBACK_MODE & MODE_MASK) | (CANCON & (MODE_MASK ^ 0xFF));
		while((CANSTAT & MODE_MASK) != (LOOPBACK_MODE & MODE_MASK));	
	}
	else
#endif
	{
		CANCON = (Mode & MODE_MASK) | (CANCON & (MODE_MASK ^ 0xFF));
		while((CANSTAT & MODE_MASK) != (Mode & MODE_MASK));
	}

}


⌨️ 快捷键说明

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