// -----------------------------------------------------------------------------
void mcp2515_regdump(void)
{
	uint8_t mode = mcp2515_read_register( CANSTAT );
	
	// change to configuration mode
	mcp2515_change_operation_mode( (1<<REQOP2) );
	
	printf_P("MCP2515 Regdump:\n");
	uint8_t i;
	for (i=0; i < 16; i++) {
		printf_P("%3i: %02x   ", i, mcp2515_read_register(i));
		printf_P("%3i: %02x   ", i+16*1, mcp2515_read_register(i+16*1));
		printf_P("%3i: %02x   ", i+16*2, mcp2515_read_register(i+16*2));
		printf_P("%3i: %02x   ", i+16*3, mcp2515_read_register(i+16*3));
		printf_P("%3i: %02x   ", i+16*4, mcp2515_read_register(i+16*4));
		printf_P("%3i: %02x   ", i+16*5, mcp2515_read_register(i+16*5));
		printf_P("%3i: %02x   ", i+16*6, mcp2515_read_register(i+16*6));
		printf_P("%3i: %02x\n", i+16*7, mcp2515_read_register(i+16*7));
	}
	
	mcp2515_change_operation_mode( mode );
}
// ----------------------------------------------------------------------------
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 #3
0
// -------------------------------------------------------------------------
uint8_t mcp2515_init(uint8_t speed)
{
		
	
	SET(MCP2515_CS);
	SET_OUTPUT(MCP2515_CS);
	
	RESET(P_SCK);
	RESET(P_MOSI);
	RESET(P_MISO);
	
	SET_OUTPUT(P_SCK);
	SET_OUTPUT(P_MOSI);
	SET_INPUT(P_MISO);
	
	SET_INPUT(MCP2515_INT);
	SET(MCP2515_INT);
	
	// active SPI master interface
	SPCR = (1<<SPE)|(1<<MSTR) | (0<<SPR1)|(1<<SPR0);
	SPSR = 0;
	
	// reset MCP2515 by software reset.
	// After this he is in configuration mode.
	RESET(MCP2515_CS);
	spi_putc(SPI_RESET);
	SET(MCP2515_CS);
	
	// wait a little bit until the MCP2515 has restarted
	_delay_us(10);
	
	// load CNF1..3 Register
	RESET(MCP2515_CS);
	spi_putc(SPI_WRITE);
	spi_putc(CNF3);
	
/*	spi_putc((1<<PHSEG21));		// Bitrate 125 kbps at 16 MHz
	spi_putc((1<<BTLMODE)|(1<<PHSEG11));
	spi_putc((1<<BRP2)|(1<<BRP1)|(1<<BRP0));
*/
/*	
	spi_putc((1<<PHSEG21));		// Bitrate 250 kbps at 16 MHz
	spi_putc((1<<BTLMODE)|(1<<PHSEG11));
	spi_putc((1<<BRP1)|(1<<BRP0));
*/	
	spi_putc((1<<PHSEG21));		// Bitrate 250 kbps at 16 MHz
	spi_putc((1<<BTLMODE)|(1<<PHSEG11));
	//spi_putc(1<<BRP0);
    spi_putc(speed);

	// activate interrupts
	spi_putc((1<<RX1IE)|(1<<RX0IE));
	SET(MCP2515_CS);
	
	// test if we could read back the value => is the chip accessible?
	if (mcp2515_read_register(CNF1) != speed) {
		SET(LED2_HIGH);

		return false;
	}
	
	// deaktivate the RXnBF Pins (High Impedance State)
	mcp2515_write_register(BFPCTRL, 0);
	
	// set TXnRTS as inputs
	mcp2515_write_register(TXRTSCTRL, 0);
	
	// turn off filters => receive any message
	mcp2515_write_register(RXB0CTRL, (1<<RXM1)|(1<<RXM0));
	mcp2515_write_register(RXB1CTRL, (1<<RXM1)|(1<<RXM0));
	
	// reset device to normal mode
	mcp2515_write_register(CANCTRL, 0);
//	SET(LED2_HIGH);
	return true;
}
Beispiel #4
0
// -------------------------------------------------------------------------
bool mcp2515_init(can_bitrate_t bitrate)
{
    if (bitrate >= 8)
        return false;

    SET(MCP2515_CS);
    SET_OUTPUT(MCP2515_CS);

    // Aktivieren der Pins fuer das SPI Interface
    RESET(P_SCK);
    RESET(P_MOSI);
    RESET(P_MISO);

    SET_OUTPUT(P_SCK);
    SET_OUTPUT(P_MOSI);
    SET_INPUT(P_MISO);

    // SPI Einstellung setzen
    mcp2515_spi_init();

    // MCP2515 per Software Reset zuruecksetzten,
    // danach ist er automatisch im Konfigurations Modus
    RESET(MCP2515_CS);
    spi_putc(SPI_RESET);

    _delay_ms(1);

    SET(MCP2515_CS);

    // ein bisschen warten bis der MCP2515 sich neu gestartet hat
    _delay_ms(10);

    // CNF1..3 Register laden (Bittiming)
    RESET(MCP2515_CS);
    spi_putc(SPI_WRITE);
    spi_putc(CNF3);
    for (uint8_t i=0; i<3 ;i++ ) {
        spi_putc(pgm_read_byte(&_mcp2515_cnf[bitrate][i]));
    }
    // aktivieren/deaktivieren der Interrupts
    spi_putc(MCP2515_INTERRUPTS);
    SET(MCP2515_CS);

    // TXnRTS Bits als Inputs schalten
    mcp2515_write_register(TXRTSCTRL, 0);

    #if defined(MCP2515_INT)
        SET_INPUT(MCP2515_INT);
        SET(MCP2515_INT);
    #endif

    #ifdef RXnBF_FUNKTION
        SET_INPUT(MCP2515_RX0BF);
        SET_INPUT(MCP2515_RX1BF);

        SET(MCP2515_RX0BF);
        SET(MCP2515_RX1BF);

        // Aktivieren der Pin-Funktionen fuer RX0BF und RX1BF
        mcp2515_write_register(BFPCTRL, (1<<B0BFE)|(1<<B1BFE)|(1<<B0BFM)|(1<<B1BFM));
    #else
        #ifdef MCP2515_TRANSCEIVER_SLEEP
            // activate the pin RX1BF as GPIO which is connected
            // to RS of MCP2551 and set it to 0
            mcp2515_write_register(BFPCTRL, (1<<B1BFE));
        #else
            // Deaktivieren der Pins RXnBF Pins (High Impedance State)
            mcp2515_write_register(BFPCTRL, 0);
        #endif
    #endif

    // Testen ob das auf die beschreibenen Register zugegriffen werden kann
    // (=> ist der Chip ueberhaupt ansprechbar?)
    bool error = false;
    if (mcp2515_read_register(CNF2) != pgm_read_byte(&_mcp2515_cnf[bitrate][1])) {
        error = true;
    }

    // Device zurueck in den normalen Modus versetzten
    // und aktivieren/deaktivieren des Clkout-Pins
    mcp2515_write_register(CANCTRL, CLKOUT_PRESCALER_);

    if (error) {
        return false;
    }
    else
    {
        while ((mcp2515_read_register(CANSTAT) & 0xe0) != 0) {
            // warten bis der neue Modus uebernommen wurde
        }

        return true;
    }
}
uint8_t mcp2515_get_filter(uint8_t number, can_filter_t *filter)
{
	uint8_t mask_address;
	uint8_t filter_address;
	uint8_t temp;
	uint8_t mode = mcp2515_read_register(CANSTAT);
	
	if (number > 5)
		return 0;
	
	// change to configuration mode
	mcp2515_change_operation_mode( (1<<REQOP2) );
	
	if (number <= 1)
	{
		mask_address = RXM0SIDH;
		temp = mcp2515_read_register(RXB0CTRL);
	}
	else
	{
		mask_address = RXM1SIDH;
		temp = mcp2515_read_register(RXB1CTRL);
	}
	
	temp &= (1<<RXM1)|(1<<RXM0);
	
	if (temp == 0) {
		// filter and masks are disabled
		#if SUPPORT_EXTENDED_CANID
		filter->flags.extended = 0;
		#endif
		filter->flags.rtr = 0;
		filter->mask = 0;
		filter->id = 0;
		
		return 1;
	}
	
	#if SUPPORT_EXTENDED_CANID
	// transform bits so that they match the format from can.h
	temp >>= 5;
	temp = ~temp;
	if (temp & 1) temp = 0x3;
	
	filter->flags.extended = temp;
	#endif
	
	// read mask
	RESET(MCP2515_CS);
	spi_putc(SPI_READ);
	spi_putc(mask_address);
	mcp2515_read_id(&filter->mask);
	SET(MCP2515_CS);
	
	if (number <= 2)
	{
		filter_address = RXF0SIDH + number * 4;
	}
	else
	{
		filter_address = RXF3SIDH + (number - 3) * 4;
	}
	
	// read filter
	RESET(MCP2515_CS);
	spi_putc(SPI_READ);
	spi_putc(filter_address);
	mcp2515_read_id(&filter->id);
	SET(MCP2515_CS);
	
	// restore previous mode
	mcp2515_change_operation_mode( mode );
	
	return 1;
}
Beispiel #6
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);
}
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;
}