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);
}
Exemplo n.º 2
0
void mcp2515_write_register(uint8_t adress, uint8_t data )
{
	RESET(MCP2515_CS);
	spi_putc(SPI_WRITE);
	spi_putc(adress);
	spi_putc(data);
	SET(MCP2515_CS);
}
Exemplo n.º 3
0
// -------------------------------------------------------------------------
void mcp2515_bit_modify(uint8_t adress, uint8_t mask, uint8_t data)
{
	RESET(MCP2515_CS);
	
	spi_putc(SPI_BIT_MODIFY);
	spi_putc(adress);
	spi_putc(mask);
	spi_putc(data);
	
	SET(MCP2515_CS);
}
Exemplo n.º 4
0
// ----------------------------------------------------------------------------
uint8_t mcp2515_read_status(uint8_t type)
{
	uint8_t data;
	
	RESET(MCP2515_CS);
	
	spi_putc(type);
	data = spi_putc(0xff);
	
	SET(MCP2515_CS);
	
	return data;
}
Exemplo n.º 5
0
/**
 * \brief  write to MCP2515 registers
 *
 * \param  chip      - select chip to use
 * \param  address   - register address of MCP2515
 * \param  data      - data byte
 */
void write_register_mcp2515(eChipSelect   chip,
                            uint8_t       address,
                            uint8_t       data)
{
   // /CS of MCP2515 to Low
   unset_chip_select(chip);

   spi_putc(MCP2515_WRITE);
   spi_putc(address);
   spi_putc(data);

   // /CS of MCP2515 to High
   set_chip_select(chip);
}
Exemplo n.º 6
0
// -------------------------------------------------------------------------
uint8_t mcp2515_read_register(uint8_t adress)
{
	uint8_t data;
	
	RESET(MCP2515_CS);
	
	spi_putc(SPI_READ);
	spi_putc(adress);
	
	data = spi_putc(0xff);	
	
	SET(MCP2515_CS);
	
	return data;
}
Exemplo n.º 7
0
/* Configures the nRF2401 with the given number of bytes (1 - 15) of
   configuration data.  */
static void
nrf_configure (nrf_t nrf, uint8_t size)
{
    nrf_obj_t *dev = nrf;
    uint8_t i;

    /* Put the nRF2401 into configuration mode.  */
    NRF_CE_LOW_SET (dev);
    NRF_CS_HIGH_SET (dev);

    DELAY_US (NRF_LINE_TIME_ENABLE_US);

    /* Decrementing logic is to ensure data is clocked out MSB first.  */
    for (i = size; i > 0; i--)
    {
        /* Write to the SPI port.  */
        spi_putc (dev->spi, dev->config.bytes[i - 1]);
    }

    DELAY_US (NRF_CONFIG_DELAY_US);
    
    /* Put the chip into standby mode.  */
    NRF_CS_LOW_SET (dev);
    
    DELAY_US (NRF_LINE_TIME_ENABLE_US);
}
Exemplo n.º 8
0
/**
 * \brief  write masked bits to MCP2515 registers
 *
 * Note: Not all registers are able to provide this functionality. Mostly
 *       configuration registers do. Read the datasheet for details.
 *
 * \param  chip      - select chip to use
 * \param  address   - register address of MCP2515
 * \param  mask      - bit mask for modify
 * \param  data      - data byte
 */
void bit_modify_mcp2515(eChipSelect chip,
                        uint8_t     address,
                        uint8_t     mask,
                        uint8_t     data)
{
   // /CS of MCP2515 to Low
   unset_chip_select(chip);

   spi_putc(MCP2515_BITMODIFY);
   spi_putc(address);
   spi_putc(mask);
   spi_putc(data);

   // /CS of MCP2515 to High
   set_chip_select(chip);
}
Exemplo n.º 9
0
uint8_t mcp2515_read_id(uint32_t *id)
{
	uint8_t first;
	uint8_t tmp;
	
	first = spi_putc(0xff);
	tmp   = spi_putc(0xff);
	
	if (tmp & (1 << IDE)) {
	  // Nur Extended IDs empfangen
		*((uint16_t *) id + 1)  = (uint16_t) first << 5;
		*((uint8_t *)  id + 1)  = spi_putc(0xff);
		*((uint8_t *)  id + 2) |= (tmp >> 3) & 0x1C;
		*((uint8_t *)  id + 2) |=  tmp & 0x03;
		*((uint8_t *)  id)      = spi_putc(0xff);
		return TRUE;
	} else {
Exemplo n.º 10
0
/**
 * \brief  reads MCP2515 status registers
 *
 * \param  chip    - select chip to use
 * \param  command - read quick status command of MCP2515
 * \return value of status register
 */
uint8_t read_status_mcp2515(eChipSelect  chip,
                            uint8_t      command)
{
   uint8_t data;

   // /CS of MCP2515 to Low
   unset_chip_select(chip);

   // status commend to use
   spi_putc(command);
   // write something to SPI, so the byte can be read from SPI
   data = spi_putc(0xFF);

   // /CS of MCP2515 to High
   set_chip_select(chip);

   return (data);
}
Exemplo n.º 11
0
/**
 * \brief  read from MCP2515 registers
 *
 * \param  chip      - select chip to use
 * \param  address   - register address of MCP2515
 * \return data      - data byte
 */
uint8_t read_register_mcp2515(eChipSelect chip,
                              uint8_t     address)
{
   uint8_t data;

   // /CS of MCP2515 to Low
   unset_chip_select(chip);

   spi_putc(MCP2515_READ);
   spi_putc(address);
   // write something to SPI, so the byte can be read from SPI
   data = spi_putc(0xFF);

   // /CS of MCP2515 to High
   set_chip_select(chip);

   return (data);
}
Exemplo n.º 12
0
/**
 * \brief  write sequential to MCP2515 registers
 *
 * \param  chip      - select chip to use
 * \param  length    - length of buffer
 * \param  address   - register address of MCP2515 (start)
 * \param  data      - data buffer
 */
void write_multi_registers_mcp2515(eChipSelect   chip,
                                   uint8_t       length,
                                   uint8_t       address,
                                   uint8_t*      data)
{
   uint8_t i;

   // /CS of MCP2515 to Low
   unset_chip_select(chip);

   spi_putc(MCP2515_WRITE);
   spi_putc(address);
   for(i = 0; i < length; ++i)
   {
      spi_putc(data[i]);
   }

   // /CS of MCP2515 to High
   set_chip_select(chip);
}
Exemplo n.º 13
0
void mcp2515_write_id(const uint32_t *id, uint8_t extended)
{
	uint8_t tmp;
	
	if (extended) {
		spi_start(*((uint16_t *) id + 1) >> 5);
		
		// naechsten Werte berechnen
		tmp  = (*((uint8_t *) id + 2) << 3) & 0xe0;
		tmp |= (1 << IDE);
		tmp |= (*((uint8_t *) id + 2)) & 0x03;
		
		// warten bis der vorherige Werte geschrieben wurde
		spi_wait();
		
		// restliche Werte schreiben
		spi_putc(tmp);
		spi_putc(*((uint8_t *) id + 1));
		spi_putc(*((uint8_t *) id));
	}
	else {
Exemplo n.º 14
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;
}
Exemplo n.º 15
0
void mcp2515_init(void)
{
	// Aktivieren der Pins fuer das SPI Interface
	PORT_SPI &=  ~((1 << PIN_NUM(P_SCK)) | (1 << PIN_NUM(P_MOSI)));
	DDR_SPI |= (1 << PIN_NUM(P_SCK)) | (1 << PIN_NUM(P_MOSI));
	
	SET(MCP2515_CS);
	SET_OUTPUT(MCP2515_CS);
	
	// Aktivieren des SPI Master Interfaces
	SPCR = (1 << SPE) | (1 << MSTR) | R_SPCR;
	SPSR = R_SPSR;
	
	_delay_us(1);
	
	// MCP2515 per Software Reset zuruecksetzten,
	// danach ist er automatisch im Konfigurations Modus
	RESET(MCP2515_CS);
	spi_putc(SPI_RESET);
	SET(MCP2515_CS);
	
	// ein bisschen warten bis der MCP2515 sich neu gestartet hat
	_delay_ms(0.1);
	
	// Filter usw. setzen
	RESET(MCP2515_CS);
	spi_putc(SPI_WRITE);
	spi_putc(RXF0SIDH);
	for (uint8_t i = 0; i < sizeof(mcp2515_register_map); i++) {
		spi_putc(pgm_read_byte(&mcp2515_register_map[i]));
	}
	SET(MCP2515_CS);
	
	// nur Standard IDs, Message Rollover nach Puffer 1
	mcp2515_write_register(RXB0CTRL, (0 << RXM1) | (1 << RXM0) | (1 << BUKT));
	mcp2515_write_register(RXB1CTRL, (0 << RXM1) | (1 << RXM0));
	
	// MCP2515 zurueck in den normalen Modus versetzten
	mcp2515_write_register(CANCTRL, CLKOUT_PRESCALER_);
}
Exemplo n.º 16
0
uint8_t mcp2515_read_id(uint32_t *id)
{
	uint8_t first;
	uint8_t tmp;
	
	first = spi_putc(0xff);
	tmp   = spi_putc(0xff);
	
	if (tmp & (1 << IDE)) {
		spi_start(0xff);
		
		*((uint16_t *) id + 1)  = (uint16_t) first << 5;
		*((uint8_t *)  id + 1)  = spi_wait();
		spi_start(0xff);
		
		*((uint8_t *)  id + 2) |= (tmp >> 3) & 0x1C;
		*((uint8_t *)  id + 2) |=  tmp & 0x03;
		
		*((uint8_t *)  id)      = spi_wait();
		
		return TRUE;
	}
Exemplo n.º 17
0
uint8_t mcp2515_read_id(uint32_t *id)
{
	uint8_t first;
	uint8_t tmp;
	uint8_t spi_temp;
	
	first = spi_putc(0xff);
	tmp   = spi_putc(0xff);
	
	if (tmp & (1 << IDE)) {
		spi_temp = spi_putc(0xff);

		*((uint16_t *) id + 1)  = (uint16_t) first << 5;
		*((uint8_t *)  id + 1)  = spi_temp;

		spi_temp = spi_putc(0xff);
		
		*((uint8_t *)  id + 2) |= (tmp >> 3) & 0x1C;
		*((uint8_t *)  id + 2) |=  tmp & 0x03;
		
		*((uint8_t *)  id)      = spi_temp;
		
		return (1);
	}
Exemplo n.º 18
0
// ----------------------------------------------------------------------------
uint8_t mcp2515_send_message(tCAN *message)
{
	uint8_t status = mcp2515_read_status(SPI_READ_STATUS);
	
	/* Statusbyte:
	 *
	 * Bit	Function
	 *  2	TXB0CNTRL.TXREQ
	 *  4	TXB1CNTRL.TXREQ
	 *  6	TXB2CNTRL.TXREQ
	 */
	uint8_t address;
	uint8_t t;
//	SET(LED2_HIGH);
	if (bit_is_clear(status, 2)) {
		address = 0x00;
	}
	else if (bit_is_clear(status, 4)) {
		address = 0x02;
	} 
	else if (bit_is_clear(status, 6)) {
		address = 0x04;
	}
	else {
		// all buffer used => could not send message
		return 0;
	}
	
	RESET(MCP2515_CS);
	spi_putc(SPI_WRITE_TX | address);
	
	spi_putc(message->id >> 3);
    spi_putc(message->id << 5);
	
	spi_putc(0);
	spi_putc(0);
	
	uint8_t length = message->header.length & 0x0f;
	
	if (message->header.rtr) {
		// a rtr-frame has a length, but contains no data
		spi_putc((1<<RTR) | length);
	}
	else {
		// set message length
		spi_putc(length);
		
		// data
		for (t=0;t<length;t++) {
			spi_putc(message->data[t]);
		}
	}
	SET(MCP2515_CS);
	
	_delay_us(1);
	
	// send message
	RESET(MCP2515_CS);
	address = (address == 0) ? 1 : address;
	spi_putc(SPI_RTS | address);
	SET(MCP2515_CS);
	
	return address;
}
Exemplo n.º 19
0
/* Transmit a packet in ShockBurst mode without any retransmission.  */
uint8_t
nrf_transmit (nrf_t nrf, nrf_node_t *node, void *buffer, uint8_t len)
{
    nrf_obj_t *dev = nrf;
    uint8_t i;
    uint8_t length;
    uint16_t packet_length;
    uint8_t *data = buffer;
    uint8_t delay;

    /* Changing channel requires a one byte configure.  */
    nrf_channel_set (dev, node->tx.channel);

    /* Changing direction requires a one byte configure.  */
    nrf_dir_set (dev, NRF_TX_MODE);

    nrf_configure (dev, 1);

    /* Clock out a packet to the nRF chip, with zero-padding if len is
       less than the packet length.  */

    /* Set the chip enable pin high to begin clocking in data.  */
    NRF_CE_HIGH_SET (dev);

    DELAY_US (NRF_LINE_TIME_ENABLE_US);

    /* Set length to address length in bytes.  */
    length = (dev->config.bits.addr_w / CHAR_BIT);

    /* Clock out address.  */
    for (i = length; i > 0; i--)
        spi_putc (dev->spi, node->tx.address.bytes[i - 1]);

    /* Set length to payload length in bytes.  */
    length = (dev->config.bits.data1_w / CHAR_BIT);

    /* Clock out data.  */
    for (i = 0; i < len; i++)
        spi_putc (dev->spi, data[i]);

    /* If size is smaller than the payload length, append zeros.  */
    if (len < length)
    {
        for (i = 0; i < (length - len); i++)
            spi_putc (dev->spi, 0);
    }

    /* Set the chip enable pin low to transmit data and return to
       standby mode.  */
    NRF_CE_LOW_SET (dev);

    /* Delay to allow chip to enter ShockBurst mode.  */
    DELAY_US (NRF_T_SB_ACTIVE);

    /* Delay to allow for transmission time.  */
    
    /* Transmission delay time depends on many factors.  */
    /* The packet length = address length + data length + crc.  */
    packet_length = ((dev->config.bits.addr_w) + (dev->config.bits.data1_w));
    /* If CRC is enabled, add its length on.  */
    if (dev->config.bits.crc_en == NRF_CRC_ENABLED)
    {
        if (dev->config.bits.crc_l == NRF_CRC_8) /* 8-bit CRC enabled.  */
        {
            packet_length += 8;
        }
        else /* 16-bit CRC enabled.  */
        {
            packet_length += 16;
        }
    }

    /* If data rate = 1Mbit/s, delay for a number of microseconds
       equal to the packet length.  Otherwise, if data rate = 250kbps,
       delay for 4 times as long.  Now we don't want to calculate
       microsecond delays since this requires floating point
       arithmetic.  */
    delay = packet_length;
    if (dev->config.bits.rfdr_sb != NRF_DATA_1M)
        delay <<= 2;
    while (delay)
    {
        DELAY_US (1);
        delay--;
    }

    /* The chip automatically returns to standby mode after transmission.  */
    
    return len;
}
Exemplo n.º 20
0
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
}
Exemplo n.º 21
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;
}
Exemplo n.º 22
0
// ----------------------------------------------------------------------------
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;
}
Exemplo n.º 23
0
/**
 * \brief  initializes MCP2515 selected
 *
 * \par Clock Speed
 * All MCP2515 connected to AVR need to have the same clock speed when
 * using the same bitrate! See array in can_init_mcp2515.c.
 *
 * \par SPI
 * MCP2515 init routine does NOT initializes SPI. This has to be done before.
 *
 * \par Filters
 * The filters are cleared here, to allow simply every CAN message to be
 * received, which is for testing purposes the right choice. Any special
 * filter needs to be set up by the main program. The mode of operation needs
 * to be the configuration mode for that.
 *
 * \param  chip      - select chip to use
 * \param  bitrate   - CAN bitrate of chip selected
 * \param  mode      - mode of operation of MCP2515 after init
 * \return true if ok, false if error
 */
bool can_init_mcp2515(eChipSelect chip,
                      eCanBitRate bitrate,
                      uint8_t mode)
{
   bool retVal = false;
   uint8_t *cnf = 0;

   if ((bitrate < NUM_OF_CAN_BITRATES) && (chip < NUM_OF_MCP2515))
   {
      cnf = getCanConfiguration(bitrate);

      // set interrupt pins
      setup_interrupt_pins(chip);
      // set chip select pins
      setup_cs_pins(chip);
      // wait for MCP2515 to get pin status
      _delay_ms(10);

      // software reset MCP2515 to change it to configuration mode
      unset_chip_select(chip);
      spi_putc(MCP2515_RESET);
      _delay_ms(1);  // wait a little bit
      set_chip_select(chip);
      // wait for MCP2515 to reset itself
      _delay_ms(10);

      // setup configuration registers
      write_register_mcp2515(chip, CNF1, cnf[0]);
      write_register_mcp2515(chip, CNF2, cnf[1]);
      write_register_mcp2515(chip, CNF3, cnf[2]);

      // test if MCP2515 is accessible and CNF set up correctly
      if(read_register_mcp2515(chip, CNF1) != cnf[0])
      {
         return false;
      }

      // assume it works
      retVal = true;

      // initialize RX interrupts
      write_register_mcp2515(chip, CANINTE, (1<<RX1IE) | (1<<RX0IE));

#ifdef ___MASTER_CAN_CLKOUT_ENABLE___
      // init CLKOUT on master CAN
      if(CAN_CHIP1 == chip)
      {  // prescaler is CLKPREx = 00 -> fosc/1
         bit_modify_mcp2515(chip, CANCTRL(0), (1 << CLKEN), (1 << CLKEN));
      }
#endif

      // clear filters: Now all messages are received. Any other filters need
      // to be set up by main program.
      clear_filters(chip);

      // setup PIN functions
      // deactivate RX0BF pin and set to high impedance state;
      // set RX1BF to digital output (0) for MCP2551 sleep mode control
      write_register_mcp2515(chip, BFPCTRL, (1 << B1BFE));
      // setup TXnRTS pins as input
      write_register_mcp2515(chip, TXRTSCTRL, 0);
      // set MCP2515 into normal operations mode (no longer configurable)
      set_mode_mcp2515(chip, mode);
   }

   return(retVal);
}
Exemplo n.º 24
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;
}
Exemplo n.º 25
0
static void spi_start(uint8_t data) {
	usi_interface_spi_temp = spi_putc(data);
}
Exemplo n.º 26
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;
    }
}
Exemplo n.º 27
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);
	};
};
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;
}
Exemplo n.º 29
0
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;
}