Subversion Repositories HomeAutomation

Rev

Rev 73 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /**
  2.  * @file    mcp2510.c
  3.  * Low level drivers for the MCP2510 CAN controller. Target MCU is the ATmega8.
  4.  *
  5.  * @author  Jimmy Myhrman (jimmy@myhrman.org)
  6.  * @date    2005-11-28
  7.  */
  8.  
  9. /* -----------------------------------------------------------------------------
  10.  * Includes
  11.  * ---------------------------------------------------------------------------*/
  12. #include "mcp2510.h"
  13. #include "spi.h"
  14.  
  15. /* -----------------------------------------------------------------------------
  16.  * Functions
  17.  * ---------------------------------------------------------------------------*/
  18.  
  19. /**
  20.  * Initializes and resets the MCP controller.
  21.  */
  22. void MCP_init() {
  23.     SPI_master_init();
  24.     SPI_chip_select();
  25.     SPI_master_send(MCP_OP_RESET);  /* reset instruction */
  26.     SPI_chip_unselect();
  27.     volatile uint8_t counter;
  28.     for (counter=0; counter<128; counter++) {
  29.         /* wait a few cycles for reset to complete */
  30.         __asm("nop");
  31.     }
  32. }
  33.  
  34.  
  35. /**
  36.  * Writes a byte to an address in the MCP. The function waits till the byte
  37.  * has been written before it returns.
  38.  *
  39.  * @param value The data byte.
  40.  * @param address The address to which the data should be written in the MCP.
  41.  */
  42. void MCP_write(uint8_t value, uint8_t address) {
  43.     SPI_chip_select();
  44.     SPI_master_send(MCP_OP_WRITE);  /* write command */
  45.     SPI_master_send(address);   /* the address */
  46.     SPI_master_send(value);     /* the value */
  47.     SPI_chip_unselect();
  48. }
  49.  
  50.  
  51. /**
  52.  * Reads a byte from an address in the MCP.
  53.  *
  54.  * @param address The address from which the data should be read in the MCP.
  55.  * @return The byte read from the given address in the MCP.
  56.  */
  57. uint8_t MCP_read(uint8_t address) {
  58.     SPI_chip_select();
  59.     SPI_master_send(MCP_OP_READ);   /* read command */
  60.     SPI_master_send(address);   /* the address */
  61.     SPI_master_send(0xFF);      /* any byte (reception will occur simultaneously) */
  62.     uint8_t data = SPDR;        /* get the received byte */
  63.     SPI_chip_unselect();
  64.     return data;
  65. }
  66.  
  67.  
  68.  
  69.  
  70.  
  71. void mcp_write_can_id(uint8_t address, uint8_t ext, unsigned long can_id);
  72. void mcp_write_can(uint8_t buffer, uint8_t ext, unsigned long can_id,uint8_t dlc, uint8_t rtr, const uint8_t* data);
  73. void mcp_read_can(uint8_t buffer, uint8_t* ext, unsigned long* can_id,uint8_t* dlc, uint8_t* rtr, uint8_t* data);
  74. void mcp_read_can_id(uint8_t mcp_addr, uint8_t* ext, unsigned long* can_id);
  75. void mcp_write(uint8_t MCPaddr, const uint8_t* writedata, uint8_t length);
  76. void mcp_read(uint8_t MCPaddr, uint8_t* readdata, uint8_t length);
  77.  
  78.  
  79. #define SIDH        0
  80. #define SIDL        1
  81. #define EID8        2
  82. #define EID0        3
  83.  
  84. #define TXB_EXIDE_M     0x08    // In TXBnSIDL
  85. #define DLC_MASK        0x0F
  86. #define RTR_MASK        0x40
  87.  
  88. /*
  89.  ** Read one or more registers in the MCP2510, starting at address
  90.  ** readdata.
  91.  */
  92. void mcp_read(uint8_t MCPaddr, uint8_t* readdata, uint8_t length) {
  93.     uint8_t loopCnt;
  94.     SPI_chip_select();
  95.     // Start reading and set first address
  96.     SPI_master_send(MCP_OP_READ);
  97.     //SPI_mcp_RD_address(MCPaddr);
  98.     for (loopCnt=0; loopCnt < length; loopCnt++) {
  99.         // Get a byte and store at pointer
  100.         *readdata  = SPI_master_send(MCPaddr);
  101.         // Increment the pointers to next location
  102.         // Test++;
  103.         MCPaddr++;
  104.         readdata++;
  105.     }
  106.     SPI_chip_unselect();
  107. }
  108.  
  109.  
  110. /*
  111.  ** Write to one or more registers in the MCP2510, starting at address
  112.  ** writedata.
  113.  */
  114. void mcp_write(uint8_t MCPaddr, const uint8_t* writedata, uint8_t length) {
  115.     uint8_t loopCnt;
  116.     SPI_chip_select();
  117.     // Start write and set first address
  118.     //SPI_mcp_WR_address(MCPaddr);
  119.     SPI_master_send(MCPaddr);
  120.     for (loopCnt=0; loopCnt < length; loopCnt++) {
  121.         // Write a byte
  122.         //SPI_putch( *writedata  );
  123.         SPI_master_send(*writedata);
  124.         // Increment the pointer to next location
  125.         writedata++;
  126.     }
  127.     SPI_chip_unselect();
  128. }
  129.  
  130.  
  131. void mcp_read_can_id(uint8_t mcp_addr, uint8_t* ext, unsigned long* can_id) {
  132.     uint8_t tbufdata[4];
  133.     *ext = 0;
  134.     *can_id = 0;
  135.     mcp_read( mcp_addr, tbufdata, 4);
  136.     *can_id = (tbufdata[SIDH]<<3) + (tbufdata[SIDL]>>5);
  137.     if ( (tbufdata[SIDL] & TXB_EXIDE_M) ==  TXB_EXIDE_M ) {
  138.         *can_id = (*can_id<<2) + (tbufdata[SIDL] & 0x03);
  139.         *can_id <<= 16;
  140.         *can_id = *can_id +(tbufdata[EID8]<<8) + tbufdata[EID0];
  141.         *ext = 1;
  142.     }
  143. }
  144.  
  145.  
  146. // Buffer can be 4..5
  147. void mcp_read_can(uint8_t buffer, uint8_t* ext, unsigned long* can_id,uint8_t* dlc, uint8_t* rtr, uint8_t* data) {
  148.     uint8_t mcp_addr = buffer*16 + 0x21, ctrl;
  149.     mcp_read_can_id( mcp_addr, ext, can_id );
  150.     mcp_read( mcp_addr-1, &ctrl, 1 );
  151.     mcp_read( mcp_addr+4, dlc, 1 );
  152.     if (/*(*dlc & RTR_MASK) || */(ctrl & 0x08)) {
  153.         *rtr = 1;
  154.     } else {
  155.         *rtr = 0;
  156.     }
  157.     *dlc &= DLC_MASK;
  158.     mcp_read( mcp_addr+5, data, *dlc );
  159. }
  160.  
  161.  
  162. void mcp_write_can(uint8_t buffer, uint8_t ext, unsigned long can_id,uint8_t dlc, uint8_t rtr, const uint8_t* data) {
  163.     uint8_t mcp_addr = buffer*16 + 0x21;
  164.     mcp_write(mcp_addr+5, data, dlc );  // write data bytes
  165.     mcp_write_can_id( mcp_addr, ext, can_id );  // write CAN id
  166.     if ( rtr == 1)  dlc |= RTR_MASK;  // if RTR set bit in byte
  167.     mcp_write((mcp_addr+4), &dlc, 1 );            // write the RTR and DLC
  168. }
  169.  
  170.  
  171. void mcp_write_can_id(uint8_t address, uint8_t ext, unsigned long can_id) {
  172.     unsigned int canid;
  173.     uint8_t tbufdata[4];
  174.     canid = (unsigned int)(can_id & 0x0FFFF);
  175.     if (ext == 1) {
  176.         tbufdata[EID0] = (uint8_t) (canid & 0xFF);
  177.         tbufdata[EID8] = (uint8_t) (canid / 256);
  178.         canid = (unsigned int)(can_id / 0x10000L);
  179.         tbufdata[SIDL] = (uint8_t) (canid & 0x03);
  180.         tbufdata[SIDL] += (uint8_t) ((canid & 0x1C )*8);
  181.         tbufdata[SIDL] |= TXB_EXIDE_M;
  182.         tbufdata[SIDH] = (uint8_t) (canid / 32 );
  183.     }
  184.     else {
  185.         tbufdata[SIDH] = (uint8_t)(canid / 8 );
  186.         tbufdata[SIDL] = (uint8_t)((canid & 0x07 )*32);
  187.         tbufdata[EID0] = 0;
  188.         tbufdata[EID8] = 0;
  189.     }
  190.     mcp_write(address, tbufdata, 4 );
  191. }