diff --git a/IO_ADI.ino b/IO_ADI.ino new file mode 100644 index 0000000..ac66ab9 --- /dev/null +++ b/IO_ADI.ino @@ -0,0 +1,145 @@ +#include "IO_ADI.h" + +void initIO(void) +{ + // GPIO Setup + pinMode(SPAREOUTPIN, OUTPUT); // Spare output + digitalWrite(SPAREOUTPIN, HIGH); + + pinMode(33, OUTPUT); // Heartbeat LED + + pinMode(25, INPUT); // Spare input + pinMode(35, INPUT); // Obstruction + + memset(io_array, 0, sizeof(io_array)); + + pinMode(BATTERYINPUTPIN, INPUT); +} + +void serviceIO(void) +{ + uint8_t io8; + uint16_t io16; + uint16_t mask; + uint16_t i; + + // INPUTS + io8 = readMCP23S08(IOEXP_CS, 9); + + if (bitRead(io8, 0) == 0) + io_array[RET_LIMIT]++; + else + io_array[RET_LIMIT] = 0; + if (bitRead(io8, 1) == 0) + io_array[EXT_LIMIT]++; + else + io_array[EXT_LIMIT] = 0; + if (bitRead(io8, 2) == 0) + io_array[OPEN_LIMIT]++; + else + io_array[OPEN_LIMIT] = 0; + if (bitRead(io8, 3) == 0) + io_array[ADDRBUTTON]++; + else + io_array[ADDRBUTTON] = 0; + if (bitRead(io8, 6) == 0) + io_array[RF_KEYPAD]++; + else + io_array[RF_KEYPAD] = 0; + + io_array[SPARE_IN] = digitalRead(25); + // io_array[ADDRBUTTON] = digitalRead(ADDR_PB); + + io_array[BATT_V] = read_BatteryVoltage(); + + // OUTPUTS + io8 = 0; + + bitWrite(io8, 4, (io_array[COMPRESSOR] & 1)); + bitWrite(io8, 5, (io_array[EN_12V_SW] & 1)); + bitWrite(io8, 7, (io_array[POWER_RLY] & 1)); + + setMCP23S08(IOEXP_CS, 9, io8); + + digitalWrite(SPAREOUTPIN, io_array[SPARE_OUT]); +} + +#define A2DSIZE 15 +uint16_t A2D_array[A2DSIZE + 1]; +uint16_t A2D_index = 0; + +uint16_t A2D_count = 0; // v527 fix low batt error on startup + +uint16_t read_BatteryVoltage(void) +{ + uint16_t i, j; + float f, b; + uint32_t batteryInput; + + i = analogRead(BATTERYINPUTPIN); + // Serial.println(i); + A2D_array[A2D_index++] = i; + + // uase the A2D_count it is the size of the A2DSIZE + if (A2D_count < A2DSIZE) + A2D_count++; + + if (A2D_index >= A2DSIZE) + A2D_index = 0; + + batteryInput = 0; + for (i = 0; i < A2D_count; i++) + batteryInput += A2D_array[i]; + + // use the count if less than the A2DSize for the average + batteryInput = batteryInput / (A2D_count < A2DSIZE ? A2D_count : A2DSIZE); + batteryInput = ((batteryInput)*parm[18]) / 1000; // 1 point cal + + b = float(batteryInput) / 100; + + f = -0.0321 * b * b; + + f = f + (1.652 * b); + + f = f - 3.07; + + f = f * 100; + batteryInput = f; + // Serial.print("float: ");Serial.print(f);Serial.print(" int: ");Serial.println(batteryInput); + + return (batteryInput / 10); +} + +/* +uint16_t read_BatteryVoltage(void) +{ + uint16_t i, j; + float f, b; + uint32_t batteryInput; + + i = analogRead(BATTERYINPUTPIN); + //Serial.println(i); + A2D_array[A2D_index++] = i; + if (A2D_index >= A2DSIZE) A2D_index = 0; + + batteryInput = 0; + for (i = 0; i < A2DSIZE; i++) batteryInput += A2D_array[i]; + + batteryInput = ((batteryInput / A2DSIZE) * parm[18]) / 1000; //1 point cal + + + b = float(batteryInput) / 100; + + f = -0.0321 * b * b; + + f = f + (1.652 * b); + + f = f - 3.07; + + f = f * 100; + batteryInput = f; + //Serial.print("float: ");Serial.print(f);Serial.print(" int: ");Serial.println(batteryInput); + + return (batteryInput / 10); +} +*/ diff --git a/MCP7940_ADI.h b/MCP7940_ADI.h new file mode 100644 index 0000000..a1e6b7f --- /dev/null +++ b/MCP7940_ADI.h @@ -0,0 +1,22 @@ +#ifndef MCP7940_ADI + +#define MCP7940_ADI + +// #include "TimeLib.h" +#include "Time.h" +/* +typedef struct { + uint8_t Second; + uint8_t Minute; + uint8_t Hour; + uint8_t Wday; // day of week, sunday is day 1 + uint8_t Day; + uint8_t Month; + uint8_t Year; // offset from 1970; +} tmElements_t, TimeElements, *tmElementsPtr_t; +*/ +tmElements_t dt; + +// String datetimestr = ""; + +#endif diff --git a/mcp_can.h b/mcp_can.h new file mode 100644 index 0000000..5fe49cd --- /dev/null +++ b/mcp_can.h @@ -0,0 +1,110 @@ +/* + mcp_can.h + 2012 Copyright (c) Seeed Technology Inc. All right reserved. + + Author:Loovee + Contributor: Cory J. Fowler + 2014-1-16 + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110- + 1301 USA +*/ +#ifndef _MCP2515_H_ +#define _MCP2515_H_ + +#include "mcp_can_dfs.h" +#define MAX_CHAR_IN_MESSAGE 8 + +class MCP_CAN +{ +private: + INT8U m_nExtFlg; /* identifier xxxID */ + /* either extended (the 29 LSB) */ + /* or standard (the 11 LSB) */ + INT32U m_nID; /* can id */ + INT8U m_nDlc; /* data length: */ + INT8U m_nDta[MAX_CHAR_IN_MESSAGE]; /* data */ + INT8U m_nRtr; /* rtr */ + INT8U m_nfilhit; + INT8U SPICS; + + /* + * mcp2515 driver function + */ + // private: +private: + void mcp2515_reset(void); /* reset mcp2515 */ + + INT8U mcp2515_readRegister(const INT8U address); /* read mcp2515's register */ + + void mcp2515_readRegisterS(const INT8U address, + INT8U values[], + const INT8U n); + void mcp2515_setRegister(const INT8U address, /* set mcp2515's register */ + const INT8U value); + + void mcp2515_setRegisterS(const INT8U address, /* set mcp2515's registers */ + const INT8U values[], + const INT8U n); + + void mcp2515_initCANBuffers(void); + + void mcp2515_modifyRegister(const INT8U address, /* set bit of one register */ + const INT8U mask, + const INT8U data); + + INT8U mcp2515_readStatus(void); /* read mcp2515's Status */ + INT8U mcp2515_setCANCTRL_Mode(const INT8U newmode); /* set mode */ + INT8U mcp2515_configRate(const INT8U canSpeed); /* set boadrate */ + INT8U mcp2515_init(const INT8U canSpeed); /* mcp2515init */ + + void mcp2515_write_id(const INT8U mcp_addr, /* write can id */ + const INT8U ext, + const INT32U id); + + void mcp2515_read_id(const INT8U mcp_addr, /* read can id */ + INT8U *ext, + INT32U *id); + + void mcp2515_write_canMsg(const INT8U buffer_sidh_addr); /* write can msg */ + void mcp2515_read_canMsg(const INT8U buffer_sidh_addr); /* read can msg */ + void mcp2515_start_transmit(const INT8U mcp_addr); /* start transmit */ + INT8U mcp2515_getNextFreeTXBuf(INT8U *txbuf_n); /* get Next free txbuf */ + + /* + * can operator function + */ + + INT8U setMsg(INT32U id, INT8U ext, INT8U len, INT8U *pData); /* set message */ + INT8U clearMsg(); /* clear all message to zero */ + INT8U readMsg(); /* read message */ + INT8U sendMsg(); /* send message */ + +public: + MCP_CAN(INT8U _CS); + INT8U begin(INT8U speedset); /* init can */ + INT8U init_Mask(INT8U num, INT8U ext, INT32U ulData); /* init Masks */ + INT8U init_Filt(INT8U num, INT8U ext, INT32U ulData); /* init filters */ + INT8U sendMsgBuf(INT32U id, INT8U ext, INT8U len, INT8U *buf); /* send buf */ + INT8U readMsgBuf(INT8U *len, INT8U *buf); /* read buf */ + INT8U checkReceive(void); /* if something received */ + INT8U checkError(void); /* if something error */ + INT32U getCanId(void); /* get can id when receive */ +}; + +extern MCP_CAN CAN; +#endif +/********************************************************************************************************* + END FILE +*********************************************************************************************************/ diff --git a/mcp_can.ino b/mcp_can.ino new file mode 100644 index 0000000..c1b2b73 --- /dev/null +++ b/mcp_can.ino @@ -0,0 +1,818 @@ +/* + mcp_can.cpp + 2012 Copyright (c) Seeed Technology Inc. All right reserved. + + Author:Loovee + Contributor: Cory J. Fowler + 2014-1-16 + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110- + 1301 USA +*/ +#include "mcp_can.h" + +// #define spi_readwrite SPI.transfer +#define spi_read() spi_readwrite(0x00) + +/********************************************************************************************************* +** Function name: mcp2515_reset +** Descriptions: reset the device +*********************************************************************************************************/ +void MCP_CAN::mcp2515_reset(void) +{ + MCP2515_SELECT(); + spi_readwrite(MCP_RESET); + MCP2515_UNSELECT(); + delay(10); +} + +/********************************************************************************************************* +** Function name: mcp2515_readRegister +** Descriptions: read register +*********************************************************************************************************/ +INT8U MCP_CAN::mcp2515_readRegister(const INT8U address) +{ + INT8U ret; + + MCP2515_SELECT(); + spi_readwrite(MCP_READ); + spi_readwrite(address); + ret = spi_read(); + MCP2515_UNSELECT(); + + return ret; +} + +/********************************************************************************************************* +** Function name: mcp2515_readRegisterS +** Descriptions: read registerS +*********************************************************************************************************/ +void MCP_CAN::mcp2515_readRegisterS(const INT8U address, INT8U values[], const INT8U n) +{ + INT8U i; + MCP2515_SELECT(); + spi_readwrite(MCP_READ); + spi_readwrite(address); + // mcp2515 has auto-increment of address-pointer + for (i = 0; i < n; i++) + { + values[i] = spi_read(); + } + MCP2515_UNSELECT(); +} + +/********************************************************************************************************* +** Function name: mcp2515_setRegister +** Descriptions: set register +*********************************************************************************************************/ +void MCP_CAN::mcp2515_setRegister(const INT8U address, const INT8U value) +{ + MCP2515_SELECT(); + spi_readwrite(MCP_WRITE); + spi_readwrite(address); + spi_readwrite(value); + MCP2515_UNSELECT(); +} + +/********************************************************************************************************* +** Function name: mcp2515_setRegisterS +** Descriptions: set registerS +*********************************************************************************************************/ +void MCP_CAN::mcp2515_setRegisterS(const INT8U address, const INT8U values[], const INT8U n) +{ + INT8U i; + MCP2515_SELECT(); + spi_readwrite(MCP_WRITE); + spi_readwrite(address); + + for (i = 0; i < n; i++) + { + spi_readwrite(values[i]); + } + MCP2515_UNSELECT(); +} + +/********************************************************************************************************* +** Function name: mcp2515_modifyRegister +** Descriptions: set bit of one register +*********************************************************************************************************/ +void MCP_CAN::mcp2515_modifyRegister(const INT8U address, const INT8U mask, const INT8U data) +{ + MCP2515_SELECT(); + spi_readwrite(MCP_BITMOD); + spi_readwrite(address); + spi_readwrite(mask); + spi_readwrite(data); + MCP2515_UNSELECT(); +} + +/********************************************************************************************************* +** Function name: mcp2515_readStatus +** Descriptions: read mcp2515's Status +*********************************************************************************************************/ +INT8U MCP_CAN::mcp2515_readStatus(void) +{ + INT8U i; + MCP2515_SELECT(); + spi_readwrite(MCP_READ_STATUS); + i = spi_read(); + MCP2515_UNSELECT(); + + return i; +} + +/********************************************************************************************************* +** Function name: mcp2515_setCANCTRL_Mode +** Descriptions: set control mode +*********************************************************************************************************/ +INT8U MCP_CAN::mcp2515_setCANCTRL_Mode(const INT8U newmode) +{ + INT8U i; + + mcp2515_modifyRegister(MCP_CANCTRL, MODE_MASK, newmode); + + i = mcp2515_readRegister(MCP_CANCTRL); + i &= MODE_MASK; + + if (i == newmode) + { + return MCP2515_OK; + } + + return MCP2515_FAIL; +} + +/********************************************************************************************************* +** Function name: mcp2515_configRate +** Descriptions: set boadrate +*********************************************************************************************************/ +INT8U MCP_CAN::mcp2515_configRate(const INT8U canSpeed) +{ + INT8U set, cfg1, cfg2, cfg3; + set = 1; + switch (canSpeed) + { + case (CAN_5KBPS): + cfg1 = MCP_16MHz_5kBPS_CFG1; + cfg2 = MCP_16MHz_5kBPS_CFG2; + cfg3 = MCP_16MHz_5kBPS_CFG3; + break; + + case (CAN_10KBPS): + cfg1 = MCP_16MHz_10kBPS_CFG1; + cfg2 = MCP_16MHz_10kBPS_CFG2; + cfg3 = MCP_16MHz_10kBPS_CFG3; + break; + + case (CAN_20KBPS): + cfg1 = MCP_16MHz_20kBPS_CFG1; + cfg2 = MCP_16MHz_20kBPS_CFG2; + cfg3 = MCP_16MHz_20kBPS_CFG3; + break; + + case (CAN_40KBPS): + cfg1 = MCP_16MHz_40kBPS_CFG1; + cfg2 = MCP_16MHz_40kBPS_CFG2; + cfg3 = MCP_16MHz_40kBPS_CFG3; + break; + + case (CAN_50KBPS): + cfg1 = MCP_16MHz_50kBPS_CFG1; + cfg2 = MCP_16MHz_50kBPS_CFG2; + cfg3 = MCP_16MHz_50kBPS_CFG3; + break; + + case (CAN_80KBPS): + cfg1 = MCP_16MHz_80kBPS_CFG1; + cfg2 = MCP_16MHz_80kBPS_CFG2; + cfg3 = MCP_16MHz_80kBPS_CFG3; + break; + + case (CAN_100KBPS): /* 100KBPS */ + cfg1 = MCP_16MHz_100kBPS_CFG1; + cfg2 = MCP_16MHz_100kBPS_CFG2; + cfg3 = MCP_16MHz_100kBPS_CFG3; + break; + + case (CAN_125KBPS): + cfg1 = MCP_16MHz_125kBPS_CFG1; + cfg2 = MCP_16MHz_125kBPS_CFG2; + cfg3 = MCP_16MHz_125kBPS_CFG3; + break; + + case (CAN_200KBPS): + cfg1 = MCP_16MHz_200kBPS_CFG1; + cfg2 = MCP_16MHz_200kBPS_CFG2; + cfg3 = MCP_16MHz_200kBPS_CFG3; + break; + + case (CAN_250KBPS): + cfg1 = MCP_16MHz_250kBPS_CFG1; + cfg2 = MCP_16MHz_250kBPS_CFG2; + cfg3 = MCP_16MHz_250kBPS_CFG3; + break; + + case (CAN_500KBPS): + cfg1 = MCP_16MHz_500kBPS_CFG1; + cfg2 = MCP_16MHz_500kBPS_CFG2; + cfg3 = MCP_16MHz_500kBPS_CFG3; + break; + + case (CAN_1000KBPS): + cfg1 = MCP_16MHz_1000kBPS_CFG1; + cfg2 = MCP_16MHz_1000kBPS_CFG2; + cfg3 = MCP_16MHz_1000kBPS_CFG3; + break; + + default: + set = 0; + break; + } + + if (set) + { + mcp2515_setRegister(MCP_CNF1, cfg1); + mcp2515_setRegister(MCP_CNF2, cfg2); + mcp2515_setRegister(MCP_CNF3, cfg3); + return MCP2515_OK; + } + else + { + return MCP2515_FAIL; + } +} + +/********************************************************************************************************* +** Function name: mcp2515_initCANBuffers +** Descriptions: init canbuffers +*********************************************************************************************************/ +void MCP_CAN::mcp2515_initCANBuffers(void) +{ + INT8U i, a1, a2, a3; + + INT8U std = 0; + INT8U ext = 1; + INT32U ulMask = 0x00, ulFilt = 0x00; + + mcp2515_write_id(MCP_RXM0SIDH, ext, ulMask); /*Set both masks to 0 */ + mcp2515_write_id(MCP_RXM1SIDH, ext, ulMask); /*Mask register ignores ext bit */ + + /* Set all filters to 0 */ + mcp2515_write_id(MCP_RXF0SIDH, ext, ulFilt); /* RXB0: extended */ + mcp2515_write_id(MCP_RXF1SIDH, std, ulFilt); /* RXB1: standard */ + mcp2515_write_id(MCP_RXF2SIDH, ext, ulFilt); /* RXB2: extended */ + mcp2515_write_id(MCP_RXF3SIDH, std, ulFilt); /* RXB3: standard */ + mcp2515_write_id(MCP_RXF4SIDH, ext, ulFilt); + mcp2515_write_id(MCP_RXF5SIDH, std, ulFilt); + + /* Clear, deactivate the three */ + /* transmit buffers */ + /* TXBnCTRL -> TXBnD7 */ + a1 = MCP_TXB0CTRL; + a2 = MCP_TXB1CTRL; + a3 = MCP_TXB2CTRL; + for (i = 0; i < 14; i++) + { /* in-buffer loop */ + mcp2515_setRegister(a1, 0); + mcp2515_setRegister(a2, 0); + mcp2515_setRegister(a3, 0); + a1++; + a2++; + a3++; + } + mcp2515_setRegister(MCP_RXB0CTRL, 0); + mcp2515_setRegister(MCP_RXB1CTRL, 0); +} + +/********************************************************************************************************* +** Function name: mcp2515_init +** Descriptions: init the device +*********************************************************************************************************/ +INT8U MCP_CAN::mcp2515_init(const INT8U canSpeed) /* mcp2515init */ +{ + + INT8U res; + + mcp2515_reset(); + + res = mcp2515_setCANCTRL_Mode(MODE_CONFIG); + if (res > 0) + { +#if DEBUG_MODE + Serial.print("Enter setting mode fall\r\n"); +#endif + return res; + } +#if DEBUG_MODE + Serial.print("Enter setting mode success \r\n"); +#endif + + /* set boadrate */ + if (mcp2515_configRate(canSpeed)) + { +#if DEBUG_MODE + Serial.print("set rate fall!!\r\n"); +#endif + return res; + } +#if DEBUG_MODE + Serial.print("set rate success!!\r\n"); +#endif + + if (res == MCP2515_OK) + { + + /* init canbuffers */ + mcp2515_initCANBuffers(); + + /* interrupt mode */ + mcp2515_setRegister(MCP_CANINTE, MCP_RX0IF | MCP_RX1IF); + +#if (DEBUG_RXANY == 1) + /* enable both receive-buffers */ + /* to receive any message */ + /* and enable rollover */ + mcp2515_modifyRegister(MCP_RXB0CTRL, + MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK, + MCP_RXB_RX_ANY | MCP_RXB_BUKT_MASK); + mcp2515_modifyRegister(MCP_RXB1CTRL, MCP_RXB_RX_MASK, + MCP_RXB_RX_ANY); +#else + /* enable both receive-buffers */ + /* to receive messages */ + /* with std. and ext. identifie */ + /* rs */ + /* and enable rollover */ + mcp2515_modifyRegister(MCP_RXB0CTRL, + MCP_RXB_RX_MASK | MCP_RXB_BUKT_MASK, + MCP_RXB_RX_STDEXT | MCP_RXB_BUKT_MASK); + mcp2515_modifyRegister(MCP_RXB1CTRL, MCP_RXB_RX_MASK, + MCP_RXB_RX_STDEXT); +#endif + /* enter normal mode */ + res = mcp2515_setCANCTRL_Mode(MODE_NORMAL); + if (res) + { +#if DEBUG_MODE + Serial.print("Enter Normal Mode Fall!!\r\n"); +#endif + return res; + } + +#if DEBUG_MODE + Serial.print("Enter Normal Mode Success!!\r\n"); +#endif + } + return res; +} + +/********************************************************************************************************* +** Function name: mcp2515_write_id +** Descriptions: write can id +*********************************************************************************************************/ +void MCP_CAN::mcp2515_write_id(const INT8U mcp_addr, const INT8U ext, const INT32U id) +{ + uint16_t canid; + INT8U tbufdata[4]; + + canid = (uint16_t)(id & 0x0FFFF); + + if (ext == 1) + { + tbufdata[MCP_EID0] = (INT8U)(canid & 0xFF); + tbufdata[MCP_EID8] = (INT8U)(canid >> 8); + canid = (uint16_t)(id >> 16); + tbufdata[MCP_SIDL] = (INT8U)(canid & 0x03); + tbufdata[MCP_SIDL] += (INT8U)((canid & 0x1C) << 3); + tbufdata[MCP_SIDL] |= MCP_TXB_EXIDE_M; + tbufdata[MCP_SIDH] = (INT8U)(canid >> 5); + } + else + { + tbufdata[MCP_SIDH] = (INT8U)(canid >> 3); + tbufdata[MCP_SIDL] = (INT8U)((canid & 0x07) << 5); + tbufdata[MCP_EID0] = 0; + tbufdata[MCP_EID8] = 0; + } + mcp2515_setRegisterS(mcp_addr, tbufdata, 4); +} + +/********************************************************************************************************* +** Function name: mcp2515_read_id +** Descriptions: read can id +*********************************************************************************************************/ +void MCP_CAN::mcp2515_read_id(const INT8U mcp_addr, INT8U *ext, INT32U *id) +{ + INT8U tbufdata[4]; + + *ext = 0; + *id = 0; + + mcp2515_readRegisterS(mcp_addr, tbufdata, 4); + + *id = (tbufdata[MCP_SIDH] << 3) + (tbufdata[MCP_SIDL] >> 5); + + if ((tbufdata[MCP_SIDL] & MCP_TXB_EXIDE_M) == MCP_TXB_EXIDE_M) + { + /* extended id */ + *id = (*id << 2) + (tbufdata[MCP_SIDL] & 0x03); + *id = (*id << 8) + tbufdata[MCP_EID8]; + *id = (*id << 8) + tbufdata[MCP_EID0]; + *ext = 1; + } +} + +/********************************************************************************************************* +** Function name: mcp2515_write_canMsg +** Descriptions: write msg +*********************************************************************************************************/ +void MCP_CAN::mcp2515_write_canMsg(const INT8U buffer_sidh_addr) +{ + INT8U mcp_addr; + mcp_addr = buffer_sidh_addr; + mcp2515_setRegisterS(mcp_addr + 5, m_nDta, m_nDlc); /* write data bytes */ + if (m_nRtr == 1) /* if RTR set bit in byte */ + { + m_nDlc |= MCP_RTR_MASK; + } + mcp2515_setRegister((mcp_addr + 4), m_nDlc); /* write the RTR and DLC */ + mcp2515_write_id(mcp_addr, m_nExtFlg, m_nID); /* write CAN id */ +} + +/********************************************************************************************************* +** Function name: mcp2515_read_canMsg +** Descriptions: read message +*********************************************************************************************************/ +void MCP_CAN::mcp2515_read_canMsg(const INT8U buffer_sidh_addr) /* read can msg */ +{ + INT8U mcp_addr, ctrl; + + mcp_addr = buffer_sidh_addr; + + mcp2515_read_id(mcp_addr, &m_nExtFlg, &m_nID); + + ctrl = mcp2515_readRegister(mcp_addr - 1); + m_nDlc = mcp2515_readRegister(mcp_addr + 4); + + if ((ctrl & 0x08)) + { + m_nRtr = 1; + } + else + { + m_nRtr = 0; + } + + m_nDlc &= MCP_DLC_MASK; + mcp2515_readRegisterS(mcp_addr + 5, &(m_nDta[0]), m_nDlc); +} + +/********************************************************************************************************* +** Function name: sendMsg +** Descriptions: send message +*********************************************************************************************************/ +void MCP_CAN::mcp2515_start_transmit(const INT8U mcp_addr) /* start transmit */ +{ + mcp2515_modifyRegister(mcp_addr - 1, MCP_TXB_TXREQ_M, MCP_TXB_TXREQ_M); +} + +/********************************************************************************************************* +** Function name: sendMsg +** Descriptions: send message +*********************************************************************************************************/ +INT8U MCP_CAN::mcp2515_getNextFreeTXBuf(INT8U *txbuf_n) /* get Next free txbuf */ +{ + INT8U res, i, ctrlval; + INT8U ctrlregs[MCP_N_TXBUFFERS] = {MCP_TXB0CTRL, MCP_TXB1CTRL, MCP_TXB2CTRL}; + + res = MCP_ALLTXBUSY; + *txbuf_n = 0x00; + + /* check all 3 TX-Buffers */ + for (i = 0; i < MCP_N_TXBUFFERS; i++) + { + ctrlval = mcp2515_readRegister(ctrlregs[i]); + if ((ctrlval & MCP_TXB_TXREQ_M) == 0) + { + *txbuf_n = ctrlregs[i] + 1; /* return SIDH-address of Buffe */ + /* r */ + res = MCP2515_OK; + return res; /* ! function exit */ + } + } + return res; +} + +/********************************************************************************************************* +** Function name: set CS +** Descriptions: init CS pin and set UNSELECTED +*********************************************************************************************************/ +MCP_CAN::MCP_CAN(INT8U _CS) +{ + SPICS = _CS; + pinMode(SPICS, OUTPUT); + MCP2515_UNSELECT(); +} + +/********************************************************************************************************* +** Function name: init +** Descriptions: init can and set speed +*********************************************************************************************************/ +INT8U MCP_CAN::begin(INT8U speedset) +{ + INT8U res; + + // SPI.begin(); + res = mcp2515_init(speedset); + if (res == MCP2515_OK) + return CAN_OK; + else + return CAN_FAILINIT; +} + +/********************************************************************************************************* +** Function name: init_Mask +** Descriptions: init canid Masks +*********************************************************************************************************/ +INT8U MCP_CAN::init_Mask(INT8U num, INT8U ext, INT32U ulData) +{ + INT8U res = MCP2515_OK; +#if DEBUG_MODE + Serial.print("Begin to set Mask!!\r\n"); +#endif + res = mcp2515_setCANCTRL_Mode(MODE_CONFIG); + if (res > 0) + { +#if DEBUG_MODE + Serial.print("Enter setting mode fall\r\n"); +#endif + return res; + } + + if (num == 0) + { + mcp2515_write_id(MCP_RXM0SIDH, ext, ulData); + } + else if (num == 1) + { + mcp2515_write_id(MCP_RXM1SIDH, ext, ulData); + } + else + res = MCP2515_FAIL; + + res = mcp2515_setCANCTRL_Mode(MODE_NORMAL); + if (res > 0) + { +#if DEBUG_MODE + Serial.print("Enter normal mode fall\r\n"); +#endif + return res; + } +#if DEBUG_MODE + Serial.print("set Mask success!!\r\n"); +#endif + return res; +} + +/********************************************************************************************************* +** Function name: init_Filt +** Descriptions: init canid filters +*********************************************************************************************************/ +INT8U MCP_CAN::init_Filt(INT8U num, INT8U ext, INT32U ulData) +{ + INT8U res = MCP2515_OK; +#if DEBUG_MODE + Serial.print("Begin to set Filter!!\r\n"); +#endif + res = mcp2515_setCANCTRL_Mode(MODE_CONFIG); + if (res > 0) + { +#if DEBUG_MODE + Serial.print("Enter setting mode fall\r\n"); +#endif + return res; + } + + switch (num) + { + case 0: + mcp2515_write_id(MCP_RXF0SIDH, ext, ulData); + break; + + case 1: + mcp2515_write_id(MCP_RXF1SIDH, ext, ulData); + break; + + case 2: + mcp2515_write_id(MCP_RXF2SIDH, ext, ulData); + break; + + case 3: + mcp2515_write_id(MCP_RXF3SIDH, ext, ulData); + break; + + case 4: + mcp2515_write_id(MCP_RXF4SIDH, ext, ulData); + break; + + case 5: + mcp2515_write_id(MCP_RXF5SIDH, ext, ulData); + break; + + default: + res = MCP2515_FAIL; + } + + res = mcp2515_setCANCTRL_Mode(MODE_NORMAL); + if (res > 0) + { +#if DEBUG_MODE + Serial.print("Enter normal mode fall\r\nSet filter fail!!\r\n"); +#endif + return res; + } +#if DEBUG_MODE + Serial.print("set Filter success!!\r\n"); +#endif + + return res; +} + +/********************************************************************************************************* +** Function name: setMsg +** Descriptions: set can message, such as dlc, id, dta[] and so on +*********************************************************************************************************/ +INT8U MCP_CAN::setMsg(INT32U id, INT8U ext, INT8U len, INT8U *pData) +{ + int i = 0; + m_nExtFlg = ext; + m_nID = id; + m_nDlc = len; + for (i = 0; i < MAX_CHAR_IN_MESSAGE; i++) + m_nDta[i] = *(pData + i); + return MCP2515_OK; +} + +/********************************************************************************************************* +** Function name: clearMsg +** Descriptions: set all message to zero +*********************************************************************************************************/ +INT8U MCP_CAN::clearMsg() +{ + m_nID = 0; + m_nDlc = 0; + m_nExtFlg = 0; + m_nRtr = 0; + m_nfilhit = 0; + for (int i = 0; i < m_nDlc; i++) + m_nDta[i] = 0x00; + + return MCP2515_OK; +} + +/********************************************************************************************************* +** Function name: sendMsg +** Descriptions: send message +*********************************************************************************************************/ +INT8U MCP_CAN::sendMsg() +{ + INT8U res, res1, txbuf_n; + uint16_t uiTimeOut = 0; + + do + { + res = mcp2515_getNextFreeTXBuf(&txbuf_n); /* info = addr. */ + uiTimeOut++; + } while (res == MCP_ALLTXBUSY && (uiTimeOut < TIMEOUTVALUE)); + + if (uiTimeOut == TIMEOUTVALUE) + { + return CAN_GETTXBFTIMEOUT; /* get tx buff time out */ + } + uiTimeOut = 0; + mcp2515_write_canMsg(txbuf_n); + mcp2515_start_transmit(txbuf_n); + do + { + uiTimeOut++; + res1 = mcp2515_readRegister(txbuf_n); /* read send buff ctrl reg */ + res1 = res1 & 0x08; + } while (res1 && (uiTimeOut < TIMEOUTVALUE)); + if (uiTimeOut == TIMEOUTVALUE) /* send msg timeout */ + { + return CAN_SENDMSGTIMEOUT; + } + return CAN_OK; +} + +/********************************************************************************************************* +** Function name: sendMsgBuf +** Descriptions: send buf +*********************************************************************************************************/ +INT8U MCP_CAN::sendMsgBuf(INT32U id, INT8U ext, INT8U len, INT8U *buf) +{ + setMsg(id, ext, len, buf); + sendMsg(); +} + +/********************************************************************************************************* +** Function name: readMsg +** Descriptions: read message +*********************************************************************************************************/ +INT8U MCP_CAN::readMsg() +{ + INT8U stat, res; + + stat = mcp2515_readStatus(); + + if (stat & MCP_STAT_RX0IF) /* Msg in Buffer 0 */ + { + mcp2515_read_canMsg(MCP_RXBUF_0); + mcp2515_modifyRegister(MCP_CANINTF, MCP_RX0IF, 0); + res = CAN_OK; + } + else if (stat & MCP_STAT_RX1IF) /* Msg in Buffer 1 */ + { + mcp2515_read_canMsg(MCP_RXBUF_1); + mcp2515_modifyRegister(MCP_CANINTF, MCP_RX1IF, 0); + res = CAN_OK; + } + else + { + res = CAN_NOMSG; + } + return res; +} + +/********************************************************************************************************* +** Function name: readMsgBuf +** Descriptions: read message buf +*********************************************************************************************************/ +INT8U MCP_CAN::readMsgBuf(INT8U *len, INT8U buf[]) +{ + readMsg(); + *len = m_nDlc; + for (int i = 0; i < m_nDlc; i++) + { + buf[i] = m_nDta[i]; + } +} + +/********************************************************************************************************* +** Function name: checkReceive +** Descriptions: check if got something +*********************************************************************************************************/ +INT8U MCP_CAN::checkReceive(void) +{ + INT8U res; + res = mcp2515_readStatus(); /* RXnIF in Bit 1 and 0 */ + if (res & MCP_STAT_RXIF_MASK) + { + return CAN_MSGAVAIL; + } + else + { + return CAN_NOMSG; + } +} + +/********************************************************************************************************* +** Function name: checkError +** Descriptions: if something error +*********************************************************************************************************/ +INT8U MCP_CAN::checkError(void) +{ + INT8U eflg = mcp2515_readRegister(MCP_EFLG); + + if (eflg & MCP_EFLG_ERRORMASK) + { + return CAN_CTRLERROR; + } + else + { + return CAN_OK; + } +} + +/********************************************************************************************************* +** Function name: getCanId +** Descriptions: when receive something ,u can get the can id!! +*********************************************************************************************************/ +INT32U MCP_CAN::getCanId(void) +{ + return m_nID; +} +/********************************************************************************************************* + END FILE +*********************************************************************************************************/ diff --git a/mcp_can_dfs.h b/mcp_can_dfs.h new file mode 100644 index 0000000..a73ce4b --- /dev/null +++ b/mcp_can_dfs.h @@ -0,0 +1,352 @@ +/* + mcp_can_dfs.h + 2012 Copyright (c) Seeed Technology Inc. All right reserved. + + Author:Loovee + Contributor: Cory J. Fowler + 2014-1-16 + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110- + 1301 USA +*/ +#ifndef _MCP2515DFS_H_ +#define _MCP2515DFS_H_ + +#include +#include +#include + +#ifndef INT32U +#define INT32U unsigned long +#endif + +#ifndef INT8U +#define INT8U byte +#endif + +// if print debug information +#define DEBUG_MODE 0 + +/* + * Begin mt + */ +#define TIMEOUTVALUE 50 +#define MCP_SIDH 0 +#define MCP_SIDL 1 +#define MCP_EID8 2 +#define MCP_EID0 3 + +#define MCP_TXB_EXIDE_M 0x08 /* In TXBnSIDL */ +#define MCP_DLC_MASK 0x0F /* 4 LSBits */ +#define MCP_RTR_MASK 0x40 /* (1<<6) Bit 6 */ + +#define MCP_RXB_RX_ANY 0x60 +#define MCP_RXB_RX_EXT 0x40 +#define MCP_RXB_RX_STD 0x20 +#define MCP_RXB_RX_STDEXT 0x00 +#define MCP_RXB_RX_MASK 0x60 +#define MCP_RXB_BUKT_MASK (1 << 2) + +/* +** Bits in the TXBnCTRL registers. +*/ +#define MCP_TXB_TXBUFE_M 0x80 +#define MCP_TXB_ABTF_M 0x40 +#define MCP_TXB_MLOA_M 0x20 +#define MCP_TXB_TXERR_M 0x10 +#define MCP_TXB_TXREQ_M 0x08 +#define MCP_TXB_TXIE_M 0x04 +#define MCP_TXB_TXP10_M 0x03 + +#define MCP_TXB_RTR_M 0x40 /* In TXBnDLC */ +#define MCP_RXB_IDE_M 0x08 /* In RXBnSIDL */ +#define MCP_RXB_RTR_M 0x40 /* In RXBnDLC */ + +#define MCP_STAT_RXIF_MASK (0x03) +#define MCP_STAT_RX0IF (1 << 0) +#define MCP_STAT_RX1IF (1 << 1) + +#define MCP_EFLG_RX1OVR (1 << 7) +#define MCP_EFLG_RX0OVR (1 << 6) +#define MCP_EFLG_TXBO (1 << 5) +#define MCP_EFLG_TXEP (1 << 4) +#define MCP_EFLG_RXEP (1 << 3) +#define MCP_EFLG_TXWAR (1 << 2) +#define MCP_EFLG_RXWAR (1 << 1) +#define MCP_EFLG_EWARN (1 << 0) +#define MCP_EFLG_ERRORMASK (0xF8) /* 5 MS-Bits */ + +/* + * Define MCP2515 register addresses + */ + +#define MCP_RXF0SIDH 0x00 +#define MCP_RXF0SIDL 0x01 +#define MCP_RXF0EID8 0x02 +#define MCP_RXF0EID0 0x03 +#define MCP_RXF1SIDH 0x04 +#define MCP_RXF1SIDL 0x05 +#define MCP_RXF1EID8 0x06 +#define MCP_RXF1EID0 0x07 +#define MCP_RXF2SIDH 0x08 +#define MCP_RXF2SIDL 0x09 +#define MCP_RXF2EID8 0x0A +#define MCP_RXF2EID0 0x0B +#define MCP_CANSTAT 0x0E +#define MCP_CANCTRL 0x0F +#define MCP_RXF3SIDH 0x10 +#define MCP_RXF3SIDL 0x11 +#define MCP_RXF3EID8 0x12 +#define MCP_RXF3EID0 0x13 +#define MCP_RXF4SIDH 0x14 +#define MCP_RXF4SIDL 0x15 +#define MCP_RXF4EID8 0x16 +#define MCP_RXF4EID0 0x17 +#define MCP_RXF5SIDH 0x18 +#define MCP_RXF5SIDL 0x19 +#define MCP_RXF5EID8 0x1A +#define MCP_RXF5EID0 0x1B +#define MCP_TEC 0x1C +#define MCP_REC 0x1D +#define MCP_RXM0SIDH 0x20 +#define MCP_RXM0SIDL 0x21 +#define MCP_RXM0EID8 0x22 +#define MCP_RXM0EID0 0x23 +#define MCP_RXM1SIDH 0x24 +#define MCP_RXM1SIDL 0x25 +#define MCP_RXM1EID8 0x26 +#define MCP_RXM1EID0 0x27 +#define MCP_CNF3 0x28 +#define MCP_CNF2 0x29 +#define MCP_CNF1 0x2A +#define MCP_CANINTE 0x2B +#define MCP_CANINTF 0x2C +#define MCP_EFLG 0x2D +#define MCP_TXB0CTRL 0x30 +#define MCP_TXB1CTRL 0x40 +#define MCP_TXB2CTRL 0x50 +#define MCP_RXB0CTRL 0x60 +#define MCP_RXB0SIDH 0x61 +#define MCP_RXB1CTRL 0x70 +#define MCP_RXB1SIDH 0x71 + +#define MCP_TX_INT 0x1C // Enable all transmit interrup ts +#define MCP_TX01_INT 0x0C // Enable TXB0 and TXB1 interru pts +#define MCP_RX_INT 0x03 // Enable receive interrupts +#define MCP_NO_INT 0x00 // Disable all interrupts + +#define MCP_TX01_MASK 0x14 +#define MCP_TX_MASK 0x54 + +/* + * Define SPI Instruction Set + */ + +#define MCP_WRITE 0x02 + +#define MCP_READ 0x03 + +#define MCP_BITMOD 0x05 + +#define MCP_LOAD_TX0 0x40 +#define MCP_LOAD_TX1 0x42 +#define MCP_LOAD_TX2 0x44 + +#define MCP_RTS_TX0 0x81 +#define MCP_RTS_TX1 0x82 +#define MCP_RTS_TX2 0x84 +#define MCP_RTS_ALL 0x87 + +#define MCP_READ_RX0 0x90 +#define MCP_READ_RX1 0x94 + +#define MCP_READ_STATUS 0xA0 + +#define MCP_RX_STATUS 0xB0 + +#define MCP_RESET 0xC0 + +/* + * CANCTRL Register Values + */ + +#define MODE_NORMAL 0x00 +#define MODE_SLEEP 0x20 +#define MODE_LOOPBACK 0x40 +#define MODE_LISTENONLY 0x60 +#define MODE_CONFIG 0x80 +#define MODE_POWERUP 0xE0 +#define MODE_MASK 0xE0 +#define ABORT_TX 0x10 +#define MODE_ONESHOT 0x08 +#define CLKOUT_ENABLE 0x04 +#define CLKOUT_DISABLE 0x00 +#define CLKOUT_PS1 0x00 +#define CLKOUT_PS2 0x01 +#define CLKOUT_PS4 0x02 +#define CLKOUT_PS8 0x03 + +/* + * CNF1 Register Values + */ + +#define SJW1 0x00 +#define SJW2 0x40 +#define SJW3 0x80 +#define SJW4 0xC0 + +/* + * CNF2 Register Values + */ + +#define BTLMODE 0x80 +#define SAMPLE_1X 0x00 +#define SAMPLE_3X 0x40 + +/* + * CNF3 Register Values + */ + +#define SOF_ENABLE 0x80 +#define SOF_DISABLE 0x00 +#define WAKFIL_ENABLE 0x40 +#define WAKFIL_DISABLE 0x00 + +/* + * CANINTF Register Bits + */ + +#define MCP_RX0IF 0x01 +#define MCP_RX1IF 0x02 +#define MCP_TX0IF 0x04 +#define MCP_TX1IF 0x08 +#define MCP_TX2IF 0x10 +#define MCP_ERRIF 0x20 +#define MCP_WAKIF 0x40 +#define MCP_MERRF 0x80 + +/* + * speed 16M + */ +#define MCP_16MHz_1000kBPS_CFG1 (0x00) +#define MCP_16MHz_1000kBPS_CFG2 (0xD0) +#define MCP_16MHz_1000kBPS_CFG3 (0x82) + +#define MCP_16MHz_500kBPS_CFG1 (0x00) +#define MCP_16MHz_500kBPS_CFG2 (0xF0) +#define MCP_16MHz_500kBPS_CFG3 (0x86) + +#define MCP_16MHz_250kBPS_CFG1 (0x41) +#define MCP_16MHz_250kBPS_CFG2 (0xF1) +#define MCP_16MHz_250kBPS_CFG3 (0x85) + +#define MCP_16MHz_200kBPS_CFG1 (0x01) +#define MCP_16MHz_200kBPS_CFG2 (0xFA) +#define MCP_16MHz_200kBPS_CFG3 (0x87) + +#define MCP_16MHz_125kBPS_CFG1 (0x03) +#define MCP_16MHz_125kBPS_CFG2 (0xF0) +#define MCP_16MHz_125kBPS_CFG3 (0x86) + +#define MCP_16MHz_100kBPS_CFG1 (0x03) +#define MCP_16MHz_100kBPS_CFG2 (0xFA) +#define MCP_16MHz_100kBPS_CFG3 (0x87) + +#define MCP_16MHz_80kBPS_CFG1 (0x03) +#define MCP_16MHz_80kBPS_CFG2 (0xFF) +#define MCP_16MHz_80kBPS_CFG3 (0x87) + +#define MCP_16MHz_50kBPS_CFG1 (0x07) +#define MCP_16MHz_50kBPS_CFG2 (0xFA) +#define MCP_16MHz_50kBPS_CFG3 (0x87) + +#define MCP_16MHz_40kBPS_CFG1 (0x07) +#define MCP_16MHz_40kBPS_CFG2 (0xFF) +#define MCP_16MHz_40kBPS_CFG3 (0x87) + +#define MCP_16MHz_20kBPS_CFG1 (0x0F) +#define MCP_16MHz_20kBPS_CFG2 (0xFF) +#define MCP_16MHz_20kBPS_CFG3 (0x87) + +#define MCP_16MHz_10kBPS_CFG1 (0x1F) +#define MCP_16MHz_10kBPS_CFG2 (0xFF) +#define MCP_16MHz_10kBPS_CFG3 (0x87) + +#define MCP_16MHz_5kBPS_CFG1 (0x3F) +#define MCP_16MHz_5kBPS_CFG2 (0xFF) +#define MCP_16MHz_5kBPS_CFG3 (0x87) + +#define MCPDEBUG (0) +#define MCPDEBUG_TXBUF (0) +#define MCP_N_TXBUFFERS (3) + +#define MCP_RXBUF_0 (MCP_RXB0SIDH) +#define MCP_RXBUF_1 (MCP_RXB1SIDH) + +// #define SPICS 10 +#define MCP2515_SELECT() digitalWrite(SPICS, LOW) +#define MCP2515_UNSELECT() digitalWrite(SPICS, HIGH) + +#define MCP2515_OK (0) +#define MCP2515_FAIL (1) +#define MCP_ALLTXBUSY (2) + +#define CANDEBUG 1 + +#define CANUSELOOP 0 + +#define CANSENDTIMEOUT (200) /* milliseconds */ + +/* + * initial value of gCANAutoProcess + */ +#define CANAUTOPROCESS (1) +#define CANAUTOON (1) +#define CANAUTOOFF (0) + +#define CAN_STDID (0) +#define CAN_EXTID (1) + +#define CANDEFAULTIDENT (0x55CC) +#define CANDEFAULTIDENTEXT (CAN_EXTID) + +#define CAN_5KBPS 1 +#define CAN_10KBPS 2 +#define CAN_20KBPS 3 +#define CAN_40KBPS 4 +#define CAN_50KBPS 5 +#define CAN_80KBPS 6 +#define CAN_100KBPS 7 +#define CAN_125KBPS 8 +#define CAN_200KBPS 9 +#define CAN_250KBPS 10 +#define CAN_500KBPS 11 +#define CAN_1000KBPS 12 + +#define CAN_OK (0) +#define CAN_FAILINIT (1) +#define CAN_FAILTX (2) +#define CAN_MSGAVAIL (3) +#define CAN_NOMSG (4) +#define CAN_CTRLERROR (5) +#define CAN_GETTXBFTIMEOUT (6) +#define CAN_SENDMSGTIMEOUT (7) +#define CAN_FAIL (0xff) + +#define CAN_MAX_CHAR_IN_MESSAGE (8) + +#endif +/********************************************************************************************************* + END FILE +*********************************************************************************************************/