Subversion Repositories HomeAutomation

Rev

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

  1. /******************************************************************************
  2.  *
  3.  * Controller Area Network (CAN) Demo-Application
  4.  * Atmel AVR with Microchip MCP2515
  5.  *
  6.  * Copyright (C) 2005 Martin THOMAS, Kaiserslautern, Germany
  7.  * <eversmith@heizung-thomas.de>
  8.  * http://www.siwawi.arubi.uni-kl.de/avr_projects
  9.  *
  10.  *****************************************************************************
  11.  *
  12.  * File    : mcp2515.c
  13.  * Version : 0.9
  14.  *
  15.  * Summary : MCP2515 "low-level" driver
  16.  *
  17.  * Parts of this code are adapted from a MCP2510 sample-application
  18.  * by KVASER AB, http://www.kvaser.com (KVASER-code is marked as free)
  19.  *
  20.  * This code-module is free to use but you have to keep the copyright
  21.  * notice.
  22.  *
  23.  *****************************************************************************/
  24.  
  25. #include <inttypes.h>
  26. #include <stdio.h>
  27. #include <avr/io.h>
  28. #include "mcp2515.h"
  29. #include "mcp2515_defs.h"
  30. #include "mcp2515_bittime.h"
  31.  
  32. #include "can.h"
  33.  
  34.  
  35. #define SPI_PORT    PORTB
  36. #define SPI_PIN     PINB
  37. #define SPI_DDR     DDRB
  38.  
  39. #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__)
  40.     #define SPI_SCK   PB5  
  41.     #define SPI_MISO  PB4
  42.     #define SPI_MOSI  PB3  
  43.     #define SPI_SS    PB2
  44. #elif defined(__AVR_ATmega32__) || defined(__AVR_ATmega16__)
  45.     #define SPI_SCK   PB7
  46.     #define SPI_MISO  PB6
  47.     #define SPI_MOSI  PB5  
  48.     #define SPI_SS    PB4
  49. #else
  50.     #error "SPI pins undefined for this target (see spi.h)"
  51. #endif
  52.  
  53. #define SPI_SS_HIGH()   (SPIPORT |= (1<<SPISS))
  54. #define SPI_SS_LOW()    (SPIPORT &= ~(1<<SPISS))
  55.  
  56. static void SPI_Init(void);
  57. static uint8_t SPI_ReadWrite(uint8_t data);
  58. static uint8_t SPI_Read(void);
  59.  
  60. #define SPI_DONTCARE (0x00)
  61.  
  62. /* init as SPI-Master */
  63. static void SPI_Init(void) {
  64.     /* SCK, SS!!, MOSI as outputs */
  65.     SPI_DDR |= (1<<SPI_SCK) | (1<<SPI_SS) | (1<<SPI_MOSI);
  66.     /* MISO as input */
  67.     SPI_DDR &= ~(1<<SPI_MISO);
  68.     /* INIT interface, Master, set clock rate fck/4 */
  69.     SPCR = (1<<SPE)|(1<<MSTR)|(0<<SPR0)|(0<<SPR1);
  70.     /* enable double rate */
  71.     SPSR = (1<<SPI2X); /* we will now gain fck/2 instead of fck/4 */
  72. }
  73.  
  74. static uint8_t SPI_ReadWrite(uint8_t data) {
  75.     /* set data to send into SPI data register */
  76.     SPDR = data;
  77.     /* Wait for transmission complete */
  78.     while(!(SPSR & (1<<SPIF)));
  79.     /* return data read from SPI (if any) */
  80.     return SPDR;
  81. }
  82.  
  83. static uint8_t SPI_Read(void) {
  84.     return SPI_ReadWrite(SPI_DONTCARE);
  85. }
  86.  
  87.  
  88. void MCP2515_Reset(void) {
  89.     MCP2515_SELECT();
  90.     SPI_ReadWrite(MCP_RESET);
  91.     MCP2515_UNSELECT();
  92.     /* delay at least 128 MCP clock cycles */
  93.     volatile int16_t i;
  94.     for (i=0; i<32000; i++) {
  95.         if (i < 0) break;
  96.     }
  97. }
  98.  
  99. uint8_t MCP2515_ReadRegister(const uint8_t address) {
  100.     uint8_t ret;
  101.    
  102.     MCP2515_SELECT();
  103.     SPI_ReadWrite(MCP_READ);
  104.     SPI_ReadWrite(address);
  105.     ret = SPI_Read();
  106.     MCP2515_UNSELECT();
  107.    
  108.     return ret;
  109. }
  110.  
  111. void MCP2515_ReadRegisterS(const uint8_t address, uint8_t values[], const uint8_t n) {
  112.     uint8_t i;
  113.    
  114.     MCP2515_SELECT();
  115.     SPI_ReadWrite(MCP_READ);
  116.     SPI_ReadWrite(address);
  117.     // mcp2515 has auto-increment of address-pointer
  118.     for (i=0; i<n; i++) {
  119.         values[i] = SPI_Read();
  120.     }
  121.     MCP2515_UNSELECT();
  122. }
  123.  
  124. void MCP2515_SetRegister(const uint8_t address, const uint8_t value) {
  125.     MCP2515_SELECT();
  126.     SPI_ReadWrite(MCP_WRITE);
  127.     SPI_ReadWrite(address);
  128.     SPI_ReadWrite(value);
  129.     MCP2515_UNSELECT();
  130. }
  131.  
  132. void MCP2515_SetRegisterS(const uint8_t address, const uint8_t values[], const uint8_t n) {
  133.     uint8_t i;
  134.    
  135.     MCP2515_SELECT();
  136.     SPI_ReadWrite(MCP_WRITE);
  137.     SPI_ReadWrite(address);
  138.     // mcp2515 has auto-increment of address-pointer
  139.     for (i=0; i<n; i++) {
  140.         SPI_ReadWrite(values[i]);
  141.     }
  142.     MCP2515_UNSELECT();
  143. }
  144.  
  145. void MCP2515_ModifyRegister(const uint8_t address, const uint8_t mask, const uint8_t data) {
  146.     MCP2515_SELECT();
  147.     SPI_ReadWrite(MCP_BITMOD);
  148.     SPI_ReadWrite(address);
  149.     SPI_ReadWrite(mask);
  150.     SPI_ReadWrite(data);
  151.     MCP2515_UNSELECT();
  152. }
  153.  
  154. static uint8_t MCP2515_ReadXXStatus_Helper(const uint8_t cmd) {
  155.     uint8_t i;
  156.    
  157.     MCP2515_SELECT();
  158.     SPI_ReadWrite(cmd);
  159.     i = SPI_Read();
  160.     MCP2515_UNSELECT();
  161.    
  162.     return i;
  163. }
  164.    
  165. uint8_t MCP2515_ReadStatus(void) {
  166.     return MCP2515_ReadXXStatus_Helper(MCP_READ_STATUS);
  167. }
  168.  
  169. uint8_t MCP2515_RxStatus(void) {
  170.     return MCP2515_ReadXXStatus_Helper(MCP_RX_STATUS);
  171. }
  172.  
  173. uint8_t MCP2515_SetCanCtrlMode(const uint8_t newmode) {
  174.     uint8_t i;
  175.     MCP2515_ModifyRegister(MCP_CANCTRL, MODE_MASK, newmode);
  176.     // verify as advised in datasheet
  177.     i = MCP2515_ReadRegister(MCP_CANCTRL);
  178.     i &= MODE_MASK;
  179.     if ( i == newmode ) {
  180.         return MCP2515_OK;
  181.     }
  182.     else {
  183.         return MCP2515_FAIL;
  184.     }
  185. }
  186.  
  187. uint8_t MCP2515_SetClkout(const uint8_t newmode) {
  188.     uint8_t i;
  189.     MCP2515_ModifyRegister(MCP_CANCTRL, CLK_MASK, newmode);
  190.     // verify, perhaps not needed?
  191.     i = MCP2515_ReadRegister(MCP_CANCTRL);
  192.     i &= CLK_MASK;
  193.     if ( i == newmode ) {
  194.         return MCP2515_OK;
  195.     }
  196.     else {
  197.         return MCP2515_FAIL;
  198.     }
  199. }
  200.  
  201.  
  202. uint8_t MCP2515_ConfigRate(const Can_Bitrate_t canBitrate) {
  203.     uint8_t set, cfg1, cfg2, cfg3;
  204.    
  205.     set = 0;
  206.    
  207.     switch (canBitrate) {
  208.         case (CAN_BITRATE_125K) :
  209.             cfg1 = MCP_125KBPS_CFG1;
  210.             cfg2 = MCP_125KBPS_CFG2;
  211.             cfg3 = MCP_125KBPS_CFG3;
  212.             set = 1;
  213.             break;
  214.         case (CAN_BITRATE_250K) :
  215.             cfg1 = MCP_250KBPS_CFG1;
  216.             cfg2 = MCP_250KBPS_CFG2;
  217.             cfg3 = MCP_250KBPS_CFG3;
  218.             set = 1;
  219.             break;
  220.         case (CAN_BITRATE_500K) :
  221.             cfg1 = MCP_500KBPS_CFG1;
  222.             cfg2 = MCP_500KBPS_CFG2;
  223.             cfg3 = MCP_500KBPS_CFG3;
  224.             set = 1;
  225.             break;
  226.         /* 1000kbit/s only available with clock freqs above 8MHz */
  227.         #if MCP_CLOCK_FREQ_MHZ > 8
  228.         case (CAN_BITRATE_1M) :
  229.             cfg1 = MCP_1000KBPS_CFG1;
  230.             cfg2 = MCP_1000KBPS_CFG2;
  231.             cfg3 = MCP_1000KBPS_CFG3;
  232.             set = 1;
  233.             break;
  234.         #endif
  235.         default:
  236.             set = 0;
  237.             break;
  238.     }
  239.    
  240.     if (set) {
  241.         MCP2515_SetRegister(MCP_CNF1, cfg1);
  242.         MCP2515_SetRegister(MCP_CNF2, cfg2);
  243.         MCP2515_SetRegister(MCP_CNF3, cfg3);
  244.         return MCP2515_OK;
  245.     }
  246.     else {
  247.         return MCP2515_FAIL;
  248.     }
  249. }
  250.  
  251.  
  252. /**
  253.  * Reads a CAN message from the specified buffer base address in the MCP2515. The message
  254.  * is stored in the following format:
  255.  *
  256.  *      BASE+0:
  257.  *      | SID10 | SID9  | SID8  | SID7  | SID6  | SID5  | SID4  | SID3  |
  258.  *     
  259.  *      BASE+1:
  260.  *      | SID2  | SID1  | SID0  | SRR   | IDE   |       | EID17 | EID16 |
  261.  *     
  262.  *      BASE+2:
  263.  *      | EID15 | EID14 | EID13 | EID12 | EID11 | EID10 | EID9  | EID8  |
  264.  *     
  265.  *      BASE+3:
  266.  *      | EID7  | EID6  | EID5  | EID4  | EID3  | EID2  | EID1  | EID0  |
  267.  *     
  268.  *      BASE+4:
  269.  *      |       |  RTR  |  RB1  |  RB0  | DLC3  | DLC2  | DLC1  | DCL0  |
  270.  *     
  271.  *      BASE+5 - BASE+12:
  272.  *      DATA0 - DATA7
  273.  *
  274.  * @param buffer_sidh_addr
  275.  *      Base address to the RX buffer.
  276.  *
  277.  * @param msg
  278.  *      Pointer to the message buffer into which the data should be copied.
  279.  *
  280.  */
  281. void MCP2515_ReadCanMsg(const uint8_t buffer_sidh_addr, Can_Message_t* msg) {
  282.     uint8_t tbufdata[13];
  283.     uint8_t mcp_addr;
  284.     mcp_addr = buffer_sidh_addr;
  285.    
  286.     /* read ID */
  287.     MCP2515_ReadRegisterS(mcp_addr, tbufdata, 13);
  288.    
  289.     /* extract SID10-SID0 */
  290.     msg->Id = 0;
  291.     msg->Id = (((uint32_t)(tbufdata[0])) << 3) + (((uint32_t)(tbufdata[1] & 0xE0)) >> 5);
  292.    
  293.     if ((tbufdata[1] & MCP_TXB_EXIDE_M) != 0) {
  294.         /* extended message */
  295.         msg->ExtendedFlag = 1;
  296.         /* SID10-SID0 are still most significant, so shift them up
  297.          * and make room for 18 extended least significant EID-bits */
  298.         msg->Id = (uint32_t)(msg->Id) << 18;
  299.         /* exctract EID17-EID16 */
  300.         msg->Id = (uint32_t)msg->Id | ((uint32_t)(((uint32_t)(tbufdata[1] & 0x03))<<16));
  301.         /* extract EID15-EID8 */
  302.         msg->Id |= (((uint32_t)tbufdata[2])<<8);
  303.         /* extract EID7-EID0 */
  304.         msg->Id |= ((uint32_t)tbufdata[3]);
  305.         /* mask ID to guarantee 29bit range */
  306.         msg->Id &= 0x1FFFFFFF;
  307.     }
  308.     else {
  309.         /* standard message */
  310.         msg->ExtendedFlag = 0;
  311.         /* mask ID to guarantee 11bit range */
  312.         msg->Id &= 0x000007FF;
  313.     }
  314.    
  315.     /* extract DLC */
  316.     msg->DataLength = tbufdata[4] & 0x0F;
  317.     if (msg->DataLength > 8) msg->DataLength = 8;   /* saturate DLC to guarantee 0-8 range */
  318.    
  319.     /* check RTR flag */
  320.     if (tbufdata[4] & 0x40) {
  321.         msg->RemoteFlag = 1;
  322.     } else {
  323.         msg->RemoteFlag = 0;
  324.     }
  325.    
  326.     /* copy data */
  327.     for (uint8_t i=0; i<msg->DataLength; i++) {
  328.         msg->Data.bytes[i] = tbufdata[5+i];
  329.     }
  330. }
  331.  
  332.  
  333.  
  334. void MCP2515_WriteCanId(const uint8_t mcp_addr, const uint8_t ext, const uint32_t can_id) {
  335.     uint16_t canid;
  336.     uint8_t tbufdata[4];
  337.     canid = (uint16_t)(can_id & 0x0FFFF);
  338.    
  339.     if (ext == 1) {
  340.         tbufdata[3] = (uint8_t) (canid & 0xFF);
  341.         tbufdata[2] = (uint8_t) (canid / 256);
  342.         canid = (uint16_t)( can_id / 0x10000L );
  343.         tbufdata[1] = (uint8_t) (canid & 0x03);
  344.         tbufdata[1] += (uint8_t) ((canid & 0x1C )*8);
  345.         tbufdata[1] |= MCP_TXB_EXIDE_M;
  346.         tbufdata[0] = (uint8_t) (canid / 32 );
  347.     }
  348.     else {
  349.         tbufdata[0] = (uint8_t) (canid / 8 );
  350.         tbufdata[1] = (uint8_t) ((canid & 0x07 )*32);
  351.         tbufdata[2] = 0;
  352.         tbufdata[3] = 0;
  353.     }
  354.     MCP2515_SetRegisterS(mcp_addr, tbufdata, 4);
  355. }
  356.  
  357. // Buffer can be MCP_TXBUF_0 MCP_TXBUF_1 or MCP_TXBUF_2
  358. void MCP2515_WriteCanMsg( const uint8_t buffer_sidh_addr, const Can_Message_t* msg) {
  359.     uint8_t mcp_addr, dlc;
  360.     mcp_addr = buffer_sidh_addr;
  361.     dlc = msg->DataLength;
  362.     MCP2515_SetRegisterS(mcp_addr+5, &(msg->Data.bytes[0]), dlc);  // write data bytes
  363.     MCP2515_WriteCanId(mcp_addr, msg->ExtendedFlag, msg->Id);  // write CAN id
  364.     if (msg->RemoteFlag == 1)  dlc |= MCP_RTR_MASK;  // if RTR set bit in byte
  365.     MCP2515_SetRegister((mcp_addr+4), dlc);  // write the RTR and DLC
  366. }
  367.  
  368. /*
  369.  ** Start the transmission from one of the tx buffers.
  370.  */
  371. // Buffer can be MCP_TXBUF_0 MCP_TXBUF_1 or MCP_TXBUF_2
  372. void MCP2515_StartTransmit(const uint8_t buffer_sidh_addr) {
  373.     // TXBnCTRL_addr = TXBnSIDH_addr - 1
  374.     MCP2515_ModifyRegister( buffer_sidh_addr-1 , MCP_TXB_TXREQ_M, MCP_TXB_TXREQ_M );
  375. }
  376.  
  377. uint8_t MCP2515_GetNextFreeTXBuf(uint8_t *txbuf_n) {
  378.     uint8_t res, i, ctrlval;
  379.     uint8_t ctrlregs[MCP_N_TXBUFFERS] = { MCP_TXB0CTRL, MCP_TXB1CTRL, MCP_TXB2CTRL };
  380.    
  381.     res = MCP_ALLTXBUSY;
  382.     *txbuf_n = 0x00;
  383.    
  384.     // check all 3 TX-Buffers
  385.     for (i=0; i<MCP_N_TXBUFFERS; i++) {
  386.         ctrlval = MCP2515_ReadRegister( ctrlregs[i] );
  387.         if ((ctrlval & MCP_TXB_TXREQ_M) == 0) {
  388. #ifdef MCP_DEBUGMODE
  389.             printf("Selected TX-Buffer: %u\n", i+1);
  390. #endif
  391.             *txbuf_n = ctrlregs[i]+1; // return SIDH-address of Buffer
  392.             res = MCP2515_OK;
  393.             return res; /* ! function exit */
  394.         }
  395.     }
  396.     return res;
  397. }
  398.  
  399. void MCP2515_InitCanBuffers(void) {
  400.     uint8_t i, a1, a2, a3;
  401.    
  402.     // TODO: check why this is needed to receive extended
  403.     //   and standard frames
  404.     // Mark all filter bits as don't care:
  405.     MCP2515_WriteCanId(MCP_RXM0SIDH, 0, 0);
  406.     MCP2515_WriteCanId(MCP_RXM1SIDH, 0, 0);
  407.     // Anyway, set all filters to 0:
  408.     MCP2515_WriteCanId(MCP_RXF0SIDH, 1, 0); // RXB0: extended
  409.     MCP2515_WriteCanId(MCP_RXF1SIDH, 0, 0); //       AND standard
  410.     MCP2515_WriteCanId(MCP_RXF2SIDH, 1, 0); // RXB1: extended
  411.     MCP2515_WriteCanId(MCP_RXF3SIDH, 0, 0); //       AND standard
  412.     MCP2515_WriteCanId(MCP_RXF4SIDH, 0, 0);
  413.     MCP2515_WriteCanId(MCP_RXF5SIDH, 0, 0);
  414.    
  415.     // Clear, deactivate the three transmit buffers
  416.     // TXBnCTRL -> TXBnD7
  417.     a1 = MCP_TXB0CTRL;
  418.     a2 = MCP_TXB1CTRL;
  419.     a3 = MCP_TXB2CTRL;
  420.     for (i = 0; i < 14; i++) { // in-buffer loop
  421.         MCP2515_SetRegister(a1, 0);
  422.         MCP2515_SetRegister(a2, 0);
  423.         MCP2515_SetRegister(a3, 0);
  424.         a1++;
  425.         a2++;
  426.         a3++;
  427.     }
  428.    
  429.     // and clear, deactivate the two receive buffers.
  430.     MCP2515_SetRegister(MCP_RXB0CTRL, 0);
  431.     MCP2515_SetRegister(MCP_RXB1CTRL, 0);
  432. }
  433.  
  434.  
  435. // ---
  436.  
  437. uint8_t MCP2515_Init(const uint8_t canSpeed) {
  438.     uint8_t res;
  439.    
  440.     SPI_Init();     // init SPI-Interface (as "Master")
  441.    
  442.     MCP2515_UNSELECT();
  443.     MCP_CS_DDR |= ( 1 << MCP_CS_BIT );
  444.    
  445.     MCP2515_Reset();
  446.    
  447.     res = MCP2515_SetCanCtrlMode(MODE_CONFIG);
  448.    
  449.     if (res == MCP2515_FAIL) return res;  /* function exit on error */
  450.  
  451.     res = MCP2515_SetClkout(CLKOUT_PS1);
  452.    
  453.     if (res == MCP2515_FAIL) return res;  /* function exit on error */
  454.    
  455.     res = MCP2515_ConfigRate(canSpeed);
  456.    
  457.     if (res == MCP2515_OK) {
  458.         MCP2515_InitCanBuffers();
  459.  
  460. #if (DEBUG_RXANY==1)
  461.     #warning DEBUG_RXANY is defined! Bypassing filter.
  462.         // enable both receive-buffers to receive any message
  463.         // and enable rollover
  464.         MCP2515_ModifyRegister(
  465.                 MCP_RXB0CTRL,
  466.                 MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK,
  467.                 MCP_RXB_RX_ANY | MCP_RXB_BUKT_MASK);
  468.         MCP2515_ModifyRegister(
  469.                 MCP_RXB1CTRL,
  470.                 MCP_RXB_RX_MASK,
  471.                 MCP_RXB_RX_ANY);
  472. #else
  473.         // enable both receive-buffers to receive messages
  474.         // with std. and ext. identifiers
  475.         // and enable rollover
  476.         MCP2515_ModifyRegister(
  477.                 MCP_RXB0CTRL,
  478.                 MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK,
  479.                 MCP_RXB_RX_STDEXT | MCP_RXB_BUKT_MASK );
  480.         MCP2515_ModifyRegister(
  481.                 MCP_RXB1CTRL,
  482.                 MCP_RXB_RX_MASK,
  483.                 MCP_RXB_RX_STDEXT);
  484. #endif
  485.     }
  486.    
  487.     return res;
  488. }
  489.  
  490. #ifdef MCP_DEBUGMODE
  491. void MCP2515_DumpExtendedStatus(void) {
  492.     uint8_t tec, rec, eflg;
  493.    
  494.     tec  = MCP2515_ReadRegister(MCP_TEC);
  495.     rec  = MCP2515_ReadRegister(MCP_REC);
  496.     eflg = MCP2515_ReadRegister(MCP_EFLG);
  497.    
  498.     printf("MCP2515 Extended Status:\n");
  499.     printf("MCP Transmit Error Count: %u\n", tec);
  500.     printf("MCP Receiver Error Count: %u\n", rec);
  501.     printf("MCP Error Flag: %u\n", eflg);
  502.    
  503.     if ( (rec>127) || (tec>127) ) {
  504.         printf("Error-Passive or Bus-Off\n");
  505.     }
  506.  
  507.     if (eflg & MCP_EFLG_RX1OVR)
  508.         printf("Receive Buffer 1 Overflow\n");
  509.     if (eflg & MCP_EFLG_RX0OVR)
  510.         printf("Receive Buffer 0 Overflow\n");
  511.     if (eflg & MCP_EFLG_TXBO)
  512.         printf("Bus-Off\n");
  513.     if (eflg & MCP_EFLG_TXEP)
  514.         printf("Receive Error Passive\n");
  515.     if (eflg & MCP_EFLG_TXWAR)
  516.         printf("Transmit Error Warning\n");
  517.     if (eflg & MCP_EFLG_RXWAR)
  518.         printf("Receive Error Warning\n");
  519.     if (eflg & MCP_EFLG_EWARN )
  520.         printf("Receive Error Warning\n");
  521. }
  522. #endif
  523.  
  524. #if 0
  525. // read-modify-write - better: Bit Modify Instruction
  526. uint8_t MCP2515_SetCanCtrlMode(uint8_t newmode) {
  527.     uint8_t i;
  528.    
  529.     i = MCP2515_ReadRegister(MCP_CANCTRL);
  530.     i &= ~(MODE_MASK);
  531.     i |= newmode;
  532.     MCP2515_SetRegister(MCP_CANCTRL, i);
  533.    
  534.     // verify as advised in datasheet
  535.     i = MCP2515_ReadRegister(MCP_CANCTRL);
  536.     i &= MODE_MASK;
  537.     if ( i == newmode ) {
  538.         return MCP2515_OK;
  539.     }
  540.     else {
  541.         return MCP2515_FAIL;
  542.     }
  543. }
  544. #endif
  545.