void mcp2515_static_filter(const prog_uint8_t *filter)
{
	// change to configuration mode
	mcp2515_bit_modify(CANCTRL, 0xe0, (1<<REQOP2));
	while ((mcp2515_read_register(CANSTAT) & 0xe0) != (1<<REQOP2))
		;
	
	mcp2515_write_register(RXB0CTRL, (1<<BUKT));
	mcp2515_write_register(RXB1CTRL, 0);
    
	uint8_t i, j;
	for (i = 0; i < 0x30; i += 0x10)
	{
		RESET(MCP2515_CS);
		spi_putc(SPI_WRITE);
		spi_putc(i);
		
		for (j = 0; j < 12; j++) 
		{
			if (i == 0x20 && j >= 0x08)
				break;
			
			spi_putc(pgm_read_byte(filter++));
		}
		SET(MCP2515_CS);
	}
	
	mcp2515_bit_modify(CANCTRL, 0xe0, 0);
}
Beispiel #2
0
// ----------------------------------------------------------------------------
uint8_t mcp2515_get_message(tCAN *message)
{
	// read status
	uint8_t status = mcp2515_read_status(SPI_RX_STATUS);
	uint8_t addr;
	uint8_t t;
	if (bit_is_set(status,6)) {
		// message in buffer 0
		addr = SPI_READ_RX;
	}
	else if (bit_is_set(status,7)) {
		// message in buffer 1
		addr = SPI_READ_RX | 0x04;
	}
	else {
		// Error: no message available
		return 0;
	}

	RESET(MCP2515_CS);
	spi_putc(addr);
	
	// read id
	message->raw_data[0] = spi_putc(0xff);
	message->raw_data[1] = spi_putc(0xff);
	message->raw_data[2] = spi_putc(0xff);
	message->raw_data[3] = spi_putc(0xff);
	message->raw_data[4] = spi_putc(0xff);

	message->id = (uint16_t)message->raw_data[0] << 3;
	message->id |= message->raw_data[1] >> 5;
	
	// read DLC
	uint8_t length = message->raw_data[4] & 0x0f;
	
	message->header.length = length;
	message->header.rtr = (bit_is_set(status, 3)) ? 1 : 0;
	
	// read data
	for (t=0;t<length;t++) {
		message->data[t] = spi_putc(0xff);
		message->raw_data[t + 5] = message->data[t];
	}
	SET(MCP2515_CS);
	
	// clear interrupt flag
	if (bit_is_set(status, 6)) {
		mcp2515_bit_modify(CANINTF, (1<<RX0IF), 0);
	}
	else {
		mcp2515_bit_modify(CANINTF, (1<<RX1IF), 0);
	}
	
	return (status & 0x07) + 1;
}
// ----------------------------------------------------------------------------
void
mcp2515_wakeup(void)
{
	// reset int enable and cancel the interrupt flag
	mcp2515_bit_modify(CANINTE, (1<<WAKIE), 0);
	mcp2515_bit_modify(CANINTF, (1<<WAKIF), 0);

	// re-enable the 2551
	mcp2515_bit_modify(BFPCTRL, (1<<B1BFS), 0);

	// when we get up of sleep, we are in listen mode, return into normal mode
	mcp2515_set_mode(NORMAL_MODE);
}
// ----------------------------------------------------------------------------
void
mcp2515_sleep(void)
{
	// put also the 2551 in standby mode
	// for this, connect RX1BF to the RS pin of the 2551
	mcp2515_bit_modify(BFPCTRL, (1<<B1BFS), (1<<B1BFS));

	// put the 2515 in sleep more
	mcp2515_set_mode(SLEEP_MODE);

	// enable generating an interrupt for wakeup when activity on bus
	mcp2515_bit_modify(CANINTE, (1<<WAKIE), (1<<WAKIE));
}
Beispiel #5
0
/**
 * Initialize the can controller
 */
void can_init(void) {

	mcp2515_init();

	mcp2515_static_filter(can_filter);
	mcp2515_bit_modify(CANCTRL, (1<<REQOP2) | (1<<REQOP1) | (1<<REQOP0), 0);
}
Beispiel #6
0
char CanbusClass::message_tx(void) {
	tCAN message;


	// some test values(???) [einige Testwerte ]
	message.id = 0x7DF;
	message.header.rtr = 0;
	message.header.length = 8;
	message.data[0] = 0x02;
	message.data[1] = 0x01;
	message.data[2] = 0x05;
	message.data[3] = 0x00;
	message.data[4] = 0x00;
	message.data[5] = 0x00;
	message.data[6] = 0x00;
	message.data[7] = 0x00;						
	
	
	
	
//	mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), (1<<REQOP1));	
		mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0);
		
	if (mcp2515_send_message(&message)) {
		//	SET(LED2_HIGH);
		return 1;
	
	}
	else {
	//	PRINT("Error: Could not retrieve message\n\n");
	return 0;
	}
return 1;
 
}
Beispiel #7
0
void can_test_loopback(void){

    mcp2515_bit_modify(MCP_CANCTRL__SET_MODE_LOOPBACK);
    
    printf("MCP_CANCTRL: 0x%02x (should be 0x47)\n", mcp2515_read(MCP_CANCTRL));
    printf("MCP_CANSTAT: 0x%02x (should be 0x40)\n", mcp2515_read(MCP_CANSTAT));
    
    can_msg_t msg1;
    can_msg_t msg2;
    msg1.id = 9;
    msg1.length = 5;
    for(int i = 0; i < 8; i++){
        msg1.data.bytes[i] = i*i;
    }

    while(1){
        can_sendmsg(msg1);
        can_printmsg(msg1);

        msg2 = can_recvmsg();
        can_printmsg(msg2);

        msg1.data.bytes[0]++;
        
        _delay_ms(1000);
    }
}
Beispiel #8
0
char CanbusClass::message_tx(void) {
	tCAN message;


	// einige Testwerte
	message.id = 0x7DF;
	message.header.rtr = 0;
	message.header.length = 8;
	message.data[0] = 0x02;
	message.data[1] = 0x01;
	message.data[2] = 0x05;
	message.data[3] = 0x00;
	message.data[4] = 0x00;
	message.data[5] = 0x00;
	message.data[6] = 0x00;
	message.data[7] = 0x00;						
	
	
	
	
//	mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), (1<<REQOP1));	
		mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0);
		
	if (mcp2515_send_message(&message)) {
		//	SET(LED2_HIGH);
		return 1;
	
	}
	else {
	//	PRINT("Fehler: konnte die Nachricht nicht auslesen\n\n");
	return 0;
	}
return 1;
 
}
Beispiel #9
0
/**
 * Report errors
 *
 * MCP2515 does automatic error recovery when the it enters bus-off mode.
 * There is nothing we can do other than report to the user.
 */
static void report_error(void)
{
	uint8_t flags;

	/* Read the error flag */
	flags = mcp2515_read_reg(EFLG);

	if (flags & (EFLG_RX0OVR | EFLG_RX1OVR)) {
#if DEBUG > 1
		printf("CAN: Receive buffer overflow!\n");
#endif
		/* Overflow flags need to be cleared manually. */
		mcp2515_bit_modify(EFLG, flags & (EFLG_RX0OVR | EFLG_RX1OVR), 0);
	}

#if DEBUG > 0
	if (flags & EFLG_TXBO) {
		printf("CAN: Enter Bus-off mode, too many errors.\n");
	}

	if (flags & EFLG_RXEP) {
		printf("CAN: Enter receive error-passive mode.\n");
	}

	if (flags & EFLG_TXEP) {
		printf("CAN: Enter transmit error-passive mode.\n");
	}
#endif

#if DEBUG > 1
	if (flags & EFLG_TXWAR) {
		printf("CAN: Transmit error warning.\n");
	}

	if (flags & EFLG_RXWAR) {
		printf("CAN: Receive error warning.\n");
	}
#endif

	/* Clear interrupt flags */
	mcp2515_bit_modify(CANINTF, CANINTF_ERRIF, 0);
}
Beispiel #10
0
char CanbusClass::message_tx(tCAN *msg) {
	tCAN message;

	message = *msg;
	mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0);

	if (mcp2515_send_message(&message)) {
		return 1;
	} else {
		return 0;
	}
}
Beispiel #11
0
/**
 * Message error
 *
 * This error is intended to be used for detecting baud rate in Listen-only
 * mode.
 */
static void report_message_error(void)
{
#if DEBUG > 0
	printf("%s\n", __func__);
#endif
	enum op_mode mode;

	mode = get_mode();
	if (mode == REQOP_LISTEN) {
		set_mode(REQOP_CONFIG);
		/* Auto baud rate detection. */
		set_mode(REQOP_LISTEN);
	}

	/* Clear interrupt flags */
	mcp2515_bit_modify(CANINTF, CANINTE_MERRE, 0);
}
// ----------------------------------------------------------------------------
void mcp2515_set_mode(uint8_t IF, can_mode_t mode)
{
	uint8_t reg = 0;
	
	if (mode == LISTEN_ONLY_MODE) {
		reg = (1<<REQOP1)|(1<<REQOP0);
	}
	else if (mode == LOOPBACK_MODE) {
		reg = (1<<REQOP1);
	}
		
	// set the new mode
	mcp2515_bit_modify(IF, CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), reg);
	while ((mcp2515_read_register(IF, CANSTAT) & 0xe0) != reg) {
		// wait for the new mode to become active
	}
}
Beispiel #13
0
/**
 * Put message queue into TXB.
 *
 * @tx: TXB bits(Bit 0 -- TXB0, Bit 1 -- TXB1, Bit 2 -- TXB2)
 */
static void transmit_message(uint8_t tx)
{
	struct can_frame frame;
	uint8_t rts = 0;

	/* Clear interrupt flags */
	mcp2515_bit_modify(CANINTF, tx << TXIF_SHF, 0);

	/* Load messages into empty TX buffers. */
	for (int i = TXB_NUM - 1; i >= 0; i--) {
		if (tx & BIT(i)) {
			canid_clear_cache(i);
			switch (i) {
				case 0:
					txb0_ack_emit();
					break;
				case 1:
					txb1_ack_emit();
					break;
				case 2:
					txb2_ack_emit();
					break;
				default:
					break;
			}

			if (tx_queue_pop(&frame)) {
				/* Make sure the previous message is sent. */
				while (mcp2515_read_reg(TXBCTRL(i) & TXBCTRL_TXREQ));
				load_txb(i, &frame);
				rts |= BIT(i);
			} else {
				/* The TX queue is empty, stop transmission. */
				sync_spinlock_lock(&txb_lock);
				xmit_stopped = 1;
				sync_spinlock_unlock(&txb_lock);
			}
		}
	}

	/* Initiating transmission */
	mcp2515_rts(rts);
}
Beispiel #14
0
void CAN_init(){
	clear_bit(INTERRUPT_DDR, INTERRUPT_BIT); //Input on the interrupt pin
	
	uint8_t value;
	SPI_init(); // Initialize SPI
	mcp2515_reset(); // Send reset-command
	
	_delay_us(20);
	// Self-test
	value = mcp2515_read(MCP_CANSTAT);
	if ((value & MODE_MASK) != MODE_CONFIG) {
		puts("MCP2515 is NOT in configuration mode after reset!\n");
	}
		
	//Sets up RXBOCTRL
		//RXM = 01, activate filter, only short ID
	mcp2515_bit_modify(MCP_RXB0CTRL, MCP_RXB0RXM_MASK, 1 << 5);
		//BUKT: 1 -> transfers to RXB1 when RXB0 is full
	mcp2515_bit_modify(MCP_RXB0CTRL, MCP_RXB0BUKT_MASK, 1 << 2);
	//RXB1CTRL
		//RXM = 01, activate filter, only short ID
	mcp2515_bit_modify(MCP_RXB1CTRL, MCP_RXB1RXM_MASK, 1 << 5);
	
	//Set interrupt enable
	//MERRE = 0 Message error interrupt
	//WAKIE = 0 (We dont use sleep)
	//ERRIE = 1 Error interrupt 
	//TX2IE = 0 Transmit 2 empty interrupt
	//TX1IE = 0 Transmit 1 empty interrupt
	//TX0IE = 0 Transmit 0 empty interrupt
	//RX1IE = 1 Interrupt when there is data RX1
	//RX0IE = 1 Interrupt when there is data RX2
	mcp2515_write(MCP_CANINTE, 0b00000011);
	
	//Filters:
	//Mask for RX0
	mcp2515_write(MCP_RXM0SIDH, NODE2_CANID_H_MASK >> 3);
	mcp2515_bit_modify(MCP_RXM0SIDL, 0b11100000U, NODE2_CANID_H_MASK << 5);
	
	//Mask for RX1
	mcp2515_write(MCP_RXM1SIDH, NODE2_CANID_L_MASK >> 3);
	mcp2515_bit_modify(MCP_RXM1SIDL, 0b11100000U, NODE2_CANID_L_MASK << 5);
	
	//Filter 0 (RX0, goes to RX1 if RX0 is full)
	mcp2515_write(MCP_RXF0SIDH, NODE2_CANID_HIGHPRIO_0 >> 3);
	mcp2515_bit_modify(MCP_RXF0SIDL, 0b11100000U, NODE2_CANID_HIGHPRIO_0 << 5);
	
	//Filter 1 (RX0, goes to RX1 if RX0 is full)
	mcp2515_write(MCP_RXF1SIDH, NODE2_CANID_HIGHPRIO_1 >> 3);
	mcp2515_bit_modify(MCP_RXF1SIDL, 0b11100000U, NODE2_CANID_HIGHPRIO_1 << 5);
	
	//Filter 2 (RX1)
	mcp2515_write(MCP_RXF2SIDH, NODE2_CANID_0 >> 3);
	mcp2515_bit_modify(MCP_RXF2SIDL, 0b11100000U, NODE2_CANID_0 << 5);
	
	//Filter 3 (RX1)
	mcp2515_write(MCP_RXF3SIDH, NODE2_CANID_1 >> 3);
	mcp2515_bit_modify(MCP_RXF3SIDL, 0b11100000U, NODE2_CANID_1 << 5);
	
	//Filter 4 (RX1)
	mcp2515_write(MCP_RXF4SIDH, NODE2_CANID_2 >> 3);
	mcp2515_bit_modify(MCP_RXF4SIDL, 0b11100000U, NODE2_CANID_2 << 5);
	
	//Filter 5 (RX1)
	mcp2515_write(MCP_RXF5SIDH, NODE2_CANID_3 >> 3);
	mcp2515_bit_modify(MCP_RXF5SIDL, 0b11100000U, NODE2_CANID_3 << 5);
	
	CAN_all_int_clear();
	mcp2515_bit_modify(MCP_CANCTRL, MODE_MASK, MODE_NORMAL);
}
Beispiel #15
0
char CanbusClass::ecu_req(unsigned char pid,  char *buffer) 
{
	tCAN message;
	float engine_data;
	int timeout = 0;
	char message_ok = 0;
	// Prepair message
	message.id = PID_REQUEST;
	message.header.rtr = 0;
	message.header.length = 8;
	message.data[0] = 0x02;
	message.data[1] = 0x01;
	message.data[2] = pid;
	message.data[3] = 0x00;
	message.data[4] = 0x00;
	message.data[5] = 0x00;
	message.data[6] = 0x00;
	message.data[7] = 0x00;						
	

	mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0);
	
	if (mcp2515_send_message(&message)) {
	}
				if (mcp2515_check_message()) 
				{

					if (mcp2515_get_message(&message)) 
					{
							switch(message.data[2])
								{   /* Details from http://en.wikipedia.org/wiki/OBD-II_PIDs */
									
									case ENGINE_LOAD:				// Throttle Position
									engine_data = (message.data[3]*100)/255;
									sprintf(buffer,"%d %% ",(int) engine_data);
									break;
																	
									case ENGINE_RPM:  			//   ((A*256)+B)/4    [RPM]
									engine_data =  ((message.data[3]*256) + message.data[4])/4;
									sprintf(buffer,"%d rpm ",(int) engine_data);
									break;
							
									case ENGINE_COOLANT_TEMP: 	// 	A-40			  [degree C]
									engine_data =  message.data[3] - 40;
									sprintf(buffer,"%d degC",(int) engine_data);
									break;
							
									case VEHICLE_SPEED: 		// A				  [km]
									engine_data =  message.data[3];
									sprintf(buffer,"%d km ",(int) engine_data);
									break;

									case MAF_SENSOR:   			// ((256*A)+B) / 100  [g/s]
									engine_data =  ((message.data[3]*256) + message.data[4])/100;
									sprintf(buffer,"%d g/s",(int) engine_data);
									break;

									case O2_VOLTAGE:    		// A * 0.005   (B-128) * 100/128 (if B==0xFF, sensor is not used in trim calc)
									engine_data = message.data[3]*0.005;
									sprintf(buffer,"%d V",(int) engine_data);
									break;
									
									case THROTTLE:				// Throttle Position
									engine_data = (message.data[3]*100)/255;
									sprintf(buffer,"%d %% ",(int) engine_data);
									break;
									
									case INTAKE_AIR_TEMP: 	// 	A-40			  [degree C]
									engine_data =  message.data[3] - 40;
									sprintf(buffer,"%d degC",(int) engine_data);
									break;
									
									case FUEL_TAKE_LEVEL:   // Fuel Tank Level
									engine_data = (message.data[3]*100)/255;
									sprintf(buffer,"%d %% ",(int) engine_data);
									break;
							
							        case OBD_STANDARD:   // OBD_STD
									sprintf(buffer,"%d  ",(int) message.data[3]);
									break;
							
								}
					}
				}

}
uint8_t mcp2515_get_message(can_t *msg)
{
    uint8_t addr;

    #ifdef  RXnBF_FUNKTION
        if (!IS_SET(MCP2515_RX0BF))
            addr = SPI_READ_RX;
        else if (!IS_SET(MCP2515_RX1BF))
            addr = SPI_READ_RX | 0x04;
        else
            return 0;
    #else
        // read status
        uint8_t status = mcp2515_read_status(SPI_RX_STATUS);

        if (_bit_is_set(status,6)) {
            // message in buffer 0
            addr = SPI_READ_RX;
        }
        else if (_bit_is_set(status,7)) {
            // message in buffer 1
            addr = SPI_READ_RX | 0x04;
        }
        else {
            // Error: no message available
            return 0;
        }
    #endif

    RESET(MCP2515_CS);
    spi_putc(addr);

    // CAN ID auslesen und ueberpruefen
    uint8_t tmp = mcp2515_read_id(&msg->id);
    #if SUPPORT_EXTENDED_CANID
        msg->flags.extended = tmp & 0x01;
    #else
        if (tmp & 0x01) {
            // Nachrichten mit extended ID verwerfen
            SET(MCP2515_CS);
            #ifdef  RXnBF_FUNKTION
            if (!IS_SET(MCP2515_RX0BF))
            #else
            if (_bit_is_set(status, 6))
            #endif
                mcp2515_bit_modify(CANINTF, (1<<RX0IF), 0);
            else
                mcp2515_bit_modify(CANINTF, (1<<RX1IF), 0);

            return 0;
        }
    #endif

    // read DLC
    uint8_t length = spi_putc(0xff);
    #ifdef RXnBF_FUNKTION
        if (!(tmp & 0x01))
            msg->flags.rtr = (tmp & 0x02) ? 1 : 0;
        else
            msg->flags.rtr = (length & (1<<RTR)) ? 1 : 0;
    #else
        msg->flags.rtr = (_bit_is_set(status, 3)) ? 1 : 0;
    #endif

    length &= 0x0f;
    msg->length = length;
    // read data
    for (uint8_t i=0;i<length;i++) {
        msg->data[i] = spi_putc(0xff);
    }
    SET(MCP2515_CS);

    // clear interrupt flag
    #ifdef RXnBF_FUNKTION
    if (!IS_SET(MCP2515_RX0BF))
    #else
    if (_bit_is_set(status, 6))
    #endif
        mcp2515_bit_modify(CANINTF, (1<<RX0IF), 0);
    else
        mcp2515_bit_modify(CANINTF, (1<<RX1IF), 0);

    CAN_INDICATE_RX_TRAFFIC_FUNCTION;

    #ifdef RXnBF_FUNKTION
        return 1;
    #else
        return (status & 0x07) + 1;
    #endif
}
Beispiel #17
0
char CanbusClass::ecu_req(unsigned char pid,  char *buffer) 
{
	tCAN message;
	float engine_data;
	int timeout = 0;
	char message_ok = 0;
	// Prepair message
	message.id = PID_REQUEST;
	message.header.rtr = 0;
	message.header.length = 8;
	message.data[0] = 0x02;
	message.data[1] = 0x01;
	message.data[2] = pid;
	message.data[3] = 0x00;
	message.data[4] = 0x00;
	message.data[5] = 0x00;
	message.data[6] = 0x00;
	message.data[7] = 0x00;						
	

	mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0);
//		SET(LED2_HIGH);	
	if (mcp2515_send_message(&message)) {
	}
	
	while(timeout < 4000)
	{
		timeout++;
				if (mcp2515_check_message()) 
				{

					if (mcp2515_get_message(&message)) 
					{
							if((message.id == PID_REPLY) && (message.data[2] == pid))	// Check message is the reply and its the right PID
							{
								switch(message.data[2])
								{   /* Details from http://en.wikipedia.org/wiki/OBD-II_PIDs */
									case ENGINE_RPM:  			//   ((A*256)+B)/4    [RPM]
									engine_data =  ((message.data[3]*256) + message.data[4])/4;
									sprintf(buffer,"%d rpm ",(int) engine_data);
									break;
							
									case ENGINE_COOLANT_TEMP: 	// 	A-40			  [degree C]
									engine_data =  message.data[3] - 40;
									sprintf(buffer,"%d degC",(int) engine_data);
							
									break;
							
									case VEHICLE_SPEED: 		// A				  [km]
									engine_data =  message.data[3];
									sprintf(buffer,"%d km ",(int) engine_data);
							
									break;

									case MAF_SENSOR:   			// ((256*A)+B) / 100  [g/s]
									engine_data =  ((message.data[3]*256) + message.data[4])/100;
									sprintf(buffer,"%d g/s",(int) engine_data);
							
									break;

									case O2_VOLTAGE:    		// A * 0.005   (B-128) * 100/128 (if B==0xFF, sensor is not used in trim calc)
									engine_data = message.data[3]*0.005;
									sprintf(buffer,"%d v",(int) engine_data);
							
									case THROTTLE:				// Throttle Position
									engine_data = (message.data[3]*100)/255;
									sprintf(buffer,"%d %% ",(int) engine_data);
									break;
							
								}
								message_ok = 1;
							}

					}
				}
				if(message_ok == 1) return 1;
	}


 	return 0;
}
Beispiel #18
0
void Speedo_CAN::init(){
	// Interrupt for CAN Interface active, auf pk4, pcint20
	can_missed_count=0;
	// Chipselect as output
	if(pConfig->get_hw_version()==7){
		// Interrupt as Input with pull up
		CAN_DDR_CS_TILL_V7 &= ~(1<<CAN_INTERRUPT_PIN_V7); // input
		CAN_PORT_CS_TILL_V7 |= (1<<CAN_INTERRUPT_PIN_V7); //  active low => pull up
		// CS as output
		CAN_DDR_CS_TILL_V7 |= (1<<CAN_PIN_CS_TILL_V7);
		PCMSK2|=(1<<PCINT20); // CAN interrupt pin v7
	} else if(pConfig->get_hw_version()>7){
		// CS Input with pull up
		CAN_DDR_CS_FROM_V8 &= ~(1<<CAN_INTERRUPT_PIN_FROM_V8); // input
		CAN_PORT_CS_FROM_V8 |= (1<<CAN_INTERRUPT_PIN_FROM_V8); //  active low => pull up
		// CS as output
		CAN_DDR_CS_FROM_V8 |= (1<<CAN_PIN_CS_FROM_V8);
		PCMSK0|=(1<<PCINT4); // CAN interrupt pin v(>7)
		PCICR |=(1<<PCIE0); //new interrupt just for CAN
	};


	/********************************************* MCP2515 SETUP ***********************************/
	// MCP2515 per Software Reset zuruecksetzten,
	// danach ist der MCP2515 im Configuration Mode
	set_cs_high(false); //CS low
	spi_putc( SPI_CMD_RESET );
	_delay_ms(1);
	set_cs_high(true); //CS high

	// etwas warten bis sich der MCP2515 zurueckgesetzt hat
	_delay_ms(10);
	/******************** BAUD Rate ************************************************
	 *  Einstellen des Bit Timings
	 *
	 *  Fosc       = 16MHz
	 *  Bus Speed  = 500 kHz
	 *
	 *  Sync Seg   = 1TQ
	 *  Prop Seg   = (PRSEG + 1) * TQ  = 1 TQ
	 *  Phase Seg1 = (PHSEG1 + 1) * TQ = 3 TQ
	 *  Phase Seg2 = (PHSEG2 + 1) * TQ = 3 TQ
	 *
	 *  Bus speed  = 1 / (Total # of TQ) * TQ
	 *  500kHz= 1 / (8 * TQ)
	 * 	TQ = 1/(500kHz*8)
	 *  TQ = 2 * (BRP + 1) / Fosc
	 *  1/(500kHz*8) = 2 * (BRP + 1) / Fosc
	 *  1/(500kHz*8) = 2 * (BRP + 1) / 16000kHz
	 *  16000kHz/(500kHz*8*2) - 1 = BRP
	 *
	 *  BRP        = 1
	 ******************** BAUD Rate ************************************************/

	// BRP = 1
	mcp2515_write_register( CNF1, (1<<BRP0));
	// Prop Seg und Phase Seg1 einstellen
	mcp2515_write_register( CNF2, (1<<BTLMODE)|(1<<PHSEG11) );
	// Wake-up Filter deaktivieren, Phase Seg2 einstellen
	mcp2515_write_register( CNF3, (1<<PHSEG21) );
	// Aktivieren der Rx Buffer Interrupts
	mcp2515_write_register( CANINTE, (1<<RX1IE)|(1<<RX0IE) );

	/******************** FILTER ************************************************
	 * There are two input buffer: RXB0/1
	 * RXB0 has two Filters RXF0 / REF1
	 * RXB1 has four Filters RXF2 / REF3 / REF4 / REF5
	 *
	 * BUKT
	 * Additionally, the RXB0CTRL register can be configured
	 * such that, if RXB0 contains a valid message and
	 * another valid message is received, an overflow error
	 * will not occur and the new message will be moved into
	 * RXB1, regardless of the acceptance criteria of RXB1.
	 *
	 * RXBnCTRL.FILHITm determines if the Filter m is in use for buffer n
	 *
	 ******************** FILTER ************************************************/

	// BUKT: RXB0 message will rollover and be written to RXB1 if RXB0 is full
	// RXM0: Only accept messages with standard identifiers that meet filter criteria
	mcp2515_write_register( RXB0CTRL, (1<<BUKT)|(1<<RXM0)); // use 11bit with filter + rollover
	mcp2515_write_register( RXB1CTRL, (1<<RXM0)); // use 11bit with filter

	/************************************************** Filter definition **************************************************
	 * CAN Filter: We have two Buffers. Each has a Mask RXM0SIDH/RXM0SIDL, RXM1SIDH/RXM1SIDL.
	 * Buffer0 has two Filters RXF0 and RXF1
	 * Buffer1 has three addition Filters RXF2,RXF3,RXF4 and RXF5
	 *
	 ***************************************************** TRIUMPH CAN *****************************************************
	 * If we are using the Triumph CAN, we have to Catch the IDs: 530,540,568,570 and avoid 518,519,550
	 * in addition 568 has a very high priority! Thus 568 should be accepted in buffer 0 to be rollover activ to buffer1
	 *
	 * 568	= 0b 101 0110 1000
	 * Mask0     111 1111 1111
	 * Filter0   101 0110 1000 <- accept only 568
	 * Filter1   101 0110 1000 <- just a copy
	 *
	 * Buffer1 should catch 530,540,570
	 * 530 = 0b 101 0011 0000
	 * 570 = 0b 101 0111 0000
	 * 540 = 0b 101 0100 0000
	 * Mask     111 1111 1111
	 * Filter2  101 0011 0000 <- 530 RPM/Speed
	 * Filter3  101 0111 0000 <- 570 Temp
	 * Filter4  101 0100 0000 <- 540 Status
	 * Filter5  101 0100 0000 <- just a copy
	 *
	 *
	 ***************************************************** OBD2 *****************************************************
	 * We have to catch all IDs from 780-7FF, easy very low traffic compared to Triumph
	 *
	 * Mask0     111 1000 0000
	 * Mask1     111 1000 0000
	 * Filter0   111 1XXX XXXX
	 * Filter1   111 1XXX XXXX
	 * Filter2   111 1XXX XXXX
	 * Filter3   111 1XXX XXXX
	 * Filter4   111 1XXX XXXX
	 * Filter5   111 1XXX XXXX
	 *
	 ************************************************** Filter definition **************************************************/
	can_filter_t filter;

	if(can_bus_type==CAN_TYPE_TRIUMPH){
		// Mask0     111 1111 1111
		filter.id=0x568;
		filter.mask=0xffff;
		mcp2515_set_filter(0,&filter);
		mcp2515_set_filter(1,&filter);

		//Mask1     111 1000 1111
		// Filter2  101 0011 0000 <- 530
		// Filter3  101 0111 0000 <- 570
		// Filter4  101 0100 0000 <- 540
		// Filter5  101 0100 0000 <- just a copy
		filter.mask=0xffff;
		filter.id=0x530;
		mcp2515_set_filter(2,&filter);
		filter.id=0x540;
		mcp2515_set_filter(3,&filter);
		filter.id=0x570;
		mcp2515_set_filter(4,&filter);
		filter.id=0x570;
		mcp2515_set_filter(5,&filter);

		high_prio_processing=true;

	} else { // assume OBD2 as fallback
		// Mask0:   111 1000 0000
		// Filter0 111 1000 0000
		// Filter1 111 1000 0000
		filter.mask=0b11110000000;
		filter.id=0b11110000000;
		mcp2515_set_filter(0,&filter);
		mcp2515_set_filter(1,&filter);

		// Mask1:   111 1000 0000
		// Filter2 111 1000 0000
		// Filter3 111 1000 0000
		// Filter4 111 1000 0000
		// Filter5 111 1000 0000
		filter.mask=0b11110000000;
		filter.id=0b11110000000;
		mcp2515_set_filter(2,&filter);
		mcp2515_set_filter(3,&filter);
		mcp2515_set_filter(4,&filter);
		mcp2515_set_filter(5,&filter);

		high_prio_processing=false;
	}


	/*
	 *  Einstellen der Pin Funktionen
	 */
	// Deaktivieren der Pins RXnBF Pins (High Impedance State)
	mcp2515_write_register( BFPCTRL, 0 );
	// TXnRTS Bits als Inputs schalten
	mcp2515_write_register( TXRTSCTRL, 0 );
	// Device zurueck in den normalen Modus versetzten
	mcp2515_bit_modify( CANCTRL, 0xE0, 0);
	/********************************************* MCP2515 SETUP ***********************************/
	_delay_ms(1);

	// to check if obd2 can is present, triumph talks alone
	if(can_bus_type==CAN_TYPE_OBD2){
		request(CAN_CURRENT_INFO,CAN_RPM);
	};
};
Beispiel #19
0
/**
 * Parse given command line
 *
 * @param line Line string to parse
 */
void parseLine(char * line) {

    unsigned char result = BELL;

    switch (line[0]) {
        case 'S': // Setup with standard CAN bitrates
            if (state == STATE_CONFIG)
            {
                switch (line[1]) {
                    case '0': mcp2515_set_bittiming(MCP2515_TIMINGS_10K);  result = CR; break;
                    case '1': mcp2515_set_bittiming(MCP2515_TIMINGS_20K);  result = CR; break;
                    case '2': mcp2515_set_bittiming(MCP2515_TIMINGS_50K);  result = CR; break;
                    case '3': mcp2515_set_bittiming(MCP2515_TIMINGS_100K); result = CR; break;
                    case '4': mcp2515_set_bittiming(MCP2515_TIMINGS_125K); result = CR; break;
                    case '5': mcp2515_set_bittiming(MCP2515_TIMINGS_250K); result = CR; break;
                    case '6': mcp2515_set_bittiming(MCP2515_TIMINGS_500K); result = CR; break;
                    case '7': mcp2515_set_bittiming(MCP2515_TIMINGS_800K); result = CR; break;
                    case '8': mcp2515_set_bittiming(MCP2515_TIMINGS_1M);   result = CR; break;
                }

            }
            break;
        case 's': // Setup with user defined timing settings for CNF1/CNF2/CNF3
            if (state == STATE_CONFIG)
            {
                unsigned long cnf1, cnf2, cnf3;
                if (parseHex(&line[1], 2, &cnf1) && parseHex(&line[3], 2, &cnf2) && parseHex(&line[5], 2, &cnf3)) {
                    mcp2515_set_bittiming(cnf1, cnf2, cnf3);
                    result = CR;
                }
            } 
            break;
        case 'G': // Read given MCP2515 register
            {
                unsigned long address;
                if (parseHex(&line[1], 2, &address)) {
                    unsigned char value = mcp2515_read_register(address);
		    sendByteHex(value);
                    result = CR;
                }
            }
            break;
        case 'W': // Write given MCP2515 register
            {
                unsigned long address, data;
                if (parseHex(&line[1], 2, &address) && parseHex(&line[3], 2, &data)) {
                    mcp2515_write_register(address, data);
                    result = CR;
                }

            }
            break;
        case 'V': // Get versions
            {
                usb_putch('V');
                sendByteHex(VERSION_HARDWARE);
                sendByteHex(VERSION_FIRMWARE_MAJOR);
                result = CR;
            }
            break;
        case 'v': // Get firmware version
            {
                usb_putch('v');
                sendByteHex(VERSION_FIRMWARE_MAJOR);
                sendByteHex(VERSION_FIRMWARE_MINOR);
                result = CR;
            }
            break;
        case 'N': // Get serial number
            {
                usb_putch('N');
                sendHex(0xFFFF, 4);
                result = CR;
            }
            break;     
        case 'O': // Open CAN channel
            if (state == STATE_CONFIG)
            {
		mcp2515_bit_modify(MCP2515_REG_CANCTRL, 0xE0, 0x00); // set normal operating mode

                clock_reset();

                state = STATE_OPEN;
                result = CR;
            }
            break; 
        case 'l': // Loop-back mode
            if (state == STATE_CONFIG)
            {
		mcp2515_bit_modify(MCP2515_REG_CANCTRL, 0xE0, 0x40); // set loop-back

                state = STATE_OPEN;
                result = CR;
            }
            break; 
        case 'L': // Open CAN channel in listen-only mode
            if (state == STATE_CONFIG)
            {
		mcp2515_bit_modify(MCP2515_REG_CANCTRL, 0xE0, 0x60); // set listen-only mode

                state = STATE_LISTEN;
                result = CR;
            }
            break; 
        case 'C': // Close CAN channel
            if (state != STATE_CONFIG)
            {
		mcp2515_bit_modify(MCP2515_REG_CANCTRL, 0xE0, 0x80); // set configuration mode

                state = STATE_CONFIG;
                result = CR;
            }
            break; 
        case 'r': // Transmit standard RTR (11 bit) frame
        case 'R': // Transmit extended RTR (29 bit) frame
        case 't': // Transmit standard (11 bit) frame
        case 'T': // Transmit extended (29 bit) frame
            if (state == STATE_OPEN)
            {
                if (transmitStd(line)) {
                    if (line[0] < 'Z') usb_putch('Z');
                    else usb_putch('z');
                    result = CR;
                }

            }
            break;        
        case 'F': // Read status flags
            {
                unsigned char flags = mcp2515_read_register(MCP2515_REG_EFLG);
                unsigned char status = 0;

                if (flags & 0x01) status |= 0x04; // error warning
                if (flags & 0xC0) status |= 0x08; // data overrun
                if (flags & 0x18) status |= 0x20; // passive error
                if (flags & 0x20) status |= 0x80; // bus error

                usb_putch('F');
                sendByteHex(status);
                result = CR;
            }
            break;
         case 'Z': // Set time stamping
            {
                unsigned long stamping;
                if (parseHex(&line[1], 1, &stamping)) {
                    timestamping = (stamping != 0);
                    result = CR;
                }
            }
            break;
         case 'm': // Set accpetance filter mask
            if (state == STATE_CONFIG)
            {
                unsigned long am0, am1, am2, am3;
                if (parseHex(&line[1], 2, &am0) && parseHex(&line[3], 2, &am1) && parseHex(&line[5], 2, &am2) && parseHex(&line[7], 2, &am3)) {
                    mcp2515_set_SJA1000_filter_mask(am0, am1, am2, am3);
                    result = CR;
                }
            } 
            break;
         case 'M': // Set accpetance filter code
            if (state == STATE_CONFIG)
            {
                unsigned long ac0, ac1, ac2, ac3;
                if (parseHex(&line[1], 2, &ac0) && parseHex(&line[3], 2, &ac1) && parseHex(&line[5], 2, &ac2) && parseHex(&line[7], 2, &ac3)) {
                    mcp2515_set_SJA1000_filter_code(ac0, ac1, ac2, ac3);
                    result = CR;
                }
            } 
            break;
         
    }

   usb_putch(result);
}
Beispiel #20
0
int main(void)
{
	// Initialisiere die UART Schnittstelle
	uart_init(UART_BAUD_SELECT(9600UL, F_CPU));
	
	// Aktiviere Interrupts
	sei();
	
	// Umleiten der Standardausgabe => ab jetzt koennen wir printf() verwenden
	stdout = &mystdout;
	
	// Versuche den MCP2515 zu initilaisieren
	if (!mcp2515_init()) {
		PRINT("Fehler: kann den MCP2515 nicht ansprechen!\n");
		for (;;);
	}
	else {
		PRINT("MCP2515 is aktiv\n\n");
	}
	
	PRINT("Erzeuge Nachricht\n");
	tCAN message;
	
	// einige Testwerte
	message.id = 0x123;
	message.header.rtr = 0;
	message.header.length = 2;
	message.data[0] = 0xab;
	message.data[1] = 0xcd;
	
	print_can_message(&message);
	
	PRINT("\nwechsle zum Loopback-Modus\n\n");
	mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), (1<<REQOP1));
	
	// Sende eine Nachricht
	if (mcp2515_send_message(&message)) {
		PRINT("Nachricht wurde in die Puffer geschrieben\n");
	}
	else {
		PRINT("Fehler: konnte die Nachricht nicht senden\n");
	}
	
	// warte ein bisschen
	_delay_ms(10);
	
	if (mcp2515_check_message()) {
		PRINT("Nachricht empfangen!\n");
		
		// read the message from the buffers
		if (mcp2515_get_message(&message)) {
			print_can_message(&message);
			PRINT("\n");
		}
		else {
			PRINT("Fehler: konnte die Nachricht nicht auslesen\n\n");
		}
	}
	else {
		PRINT("Fehler: keine Nachricht empfangen\n\n");
	}
	
	PRINT("zurueck zum normalen Modus\n\n");
	mcp2515_bit_modify(CANCTRL, (1<<REQOP2)|(1<<REQOP1)|(1<<REQOP0), 0);
	
	// wir sind ab hier wieder mit dem CAN Bus verbunden
	
	PRINT("Versuche die Nachricht per CAN zu verschicken\n");
	
	// Versuche nochmal die Nachricht zu verschicken, diesmal per CAN
	if (mcp2515_send_message(&message)) {
		PRINT("Nachricht wurde in die Puffer geschrieben\n\n");
	}
	else {
		PRINT("Fehler: konnte die Nachricht nicht senden\n\n");
	}
	
	PRINT("Warte auf den Empfang von Nachrichten\n\n");
	
	while (1) {
		// warten bis wir eine Nachricht empfangen
		if (mcp2515_check_message()) {
			PRINT("Nachricht empfangen!\n");
			
			// Lese die Nachricht aus dem Puffern des MCP2515
			if (mcp2515_get_message(&message)) {
				print_can_message(&message);
				PRINT("\n");
			}
			else {
				PRINT("Kann die Nachricht nicht auslesen\n\n");
			}
		}
	}
	
	return 0;
}