Exemple #1
0
/*********************************************************************************************************
** Function name:           mcp2515_initCANBuffers
** Descriptions:            init canbuffers
*********************************************************************************************************/
void MCP_CAN::mcp2515_initCANBuffers(void)
{
	INT8U i, a1, a2, a3;

	INT8U std = 0;
	INT8U ext = 1;
	INT32U ulMask = 0x00, ulFilt = 0x00;


	mcp2515_write_id(MCP_RXM0SIDH, ext, ulMask);			/*Set both masks to 0           */
	mcp2515_write_id(MCP_RXM1SIDH, ext, ulMask);			/*Mask register ignores ext bit */

	/* Set all filters to 0         */
	mcp2515_write_id(MCP_RXF0SIDH, ext, ulFilt);			/* RXB0: extended               */
	mcp2515_write_id(MCP_RXF1SIDH, std, ulFilt);			/* RXB1: standard               */
	mcp2515_write_id(MCP_RXF2SIDH, ext, ulFilt);			/* RXB2: extended               */
	mcp2515_write_id(MCP_RXF3SIDH, std, ulFilt);			/* RXB3: standard               */
	mcp2515_write_id(MCP_RXF4SIDH, ext, ulFilt);
	mcp2515_write_id(MCP_RXF5SIDH, std, ulFilt);

	/* Clear, deactivate the three  */
	/* transmit buffers             */
	/* TXBnCTRL -> TXBnD7           */
	a1 = MCP_TXB0CTRL;
	a2 = MCP_TXB1CTRL;
	a3 = MCP_TXB2CTRL;
	for (i = 0; i < 14; i++) {                                          /* in-buffer loop               */
		mcp2515_setRegister(a1, 0);
		mcp2515_setRegister(a2, 0);
		mcp2515_setRegister(a3, 0);
		a1++;
		a2++;
		a3++;
	}
	mcp2515_setRegister(MCP_RXB0CTRL, 0);
	mcp2515_setRegister(MCP_RXB1CTRL, 0);
}
bool mcp2515_set_filter(uint8_t number, const can_filter_t *filter)
{
	uint8_t mask_address = 0;
	uint8_t mode = mcp2515_read_register(CANSTAT);
	
	if (number > 5)
		return false;
	
	// change to configuration mode
	mcp2515_change_operation_mode( (1<<REQOP2) );
	
	// set filter mask
	if (number == 0)
	{
		mask_address = RXM0SIDH;
		
		#if SUPPORT_EXTENDED_CANID
			if (filter->flags.extended == 0x3) {
				// only extended identifier
				mcp2515_write_register(RXB0CTRL, (1<<RXM1));
			}
			else if (filter->flags.extended == 0x2) {
				// only standard identifier
				mcp2515_write_register(RXB0CTRL, (1<<RXM0));
			}
			else {
				// receive all messages
				mcp2515_write_register(RXB0CTRL, 0);
			}
		#else
			// Buffer 0: Empfangen aller Nachrichten mit Standard Identifier 
			// die den Filter Kriterien gengen
			mcp2515_write_register(RXB0CTRL, (1<<RXM0));
		#endif
	}
	else if (number == 2)
	{
		mask_address = RXM1SIDH;
		
		#if SUPPORT_EXTENDED_CANID
			if (filter->flags.extended == 0x3) {
				// only extended identifier
				mcp2515_write_register(RXB1CTRL, (1<<RXM1));
			}
			else if (filter->flags.extended == 0x2) {
				// only standard identifier
				mcp2515_write_register(RXB1CTRL, (1<<RXM0));
			}
			else {
				mcp2515_write_register(RXB1CTRL, 0);
			}
		#else
			// Buffer 1: Empfangen aller Nachrichten mit Standard Identifier 
			// die den Filter Kriterien gengen
			mcp2515_write_register(RXB1CTRL, (1<<RXM0));
		#endif
	}
	
	if (mask_address)
	{
		RESET(MCP2515_CS);
		spi_putc(SPI_WRITE);
		spi_putc(mask_address);
		#if SUPPORT_EXTENDED_CANID
			mcp2515_write_id(&filter->mask, (filter->flags.extended == 0x2) ? 0 : 1);
		#else
			mcp2515_write_id(&filter->mask);
		#endif
		SET(MCP2515_CS);
		
		_delay_us(1);
	}
	
	// write filter
	uint8_t filter_address;
	if (number >= 3) {
		number -= 3;
		filter_address = RXF3SIDH;
	}
	else {
		filter_address = RXF0SIDH;
	}
	
	RESET(MCP2515_CS);
	spi_putc(SPI_WRITE);
	spi_putc(filter_address | (number * 4));
	#if SUPPORT_EXTENDED_CANID
		mcp2515_write_id(&filter->id, (filter->flags.extended == 0x2) ? 0 : 1);
	#else
		mcp2515_write_id(&filter->id);
	#endif
	SET(MCP2515_CS);
	
	_delay_us(1);
	
	// restore previous mode
	mcp2515_change_operation_mode( mode );
	
	return true;
}
// ----------------------------------------------------------------------------
uint8_t mcp2515_send_message(const can_t *msg)
{
	// Status des MCP2515 auslesen
	uint8_t status = mcp2515_read_status(SPI_READ_STATUS);
	
	/* Statusbyte:
	 *
	 * Bit	Funktion
	 *  2	TXB0CNTRL.TXREQ
	 *  4	TXB1CNTRL.TXREQ
	 *  6	TXB2CNTRL.TXREQ
	 */
	uint8_t address;
	if (_bit_is_clear(status, 2)) {
		address = 0x00;
	}
	else {
		// Alle Puffer sind belegt,
		// Nachricht kann nicht verschickt werden
		return 0;
	}
	
	RESET(MCP2515_CS);
	spi_putc(SPI_WRITE_TX | address);
	#if SUPPORT_EXTENDED_CANID
		mcp2515_write_id(&msg->id, msg->flags.extended);
	#else
		mcp2515_write_id(&msg->id);
	#endif
	uint8_t length = msg->length & 0x0f;
	
	// Ist die Nachricht ein "Remote Transmit Request" ?
	if (msg->flags.rtr)
	{
		// Ein RTR hat zwar eine Laenge,
		// enthaelt aber keine Daten
		
		// Nachrichten Laenge + RTR einstellen
		spi_putc((1<<RTR) | length);
	}
	else
	{
		// Nachrichten Laenge einstellen
		spi_putc(length);
		
		// Daten
		for (uint8_t i=0;i<length;i++) {
			spi_putc(msg->data[i]);
		}
	}
	SET(MCP2515_CS);
	
	_delay_us(1);
	
	// CAN Nachricht verschicken
	// die letzten drei Bit im RTS Kommando geben an welcher
	// Puffer gesendet werden soll.
	RESET(MCP2515_CS);
	address = (address == 0) ? 1 : address;
	spi_putc(SPI_RTS | address);
	SET(MCP2515_CS);
	
	CAN_INDICATE_TX_TRAFFIC_FUNCTION;
	
	return address;
}
uint8_t mcp2515_set_filter(uint8_t number, const can_filter_t *filter)
{
	uint8_t mask_address = 0;
	
	if (number > 5)
		return false;
	
	// Konfiguration einschalten
	mcp2515_change_operation_mode( (1<<REQOP2) );
	
	// Filtermaske setzen
	if (number == 0)
	{
		mask_address = RXM0SIDH;	
	}
	else if (number == 2)
	{
		mask_address = RXM1SIDH;
	}
	
	if (mask_address)
	{
		RESET(MCP2515_CS);
		spi_putc(SPI_WRITE);
		spi_putc(mask_address);
		mcp2515_write_id(&filter->mask);

		asm volatile ("nop");
		asm volatile ("nop");
		
		SET(MCP2515_CS);
		
		asm volatile ("nop");
		asm volatile ("nop");

	}
	
	// Filter setzen
	uint8_t filter_address;
	if (number >= 3) {
		number -= 3;
		filter_address = RXF3SIDH;
	}
	else {
		filter_address = RXF0SIDH;
	}
	
	RESET(MCP2515_CS);
	spi_putc(SPI_WRITE);
	spi_putc(filter_address | (number * 4));
	mcp2515_write_id(&filter->id);

	asm volatile ("nop");
	asm volatile ("nop");

	SET(MCP2515_CS);
	
	asm volatile ("nop");
	asm volatile ("nop");

	if (number == 0)
	{
		mcp2515_write_register(RXB0CTRL, (1<<RXM1));
	} 
	else if (number==2)
	{
		mcp2515_write_register(RXB1CTRL, (1<<RXM1));
	} ;
	
	// zurueck zum normalen modus
	mcp2515_write_register(CANCTRL, 0);
	
	return true;
}