151 Commits
Author SHA1 Message Date
alias pillar1989 cb607da7da bump version to 2.3.4 2026-05-26 11:32:12 +08:00
fc19066027 fix: use pSPI->begin() and add skipSpiBegin option for ESP32 compatibility (#159)
ESP32 users need to call SPI.begin() with custom pin assignments before
using the library (GPIO matrix). The hardcoded SPI.begin() in
mcp2518fd::begin() overwrites this configuration.

Changes:
- Replace SPI.begin() with pSPI->begin() (consistent with MCP2515)
- Add optional _initSPI parameter (default true) to begin() across
  MCP_CAN, mcp2515, and mcp2518fd so ESP32 users can skip SPI init

Existing code is unaffected — default behavior unchanged.

Closes #158

Co-authored-by: pillar1989 <zuobaozhu@gmail.com>
2026-05-26 11:23:15 +08:00
alias pillar1989andGitHub ca8fcc7fe3 Add MCP2515 8MHz 83.3kbps bitrate support
Add the missing MCP_8MHz_83k3BPS timing macros and wire CAN_83K3BPS into the MCP_8MHz bitrate switch. Fixes #79.
2026-04-28 11:09:23 +08:00
yuan_mo 31438c426b add send and receive extended frames examples 2025-04-21 09:48:53 +08:00
ShuishengPengandGitHub ad48756e56 Merge pull request #153 from techie66/bugfix_140
Change order of TX buffer fill to ensure in-order sending of frames.
2025-02-06 10:22:56 +08:00
Jacob Geigle c8556d5c1b Change order of TX buffer fill to ensure in-order sending of frames. 2025-02-02 11:45:28 -05:00
Lesords 23b23eff5c ci: add an action to automatically close stale issues and PRs 2025-01-08 07:43:42 +00:00
ackPeng 6f556e2ac8 add run-cl-arduino.yml and add SERIAL_PORT_MONITOR define 2024-12-27 14:48:26 +08:00
Matthew 491283753f Add sync_issues GitHub Action for workflows 2024-10-08 18:24:20 +08:00
EthanethiolandGitHub 23666a81df Added MCP_8MHz_95k2BPS (#150) 2024-03-18 09:06:42 +08:00
Micah MundyandGitHub 6dcfabc65e Patch four-argument sendmsgbuf (#146)
maintains backward compatibility with previous versions of
the function call
2023-08-09 08:23:01 +08:00
Pasakorn TiwatthanontandGitHub 02d18fb3b3 Reset rx overflow flag (#144) 2023-06-01 08:54:16 +08:00
JaxonandGitHub 7328966ef0 Merge pull request #139 from Maxwelltoo/master
fix subclass reference error
2023-01-10 10:30:59 +08:00
Jaxon adceb9b415 fix subclass reference error 2023-01-10 10:24:18 +08:00
Micah MundyandGitHub eb6887ba3c Move the four-argument sendMsgBuf wrapper to mcp_can.h (#136) 2022-08-30 13:44:00 +08:00
Lakshantha Dissanayake b946ae7c24 Update: library.json and library.properties 2022-04-11 23:38:18 +05:30
Lakshantha 58a38c9387 Update: version 2022-04-11 09:02:38 +05:30
Lucas DietrichandGitHub e2cbc7bb07 Fix compilation warning -Wshift-count-overflow (#134)
Fix issue #129

Signed-off-by: Lucas Dietrich <ld.adecy@gmail.com>
2022-03-14 14:08:36 +08:00
Baozhu ZuoandGitHub 06e6e163a9 Merge pull request #131 from ivankravets/patch-2
Sync version to 2.3.1
2021-12-06 08:27:11 +08:00
Ivan KravetsandGitHub 9226a0ae6b Sync version to 2.3.1 2021-12-04 14:26:14 +02:00
Lakshantha DissanayakeandGitHub 6acaf5a258 Update version 2021-07-22 14:05:23 +05:30
Baozhu ZuoandGitHub b517530d07 Merge pull request #127 from techie66/master
Support for 12Mhz Crystals
2021-07-22 16:32:45 +08:00
Jacob GandGitHub c991cacd9a Merge branch 'Seeed-Studio:master' into master 2021-07-06 16:44:28 -07:00
Baozhu ZuoandGitHub 5a41853758 Merge pull request #123 from QuentinTorg/uno_wifi_r2_compatibility
Fix Arduino Uno Wifi Rev2 and Arduino Nano Every Compatibility
2021-06-08 07:45:39 +08:00
QuentinTorg 4080671c63 fix variable collision that broke compatibility with Arudino Uno Wifi R2 boards. May also affect Arduino Nano Every 2021-06-06 09:31:59 -04:00
Baozhu ZuoandGitHub c110bf10c0 Merge pull request #122 from adamayd/master
Removed special character and updated keywords.
2021-06-05 12:37:13 +08:00
Adam Ayd 1351334686 Removed special character and updated keywords. 2021-06-05 00:17:25 -04:00
Baozhu ZuoandGitHub f579f66402 Merge pull request #121 from adamayd/master
Updated libary.json to current version
2021-06-05 10:34:53 +08:00
Adam AydandGitHub 1b63d26adc Updated libary.json to current version 2021-06-03 22:49:02 -04:00
Jacob Geigle e9adda5cea 12MHz 10KBPS and 5KBPS removed 2021-05-15 12:16:58 -07:00
Jacob Geigle bb92e93e9b Added definitions for mcp2515 to use 12MHz clock 2021-05-15 06:44:15 -04:00
Lakshantha DissanayakeandGitHub efbcf196f8 Change version to 2.3.0 2021-05-13 11:54:03 +05:30
Lakshantha DissanayakeandGitHub 14f1e98a12 Merge pull request #120 from per1234/revert-name
Revert library name change
2021-05-13 11:53:19 +05:30
per1234 78173b3225 Revert library name change
Libraries are locked to the `name` value specified by the library.properties metadata file in the release at the time of
the Library Manager submission.

Any release with a different name is rejected by the Arduino Library Manager indexer.

References:
- https://github.com/arduino/Arduino/wiki/Library-Manager-FAQ#why-arent-releases-of-my-library-being-picked-up-by-library-manager
- https://github.com/arduino/Arduino/wiki/Library-Manager-FAQ#how-can-i-change-my-librarys-name
2021-05-12 18:18:47 -07:00
Baozhu ZuoandGitHub f8a04fd600 Merge pull request #118 from silviu-toderita/master
Removed unused include statement
2021-05-10 08:15:12 +08:00
Silviu ToderitaandGitHub 5863c67c70 Re-include SoftwareSerial in conditional in can-serial.cpp 2021-05-08 12:28:14 -07:00
Silviu ToderitaandGitHub f3ae9d0f10 Removed unused include statement 2021-05-07 11:20:06 -07:00
Baozhu ZuoandGitHub 7ba9b7deff Merge pull request #117 from TyphoonSB/master
Update mcp2518fd_can.cpp
2021-05-06 08:32:19 +08:00
TyphoonSBandGitHub d756ec0980 Update mcp2518fd_can.cpp
disable filter controle register before changing the filter, and reenable it after chage.
2021-05-04 12:48:16 +02:00
turmary ef05384659 Move: library version to 2.2.0 2021-02-03 10:02:05 +08:00
turmary 66305bbf5d Move: can-serial.{h,cpp} back to src folder 2021-02-03 10:01:21 +08:00
turmary d315924485 Remove: disable SoftwareSerial by default, or else waste flash/ram space 2021-02-03 10:00:29 +08:00
turmary 85648cd0fc Add: baudrate 800KBPS to canbus-monitor 2021-02-03 09:48:35 +08:00
turmary 8b82b6ef89 Add: 800KBPS highlight 2021-02-02 21:11:00 +08:00
turmary 240bb4de04 Add: predefined CAN baudrate 800KBPS 2021-02-02 21:08:26 +08:00
turmary 438ae2bb21 Fixed: inputString maybe contain multiple commands 2021-02-01 20:27:53 +08:00
turmary 8920835971 Move: adapt canbus example to new API attach() 2021-02-01 20:26:53 +08:00
turmary 7cb25da245 Move: use pointer not object to access the dirver, to get the ability of virtual function 2021-02-01 20:26:02 +08:00
turmary feeb26e4e1 Move: rename CAN232 api init() to attach() 2021-02-01 20:24:36 +08:00
turmary d73add5f0a Move: CANFD argument to uint32_t from byte 2021-01-29 23:32:51 +08:00
turmary b2247a8436 Add: arbitary baudrate for MCP2518FD, and MCP2515 compatible definitions 2021-01-29 23:32:51 +08:00
turmary 9826a04cae Move: all wrapper functions into header file 2021-01-29 23:32:51 +08:00
turmary e1047f27e3 Optimize: code style of mcp2518fd 2021-01-29 16:36:44 +08:00
turmary d89af776af Move: CAN baudrate definitions to common header mcp_can.h 2021-01-29 16:36:06 +08:00
turmary 3dea108ee3 Update: sync code from https://github.com/latonita/arduino-canbus-monitor 2021-01-29 16:16:46 +08:00
turmary 7c195a14ed Revert "- Use Hardware Serial in CAN-monitor example"
please uncomment the line to enable Hardware Serial "//#define debug Serial"
This reverts commit 1fc462f2b2.
2021-01-29 11:24:27 +08:00
turmary c45e7935ff Remove: duplicate error code definitions 2021-01-29 11:24:27 +08:00
turmary 300c1c4a4b Add: optional argument err_ptr for checkError() 2021-01-29 09:32:40 +08:00
turmary 3dff8e3d20 Fix: product table title 2021-01-28 15:26:27 +08:00
turmary 39d55dc608 Update: all FD example works 2021-01-21 13:52:46 +08:00
turmary cfd840cd23 Add: API CANFD::len2dlc() 2021-01-18 17:30:00 +08:00
turmary 92597cb97d Fix from: example receive_interruptFD compiling fail 2021-01-18 17:28:59 +08:00
turmary efad5bb364 Add: more comments about CANFD examples 2021-01-15 19:15:49 +08:00
turmary 6dc4e7d197 Fix to: remove delay() which decrease performance 2021-01-15 17:49:56 +08:00
turmary c522d7842f Fix to: sendMsgBuf() support ext & rtr 2021-01-15 15:48:32 +08:00
turmary 0677b13bfc Fix to: readMsgBufID support ext & rtrBit 2021-01-15 14:37:22 +08:00
turmary 544d2c8eeb Add: a baudrate compatible argument to MCP2518FD CAN.begin() 2021-01-15 11:32:22 +08:00
Baozhu ZuoandGitHub e3834de29c Merge pull request #108 from GunZi200/master
Use HardwareSerial instead of SoftwareSerial in CAN-monitor example
2021-01-08 19:21:39 +08:00
Gudni 1fc462f2b2 - Use Hardware Serial in CAN-monitor example 2021-01-06 12:35:20 +00:00
turmaryandBaozhu Zuo 3a35904217 Move: can-serial source to example directory 2021-01-04 09:00:15 +08:00
turmaryandBaozhu Zuo 4577e4fa7b Move: can-serial compiled pass again 2021-01-04 09:00:15 +08:00
turmary 36a70d5cdc Move: library version to 2.1.0 2020-12-28 22:41:04 +08:00
turmary d8ecb0ddcc Move: close DEBUG message to reduce Flash or RAM usage 2020-12-28 22:38:28 +08:00
turmary 6ad2ba8c4b Move: reduce const string (RAM used on AVR-GCC platform) in examples 2020-12-28 20:52:22 +08:00
turmary dad91a1dba Move: SERIAL to SERIAL_PORT_MONITOR in examples 2020-12-28 20:50:49 +08:00
turmary cf1fbfaddf Add: example to receive all frames and print all fields id/type/data 2020-12-27 14:03:50 +08:00
turmary 06cf5a136d Add: random packets generator example 2020-12-27 13:01:40 +08:00
turmary fc04762c9e Fix: make all examples sequence proper 2020-12-25 15:52:28 +08:00
turmary 4e171d138e Fix: make send example sequence proper 2020-12-21 21:01:14 +08:00
wangcoolc 9a153768ee Remove useless debugging information 2020-12-10 19:32:14 +08:00
wangcoolc 69791769cf Add TransmitChannelEventAttemptClear() function 2020-12-10 19:31:16 +08:00
Anson HeandBaozhu Zuo 8c8500aa8c Added Self send and receive + FD examples 2020-12-10 17:10:14 +08:00
Anson HeandBaozhu Zuo c11356b4e5 Clear up Arduino examples for all Arduino boards 2020-12-10 17:10:14 +08:00
Baozhu Zuo 3ff9e1b4c3 update readme 2020-12-10 17:10:14 +08:00
Baozhu Zuo fc85852e2e Formatting using clang 2020-12-10 17:10:14 +08:00
Baozhu Zuo 0838960cdd add canbus monitor exmaple,compiled 2020-12-10 17:10:14 +08:00
Baozhu Zuo 57d8f936b2 use enum to aline bittime 2020-12-10 17:10:14 +08:00
Baozhu Zuo c31b9fbbd6 use MCP2518FD_BITTIME_SETUP to mark mcp2518fd's bittime 2020-12-10 17:10:14 +08:00
Baozhu Zuo 7d08979ce1 delete src/mcp2518fd_can_def.h 2020-12-10 17:10:14 +08:00
Baozhu Zuo 0a1883947a change to arduino recomanded dir structure 2020-12-10 17:10:14 +08:00
Baozhu Zuo a899ff745b Add CAN BUS Serial monitor example 2020-12-10 17:10:14 +08:00
Baozhu Zuo 62f484a4b4 change the repo's name 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo bfc70f2099 Modified put the receive interrupt before begin 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo 3c78368258 Modified mcp2518fd sendmsgbuf() len 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo cbe5bf3af0 Remove mcp2518fd code debug info 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo 576e6c9548 Modified mcp2515 send sleep example 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo 1007209ac4 Modified mcp2515 send Blink ROS example 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo 41b900754c Modified canbus send Blink example 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo 2ef6a99dd2 Modified canbus send example 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo bc014ccbd8 Modified canbus rece SD example 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo 68da38c24b Modified canbus receive check example 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo 81ecabba1c Modified canbus receive blink example 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo c26bfa704b Modified mcp2518fd setmode and set fd format 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo c72a842c31 Modified canbus send and receive example 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo a827db4891 Add canbus FD send example 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo d310e299c6 Add canbus FD receive interrupt example 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo a1dbce2513 Complete canbus set_mask_filter_send example 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo e2d0f87918 Complete canbus set_mask_filter_recv example 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo d50624c15a Complete canbus OBDII_PIDS example 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo da74297193 Complete mcp2515 canbus reveive sleep example 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo 1a927343eb Complete canbus gpio write example 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo 391a4891b0 Complete canbus send example 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo 6e9112c4f1 Complete can bus receive interrupt example 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo 1e5d371fe2 Modified mcp2518fd canbus checkreceive() return +2 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo 7eda1c5315 Complete canbus gpio read example 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo ed18dd50ad Modified separate 2515 code, provide public interface 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo 4a9eb41389 Add mcp2515 canbus code 2020-12-10 17:10:14 +08:00
wangcoolcandBaozhu Zuo fd0d620578 Add mcp2518fd canbus code 2020-12-10 17:10:14 +08:00
Baozhu ZuoandGitHub dc2fb92dad Update issue templates 2020-12-10 11:39:19 +08:00
Baozhu ZuoandGitHub 22d5092c4b Create CONTRIBUTING.md 2020-12-10 11:38:35 +08:00
Baozhu ZuoandGitHub cec72bf65a Create CODE_OF_CONDUCT.md 2020-12-10 11:37:17 +08:00
Baozhu ZuoandBaozhu Zuo edaba2d87e Merge branch 'mbaum0193-master' 2020-05-12 17:21:50 +08:00
Baozhu Zuo 055c0024ea Merge branch 'master' of https://github.com/mbaum0193/CAN_BUS_Shield into mbaum0193-master 2020-03-30 10:20:33 +08:00
Baozhu Zuo dc03e48b66 Avr dedicated header file, should be specified. 2020-03-30 10:14:04 +08:00
Michael Baumgarten 33bb082ecf Merge https://github.com/Seeed-Studio/CAN_BUS_Shield 2020-03-29 21:13:50 -04:00
Baozhu Zuo bea2f9dd4d Seeed:Arduino: fix travis.yml write error 2020-02-04 21:48:25 +08:00
Baozhu Zuo 54030c8ced Seeed:Arduino: Add travis build status 2020-02-04 18:49:31 +08:00
Baozhu Zuo cab016e7d5 Seeed:Arduino: Add travis.yml 2020-02-04 15:11:54 +08:00
Baozhu Zuo 7d30ccccc8 Pretty printed the Arduino code with astyle 2020-02-03 15:00:22 +08:00
Daniel SurizonandBaozhu Zuo 7d41ceb28a More recomended way to use attachInterrupt 2019-10-08 09:43:26 +08:00
nickandBaozhu Zuo 1935258e58 required change for compatibility with Leonardo and probably other boards 2019-08-13 09:16:27 +08:00
nickandBaozhu Zuo 34de82b7ec required change for compatibility with Leonardo and probably other boards 2019-08-13 09:16:27 +08:00
zhengxing LuandBaozhu Zuo 81a975210b add samd compatibility 2019-08-08 13:48:23 +08:00
Jenkinlu001andBaozhu Zuo ad54af425f modify errors 2019-08-08 13:48:23 +08:00
Michael BaumgartenandGitHub 6ff126f5ba Merge pull request #1 from mbaum0193/add-01-saab-baud
added support for 2001 saab CAN bus baud ~47kbps
2019-07-18 21:37:09 -04:00
Michael Baumgarten 05124b74b9 added support for 2001 saab CAN bus baud ~47kbps 2019-07-18 20:02:43 -04:00
Baozhu ZuoandGitHub 5020428581 Merge pull request #77 from kaixxx/master
Add sleep and gpio support + examples
2019-02-18 16:03:01 +08:00
Baozhu ZuoandGitHub f2946d199b Merge pull request #74 from rubik83/master
add #ifndef DEBUG_EN ... #endif around #define DEBUG_EN 1
2019-01-08 09:37:47 +08:00
kaixxx 19203a365d Add sleep and gpio support + examples
Added sleep support for MCP2515 + MCP2551. This way, you can reduce the power consumption of a complete node down to around 240uA!
Changes:
- Reintroduced gpio support from commits 43521de/bac66d1 (adlerweb, 15/01/2018) and corrected the errors
- Introduced advanced sleep support based on https://github.com/coryjfowler/MCP_CAN_lib/pull/10/files
- added example code (receive_sleep and send_sleep)
- tested everything
2019-01-07 15:37:30 +01:00
François SOLANET ee45ed5eae add #ifndef DEBUG_EN ... #endif around #define DEBUG_EN 1
user can disable debug informations without source modification
2018-11-29 10:22:44 +01:00
Jack ShaoandGitHub 962660f3e8 Merge pull request #65 from ntb001/master
Allow for extended CAN IDs in the example programs
2018-06-19 17:32:47 +08:00
Neil Bajorin 3594a57299 Merge branch 'master' of https://github.com/ntb001/CAN_BUS_Shield 2018-05-28 07:29:15 -04:00
Neil Bajorin 75df0a0e9b more cleanup 2018-05-28 07:28:56 -04:00
Neil Bajorin 00ef33618b Atom cleaned up the spaces and newlines 2018-05-28 07:28:10 -04:00
Neil Bajorin 7b7c780451 Atom cleaned up all the spaces and newlines 2018-05-28 07:27:11 -04:00
Neil Bajorin 7368740360 add .gitignore 2018-05-28 06:55:07 -04:00
ntb001andGitHub 8dc685cedc Fix link to wiki page 2018-05-28 05:30:20 -04:00
Neil Bajorin 7a35c12770 incorporate @horace3 changes to fix ext and rtr #58 2018-05-26 14:15:36 -04:00
Neil Bajorin d7ce9e6779 Always store CAN IDs as unsigned long.
Explicitly show that the CAN ID is printed in HEX.
2018-05-17 13:08:27 -04:00
Neil Bajorin cefe36904e Update comments. 2018-05-17 12:57:25 -04:00
Yihui XiongandGitHub 6f25bcddb9 Update README.md 2018-05-14 10:40:01 +08:00
52 changed files with 9461 additions and 2068 deletions
+38
View File
@@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.
+10
View File
@@ -0,0 +1,10 @@
---
name: Custom issue template
about: Describe this issue template's purpose here.
title: ''
labels: ''
assignees: ''
---
+20
View File
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
+87
View File
@@ -0,0 +1,87 @@
name: Run Ci Arduino
on:
push:
pull_request:
repository_dispatch:
types: [trigger-workflow]
jobs:
ci-arduino:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Checkout script repository
uses: actions/checkout@v4
with:
repository: Seeed-Studio/ci-arduino
path: ci
- name: Setup arduino cli
uses: arduino/setup-arduino-cli@v2.0.0
- name: Create a depend.list file
run: |
# eg: echo "<repo>" >> depend.list
echo "arduino-libraries/SD" >> depend.list
echo "frankjoshua/rosserial_arduino_lib" >> depend.list
- name: Create a ignore.list file
run: |
# eg: echo "<path>,<fqbn>" >> ignore.list
# ROS library has some issue with std_msg, so we ignore them,waiting for the fix
echo "send_Blink_ROS,Seeeduino:samd:seeed_XIAO_m0" >> ignore.list
echo "send_Blink_ROS,Seeeduino:nrf52:xiaonRF52840" >> ignore.list
echo "send_Blink_ROS,Seeeduino:nrf52:xiaonRF52840Sense" >> ignore.list
echo "send_Blink_ROS,Seeeduino:renesas_uno:XIAO_RA4M1" >> ignore.list
echo "send_Blink_ROS,rp2040:rp2040:seeed_xiao_rp2040" >> ignore.list
echo "send_Blink_ROS,rp2040:rp2040:seeed_xiao_rp2350" >> ignore.list
echo "send_Blink_ROS,esp32:esp32:XIAO_ESP32C3" >> ignore.list
echo "send_Blink_ROS,esp32:esp32:XIAO_ESP32C6" >> ignore.list
echo "send_Blink_ROS,esp32:esp32:XIAO_ESP32S3" >> ignore.list
echo "receive_sleep,Seeeduino:samd:seeed_XIAO_m0" >> ignore.list
echo "receive_sleep,Seeeduino:nrf52:xiaonRF52840" >> ignore.list
echo "receive_sleep,Seeeduino:nrf52:xiaonRF52840Sense" >> ignore.list
echo "receive_sleep,Seeeduino:renesas_uno:XIAO_RA4M1" >> ignore.list
echo "receive_sleep,rp2040:rp2040:seeed_xiao_rp2040" >> ignore.list
echo "receive_sleep,rp2040:rp2040:seeed_xiao_rp2350" >> ignore.list
echo "receive_sleep,esp32:esp32:XIAO_ESP32C3" >> ignore.list
echo "receive_sleep,esp32:esp32:XIAO_ESP32C6" >> ignore.list
echo "receive_sleep,esp32:esp32:XIAO_ESP32S3" >> ignore.list
echo "send_sleep,Seeeduino:samd:seeed_XIAO_m0" >> ignore.list
echo "send_sleep,Seeeduino:nrf52:xiaonRF52840" >> ignore.list
echo "send_sleep,Seeeduino:nrf52:xiaonRF52840Sense" >> ignore.list
echo "send_sleep,Seeeduino:renesas_uno:XIAO_RA4M1" >> ignore.list
echo "send_sleep,rp2040:rp2040:seeed_xiao_rp2040" >> ignore.list
echo "send_sleep,rp2040:rp2040:seeed_xiao_rp2350" >> ignore.list
echo "send_sleep,esp32:esp32:XIAO_ESP32C3" >> ignore.list
echo "send_sleep,esp32:esp32:XIAO_ESP32C6" >> ignore.list
echo "send_sleep,esp32:esp32:XIAO_ESP32S3" >> ignore.list
- name: Build sketch
run: ./ci/tools/compile.sh
- name: Build result
run: |
cat build.log
if [ ${{ github.event_name }} == 'pull_request' ] && [ -f compile.failed ]; then
exit 1
fi
- name: Generate issue
if: ${{ github.event_name != 'pull_request' }}
run: ./ci/tools/issue.sh
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+25
View File
@@ -0,0 +1,25 @@
name: 'Close stale issues and PRs'
on:
workflow_dispatch:
schedule:
- cron: '0 4 * * *'
jobs:
stale:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Checkout script repository
uses: actions/checkout@v4
with:
repository: Seeed-Studio/sync-github-all-issues
path: ci
- name: Run script
run: ./ci/tools/stale.sh
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+24
View File
@@ -0,0 +1,24 @@
name: Automate Issue Management
on:
issues:
types:
- opened
- edited
- assigned
- unassigned
- labeled
- unlabeled
- reopened
jobs:
add_issue_to_project:
runs-on: ubuntu-latest
steps:
- name: Add issue to GitHub Project
uses: actions/add-to-project@v1.0.2
with:
project-url: https://github.com/orgs/Seeed-Studio/projects/17
github-token: ${{ secrets.ISSUE_ASSEMBLE }}
labeled: bug
label-operator: NOT
+131
View File
@@ -0,0 +1,131 @@
## WINDOWS
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
## MAC OS
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
## DROPBOX
# Dropbox settings and caches
.dropbox
.dropbox.attr
.dropbox.cache
## VS CODE
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
## VIM
# Swap
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-v][a-z]
[._]sw[a-p]
# Session
Session.vim
# Temporary
.netrwhist
*~
# Auto-generated tag files
tags
# Persistent undo
[._]*.un~
## EMACS
# -*- mode: gitignore; -*-
*~
\#*\#
/.emacs.desktop
/.emacs.desktop.lock
*.elc
auto-save-list
tramp
.\#*
# Org-mode
.org-id-locations
*_archive
# flymake-mode
*_flymake.*
# eshell files
/eshell/history
/eshell/lastdir
# elpa packages
/elpa/
# reftex files
*.rel
# AUCTeX auto folder
/auto/
# cask packages
.cask/
dist/
# Flycheck
flycheck_*.el
# server auth directory
/server/
# projectiles files
.projectile
# directory configuration
.dir-locals.el
+8
View File
@@ -0,0 +1,8 @@
build:
tags:
- nas
script:
- wget -c https://files.seeedstudio.com/arduino/seeed-arduino-ci.sh
- chmod +x seeed-arduino-ci.sh
- bash $PWD/seeed-arduino-ci.sh test
+21
View File
@@ -0,0 +1,21 @@
language: generic
dist: bionic
sudo: false
cache:
directories:
- ~/arduino_ide
- ~/.arduino15/packages/
before_install:
- wget -c https://files.seeedstudio.com/arduino/seeed-arduino-ci.sh
script:
- chmod +x seeed-arduino-ci.sh
- cat $PWD/seeed-arduino-ci.sh
- bash $PWD/seeed-arduino-ci.sh test
notifications:
email:
on_success: change
on_failure: change
+76
View File
@@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at zuobaozhu@gmail.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq
+41
View File
@@ -0,0 +1,41 @@
## How to contribute to Seeed Software
#### **Did you find a bug?**
* **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/Seeed-Studio/Seeed_Arduino_CAN/issues).
* If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/Seeed-Studio/Seeed_Arduino_CAN/issues/new). Be sure to include a **title and clear description**, as much relevant information as possible, and a **code sample** or an **executable test case** demonstrating the expected behavior that is not occurring.
* If possible, use the relevant bug report templates to create the issue. Simply copy the content of the appropriate template into a .md file, make the necessary changes to demonstrate the issue, and **paste the content into the issue description**:
* [**Bug** issues](https://github.com/Seeed-Studio/Seeed_Arduino_CAN/blob/master/.github/ISSUE_TEMPLATE/bug_report.md)
* [**feature** issues](https://github.com/Seeed-Studio/Seeed_Arduino_CAN/blob/master/.github/ISSUE_TEMPLATE/feature_request.md)
* [**custom** for other issues](https://github.com/Seeed-Studio/Seeed_Arduino_CAN/blob/master/.github/ISSUE_TEMPLATE/custom.md)
#### **Did you write a patch that fixes a bug?**
* Open a new GitHub pull request with the patch.
* Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable.
* Before submitting, please read the [Contributing to Seeed Software](https://github.com/Seeed-Studio/Seeed_Arduino_CAN/blob/master/CONTRIBUTING.md) guide to know more about coding conventions and benchmarks.
#### **Did you fix whitespace, format code, or make a purely cosmetic patch?**
Changes that are cosmetic in nature and do not add anything substantial to the stability, functionality, or testability of Software will generally not be accepted .
#### **Do you intend to add a new feature or change an existing one?**
* Suggest you mailing our administrator(zuobaozhu@gmail.com) first and start writing code.
* Do not open an issue on GitHub until you have collected positive feedback about the change. GitHub issues are primarily intended for bug reports and fixes.
#### **Do you want to contribute to the Seeed documentation?**
* Please read [Contributing to the Seeed Documentation](https://github.com/Seeed-Studio/wiki-documents/blob/master/README.md).
Seeed Software is a volunteer effort. We encourage you to pitch in and join [the team](https://github.com/Seeed-Studio)!
Thanks! :heart: :heart: :heart:
Seeed Software Team
+1 -1
View File
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
THE SOFTWARE.
+15 -152
View File
@@ -1,168 +1,31 @@
# CAN BUS Shield
---
![CAN BUS Shield](https://statics3.seeedstudio.com/seeed/file/2017-08/bazaar528529_img_2653a.jpg)
# Seeed Arduino CAN [![Build Status](https://travis-ci.com/Seeed-Studio/CAN_BUS_Shield.svg?branch=master)](https://travis-ci.com/Seeed-Studio/CAN_BUS_Shield)
[CAN-BUS Shield V2](https://www.seeedstudio.com/CAN-BUS-Shield-V2-p-2921.html)
CAN-BUS is a common industrial bus because of its long travel distance, medium communication speed and high reliability. It is commonly found on modern machine tools and as an automotive diagnostic bus. This CAN-BUS Shield adopts MCP2515 CAN Bus controller with SPI interface and MCP2551 CAN transceiver to give your Arduino/Seeeduino CAN-BUS capability. With an OBD-II converter cable added on and the OBD-II library imported, you are ready to build an onboard diagnostic device or data logger.
CAN BUS Shield | 2-Channel CAN-BUS(FD) Shield
:-------------------------:|:-------------------------:
[![CAN BUS Shield](https://statics3.seeedstudio.com/seeed/file/2017-08/bazaar528529_img_2653a.jpg)](https://www.seeedstudio.com/CAN-BUS-Shield-V2-p-2921.html) | [![CAN BUS Shield](https://files.seeedstudio.com/wiki/CANBUS-HAT-for-Raspberry-Pi/103990563%20_Preview-07.png)](https://www.seeedstudio.com/CAN-BUS-FD-HAT-for-Raspberry-Pi-p-4742.html)
- Implements CAN V2.0B at up to 1 Mb/s
- SPI Interface up to 10 MHz
- Standard (11 bit) and extended (29 bit) data and remote frames
- Two receive buffers with prioritized message storage
- Industrial standard 9 pin sub-D connector
- Two LED indicators
### Alternative Choice
If your project is space limited, here is a [Serial CAN-BUS module](https://www.seeedstudio.com/Serial-CAN-BUS-Module-based-on-MCP2551-and-MCP2515-p-2924.html) which has the full features of CAN Bus. The Serial CAN-BUS provides your Arduino or others MCU with the capability to communication to CAN Bus, such as hacking your vehicle. This Grove CAN-BUS module is controled by UART, that means if your MCU has a UART interface, this serial CAN BUS is available. Good news is that this Serial CAN BUS module needs only $14.9
[![](https://www.seeedstudio.com/upload/image/20170826/1503688824337934.jpg)](https://www.seeedstudio.com/Serial-CAN-BUS-Module-based-on-MCP2551-and-MCP2515-p-2924.html)
- [CAN-BUS Shield V2](https://www.seeedstudio.com/CAN-BUS-Shield-V2-p-2921.html)
- [ 2-Channel CAN-BUS(FD) Shield for Raspberry Pi (MCP2518FD)](https://www.seeedstudio.com/CAN-BUS-FD-HAT-for-Raspberry-Pi-p-4742.html)
CAN-BUS is a common industrial bus because of it's long travel distance, medium communication speed and high reliability.
It is commonly found on modern machine tools and as an automotive diagnostic bus.
## Installation:
git clone https://github.com/Seeed-Studio/CAN_BUS_Shield.git
or download the zip.
For more information, please refer to [CAN-BUS_Shield_V2.0 wiki page](http://wiki.seeedstudio.com/CAN-BUS_Shield_V2.0/) and
[CAN-BUS FD wiki page](https://wiki.seeedstudio.com/2-Channel-CAN-BUS-FD-Shield-for-Raspberry-Pi/)
## Usage:
# License
This software is written by seeed studio and is licensed under The MIT License. Check License.txt for more information.
Simply copy the CAN_BUS_Shield folder to your Arduino library collection. For example,
arduino-1.6.12/libraries. Next time you run the Arduino IDE, you'll have a new option
in Sketch -> Include Library -> CAN_BUS_Shield. Review the included examples in
CAN_BUS_Shield/examples.
### 1. Set the BaudRate
This function is used to initialize the baudrate of the CAN Bus system.
The available baudrates are listed as follows:
#define CAN_5KBPS 1
#define CAN_10KBPS 2
#define CAN_20KBPS 3
#define CAN_25KBPS 4
#define CAN_31K25BPS 5
#define CAN_33KBPS 6
#define CAN_40KBPS 7
#define CAN_50KBPS 8
#define CAN_80KBPS 9
#define CAN_83K3BPS 10
#define CAN_95KBPS 11
#define CAN_100KBPS 12
#define CAN_125KBPS 13
#define CAN_200KBPS 14
#define CAN_250KBPS 15
#define CAN_500KBPS 16
#define CAN_666kbps 17
#define CAN_1000KBPS 18
### 2. Set Receive Mask and Filter
There are 2 receive mask registers and 5 filter registers on the controller chip that guarantee you get data from the target device. They are useful especially in a large network consisting of numerous nodes.
We provide two functions for you to utilize these mask and filter registers. They are:
init_Mask(unsigned char num, unsigned char ext, unsigned char ulData);
init_Filt(unsigned char num, unsigned char ext, unsigned char ulData);
**num** represents which register to use. You can fill 0 or 1 for mask and 0 to 5 for filter.
**ext** represents the status of the frame. 0 means it's a mask or filter for a standard frame. 1 means it's for a extended frame.
**ulData** represents the content of the mask of filter.
### 3. Check Receive
The MCP2515 can operate in either a polled mode, where the software checks for a received frame, or using additional pins to signal that a frame has been received or transmit completed. Use the following function to poll for received frames.
INT8U MCP_CAN::checkReceive(void);
The function will return 1 if a frame arrives, and 0 if nothing arrives.
### 4. Get CAN ID
When some data arrives, you can use the following function to get the CAN ID of the "send" node.
INT32U MCP_CAN::getCanId(void);
### 5. Send Data
CAN.sendMsgBuf(INT32U id, INT8U ext, INT8U len, INT8U *buf);
This is a function to send data onto the bus. In which:
**id** represents where the data come from.
**ext** represents the status of the frame. '0' means standard frame. '1' means extended frame.
**len** represents the length of this frame.
**buf** is the content of this message.
For example, In the 'send' example, we have:
```
unsigned char stmp[8] = {0, 1, 2, 3, 4, 5, 6, 7};
CAN.sendMsgBuf(0x00, 0, 8, stmp); //send out the message 'stmp' to the bus and tell other devices this is a standard frame from 0x00.
```
### 6. Receive Data
The following function is used to receive data on the 'receive' node:
CAN.readMsgBuf(INT8U *len, INT8U *buf);
Under the condition that masks and filters have been set, this function will only get frames that meet the requirements of those masks and filters.
**len** represents the data length.
**buf** is where you store the data.
### 7. Check additional flags
When frame is received you may check whether it was remote request and whether it was an extended (29bit) frame.
CAN.isRemoteRequest();
CAN.isExtendedFrame();
**return value** is '0' for a negative response and '1' for a positive
<br>
For more information, please refer to [wiki page](http://www.seeedstudio.com/wiki/CAN-BUS_Shield).
----
This software is written by loovee ([luweicong@seeed.cc](luweicong@seeed.cc "luweicong@seeed.cc")) for seeed studio<br>
and is licensed under [The MIT License](http://opensource.org/licenses/mit-license.php). Check License.txt for more information.<br>
Contributing to this software is warmly welcomed. You can do this basically by<br>
[forking](https://help.github.com/articles/fork-a-repo), committing modifications and then [pulling requests](https://help.github.com/articles/using-pull-requests) (follow the links above<br>
for operating guide). Adding change log and your contact into file header is encouraged.<br>
Contributing to this software is warmly welcomed.
You can do this basically by forking, committing modifications and then pulling requests (follow the links above for operating guide).
Adding change log and your contact into file header is encouraged.
Thanks for your contribution.
Seeed Studio is an open hardware facilitation company based in Shenzhen, China. <br>
Benefiting from local manufacture power and convenient global logistic system, <br>
we integrate resources to serve new era of innovation. Seeed also works with <br>
global distributors and partners to push open hardware movement.<br>
[![Analytics](https://ga-beacon.appspot.com/UA-46589105-3/CAN_BUS_Shield)](https://github.com/igrigorik/ga-beacon)
+82 -74
View File
@@ -1,27 +1,52 @@
/*************************************************************************************************
OBD-II_PIDs TEST CODE
LOOVEE @ JUN24, 2017
Query
send id: 0x7df
/*************************************************************************************************
OBD-II_PIDs TEST CODE
LOOVEE @ JUN24, 2017
Query
send id: 0x7df
dta: 0x02, 0x01, PID_CODE, 0, 0, 0, 0, 0
Response
From id: 0x7E9 or 0x7EA or 0x7EB
Response
From id: 0x7E9 or 0x7EA or 0x7EB
dta: len, 0x41, PID_CODE, byte0, byte1(option), byte2(option), byte3(option), byte4(option)
https://en.wikipedia.org/wiki/OBD-II_PIDs
Input a PID, then you will get reponse from vehicle, the input should be end with '\n'
https://en.wikipedia.org/wiki/OBD-II_PIDs
Input a PID, then you will get reponse from vehicle, the input should be end with '\n'
***************************************************************************************************/
#include <SPI.h>
#include "mcp_can.h"
#define CAN_2515
// #define CAN_2518FD
// Set SPI CS Pin according to your hardware
#if defined(SEEED_WIO_TERMINAL) && defined(CAN_2518FD)
// For Wio Terminal w/ MCP2518FD RPi Hat
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
const int SPI_CS_PIN = BCM8;
const int CAN_INT_PIN = BCM25;
#else
// For Arduino MCP2515 Hat:
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
#endif
MCP_CAN CAN(SPI_CS_PIN); // Set CS pin
#ifdef CAN_2518FD
#include "mcp2518fd_can.h"
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
#endif
#ifdef CAN_2515
#include "mcp2515_can.h"
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#endif
#define PID_ENGIN_PRM 0x0C
#define PID_VEHICLE_SPEED 0x0D
@@ -32,109 +57,92 @@ MCP_CAN CAN(SPI_CS_PIN); // Set CS pin
unsigned char PID_INPUT;
unsigned char getPid = 0;
void set_mask_filt()
{
void set_mask_filt() {
/*
* set mask, set both the mask to 0x3ff
*/
set mask, set both the mask to 0x3ff
*/
CAN.init_Mask(0, 0, 0x7FC);
CAN.init_Mask(1, 0, 0x7FC);
/*
* set filter, we can receive id from 0x04 ~ 0x09
*/
CAN.init_Filt(0, 0, 0x7E8);
set filter, we can receive id from 0x04 ~ 0x09
*/
CAN.init_Filt(0, 0, 0x7E8);
CAN.init_Filt(1, 0, 0x7E8);
CAN.init_Filt(2, 0, 0x7E8);
CAN.init_Filt(3, 0, 0x7E8);
CAN.init_Filt(4, 0, 0x7E8);
CAN.init_Filt(4, 0, 0x7E8);
CAN.init_Filt(5, 0, 0x7E8);
}
void sendPid(unsigned char __pid)
{
void sendPid(unsigned char __pid) {
unsigned char tmp[8] = {0x02, 0x01, __pid, 0, 0, 0, 0, 0};
Serial.print("SEND PID: 0x");
Serial.println(__pid, HEX);
SERIAL_PORT_MONITOR.print("SEND PID: 0x");
SERIAL_PORT_MONITOR.println(__pid, HEX);
CAN.sendMsgBuf(CAN_ID_PID, 0, 8, tmp);
}
void setup()
{
Serial.begin(115200);
while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println("CAN BUS Shield init fail");
Serial.println(" Init CAN BUS Shield again");
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
while(!Serial){};
while (CAN_OK != CAN.begin(CAN_500KBPS)) { // init can bus : baudrate = 500k
SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
delay(100);
}
Serial.println("CAN BUS Shield init ok!");
SERIAL_PORT_MONITOR.println("CAN init ok!");
set_mask_filt();
}
void loop()
{
void loop() {
taskCanRecv();
taskDbg();
if(getPid) // GET A PID
{
if (getPid) { // GET A PID
getPid = 0;
sendPid(PID_INPUT);
PID_INPUT = 0;
}
}
void taskCanRecv()
{
void taskCanRecv() {
unsigned char len = 0;
unsigned char buf[8];
if(CAN_MSGAVAIL == CAN.checkReceive()) // check if get data
{
if (CAN_MSGAVAIL == CAN.checkReceive()) { // check if get data
CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf
Serial.println("\r\n------------------------------------------------------------------");
Serial.print("Get Data From id: ");
Serial.println(CAN.getCanId(), HEX);
for(int i = 0; i<len; i++) // print the data
{
Serial.print("0x");
Serial.print(buf[i], HEX);
Serial.print("\t");
SERIAL_PORT_MONITOR.println("\r\n------------------------------------------------------------------");
SERIAL_PORT_MONITOR.print("Get Data From id: 0x");
SERIAL_PORT_MONITOR.println(CAN.getCanId(), HEX);
for (int i = 0; i < len; i++) { // print the data
SERIAL_PORT_MONITOR.print("0x");
SERIAL_PORT_MONITOR.print(buf[i], HEX);
SERIAL_PORT_MONITOR.print("\t");
}
Serial.println();
SERIAL_PORT_MONITOR.println();
}
}
void taskDbg()
{
while(Serial.available())
{
char c = Serial.read();
if(c>='0' && c<='9')
{
void taskDbg() {
while (SERIAL_PORT_MONITOR.available()) {
char c = SERIAL_PORT_MONITOR.read();
if (c >= '0' && c <= '9') {
PID_INPUT *= 0x10;
PID_INPUT += c-'0';
}
else if(c>='A' && c<='F')
{
PID_INPUT += c - '0';
} else if (c >= 'A' && c <= 'F') {
PID_INPUT *= 0x10;
PID_INPUT += 10+c-'A';
}
else if(c>='a' && c<='f')
{
PID_INPUT += 10 + c - 'A';
} else if (c >= 'a' && c <= 'f') {
PID_INPUT *= 0x10;
PID_INPUT += 10+c-'a';
}
else if(c == '\n') // END
{
PID_INPUT += 10 + c - 'a';
} else if (c == '\n') { // END
getPid = 1;
}
}
}
// END FILE
// END FILE
+62
View File
@@ -0,0 +1,62 @@
# arduino-canbus-monitor [![Build Status](https://api.travis-ci.org/latonita/arduino-canbus-monitor.svg?branch=master)](https://travis-ci.org/latonita/arduino-canbus-monitor) [![Coverity Scan](https://scan.coverity.com/projects/11684/badge.svg)](https://scan.coverity.com/projects/latonita-arduino-canbus-monitor) [![Analytics](https://ga-beacon.appspot.com/UA-99380399-1/welcome-page)](https://github.com/igrigorik/ga-beacon)
CAN BUS monitoring software based on Arduino with Seeduino/ElecFreaks CAN BUS shield based on MCP2515 (Numerous other MCP2515 based CAN BUS modules from ebay and aliexpress work well to).
This software implements CAN ASCII / Serial CAN / SLCAN protocol compatible with Lawicel CAN232/CANUSB.
As for PC counterpart software I personally used and can recommend two tools:
1) [Windows] CANHacker tool v.2.00.01 (by fuchs) to sniff and visualize data on the bus. You can download CANHacker tool from this forum page: http://www.canhack.net/viewforum.php?f=25&sid=ac01d465f19e088cb160cab630561607
2) [Windows] CAN-COOL (by MHS Elektronik), open source, but unfortunaly available only in German. Download link: http://www.mhs-elektronik.de/index.php?module=content&action=show&page=can_cool (Make sure you select RS232 and SL-CAN protocol and then click hardware bus reset icon on a toolbar)
3) [Linux] Please dig into direction of SLCAN/SocketCAN, but start from https://github.com/linux-can/can-utils
This monitor uses CAN BUS library forked from https://github.com/Seeed-Studio/CAN_BUS_Shield.
Copyright (C) 2015,2016 Anton Viktorov <latonita@yandex.ru>
You can buy me a beer if you like the tool :o) [![Donate](https://www.paypal.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JPDVHYWUY3LW)
See protocol definition here http://www.can232.com/docs/can232_v3.pdf and here http://www.can232.com/docs/canusb_manual.pdf
Commands not supported/not implemented:
- s, W, M, m, U.
Commands modified:
- S - supports not declared 83.3 rate
- F - returns MCP2515 error flags
- Z - extra Z2 option enables 4 byte timestamp vs standard 2 byte (60000ms max)
```
CMD | IMPLEMENTED | SYNTAX | DESCRIPTION
------------------------------------------------------------------------------------------------------------
'S' | YES+ | Sn[CR] Setup with standard CAN bit-rates where n is 0-8.
| | S0 10Kbit S4 125Kbit S8 1Mbit
| | S1 20Kbit S5 250Kbit S9 83.3Kbit
| | S2 50Kbit S6 500Kbit
| | S3 100Kbit S7 800Kbit
's' | - | sxxyy[CR] Setup with BTR0/BTR1 CAN bit-rates where xx and yy is a hex value.
'O' | YES | O[CR] Open the CAN channel in normal mode (sending & receiving).
'L' | YES | L[CR] Open the CAN channel in listen only mode (receiving).
'C' | YES | C[CR] Close the CAN channel.
't' | YES | tiiildd...[CR] Transmit a standard (11bit) CAN frame.
'T' | YES | Tiiiiiiiildd...[CR] Transmit an extended (29bit) CAN frame
'r' | YES | riiil[CR] Transmit an standard RTR (11bit) CAN frame.
'R' | YES | Riiiiiiiil[CR] Transmit an extended RTR (29bit) CAN frame.
'P' | YES | P[CR] Poll incomming FIFO for CAN frames (single poll)
'A' | YES | A[CR] Polls incomming FIFO for CAN frames (all pending frames)
'F' | YES+ | F[CR] Read Status Flags.
'X' | YES | Xn[CR] Sets Auto Poll/Send ON/OFF for received frames.
'W' | - | Wn[CR] Filter mode setting. By default CAN232 works in dual filter mode (0) and is backwards compatible with previous CAN232 versions.
'M' | - | Mxxxxxxxx[CR] Sets Acceptance Code Register (ACn Register of SJA1000). // we use MCP2515, not supported
'm' | - | mxxxxxxxx[CR] Sets Acceptance Mask Register (AMn Register of SJA1000). // we use MCP2515, not supported
'U' | YES | Un[CR] Setup UART with a new baud rate where n is 0-6.
'V' | YES | v[CR] Get Version number of both CAN232 hardware and software
'v' | YES | V[CR] Get Version number of both CAN232 hardware and software
'N' | YES | N[CR] Get Serial number of the CAN232.
'Z' | YES+ | Zn[CR] Sets Time Stamp ON/OFF for received frames only. EXTENSION to LAWICEL: Z2 - millis() timestamp w/o standard 60000ms cycle
'Q' | YES todo | Qn[CR] Auto Startup feature (from power on).
```
+105
View File
@@ -0,0 +1,105 @@
/*****************************************************************************************
* This is implementation of CAN BUS ASCII protocol based on LAWICEL v1.3 serial protocol
* of CAN232/CANUSB device (http://www.can232.com/docs/can232_v3.pdf)
*
* Made for Arduino with Seeduino/ElecFreaks CAN BUS Shield based on MCP2515
*
* Copyright (C) 2015 Anton Viktorov <latonita@yandex.ru>
* https://github.com/latonita/arduino-canbus-monitor
*
* This library is free software. You may use/redistribute it under The MIT License terms.
*
*****************************************************************************************/
#include <SPI.h>
#include "mcp_can.h"
#include "can-serial.h"
// #define CAN_2518FD
#define CAN_2515
#ifdef CAN_2518FD
#include "mcp2518fd_can.h"
const int SPI_CS_PIN = BCM8;
const int CAN_INT_PIN = BCM25;
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
#endif
#ifdef CAN_2515
#include "mcp2515_can.h"
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#endif
void setup() {
Serial.begin(LW232_DEFAULT_BAUD_RATE); // default COM baud rate is 115200.
while (!Serial) {
delay(10);
}
// associate the Can232 and the CAN lowlevel driver
Can232::attach(&CAN);
/*
* Warning:
* CAN232 protocol command Sn[CR] --- setup with standard CAN bit-rates
* not works on ARDUINO UNO when used with Linux slcand.
*
* Linux slcand open the USB-SERAIL and send commands imediately,
* but the UNO are in startup(reset fired by UNO builtin USB-SERIAL),
* UNO missed those commands.
*
*/
// Can232::init (RATE, CLOCK)
// Rates: CAN_10KBPS, CAN_20KBPS, CAN_50KBPS, CAN_100KBPS, CAN_125KBPS, CAN_250KBPS, CAN_500KBPS, CAN_800KBPS, CAN_1000KBPS, CAN_83K3BPS
// Default is CAN_83K3BPS.
// Clock: MCP_16MHz or MCP_8MHz.
// Default is MCP_16MHz. Please note, not all CAN speeds supported. check big switch in mcp_can.cpp
// defaults can be changed according to mcp_can.h
// Can232::init(); // rate and clock = LW232_DEFAULT_CAN_RATE and LW232_DEFAULT_CLOCK_FREQ
// Can232::init(CAN_125KBPS); // rate = 125, clock = LW232_DEFAULT_CLOCK_FREQ
Can232::init(CAN_125KBPS, MCP_16MHz); // set default rate you need here and clock frequency of CAN shield. Typically it is 16MHz, but on some MCP2515 + TJA1050 it is 8Mhz
// optional custom packet filter to reduce number of messages comingh through to canhacker
// Can232::setFilter(myCustomAddressFilter);
}
INT8U myCustomAddressFilter(INT32U addr) {
INT8U ret = LW232_FILTER_SKIP; //LW232_FILTER_PROCESS or LW232_FILTER_SKIP
switch(addr) {
// case 0x01b: //VIN
// case 0x1C8: //lights
// case 0x2C0: // pedals
case 0x3d0: // sound vol, treb..
ret = LW232_FILTER_PROCESS;
// case 0x000: // ?
// case 0x003: //shifter
// case 0x015: // dor open close affects this as well
// case 0x02c: // ???
// ret = 0;
// break;
// case 0x002:
// case 0x1a7: //fuel cons or some other
// ret = 1;
// break;
// default:
// ret = 0;
}
return ret;
}
void loop() {
Can232::loop();
}
#if defined(ARDUINO_ARCH_AVR)
void serialEvent()
#else
void serialEventRun()
#endif
{
Can232::serialEvent();
}
+50 -23
View File
@@ -1,41 +1,68 @@
// demo: Use TX2RTS as digital input
// adlerweb, 2017-06-24
#include <SPI.h>
#include "mcp_can.h"
#include "mcp2515_can.h"
#include "mcp2518fd_can.h"
#define SPI_CS_PIN 10
#define CAN_2515
// #define CAN_2518FD
MCP_CAN CAN(SPI_CS_PIN); // Set CS pin
// Set SPI CS Pin according to your hardware
#if defined(SEEED_WIO_TERMINAL) && defined(CAN_2518FD)
// For Wio Terminal w/ MCP2518FD RPi Hat
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
const int SPI_CS_PIN = BCM8;
const int CAN_INT_PIN = BCM25;
#else
// For Arduino MCP2515 Hat:
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
#endif
void setup()
{
Serial.begin(115200);
#ifdef CAN_2518FD
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
#endif
while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println("CAN init failed, retry");
#ifdef CAN_2515
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#endif
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
while (CAN_OK != CAN.begin(CAN_500KBPS)) {
SERIAL_PORT_MONITOR.println("CAN init failed, retry...");
delay(100);
}
Serial.println("CAN init ok");
if(CAN.pinMode(MCP_TX2RTS, MCP_PIN_IN))
{
Serial.println("TX2RTS is now an input");
}
else
{
Serial.println("Could not switch TX2RTS");
SERIAL_PORT_MONITOR.println("CAN init ok");
#ifdef CAN_2518FD
if (CAN.mcpPinMode(GPIO_PIN_0, GPIO_MODE_INT)) {
#else
if (CAN.mcpPinMode(MCP_TX2RTS, MCP_PIN_IN)) {
#endif
SERIAL_PORT_MONITOR.println("TX2RTS is now an input");
} else {
SERIAL_PORT_MONITOR.println("Could not switch TX2RTS");
}
}
void loop()
{
Serial.print("TX2RTS is currently ");
Serial.println(CAN.digitalRead(MCP_TX2RTS));
void loop() {
SERIAL_PORT_MONITOR.print("TX2RTS is currently ");
#ifdef CAN_2518FD
SERIAL_PORT_MONITOR.println(CAN.mcpDigitalRead(GPIO_PIN_0));
#else
SERIAL_PORT_MONITOR.println(CAN.mcpDigitalRead(MCP_TX2RTS));
#endif
delay(500);
}
/*********************************************************************************************************
END FILE
END FILE
*********************************************************************************************************/
+70 -33
View File
@@ -1,55 +1,92 @@
// demo: Use RX0BF and RX1BF as digital outputs
// adlerweb, 2017-06-24
#include <SPI.h>
#include "mcp_can.h"
#include "mcp2515_can.h"
#include "mcp2518fd_can.h"
#define SPI_CS_PIN 10
#define CAN_2515
// #define CAN_2518FD
MCP_CAN CAN(SPI_CS_PIN); // Set CS pin
// Set SPI CS Pin according to your hardware
#if defined(SEEED_WIO_TERMINAL) && defined(CAN_2518FD)
// For Wio Terminal w/ MCP2518FD RPi Hat
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
const int SPI_CS_PIN = BCM8;
const int CAN_INT_PIN = BCM25;
#else
// For Arduino MCP2515 Hat:
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
#endif
void setup()
{
Serial.begin(115200);
#ifdef CAN_2518FD
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
#endif
while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println("CAN init failed, retry");
#ifdef CAN_2515
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#endif
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
while (CAN_OK != CAN.begin(CAN_500KBPS)) { // init can bus : baudrate = 500k
SERIAL_PORT_MONITOR.println("CAN init failed, retry");
delay(100);
}
Serial.println("CAN init ok");
SERIAL_PORT_MONITOR.println("CAN init ok");
if(CAN.pinMode(MCP_RX0BF, MCP_PIN_OUT))
{
Serial.println("RX0BF is now an output");
}
else
{
Serial.println("Could not switch RX0BF");
#ifdef CAN_2518FD
if (CAN.mcpPinMode(GPIO_PIN_0, GPIO_MODE_INT)) {
#else
if (CAN.mcpPinMode(MCP_TX2RTS, MCP_PIN_IN)) {
#endif
SERIAL_PORT_MONITOR.println("RX0BF is now an output");
} else {
SERIAL_PORT_MONITOR.println("Could not switch RX0BF");
}
if(CAN.pinMode(MCP_RX1BF, MCP_PIN_OUT))
{
Serial.println("RX1BF is now an output");
}
else
{
Serial.println("Could not switch RX1BF");
#ifdef CAN_2518FD
if (CAN.mcpPinMode(GPIO_PIN_1, GPIO_MODE_INT)) {
#else
if (CAN.mcpPinMode(MCP_TX2RTS, MCP_PIN_IN)) {
#endif
SERIAL_PORT_MONITOR.println("RX1BF is now an output");
} else {
SERIAL_PORT_MONITOR.println("Could not switch RX1BF");
}
}
void loop()
{
Serial.println("10");
CAN.digitalWrite(MCP_RX0BF, HIGH);
CAN.digitalWrite(MCP_RX1BF, LOW);
void loop() {
SERIAL_PORT_MONITOR.println("10");
#ifdef CAN_2518FD
CAN.mcpDigitalWrite(GPIO_PIN_0, GPIO_HIGH);
CAN.mcpDigitalWrite(GPIO_PIN_1, GPIO_LOW);
#else
CAN.mcpDigitalWrite(MCP_RX0BF, HIGH);
CAN.mcpDigitalWrite(MCP_RX1BF, LOW);
#endif
delay(500);
Serial.println("01");
CAN.digitalWrite(MCP_RX0BF, LOW);
CAN.digitalWrite(MCP_RX1BF, HIGH);
SERIAL_PORT_MONITOR.println("01");
#ifdef CAN_2518FD
CAN.mcpDigitalWrite(GPIO_PIN_0, GPIO_LOW);
CAN.mcpDigitalWrite(GPIO_PIN_1, GPIO_HIGH);
#else
CAN.mcpDigitalWrite(MCP_RX0BF, LOW);
CAN.mcpDigitalWrite(MCP_RX1BF, HIGH);
#endif
delay(500);
}
/*********************************************************************************************************
END FILE
END FILE
*********************************************************************************************************/
+48 -31
View File
@@ -3,66 +3,83 @@
// loovee, 2014-6-13
#include <SPI.h>
#include "mcp_can.h"
#define CAN_2515
// #define CAN_2518FD
// Set SPI CS Pin according to your hardware
#if defined(SEEED_WIO_TERMINAL) && defined(CAN_2518FD)
// For Wio Terminal w/ MCP2518FD RPi Hat
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
const int SPI_CS_PIN = BCM8;
const int CAN_INT_PIN = BCM25;
#else
// For Arduino MCP2515 Hat:
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
#endif
#ifdef CAN_2518FD
#include "mcp2518fd_can.h"
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
#endif
#ifdef CAN_2515
#include "mcp2515_can.h"
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#endif
const int LED = 8;
boolean ledON = 1;
MCP_CAN CAN(SPI_CS_PIN); // Set CS pin
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
pinMode(LED, OUTPUT);
void setup()
{
Serial.begin(115200);
pinMode(LED,OUTPUT);
while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println("CAN BUS Shield init fail");
Serial.println("Init CAN BUS Shield again");
while (CAN_OK != CAN.begin(CAN_500KBPS)) { // init can bus : baudrate = 500k
SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
delay(100);
}
Serial.println("CAN BUS Shield init ok!");
SERIAL_PORT_MONITOR.println("CAN init ok!");
}
void loop()
{
void loop() {
unsigned char len = 0;
unsigned char buf[8];
if(CAN_MSGAVAIL == CAN.checkReceive()) // check if data coming
{
if (CAN_MSGAVAIL == CAN.checkReceive()) { // check if data coming
CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf
unsigned char canId = CAN.getCanId();
unsigned long canId = CAN.getCanId();
Serial.println("-----------------------------");
Serial.println("get data from ID: ");
Serial.println(canId);
SERIAL_PORT_MONITOR.println("-----------------------------");
SERIAL_PORT_MONITOR.println("get data from ID: 0x");
SERIAL_PORT_MONITOR.println(canId, HEX);
for(int i = 0; i<len; i++) // print the data
{
Serial.print(buf[i]);
Serial.print("\t");
if(ledON && i==0)
{
for (int i = 0; i < len; i++) { // print the data
SERIAL_PORT_MONITOR.print(buf[i]);
SERIAL_PORT_MONITOR.print("\t");
if (ledON && i == 0) {
digitalWrite(LED, buf[i]);
ledON = 0;
delay(500);
}
else if((!(ledON)) && i==4)
{
} else if ((!(ledON)) && i == 4) {
digitalWrite(LED, buf[i]);
ledON = 1;
}
}
Serial.println();
SERIAL_PORT_MONITOR.println();
}
}
//END FILE
//END FILE
+43 -27
View File
@@ -1,56 +1,72 @@
// demo: CAN-BUS Shield, receive data with check mode
// send data coming to fast, such as less than 10ms, you can use this way
// loovee, 2014-6-13
#include <SPI.h>
#include "mcp_can.h"
#define CAN_2515
// #define CAN_2518FD
// Set SPI CS Pin according to your hardware
#if defined(SEEED_WIO_TERMINAL) && defined(CAN_2518FD)
// For Wio Terminal w/ MCP2518FD RPi Hat
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
const int SPI_CS_PIN = BCM8;
const int CAN_INT_PIN = BCM25;
#else
// For Arduino MCP2515 Hat:
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
#endif
MCP_CAN CAN(SPI_CS_PIN); // Set CS pin
void setup()
{
Serial.begin(115200);
#ifdef CAN_2518FD
#include "mcp2518fd_can.h"
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
#endif
while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println("CAN BUS Shield init fail");
Serial.println(" Init CAN BUS Shield again");
#ifdef CAN_2515
#include "mcp2515_can.h"
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#endif
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
while (CAN_OK != CAN.begin(CAN_500KBPS)) { // init can bus : baudrate = 500k
SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
delay(100);
}
Serial.println("CAN BUS Shield init ok!");
SERIAL_PORT_MONITOR.println("CAN init ok!");
}
void loop()
{
void loop() {
unsigned char len = 0;
unsigned char buf[8];
if(CAN_MSGAVAIL == CAN.checkReceive()) // check if data coming
{
if (CAN_MSGAVAIL == CAN.checkReceive()) { // check if data coming
CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf
unsigned int canId = CAN.getCanId();
Serial.println("-----------------------------");
Serial.print("Get data from ID: ");
Serial.println(canId, HEX);
unsigned long canId = CAN.getCanId();
for(int i = 0; i<len; i++) // print the data
{
Serial.print(buf[i], HEX);
Serial.print("\t");
SERIAL_PORT_MONITOR.println("-----------------------------");
SERIAL_PORT_MONITOR.print("Get data from ID: 0x");
SERIAL_PORT_MONITOR.println(canId, HEX);
for (int i = 0; i < len; i++) { // print the data
SERIAL_PORT_MONITOR.print(buf[i], HEX);
SERIAL_PORT_MONITOR.print("\t");
}
Serial.println();
SERIAL_PORT_MONITOR.println();
}
}
/*********************************************************************************************************
END FILE
END FILE
*********************************************************************************************************/
@@ -3,13 +3,38 @@
// loovee, 2014-6-13
#include <SPI.h>
#include "mcp_can.h"
#define CAN_2515
// #define CAN_2518FD
// Set SPI CS Pin according to your hardware
#if defined(SEEED_WIO_TERMINAL) && defined(CAN_2518FD)
// For Wio Terminal w/ MCP2518FD RPi Hat
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
const int SPI_CS_PIN = BCM8;
const int CAN_INT_PIN = BCM25;
#else
// For Arduino MCP2515 Hat:
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
#endif
MCP_CAN CAN(SPI_CS_PIN); // Set CS pin
#ifdef CAN_2518FD
#include "mcp2518fd_can.h"
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
#endif
#ifdef CAN_2515
#include "mcp2515_can.h"
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#endif
unsigned char flagRecv = 0;
@@ -17,52 +42,47 @@ unsigned char len = 0;
unsigned char buf[8];
char str[20];
void setup()
{
Serial.begin(115200);
while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println("CAN BUS Shield init fail");
Serial.println(" Init CAN BUS Shield again");
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
while (!SERIAL_PORT_MONITOR) {
; // wait for serial port to connect. Needed for native USB port only
}
attachInterrupt(digitalPinToInterrupt(CAN_INT_PIN), MCP2515_ISR, FALLING); // start interrupt
while (CAN_OK != CAN.begin(CAN_500KBPS)) { // init can bus : baudrate = 500k
SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
delay(100);
}
Serial.println("CAN BUS Shield init ok!");
attachInterrupt(0, MCP2515_ISR, FALLING); // start interrupt
SERIAL_PORT_MONITOR.println("CAN init ok!");
}
void MCP2515_ISR()
{
void MCP2515_ISR() {
flagRecv = 1;
}
void loop()
{
if(flagRecv)
{ // check if get data
void loop() {
if (flagRecv) {
// check if get data
flagRecv = 0; // clear flag
SERIAL_PORT_MONITOR.println("into loop");
// iterate over all pending messages
// If either the bus is saturated or the MCU is busy,
// both RX buffers may be in use and reading a single
// message does not clear the IRQ conditon.
while (CAN_MSGAVAIL == CAN.checkReceive())
{
while (CAN_MSGAVAIL == CAN.checkReceive()) {
// read data, len: data length, buf: data buf
SERIAL_PORT_MONITOR.println("checkReceive");
CAN.readMsgBuf(&len, buf);
// print the data
for(int i = 0; i<len; i++)
{
Serial.print(buf[i]);Serial.print("\t");
for (int i = 0; i < len; i++) {
SERIAL_PORT_MONITOR.print(buf[i]); SERIAL_PORT_MONITOR.print("\t");
}
Serial.println();
SERIAL_PORT_MONITOR.println();
}
}
}
/*********************************************************************************************************
END FILE
END FILE
*********************************************************************************************************/
@@ -0,0 +1,89 @@
// demo: CAN-BUS Shield, receive data with interrupt mode
// when in interrupt mode, the data coming can't be too fast, must >20ms, or else you can use check mode
// loovee, 2014-6-13
#include <SPI.h>
#include "mcp2518fd_can.h"
#define CAN_2518FD
// Set SPI CS Pin according to your hardware
#if defined(SEEED_WIO_TERMINAL) && defined(CAN_2518FD)
// For Wio Terminal w/ MCP2518FD RPi Hat
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
const int SPI_CS_PIN = BCM8;
const int CAN_INT_PIN = BCM25;
#else
// For Arduino MCP2515 Hat:
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
#endif
#ifdef CAN_2518FD
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
#endif
unsigned char flagRecv = 0;
unsigned char len = 0;
unsigned char buf[64];
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
while (!SERIAL_PORT_MONITOR) {
; // wait for serial port to connect. Needed for native USB port only
}
attachInterrupt(digitalPinToInterrupt(CAN_INT_PIN), MCP2515_ISR, FALLING); // start interrupt
CAN.setMode(CAN_NORMAL_MODE);
// init can bus : arbitration bitrate = 500k, data bitrate = 1M
while (0 != CAN.begin(CAN_500K_1M)) {
SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
delay(100);
}
SERIAL_PORT_MONITOR.println("CAN init ok!");
byte mode = CAN.getMode();
#ifdef ARDUINO_XIAO_RA4M1
char buffer[50];
sprintf(buffer, "CAN BUS mode = %d\n\r", mode);
SERIAL_PORT_MONITOR.print(buffer);
#else
SERIAL_PORT_MONITOR.printf("CAN BUS mode = %d\n\r", mode);
#endif
}
void MCP2515_ISR() {
flagRecv = 1;
}
void loop() {
if (flagRecv) {
// check if get data
flagRecv = 0; // clear flag
SERIAL_PORT_MONITOR.println("into loop");
// iterate over all pending messages
// If either the bus is saturated or the MCU is busy,
// both RX buffers may be in use and reading a single
// message does not clear the IRQ conditon.
while (CAN_MSGAVAIL == CAN.checkReceive()) {
// read data, len: data length, buf: data buf
SERIAL_PORT_MONITOR.println("checkReceive");
CAN.readMsgBuf(&len, buf);
// print the data
for (int i = 0; i < len; i++) {
SERIAL_PORT_MONITOR.print(buf[i]); SERIAL_PORT_MONITOR.print("\t");
}
SERIAL_PORT_MONITOR.println();
}
}
}
/*********************************************************************************************************
END FILE
*********************************************************************************************************/
@@ -0,0 +1,112 @@
/*
* demo: CAN-BUS Shield, receive all frames and print all fields id/type/data
* to receive frame fastly, a poll in loop() is required.
*
* Copyright (C) 2020 Seeed Technology Co.,Ltd.
*/
#include <SPI.h>
#define CAN_2515
// #define CAN_2518FD
// Set SPI CS Pin according to your hardware
#if defined(SEEED_WIO_TERMINAL) && defined(CAN_2518FD)
// For Wio Terminal w/ MCP2518FD RPi Hat
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
const int SPI_CS_PIN = BCM8;
const int CAN_INT_PIN = BCM25;
#else
// For Arduino MCP2515 Hat:
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
#endif
#ifdef CAN_2518FD
#include "mcp2518fd_can.h"
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
// To TEST MCP2518FD CAN2.0 data transfer
#define MAX_DATA_SIZE 8
// To TEST MCP2518FD CANFD data transfer, uncomment below lines
// #undef MAX_DATA_SIZE
// #define MAX_DATA_SIZE 64
#endif
#ifdef CAN_2515
#include "mcp2515_can.h"
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#define MAX_DATA_SIZE 8
#endif
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
while (!SERIAL_PORT_MONITOR) {}
#if MAX_DATA_SIZE > 8
/*
* To compatible with MCP2515 API,
* default mode is CAN_CLASSIC_MODE
* Now set to CANFD mode.
*/
CAN.setMode(CAN_NORMAL_MODE);
#endif
while (CAN_OK != CAN.begin(CAN_500KBPS)) { // init can bus : baudrate = 500k
SERIAL_PORT_MONITOR.println(F("CAN init fail, retry..."));
delay(100);
}
SERIAL_PORT_MONITOR.println(F("CAN init ok!"));
}
uint32_t id;
uint8_t type; // bit0: ext, bit1: rtr
uint8_t len;
byte cdata[MAX_DATA_SIZE] = {0};
void loop() {
// check if data coming
if (CAN_MSGAVAIL != CAN.checkReceive()) {
return;
}
char prbuf[32 + MAX_DATA_SIZE * 3];
int i, n;
unsigned long t = millis();
// read data, len: data length, buf: data buf
CAN.readMsgBuf(&len, cdata);
id = CAN.getCanId();
type = (CAN.isExtendedFrame() << 0) |
(CAN.isRemoteRequest() << 1);
/*
* MCP2515(or this driver) could not handle properly
* the data carried by remote frame
*/
n = sprintf(prbuf, "%04lu.%03d ", t / 1000, int(t % 1000));
/* Displayed type:
*
* 0x00: standard data frame
* 0x02: extended data frame
* 0x30: standard remote frame
* 0x32: extended remote frame
*/
static const byte type2[] = {0x00, 0x02, 0x30, 0x32};
n += sprintf(prbuf + n, "RX: [%08lX](%02X) ", (unsigned long)id, type2[type]);
// n += sprintf(prbuf, "RX: [%08lX](%02X) ", id, type);
for (i = 0; i < len; i++) {
n += sprintf(prbuf + n, "%02X ", cdata[i]);
}
SERIAL_PORT_MONITOR.println(prbuf);
}
// END FILE
+150
View File
@@ -0,0 +1,150 @@
// demo: CAN Sleep Example - receive
// by Kai, based on the receive_interrupt example by loovee and the additions from Zak Kemble (https://github.com/coryjfowler/MCP_CAN_lib/pull/10/files)
//
// By setting the MCU, the CAN controller (MCP2515) and the transceiver (MCP2551) into sleep mode, you can reduce
// the power consumption of the whole setup from around 50mA down to 240uA (Arduino directly connected to 5V, regulator and
// power LED removed). The node will wake up when a new message arrives, process the message and go back to sleep
// afterwards.
//
// Known issues:
// - Because it takes some time for the controller to wake up, the first message is usually lost. Look at the
// send_sleep example on how to avoid this by sending a special wakeup message before the normal message.
// - If you only have 2 devices on the CAN bus (the device running this sketch and some other device sending
// messages), you may find that duplicate messages are received when waking up. This is because when
// the MCP2515 wakes up it enters LISTENONLY mode where it does not send ACKs to messages, so the transmitter
// will retransmit the same message a few times. See below for a simple solution to filter duplicate messages out.
#include <SPI.h>
#include "mcp2515_can.h"
#include <avr/sleep.h>
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
#define CAN_INT 2 // Set INT to pin 2
// To use the sleep mode of the transceiver (MCP2551), it's Rs pin must be connected to either the MCP2515 or
// any free Arduino output.
#define RS_TO_MCP2515 true // Set this to false if Rs is connected to your Arduino
#define RS_OUTPUT MCP_RX0BF // RX0BF is a pin of the MCP2515. You can also define an Arduino pin here
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#define KEEP_AWAKE_TIME 200 // time the controller will stay awake after the last activity on the bus (in ms)
unsigned long lastBusActivity = millis();
unsigned char flagRecv = 0;
unsigned char len = 0;
unsigned char buf[8];
int lastLen = -1;
unsigned char lastBuf[8]; // used for duplicate message check below
unsigned long lastMsgTime = 0;
#define DUPLICATE_TIMEOUT 20
char str[20];
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
while (CAN_OK != CAN.begin(CAN_500KBPS, MCP_16MHz)) { // init can bus : baudrate = 500k
SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
delay(100);
}
SERIAL_PORT_MONITOR.println("CAN init ok!");
// attach interrupt
pinMode(CAN_INT, INPUT);
attachInterrupt(digitalPinToInterrupt(CAN_INT), MCP2515_ISR, FALLING);
CAN.setSleepWakeup(1); // this tells the MCP2515 to wake up on incoming messages
// Pull the Rs pin of the MCP2551 transceiver low to enable it:
if (RS_TO_MCP2515) {
CAN.mcpPinMode(MCP_RX0BF, MCP_PIN_OUT);
CAN.mcpDigitalWrite(RS_OUTPUT, LOW);
} else {
pinMode(RS_OUTPUT, OUTPUT);
digitalWrite(RS_OUTPUT, LOW);
}
}
void MCP2515_ISR() {
flagRecv = 1;
}
void loop() {
if (flagRecv) {
// check if get data
flagRecv = 0; // clear flag
lastBusActivity = millis();
// iterate over all pending messages
// If either the bus is saturated or the MCU is busy,
// both RX buffers may be in use and reading a single
// message does not clear the IRQ conditon.
while (CAN_MSGAVAIL == CAN.checkReceive()) {
// read data, len: data length, buf: data buf
CAN.readMsgBuf(&len, buf);
// check if this is a duplicate message (including a timeout, so that the same message is accepted again after a while)
if ((len != lastLen) || (millis() > lastMsgTime + DUPLICATE_TIMEOUT)
|| (memcmp((const void*)lastBuf, (const void*)buf, sizeof(buf)) != 0)) {
lastLen = len;
memcpy(lastBuf, buf, sizeof(buf));
lastMsgTime = millis();
// print the data
for (int i = 0; i < len; i++) {
SERIAL_PORT_MONITOR.print(buf[i]); SERIAL_PORT_MONITOR.print("\t");
}
SERIAL_PORT_MONITOR.println();
}
}
} else if (millis() > lastBusActivity + KEEP_AWAKE_TIME) {
// Put MCP2515 into sleep mode
SERIAL_PORT_MONITOR.println(F("CAN sleep"));
CAN.sleep();
// Put the transceiver into standby (by pulling Rs high):
if (RS_TO_MCP2515) {
CAN.mcpDigitalWrite(RS_OUTPUT, HIGH);
} else {
digitalWrite(RS_OUTPUT, HIGH);
}
// Put the MCU to sleep
SERIAL_PORT_MONITOR.println(F("MCU sleep"));
// Clear serial buffers before sleeping
SERIAL_PORT_MONITOR.flush();
cli(); // Disable interrupts
if (!flagRecv) { // Make sure we havn't missed an interrupt between the check above and now. If an interrupt happens between now and sei()/sleep_cpu() then sleep_cpu() will immediately wake up again
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_bod_disable();
sei();
sleep_cpu();
// Now the Arduino sleeps until the next message arrives...
sleep_disable();
}
sei();
CAN.wake(); // When the MCP2515 wakes up it will be in LISTENONLY mode, here we put it into the mode it was before sleeping
// Wake up the transceiver:
if (RS_TO_MCP2515) {
CAN.mcpDigitalWrite(RS_OUTPUT, LOW);
} else {
digitalWrite(RS_OUTPUT, LOW);
}
SERIAL_PORT_MONITOR.println(F("Woke up"));
}
}
/*********************************************************************************************************
END FILE
*********************************************************************************************************/
@@ -0,0 +1,124 @@
// This is an example of receiving both standard frames and extended frames simultaneously.
// I have used two arrays, STANDARD_CAN_IDS and EXTENDED_CAN_IDS, to receive CAN messages with specific IDs.
// You need to set filters and masks for these IDs,
// and make sure to refer to and coordinate with the example for sending extended frames
#include <SPI.h>
#define CAN_2515
// #define CAN_2518FD
// Set SPI CS Pin according to your hardware
#if defined(SEEED_WIO_TERMINAL) && defined(CAN_2518FD)
// For Wio Terminal w/ MCP2518FD RPi Hat
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
const int SPI_CS_PIN = BCM8;
const int CAN_INT_PIN = BCM25;
#else
// For Arduino MCP2515 Hat:
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
#endif
#ifdef CAN_2518FD
#include "mcp2518fd_can.h"
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
#endif
#ifdef CAN_2515
#include "mcp2515_can.h"
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#endif
// Define the list of standard CAN IDs to receive
const unsigned long STANDARD_CAN_IDS[] = {0x123, 0x456};
const int STANDARD_CAN_ID_COUNT = sizeof(STANDARD_CAN_IDS) / sizeof(STANDARD_CAN_IDS[0]);
// Define the list of extended CAN IDs to receive
const unsigned long EXTENDED_CAN_IDS[] = {0x1234567, 0x89ABCDE};
const int EXTENDED_CAN_ID_COUNT = sizeof(EXTENDED_CAN_IDS) / sizeof(EXTENDED_CAN_IDS[0]);
void setup()
{
SERIAL_PORT_MONITOR.begin(115200);
while(!Serial){};
while (CAN_OK != CAN.begin(CAN_250KBPS))
{ // init can bus : baudrate = 250k
SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
delay(100);
}
SERIAL_PORT_MONITOR.println("CAN init ok!");
// Configure the standard frame filters
for (int i = 0; i < STANDARD_CAN_ID_COUNT; i++)
{
CAN.init_Mask(i, 0, 0x7FF); // Check all 11 bits of the standard frame
CAN.init_Filt(i, 0, STANDARD_CAN_IDS[i]);
}
// Configure the extended frame filters
for (int i = 0; i < EXTENDED_CAN_ID_COUNT; i++)
{
CAN.init_Mask(i + STANDARD_CAN_ID_COUNT, 1, 0x1FFFFFFF); // Check all 29 bits of the extended frame
CAN.init_Filt(i + STANDARD_CAN_ID_COUNT, 1, EXTENDED_CAN_IDS[i]);
}
}
void loop()
{
unsigned char len = 0;
unsigned char buf[8];
if (CAN_MSGAVAIL == CAN.checkReceive())
{ // check if data coming
CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf
unsigned long canId = CAN.getCanId();
// Check if it is a standard CAN ID
for (int i = 0; i < STANDARD_CAN_ID_COUNT; i++)
{
if (canId == STANDARD_CAN_IDS[i])
{
SERIAL_PORT_MONITOR.println("-----------------------------");
SERIAL_PORT_MONITOR.print("Get standard data from ID: 0x");
SERIAL_PORT_MONITOR.println(canId, HEX);
for (int j = 0; j < len; j++)
{ // print the data
SERIAL_PORT_MONITOR.print(buf[j], HEX);
SERIAL_PORT_MONITOR.print("\t");
}
SERIAL_PORT_MONITOR.println();
break;
}
}
// Check if it is an extended CAN ID
for (int i = 0; i < EXTENDED_CAN_ID_COUNT; i++)
{
if (canId == EXTENDED_CAN_IDS[i])
{
SERIAL_PORT_MONITOR.println("-----------------------------");
SERIAL_PORT_MONITOR.print("Get extended data from ID: 0x");
SERIAL_PORT_MONITOR.println(canId, HEX);
for (int j = 0; j < len; j++)
{ // print the data
SERIAL_PORT_MONITOR.print(buf[j], HEX);
SERIAL_PORT_MONITOR.print("\t");
}
SERIAL_PORT_MONITOR.println();
break;
}
}
}
}
+55 -40
View File
@@ -4,87 +4,102 @@
// loovee, Jun 12, 2017
#include <SPI.h>
#include "mcp_can.h"
#include <SD.h>
File myFile;
#define CAN_2515
// #define CAN_2518FD
// Set SPI CS Pin according to your hardware
#if defined(SEEED_WIO_TERMINAL) && defined(CAN_2518FD)
// For Wio Terminal w/ MCP2518FD RPi Hat
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
const int SPI_CS_PIN = BCM8;
const int CAN_INT_PIN = BCM25;
#else
// For Arduino MCP2515 Hat:
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_CAN = 9;
const int SPI_CS_SD = 4;
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
#endif
MCP_CAN CAN(SPI_CS_CAN); // Set CS pin
#ifdef CAN_2518FD
#include "mcp2518fd_can.h"
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
#endif
#ifdef CAN_2515
#include "mcp2515_can.h"
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#endif
unsigned char flagRecv = 0;
unsigned char len = 0;
unsigned char buf[8];
char str[20];
void setup()
{
Serial.begin(115200);
while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println("CAN BUS Shield init fail");
Serial.println("Init CAN BUS Shield again");
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
attachInterrupt(digitalPinToInterrupt(CAN_INT_PIN), MCP2515_ISR, FALLING); // start interrupt
while (CAN_OK != CAN.begin(CAN_500KBPS)) { // init can bus : baudrate = 500k
SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
delay(100);
}
Serial.println("CAN BUS Shield init ok!");
attachInterrupt(0, MCP2515_ISR, FALLING); // start interrupt
SERIAL_PORT_MONITOR.println("CAN init ok!");
if (!SD.begin(4)) {
Serial.println("SD initialization failed!");
while(1);
SERIAL_PORT_MONITOR.println("SD init fail!");
while (1);
}
Serial.println("SD initialization done.");
SERIAL_PORT_MONITOR.println("SD init OK.");
}
void MCP2515_ISR()
{
void MCP2515_ISR() {
flagRecv = 1;
}
void loop()
{
if(flagRecv)
{ // check if get data
void loop() {
if (flagRecv) {
// check if get data
flagRecv = 0; // clear flag
unsigned long id= 0;
unsigned long id = 0;
myFile = SD.open("can.csv", FILE_WRITE);
// iterate over all pending messages
// If either the bus is saturated or the MCU is busy,
// both RX buffers may be in use and reading a single
// message does not clear the IRQ conditon.
while (CAN_MSGAVAIL == CAN.checkReceive())
{
while (CAN_MSGAVAIL == CAN.checkReceive()) {
// read data, len: data length, buf: data buf
CAN.readMsgBufID(&id, &len, buf);
Serial.print(id);
Serial.print(",");
SERIAL_PORT_MONITOR.print(id);
SERIAL_PORT_MONITOR.print(",");
myFile.print(id);
myFile.print(",");
for(int i = 0; i<len; i++)
{
Serial.print(buf[i]);
Serial.print(",");
for (int i = 0; i < len; i++) {
SERIAL_PORT_MONITOR.print(buf[i]);
SERIAL_PORT_MONITOR.print(",");
myFile.print(buf[i]);
myFile.print(",");
}
Serial.println();
SERIAL_PORT_MONITOR.println();
myFile.println();
}
myFile.close();
}
}
// END FILE
// END FILE
+43 -21
View File
@@ -1,47 +1,69 @@
// demo: CAN-BUS Shield, send data
// loovee@seeed.cc
#include <mcp_can.h>
#include <SPI.h>
//#define CAN_2515
#define CAN_2518FD
// Set SPI CS Pin according to your hardware
#if defined(SEEED_WIO_TERMINAL) && defined(CAN_2518FD)
// For Wio Terminal w/ MCP2518FD RPi Hat
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
const int SPI_CS_PIN = BCM8;
const int CAN_INT_PIN = BCM25;
#else
// For Arduino MCP2515 Hat:
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
#endif
MCP_CAN CAN(SPI_CS_PIN); // Set CS pin
void setup()
{
Serial.begin(115200);
#ifdef CAN_2518FD
#include "mcp2518fd_can.h"
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
#endif
while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println("CAN BUS Shield init fail");
Serial.println(" Init CAN BUS Shield again");
#ifdef CAN_2515
#include "mcp2515_can.h"
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#endif
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
while(!Serial){};
while (CAN_OK != CAN.begin(CAN_500KBPS)) { // init can bus : baudrate = 500k
SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
delay(100);
}
Serial.println("CAN BUS Shield init ok!");
SERIAL_PORT_MONITOR.println("CAN init ok!");
}
unsigned char stmp[8] = {0, 0, 0, 0, 0, 0, 0, 0};
void loop()
{
void loop() {
// send data: id = 0x00, standrad frame, data len = 8, stmp: data buf
stmp[7] = stmp[7]+1;
if(stmp[7] == 100)
{
stmp[7] = stmp[7] + 1;
if (stmp[7] == 100) {
stmp[7] = 0;
stmp[6] = stmp[6] + 1;
if(stmp[6] == 100)
{
if (stmp[6] == 100) {
stmp[6] = 0;
stmp[5] = stmp[6] + 1;
stmp[5] = stmp[5] + 1;
}
}
CAN.sendMsgBuf(0x00, 0, 8, stmp);
delay(100); // send data per 100ms
SERIAL_PORT_MONITOR.println("CAN BUS sendMsgBuf ok!");
}
// END FILE
// END FILE
+62
View File
@@ -0,0 +1,62 @@
// demo: sendFD
// show how to send CANFD frames.
// only used with MCP2518FD shield.
#include <SPI.h>
#include "mcp2518fd_can.h"
#if defined(SEEED_WIO_TERMINAL)
const int SPI_CS_PIN = BCM8;
#else
const int SPI_CS_PIN = 9;
#endif
// CANFD could carry data up to 64 bytes
#define MAX_DATA_SIZE 64
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
while (!SERIAL_PORT_MONITOR) {}
/*
* To compatible with MCP2515 API,
* default mode is CAN_CLASSIC_MODE
* Now set to CANFD mode.
*/
CAN.setMode(CAN_NORMAL_MODE);
// init can bus : arbitration bitrate = 500k, data bitrate = 1M
while (0 != CAN.begin(CAN_500K_1M)) {
SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
delay(100);
}
SERIAL_PORT_MONITOR.println("CAN init ok!");
byte mode = CAN.getMode();
SERIAL_PORT_MONITOR.print("CAN mode = ");
SERIAL_PORT_MONITOR.println(mode);
}
unsigned char stmp[MAX_DATA_SIZE] = {0};
void loop() {
// send data: id = 0x00, standrad frame, data len = 64, stmp: data buf
stmp[MAX_DATA_SIZE - 1] = stmp[MAX_DATA_SIZE - 1] + 1;
if (stmp[MAX_DATA_SIZE - 1] == 100) {
stmp[MAX_DATA_SIZE - 1] = 0;
stmp[MAX_DATA_SIZE - 2] = stmp[MAX_DATA_SIZE - 2] + 1;
if (stmp[MAX_DATA_SIZE - 2] == 100) {
stmp[MAX_DATA_SIZE - 2] = 0;
stmp[MAX_DATA_SIZE - 3] = stmp[MAX_DATA_SIZE - 3] + 1;
}
}
CAN.sendMsgBuf(0x00, 0, CANFD::len2dlc(MAX_DATA_SIZE), stmp);
delay(100); // send data per 100ms
SERIAL_PORT_MONITOR.println("CAN BUS sendMsgBuf ok!");
}
// END FILE
+40 -16
View File
@@ -1,37 +1,61 @@
// demo: CAN-BUS Shield, send data
#include <mcp_can.h>
#include <SPI.h>
//#define CAN_2515
#define CAN_2518FD
// Set SPI CS Pin according to your hardware
#if defined(SEEED_WIO_TERMINAL) && defined(CAN_2518FD)
// For Wio Terminal w/ MCP2518FD RPi Hat
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
const int SPI_CS_PIN = BCM8;
const int CAN_INT_PIN = BCM25;
#else
// For Arduino MCP2515 Hat:
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
#endif
#ifdef CAN_2518FD
#include "mcp2518fd_can.h"
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
#endif
#ifdef CAN_2515
#include "mcp2515_can.h"
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#endif
const int ledHIGH = 1;
const int ledLOW = 0;
MCP_CAN CAN(SPI_CS_PIN); // Set CS pin
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
void setup()
{
Serial.begin(115200);
while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println("CAN BUS Shield init fail");
Serial.println(" Init CAN BUS Shield again");
while (CAN_OK != CAN.begin(CAN_500KBPS)) { // init can bus : baudrate = 500k
SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
delay(100);
}
Serial.println("CAN BUS Shield init ok!");
SERIAL_PORT_MONITOR.println("CAN init ok!");
}
unsigned char stmp[8] = {ledHIGH, 1, 2, 3, ledLOW, 5, 6, 7};
void loop()
{ Serial.println("In loop");
// send data: id = 0x00, standard frame, data len = 8, stmp: data buf
CAN.sendMsgBuf(0x70,0, 8, stmp);
void loop() {
SERIAL_PORT_MONITOR.println("In loop");
// send data: id = 0x70, standard frame, data len = 8, stmp: data buf
CAN.sendMsgBuf(0x70, 0, 8, stmp);
delay(1000); // send data once per second
}
/*********************************************************************************************************
END FILE
END FILE
*********************************************************************************************************/
+18 -24
View File
@@ -8,10 +8,8 @@
// rostopic pub toggle_led std_msgs/Empty -r 100
// Jaghvi: jaghvim@andrew.cmu.edu
#include <mcp_can.h>
#include <SPI.h>
#include "mcp2515_can.h"
//ROS
#include <ros.h>
#include <std_msgs/Empty.h>
@@ -19,49 +17,45 @@
ros::NodeHandle nh;
const int SPI_CS_PIN = 9;
const int ledHIGH=1;
const int ledLOW=0;
const int ledHIGH = 1;
const int ledLOW = 0;
unsigned char stmp[8] = {ledHIGH, 1, 2, 3, ledLOW, 5, 6, 7};
MCP_CAN CAN(SPI_CS_PIN); // Set CS pin
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
void messageCb( const std_msgs::Empty& toggle_msg){
//digitalWrite(13, HIGH-digitalRead(13)); // blink the led
// send data: id = 0x00, standrad frame, data len = 8, stmp: data buf
CAN.sendMsgBuf(0x70,0, 8, stmp);
delay(1000); // send data per 100ms
void messageCb(const std_msgs::Empty& toggle_msg) {
//digitalWrite(13, HIGH-digitalRead(13)); // blink the led
// send data: id = 0x00, standrad frame, data len = 8, stmp: data buf
CAN.sendMsgBuf(0x70, 0, 8, stmp);
delay(1000); // send data per 100ms
}
ros::Subscriber<std_msgs::Empty> sub("toggle_led", &messageCb );
ros::Subscriber<std_msgs::Empty> sub("toggle_led", &messageCb);
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
void setup()
{
Serial.begin(115200);
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
nh.initNode();
nh.subscribe(sub);
while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println("CAN BUS Shield init fail");
Serial.println(" Init CAN BUS Shield again");
while (CAN_OK != CAN.begin(CAN_500KBPS)) { // init can bus : baudrate = 500k
SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
delay(100);
}
Serial.println("CAN BUS Shield init ok!");
SERIAL_PORT_MONITOR.println("CAN init ok!");
}
void loop()
{
void loop() {
nh.spinOnce();
delay(1);
}
/*********************************************************************************************************
END FILE
END FILE
*********************************************************************************************************/
@@ -0,0 +1,93 @@
// demo: CAN-BUS Shield, send data
// This is an example of sending both standard frames and extended frames simultaneously.
// I have used two arrays, STANDARD_CAN_IDS and EXTENDED_CAN_IDS, to store the IDs to be sent, and it supports defining custom send IDs
#include <SPI.h>
#define CAN_2515
// #define CAN_2518FD
// Set SPI CS Pin according to your hardware
#if defined(SEEED_WIO_TERMINAL) && defined(CAN_2518FD)
// For Wio Terminal w/ MCP2518FD RPi Hat
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
const int SPI_CS_PIN = BCM8;
const int CAN_INT_PIN = BCM25;
#else
// For Arduino MCP2515 Hat:
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
#endif
#ifdef CAN_2518FD
#include "mcp2518fd_can.h"
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
#endif
#ifdef CAN_2515
#include "mcp2515_can.h"
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#endif
// Define the list of standard CAN IDs to receive
const unsigned long STANDARD_CAN_IDS[] = {0x123, 0x456};
const int STANDARD_CAN_ID_COUNT = sizeof(STANDARD_CAN_IDS) / sizeof(STANDARD_CAN_IDS[0]);
// Define the list of extended CAN IDs to receive
const unsigned long EXTENDED_CAN_IDS[] = {0x1234567, 0x89ABCDE};
const int EXTENDED_CAN_ID_COUNT = sizeof(EXTENDED_CAN_IDS) / sizeof(EXTENDED_CAN_IDS[0]);
void setup()
{
SERIAL_PORT_MONITOR.begin(115200);
while(!Serial){};
while (CAN_OK != CAN.begin(CAN_500KBPS))
{ // init can bus : baudrate = 500k
SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
delay(100);
}
SERIAL_PORT_MONITOR.println("CAN init ok!");
}
unsigned char stmp[8] = {0, 0, 0, 0, 0, 0, 0, 0};
void loop()
{
// send data: id = 0x00, standrad frame, data len = 8, stmp: data buf
stmp[7] = stmp[7] + 1;
if (stmp[7] == 100)
{
stmp[7] = 0;
stmp[6] = stmp[6] + 1;
if (stmp[6] == 100)
{
stmp[6] = 0;
stmp[5] = stmp[5] + 1;
}
}
for (int i = 0; i < STANDARD_CAN_ID_COUNT; i++)
{
CAN.sendMsgBuf(STANDARD_CAN_IDS[i], 0, 8, stmp);//using ID List ID
delay(100);
}
for (int i = 0; i < EXTENDED_CAN_ID_COUNT; i++)
{
CAN.sendMsgBuf(EXTENDED_CAN_IDS[i], 1, 8, stmp);//using ID List ID
delay(100);
}
}
/*********************************************************************************************************
END FILE
*********************************************************************************************************/
+137
View File
@@ -0,0 +1,137 @@
/*
* demo: CAN-BUS Shield, send random id/type/data
* This code has a little same with linux can-utils 'cangen -v'
*
* Copyright (C) 2020 Seeed Technology Co.,Ltd.
*/
#include <SPI.h>
#define CAN_2515
// #define CAN_2518FD
// Set SPI CS Pin according to your hardware
#if defined(SEEED_WIO_TERMINAL) && defined(CAN_2518FD)
// For Wio Terminal w/ MCP2518FD RPi Hat
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
const int SPI_CS_PIN = BCM8;
const int CAN_INT_PIN = BCM25;
#else
// For Arduino MCP2515 Hat:
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
#endif
#ifdef CAN_2518FD
#include "mcp2518fd_can.h"
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
// TEST TEST MCP2518FD CAN2.0 data transfer
#define MAX_DATA_SIZE 8
// To TEST MCP2518FD CANFD data transfer, uncomment below lines
// #undef MAX_DATA_SIZE
// #define MAX_DATA_SIZE 64
#endif//CAN_2518FD
#ifdef CAN_2515
#include "mcp2515_can.h"
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#define MAX_DATA_SIZE 8
#endif
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
while (!SERIAL_PORT_MONITOR) {}
#if MAX_DATA_SIZE > 8
/*
* To compatible with MCP2515 API,
* default mode is CAN_CLASSIC_MODE
* Now set to CANFD mode.
*/
CAN.setMode(CAN_NORMAL_MODE);
#endif
while (CAN_OK != CAN.begin(CAN_500KBPS)) { // init can bus : baudrate = 500k
SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
delay(100);
}
SERIAL_PORT_MONITOR.println("CAN init ok!");
randomSeed(millis());
}
uint32_t id;
uint8_t type; // bit0: ext, bit1: rtr
unsigned len;
byte cdata[MAX_DATA_SIZE] = {0};
void loop() {
type = random(4);
if (type & 0x1) {
// total 29 bits
// Arduino AVR only generate up to 16 bits random number
id = random(0x1U << 14);
id |= (uint32_t)random(0x1U << 15) << 14;
} else {
id = random(0x1U << 11);
}
if (type & 0x2) {
len = 0;
// remote frame could also carry data
// but don't do it.
// len = random(0, MAX_DATA_SIZE + 1);
} else {
len = random(0, MAX_DATA_SIZE + 1);
}
int i;
for (i = 0; i < len; i++) {
cdata[i] = random(0x100);
}
#if MAX_DATA_SIZE > 8
// pad CANFD extra bytes with 0
for (i = len; i < MAX_DATA_SIZE; i++) {
cdata[i] = 0;
}
#endif
CAN.sendMsgBuf(id, bool(type & 0x1),
bool(type & 0x2),
#if MAX_DATA_SIZE > 8
CANFD::len2dlc(len),
#else
len,
#endif
cdata);
char prbuf[32 + MAX_DATA_SIZE * 3];
int n;
/* Displayed type:
*
* 0x00: standard data frame
* 0x02: extended data frame
* 0x30: standard remote frame
* 0x32: extended remote frame
*/
static const byte type2[] = {0x00, 0x02, 0x30, 0x32};
n = sprintf(prbuf, "TX: [%08lX](%02X) ", (unsigned long)id, type2[type]);
// n = sprintf(prbuf, "TX: [%08lX](%02X) ", id, type);
for (i = 0; i < len; i++) {
n += sprintf(prbuf + n, "%02X ", cdata[i]);
}
SERIAL_PORT_MONITOR.println(prbuf);
unsigned d = random(30);
SERIAL_PORT_MONITOR.println(d);
delay(d);
}
// END FILE
+71
View File
@@ -0,0 +1,71 @@
/*
This is an example of sending and receiving on its own, connect two channels to each other using jumpers.
*/
#include <SPI.h>
#include "mcp2518fd_can.h"
// Set SPI CS Pin according to your hardware
// For Wio Terminal w/ MCP2518FD RPi Hat
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
// *****************************************
// For Arduino MCP2515 Hat:
// SPI_CS Pin: D9
const int SPI_CS_PIN_SEND = 9;
const int SPI_CS_PIN_RECEIVE = 10;
mcp2518fd CAN_SEND(SPI_CS_PIN_SEND);
mcp2518fd CAN_RECEIVE(SPI_CS_PIN_RECEIVE);
unsigned char len = 0;
unsigned char buf[8];
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
while(!Serial); // wait for Serial
if (CAN_SEND.begin(CAN_500K_1M) != 0 || CAN_RECEIVE.begin(CAN_500K_1M) != 0) {
SERIAL_PORT_MONITOR.println("CAN-BUS initiliased error!");
while(1);
}
SERIAL_PORT_MONITOR.println("CAN init ok!");
}
unsigned char stmp[8] = {0, 0, 0, 0, 0, 0, 0, 0};
void loop() {
// send data: id = 0x00, standrad frame, data len = 8, stmp: data buf
stmp[7] = stmp[7] + 1;
if (stmp[7] == 100) {
stmp[7] = 0;
stmp[6] = stmp[6] + 1;
if (stmp[6] == 100) {
stmp[6] = 0;
stmp[5] = stmp[5] + 1;
}
}
CAN_SEND.sendMsgBuf(0x00, 0, 8, stmp);
delay(100); // send data per 100ms
SERIAL_PORT_MONITOR.println("CAN BUS sendMsgBuf ok!");
// ---------------------
if (CAN_MSGAVAIL == CAN_RECEIVE.checkReceive()) {
// read data, len: data length, buf: data buf
SERIAL_PORT_MONITOR.println("checkReceive");
CAN_RECEIVE.readMsgBuf(&len, buf);
// print the data
for (int i = 0; i < len; i++) {
SERIAL_PORT_MONITOR.print(buf[i]); SERIAL_PORT_MONITOR.print(" ");
}
SERIAL_PORT_MONITOR.println();
}
SERIAL_PORT_MONITOR.println("---LOOP END---");
}
// END FILE
@@ -0,0 +1,87 @@
/*
* This is an example of sending and receiving (FD) on its own,
* connect two channels to each other using jumpers.
*/
#include <SPI.h>
#include "mcp2518fd_can.h"
// Set SPI CS Pin according to your hardware
// For Wio Terminal w/ MCP2518FD RPi Hat
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
// *****************************************
// For Arduino MCP2515 Hat:
// SPI_CS Pin: D9
const int SPI_CS_PIN_SEND = 9;
const int SPI_CS_PIN_RECEIVE = 2;
mcp2518fd CAN_SEND(SPI_CS_PIN_SEND);
mcp2518fd CAN_RECEIVE(SPI_CS_PIN_RECEIVE);
// CANFD could carry data up to 64 bytes
#define MAX_DATA_SIZE 64
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
while (!SERIAL_PORT_MONITOR) {} // wait for Serial
/*
* To compatible with MCP2515 API,
* default mode is CAN_CLASSIC_MODE
* Now set to CANFD mode.
*/
CAN_SEND.setMode(CAN_NORMAL_MODE);
CAN_RECEIVE.setMode(CAN_NORMAL_MODE);
if (CAN_SEND.begin(CAN_500K_1M) != 0 || CAN_RECEIVE.begin(CAN_500K_1M) != 0) {
SERIAL_PORT_MONITOR.println("CAN-BUS initiliased error!");
while (1);
}
byte send_mode = CAN_SEND.getMode();
byte receive_mode = CAN_RECEIVE.getMode();
SERIAL_PORT_MONITOR.print("CAN BUS Send Mode = "); SERIAL_PORT_MONITOR.println(send_mode);
SERIAL_PORT_MONITOR.print("CAN BUS Receive Mode = "); SERIAL_PORT_MONITOR.println(receive_mode);
SERIAL_PORT_MONITOR.println("CAN BUS Shield init ok!");
}
unsigned char stmp[MAX_DATA_SIZE] = {0};
unsigned char len = 0;
unsigned char buf[MAX_DATA_SIZE];
void loop() {
// send data: id = 0x00, standrad frame, data len = 64, stmp: data buf
stmp[MAX_DATA_SIZE - 1] = stmp[MAX_DATA_SIZE - 1] + 1;
if (stmp[MAX_DATA_SIZE - 1] == 100) {
stmp[MAX_DATA_SIZE - 1] = 0;
stmp[MAX_DATA_SIZE - 2] = stmp[MAX_DATA_SIZE - 2] + 1;
if (stmp[MAX_DATA_SIZE - 2] == 100) {
stmp[MAX_DATA_SIZE - 2] = 0;
stmp[MAX_DATA_SIZE - 3] = stmp[MAX_DATA_SIZE - 3] + 1;
}
}
CAN_SEND.sendMsgBuf(0x00, 0, CANFD::len2dlc(MAX_DATA_SIZE), stmp);
delay(100); // send data per 100ms
SERIAL_PORT_MONITOR.println("CAN BUS sendMsgBuf ok!");
// ---------------------
if (CAN_MSGAVAIL == CAN_RECEIVE.checkReceive()) {
// read data, len: data length, buf: data buf
SERIAL_PORT_MONITOR.println("checkReceive");
CAN_RECEIVE.readMsgBuf(&len, buf);
// print the data
for (int i = 0; i < len; i++) {
SERIAL_PORT_MONITOR.print(buf[i]);
SERIAL_PORT_MONITOR.print(' ');
}
SERIAL_PORT_MONITOR.println();
}
SERIAL_PORT_MONITOR.println("---LOOP END---");
}
// END FILE
+132
View File
@@ -0,0 +1,132 @@
// demo: CAN Sleep Example - send
// *** only works on AVR + MCP2515 platform
//
// by Kai, based on the send example by loovee and the additions from Zak Kemble (https://github.com/coryjfowler/MCP_CAN_lib/pull/10/files)
//
// See receive_sleep example for additional notes.
#include "mcp2515_can.h"
#include <SPI.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
// To use the sleep mode of the transceiver (MCP2551), it's Rs pin must be connected to either the MCP2515 or
// any free Arduino output.
#define RS_TO_MCP2515 true // Set this to false if Rs is connected to your Arduino
#define RS_OUTPUT MCP_RX0BF // RX0BF is a pin of the MCP2515. You can also define an Arduino pin here
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
// Watchdog interrupt, used to wake the MCU periodically.
ISR(WDT_vect) {
wdt_disable(); // disable watchdog
}
void sleepMCU()
// Sleep the MCU for one second.
// See http://www.gammon.com.au/power for details.
// (You can make your life a lot easyer by using one of the numeral low power libraries for Arduino.)
{
// disable ADC
ADCSRA = 0;
// clear various "reset" flags
MCUSR = 0;
// allow changes, disable reset
WDTCSR = bit(WDCE) | bit(WDE);
// set interrupt mode and an interval
WDTCSR = bit(WDIE) | bit(WDP2) | bit(WDP1); // set WDIE, and 1 second delay
wdt_reset(); // pat the dog
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
noInterrupts(); // timed sequence follows
sleep_enable();
// turn off brown-out enable in software
MCUCR = bit(BODS) | bit(BODSE);
MCUCR = bit(BODS);
interrupts(); // guarantees next instruction executed
sleep_cpu();
// cancel sleep as a precaution
sleep_disable();
}
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
while (CAN_OK != CAN.begin(CAN_500KBPS, MCP_16MHz)) { // init can bus : baudrate = 500k
SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
delay(100);
}
SERIAL_PORT_MONITOR.println("CAN init ok!");
CAN.setSleepWakeup(0); // the MCP2515 will NOT wake up on incoming messages,
// making it a 'send only' node
// Pull the Rs pin of the MCP2551 transceiver low to enable it:
if (RS_TO_MCP2515) {
CAN.mcpPinMode(MCP_RX0BF, MCP_PIN_OUT);
CAN.mcpDigitalWrite(RS_OUTPUT, LOW);
} else {
pinMode(RS_OUTPUT, OUTPUT);
digitalWrite(RS_OUTPUT, LOW);
}
}
unsigned char stmp[8] = {0, 0, 0, 0, 0, 0, 0, 0};
void loop() {
SERIAL_PORT_MONITOR.println("Sending message");
CAN.sendMsgBuf(0x00, 0, 0, NULL); // Send empty wakeup message
delay(100); // give the receiving node some time to wake up
// send data: id = 0x00, standard frame, data len = 8, stmp: data buf
stmp[7] = stmp[7] + 1;
if (stmp[7] == 100) {
stmp[7] = 0;
stmp[6] = stmp[6] + 1;
if (stmp[6] == 100) {
stmp[6] = 0;
stmp[5] = stmp[5] + 1;
}
}
CAN.sendMsgBuf(0x00, 0, 8, stmp);
// sleep
SERIAL_PORT_MONITOR.println("Sleep");
SERIAL_PORT_MONITOR.flush();
// Put MCP2515 into sleep mode
CAN.sleep();
// Put the transceiver into standby (by pulling Rs high):
if (RS_TO_MCP2515) {
CAN.mcpDigitalWrite(RS_OUTPUT, HIGH);
} else {
digitalWrite(RS_OUTPUT, HIGH);
}
// Put the MCU to sleep for one second
sleepMCU();
// wake MCP2515 and transceiver
CAN.wake();
if (RS_TO_MCP2515) {
CAN.mcpDigitalWrite(RS_OUTPUT, LOW);
} else {
digitalWrite(RS_OUTPUT, LOW);
}
}
// END FILE
@@ -4,45 +4,64 @@
// loovee, 2014-7-8
#include <SPI.h>
#include "mcp_can.h"
#define CAN_2515
// #define CAN_2518FD
// Set SPI CS Pin according to your hardware
#if defined(SEEED_WIO_TERMINAL) && defined(CAN_2518FD)
// For Wio Terminal w/ MCP2518FD RPi Hat
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
const int SPI_CS_PIN = BCM8;
const int CAN_INT_PIN = BCM25;
#else
// For Arduino MCP2515 Hat:
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
#endif
MCP_CAN CAN(SPI_CS_PIN); // Set CS pin
#ifdef CAN_2518FD
#include "mcp2518fd_can.h"
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
#endif
#ifdef CAN_2515
#include "mcp2515_can.h"
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#endif
unsigned char flagRecv = 0;
unsigned char len = 0;
unsigned char buf[8];
char str[20];
void setup()
{
Serial.begin(115200);
while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println("CAN BUS Shield init fail");
Serial.println(" Init CAN BUS Shield again");
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
while(!Serial){};
attachInterrupt(digitalPinToInterrupt(CAN_INT_PIN), MCP2515_ISR, FALLING); // start interrupt
while (CAN_OK != CAN.begin(CAN_500KBPS)) { // init can bus : baudrate = 500k
SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
delay(100);
}
Serial.println("CAN BUS Shield init ok!");
attachInterrupt(0, MCP2515_ISR, FALLING); // start interrupt
SERIAL_PORT_MONITOR.println("CAN init ok!");
/*
* set mask, set both the mask to 0x3ff
*/
set mask, set both the mask to 0x3ff
*/
CAN.init_Mask(0, 0, 0x3ff); // there are 2 mask in mcp2515, you need to set both of them
CAN.init_Mask(1, 0, 0x3ff);
/*
* set filter, we can receive id from 0x04 ~ 0x09
*/
set filter, we can receive id from 0x04 ~ 0x09
*/
CAN.init_Filt(0, 0, 0x04); // there are 6 filter in mcp2515
CAN.init_Filt(1, 0, 0x05); // there are 6 filter in mcp2515
@@ -50,36 +69,30 @@ void setup()
CAN.init_Filt(3, 0, 0x07); // there are 6 filter in mcp2515
CAN.init_Filt(4, 0, 0x08); // there are 6 filter in mcp2515
CAN.init_Filt(5, 0, 0x09); // there are 6 filter in mcp2515
}
void MCP2515_ISR()
{
void MCP2515_ISR() {
flagRecv = 1;
}
void loop()
{
if(flagRecv) // check if get data
{
void loop() {
if (flagRecv) { // check if get data
flagRecv = 0; // clear flag
CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf
Serial.println("\r\n------------------------------------------------------------------");
Serial.print("Get Data From id: ");
Serial.println(CAN.getCanId());
for(int i = 0; i<len; i++) // print the data
{
Serial.print("0x");
Serial.print(buf[i], HEX);
Serial.print("\t");
SERIAL_PORT_MONITOR.println("\r\n------------------------------------------------------------------");
SERIAL_PORT_MONITOR.print("Get Data From id: ");
SERIAL_PORT_MONITOR.println(CAN.getCanId());
for (int i = 0; i < len; i++) { // print the data
SERIAL_PORT_MONITOR.print("0x");
SERIAL_PORT_MONITOR.print(buf[i], HEX);
SERIAL_PORT_MONITOR.print("\t");
}
Serial.println();
SERIAL_PORT_MONITOR.println();
}
}
/*********************************************************************************************************
END FILE
*********************************************************************************************************/
END FILE
*********************************************************************************************************/
@@ -1,34 +1,55 @@
// demo: set_mask_filter_send
// this demo will show you how to use mask and filter
#include <mcp_can.h>
#include <SPI.h>
#define CAN_2515
// #define CAN_2518FD
// Set SPI CS Pin according to your hardware
#if defined(SEEED_WIO_TERMINAL) && defined(CAN_2518FD)
// For Wio Terminal w/ MCP2518FD RPi Hat
// Channel 0 SPI_CS Pin: BCM 8
// Channel 1 SPI_CS Pin: BCM 7
// Interupt Pin: BCM25
const int SPI_CS_PIN = BCM8;
const int CAN_INT_PIN = BCM25;
#else
// For Arduino MCP2515 Hat:
// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
const int CAN_INT_PIN = 2;
#endif
MCP_CAN CAN(SPI_CS_PIN); // Set CS pin
void setup()
{
Serial.begin(115200);
#ifdef CAN_2518FD
#include "mcp2518fd_can.h"
mcp2518fd CAN(SPI_CS_PIN); // Set CS pin
#endif
while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
Serial.println("CAN BUS Shield init fail");
Serial.println(" Init CAN BUS Shield again");
#ifdef CAN_2515
#include "mcp2515_can.h"
mcp2515_can CAN(SPI_CS_PIN); // Set CS pin
#endif
void setup() {
SERIAL_PORT_MONITOR.begin(115200);
while(!Serial){};
while (CAN_OK != CAN.begin(CAN_500KBPS)) { // init can bus : baudrate = 500k
SERIAL_PORT_MONITOR.println("CAN init fail, retry...");
delay(100);
}
Serial.println("CAN BUS Shield init ok!");
SERIAL_PORT_MONITOR.println("CAN init ok!");
}
unsigned char stmp[8] = {0, 1, 2, 3, 4, 5, 6, 7};
void loop()
{
for(int id=0; id<10; id++)
{
void loop() {
for (int id = 0; id < 10; id++) {
memset(stmp, id, sizeof(stmp)); // set id to send data buff
CAN.sendMsgBuf(id, 0, sizeof(stmp), stmp);
delay(100);
@@ -36,5 +57,5 @@ void loop()
}
/*********************************************************************************************************
END FILE
END FILE
*********************************************************************************************************/
+5 -3
View File
@@ -29,19 +29,21 @@ CAN_5KBPS LITERAL1
CAN_10KBPS LITERAL1
CAN_20KBPS LITERAL1
CAN_25KBPS LITERAL1
CAN_31KBPS LITERAL1
CAN_31K25BPS LITERAL1
CAN_33KBPS LITERAL1
CAN_40KBPS LITERAL1
CAN_50KBPS LITERAL1
CAN_80KBPS LITERAL1
CAN_83KBPS LITERAL1
CAN_83K3BPS LITERAL1
CAN_95KBPS LITERAL1
CAN_95K2BPS LITERAL1
CAN_100KBPS LITERAL1
CAN_125KBPS LITERAL1
CAN_200KBPS LITERAL1
CAN_250KBPS LITERAL1
CAN_500KBPS LITERAL1
CAN_666KBPS LITERAL1
CAN_800KBPS LITERAL1
CAN_1000KBPS LITERAL1
CAN_OK LITERAL1
CAN_FAILINIT LITERAL1
@@ -52,4 +54,4 @@ CAN_CTRLERROR LITERAL1
CAN_GETTXBFTIMEOUT LITERAL1
CAN_SENDMSGTIMEOUT LITERAL1
CAN_FAIL LITERAL1
SPI_CS_PIN LITERAL1
SPI_CS_PIN LITERAL1
+5 -5
View File
@@ -1,13 +1,13 @@
{
"name": "CAN_BUS_Shield",
"keywords": "can, bus, mcp2515, MCP-2515",
"description": "Library provides CAN communication on the CAN-Bus Shield.",
"keywords": "can, bus, mcp2518fd, mcp2515",
"description": "Seeed Arduino library to control CAN BUS and CAN BUS FD.",
"repository":
{
"type": "git",
"url": "https://github.com/Seeed-Studio/CAN_BUS_Shield.git"
"url": "https://github.com/Seeed-Studio/Seeed_Arduino_CAN.git"
},
"version": "1.20",
"version": "2.3.3",
"frameworks": "arduino",
"platforms": "atmelavr"
"platforms": "*"
}
+6 -6
View File
@@ -1,9 +1,9 @@
name=CAN-BUS Shield
version=1.0.0
name=CAN_BUS_Shield
version=2.3.4
author=Seeed Studio
maintainer=Seeed Studio <techsupport@seeed.cc>
sentence=Arduino library to control CAN-BUS Shield.
paragraph=Arduino library to control CAN-BUS Shield.
sentence=Seeed Arduino library to control CAN BUS and CAN BUS FD.
paragraph=Seeed Arduino library to control CAN BUS and CAN BUS FD.
category=Device Control
url=https://github.com/Seeed-Studio/CAN_BUS_Shield
architectures=*
url=https://github.com/Seeed-Studio/Seeed_Arduino_CAN
architectures=*
-1302
View File
File diff suppressed because it is too large Load Diff
-157
View File
@@ -1,157 +0,0 @@
/*
mcp_can.h
2012 Copyright (c) Seeed Technology Inc. All right reserved.
Author:Loovee (loovee@seeed.cc)
2014-1-16
Contributor:
Cory J. Fowler
Latonita
Woodward1
Mehtajaghvi
BykeBlast
TheRo0T
Tsipizic
ralfEdmund
Nathancheek
BlueAndi
Adlerweb
Btetz
Hurvajs
ttlappalainen
The MIT License (MIT)
Copyright (c) 2013 Seeed Technology Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef _MCP2515_H_
#define _MCP2515_H_
#include "mcp_can_dfs.h"
#define MAX_CHAR_IN_MESSAGE 8
class MCP_CAN
{
private:
byte ext_flg; // identifier xxxID
// either extended (the 29 LSB) or standard (the 11 LSB)
unsigned long can_id; // can id
byte rtr; // rtr
byte SPICS;
SPIClass *pSPI;
byte nReservedTx; // Count of tx buffers for reserved send
/*
* mcp2515 driver function
*/
private:
void mcp2515_reset(void); // reset mcp2515
byte mcp2515_readRegister(const byte address); // read mcp2515's register
void mcp2515_readRegisterS(const byte address,
byte values[],
const byte n);
void mcp2515_setRegister(const byte address, // set mcp2515's register
const byte value);
void mcp2515_setRegisterS(const byte address, // set mcp2515's registers
const byte values[],
const byte n);
void mcp2515_initCANBuffers(void);
void mcp2515_modifyRegister(const byte address, // set bit of one register
const byte mask,
const byte data);
byte mcp2515_readStatus(void); // read mcp2515's Status
byte mcp2515_setCANCTRL_Mode(const byte newmode); // set mode
byte mcp2515_configRate(const byte canSpeed, const byte clock); // set baudrate
byte mcp2515_init(const byte canSpeed, const byte clock); // mcp2515init
void mcp2515_write_id( const byte mcp_addr, // write can id
const byte ext,
const unsigned long id );
void mcp2515_read_id( const byte mcp_addr, // read can id
byte* ext,
unsigned long* id );
void mcp2515_write_canMsg( const byte buffer_sidh_addr, unsigned long id, byte ext, byte rtr, byte len, volatile const byte *buf); // read can msg
void mcp2515_read_canMsg( const byte buffer_load_addr, volatile unsigned long *id, volatile byte *ext, volatile byte *rtr, volatile byte *len, volatile byte *buf); // write can msg
void mcp2515_start_transmit(const byte mcp_addr); // start transmit
byte mcp2515_getNextFreeTXBuf(byte *txbuf_n); // get Next free txbuf
byte mcp2515_isTXBufFree(byte *txbuf_n, byte iBuf); // is buffer by index free
/*
* can operator function
*/
byte sendMsg(unsigned long id, byte ext, byte rtrBit, byte len, const byte *buf, bool wait_sent=true); // send message
public:
MCP_CAN(byte _CS=0);
void init_CS(byte _CS); // define CS after construction before begin()
void setSPI(SPIClass *_pSPI) { pSPI=_pSPI; } // define SPI port to use before begin()
void enableTxInterrupt(bool enable=true); // enable transmit interrupt
void reserveTxBuffers(byte nTxBuf=0) { nReservedTx=(nTxBuf<MCP_N_TXBUFFERS?nTxBuf:MCP_N_TXBUFFERS-1); }
byte getLastTxBuffer() { return MCP_N_TXBUFFERS-1; } // read index of last tx buffer
byte begin(byte speedset, const byte clockset = MCP_16MHz); // init can
byte init_Mask(byte num, byte ext, unsigned long ulData); // init Masks
byte init_Filt(byte num, byte ext, unsigned long ulData); // init filters
byte sendMsgBuf(unsigned long id, byte ext, byte rtrBit, byte len, const byte *buf, bool wait_sent=true); // send buf
byte sendMsgBuf(unsigned long id, byte ext, byte len, const byte *buf, bool wait_sent=true); // send buf
byte readMsgBuf(byte *len, byte *buf); // read buf
byte readMsgBufID(unsigned long *ID, byte *len, byte *buf); // read buf with object ID
byte checkReceive(void); // if something received
byte checkError(void); // if something error
unsigned long getCanId(void); // get can id when receive
byte isRemoteRequest(void); // get RR flag when receive
byte isExtendedFrame(void); // did we recieve 29bit frame?
byte readMsgBufID(byte status, volatile unsigned long *id, volatile byte *ext, volatile byte *rtr, volatile byte *len, volatile byte *buf); // read buf with object ID
byte trySendMsgBuf(unsigned long id, byte ext, byte rtrBit, byte len, const byte *buf, byte iTxBuf=0xff); // as sendMsgBuf, but does not have any wait for free buffer
byte sendMsgBuf(byte status, unsigned long id, byte ext, byte rtrBit, byte len, volatile const byte *buf); // send message buf by using parsed buffer status
inline byte trySendExtMsgBuf(unsigned long id, byte len, const byte *buf, byte iTxBuf=0xff) { // as trySendMsgBuf, but set ext=1 and rtr=0
return trySendMsgBuf(id,1,0,len,buf,iTxBuf);
}
inline byte sendExtMsgBuf(byte status, unsigned long id, byte len, volatile const byte *buf) { // as sendMsgBuf, but set ext=1 and rtr=0
return sendMsgBuf(status,id,1,0,len,buf);
}
void clearBufferTransmitIfFlags(byte flags=0); // Clear transmit flags according to status
byte readRxTxStatus(void); // read has something send or received
byte checkClearRxStatus(byte *status); // read and clear and return first found rx status bit
byte checkClearTxStatus(byte *status, byte iTxBuf=0xff); // read and clear and return first found or buffer specified tx status bit
};
#endif
/*********************************************************************************************************
END FILE
*********************************************************************************************************/
+576
View File
@@ -0,0 +1,576 @@
/*****************************************************************************************
* This is implementation of CAN BUS ASCII protocol based on LAWICEL v1.3 serial protocol
* of CAN232/CANUSB device (http://www.can232.com/docs/can232_v3.pdf)
*
* Made for Arduino with Seeduino/ElecFreaks CAN BUS Shield based on MCP2515
*
* Copyright (C) 2015 Anton Viktorov <latonita@yandex.ru>
* https://github.com/latonita/can-ascii
*
* This library is free software. You may use/redistribute it under The MIT License terms.
*
*****************************************************************************************/
#include <SPI.h>
#include "mcp_can.h"
#include "can-serial.h"
// #define LOGGING_ENABLED
#ifdef LOGGING_ENABLED
#define dbg_begin(x) debug.begin(x)
#define dbg0(x) debug.print(x)
#define dbg1(x) debug.println(x)
#define dbg2(x,y) debug.print(x); debug.println(y)
#define dbgH(x) debug.print(x,HEX)
#define DEBUG_RX_PIN 8
#define DEBUG_TX_PIN 9
#else
#define dbg_begin(x)
#define dbg0(x)
#define dbg1(x)
#define dbg2(x,y)
#define dbgH(x)
#endif
#ifdef LOGGING_ENABLED
#include "SoftwareSerial.h"
// software serial #2: TX = digital pin 8, RX = digital pin 9
// on the Mega, use other pins instead, since 8 and 9 don't work on the Mega
SoftwareSerial debug(DEBUG_RX_PIN, DEBUG_TX_PIN);
//#define debug Serial
#endif
Can232* Can232::_instance = 0;
Can232* Can232::instance() {
if (_instance == 0)
_instance = new Can232();
return _instance;
}
void Can232::init(INT8U defaultCanSpeed, const INT8U clock) {
dbg_begin(LW232_DEFAULT_BAUD_RATE); // logging through software serial
dbg1("CAN ASCII. Welcome to debug");
instance()->lw232CanSpeedSelection = defaultCanSpeed;
instance()->lw232McpModuleClock = clock;
instance()->initFunc();
}
MCP_CAN* Can232::MCP_OBJECT = NULL;
void Can232::attach(MCP_CAN *CAN) {
MCP_OBJECT = CAN;
#define lw232CAN MCP_OBJECT
}
void Can232::setFilter(INT8U (*userFunc)(INT32U)) {
instance()->setFilterFunc(userFunc);
}
void Can232::loop() {
instance()->loopFunc();
}
void Can232::serialEvent() {
instance()->serialEventFunc();
}
void Can232::initFunc() {
if (!inputString.reserve(LW232_INPUT_STRING_BUFFER_SIZE)) {
dbg0("inputString.reserve failed in initFunc. less optimal String work is expected");
}
// lw232AutoStart = true; //todo: read from eeprom
// lw232AutoPoll = false; //todo: read from eeprom
// lw232TimeStamp = //read from eeprom
// lw232Message[0] = 'Z'; lw232Message[1] = '1'; exec();
//if (lw232AutoStart) {
inputString = "O\x0D";
stringComplete = true;
loopFunc();
//}
}
void Can232::setFilterFunc(INT8U (*userFunc)(INT32U)) {
instance()->userAddressFilterFunc = userFunc;
}
void Can232::loopFunc() {
if (stringComplete) {
unsigned len = inputString.length();
if (len > 0 && len < LW232_FRAME_MAX_SIZE) {
// maybe not single commands
int cr_pos;
for (; (cr_pos = inputString.indexOf(LW232_CR)) >= 0;) {
strncpy((char*)lw232Message, inputString.c_str(), cr_pos + 1);
lw232Message[cr_pos] = '\0';
exec();
inputString = inputString.substring(cr_pos + 1);
}
}
// clear the string:
stringComplete = false;
}
if (lw232CanChannelMode != LW232_STATUS_CAN_CLOSED) {
int recv = 0;
while (CAN_MSGAVAIL == checkReceive() && recv++<5) {
dbg0('+');
if (CAN_OK == receiveSingleFrame()) {
Serial.write(LW232_CR);
}
}
Serial.flush();
}
}
void Can232::serialEventFunc() {
while (Serial.available()) {
char inChar = (char)Serial.read();
inputString += inChar;
if (inChar == LW232_CR) {
stringComplete = true;
}
}
}
INT8U Can232::exec() {
lw232LastErr = parseAndRunCommand();
switch (lw232LastErr) {
case LW232_OK:
Serial.write(LW232_RET_ASCII_OK);
break;
case LW232_OK_SMALL:
Serial.write(LW232_RET_ASCII_OK_SMALL);
Serial.write(LW232_RET_ASCII_OK);
break;
case LW232_OK_BIG:
Serial.write(LW232_RET_ASCII_OK_BIG);
Serial.write(LW232_RET_ASCII_OK);
break;
case LW232_ERR_NOT_IMPLEMENTED:
// Choose behavior: will it fail or not when not implemented command comes in. Some can monitors might be affected by this selection.
Serial.write(LW232_RET_ASCII_ERROR);
//Serial.write(LW232_RET_ASCII_OK);
break;
default:
Serial.write(LW232_RET_ASCII_ERROR);
}
return 0;
}
INT8U Can232::parseAndRunCommand() {
INT8U ret = LW232_OK;
INT8U idx = 0;
INT8U err = 0;
lw232LastErr = LW232_OK;
// __debug_buf("RX:", (char*)lw232Message, strlen((char*)lw232Message));
switch (lw232Message[0]) {
case LW232_CMD_SETUP:
// Sn[CR] Setup with standard CAN bit-rates where n is 0-9.
if (lw232CanChannelMode == LW232_STATUS_CAN_CLOSED) {
idx = HexHelper::parseNibbleWithLimit(lw232Message[1], LW232_CAN_BAUD_NUM);
lw232CanSpeedSelection = lw232CanBaudRates[idx];
}
else {
ret = LW232_ERR;
}
break;
case LW232_CMD_SETUP_BTR:
// sxxyy[CR] Setup with BTR0/BTR1 CAN bit-rates where xx and yy is a hex value.
ret = LW232_ERR; break;
case LW232_CMD_OPEN:
// O[CR] Open the CAN channel in normal mode (sending & receiving).
if (lw232CanChannelMode == LW232_STATUS_CAN_CLOSED) {
ret = openCanBus();
if (ret == LW232_OK) {
lw232CanChannelMode = LW232_STATUS_CAN_OPEN_NORMAL;
}
}
else {
ret = LW232_ERR;
}
break;
case LW232_CMD_LISTEN:
// L[CR] Open the CAN channel in listen only mode (receiving).
if (lw232CanChannelMode == LW232_STATUS_CAN_CLOSED) {
ret = openCanBus();
if (ret == LW232_OK) {
lw232CanChannelMode = LW232_STATUS_CAN_OPEN_LISTEN;
}
}
else {
ret = LW232_ERR;
}
break;
case LW232_CMD_CLOSE:
// C[CR] Close the CAN channel.
if (lw232CanChannelMode != LW232_STATUS_CAN_CLOSED) {
lw232CanChannelMode = LW232_STATUS_CAN_CLOSED;
}
else {
ret = LW232_ERR;
}
break;
case LW232_CMD_TX11:
// tiiildd...[CR] Transmit a standard (11bit) CAN frame.
if (lw232CanChannelMode == LW232_STATUS_CAN_OPEN_NORMAL) {
parseCanStdId();
lw232PacketLen = HexHelper::parseNibbleWithLimit(lw232Message[LW232_OFFSET_STD_PKT_LEN], LW232_FRAME_MAX_LENGTH + 1);
for (; idx < lw232PacketLen; idx++) {
lw232Buffer[idx] = HexHelper::parseFullByte(lw232Message[LW232_OFFSET_STD_PKT_DATA + idx * 2], lw232Message[LW232_OFFSET_STD_PKT_DATA + idx * 2 + 1]);
}
INT8U mcpErr = sendMsgBuf(lw232CanId, 0, 0, lw232PacketLen, lw232Buffer);
if (mcpErr != CAN_OK) {
ret = LW232_ERR;
} else if (lw232AutoPoll) {
ret = LW232_OK_SMALL;
}
}
else {
ret = LW232_ERR;
}
break;
case LW232_CMD_TX29:
// Tiiiiiiiildd...[CR] Transmit an extended (29bit) CAN frame
if (lw232CanChannelMode == LW232_STATUS_CAN_OPEN_NORMAL) {
parseCanExtId();
lw232PacketLen = HexHelper::parseNibbleWithLimit(lw232Message[LW232_OFFSET_EXT_PKT_LEN], LW232_FRAME_MAX_LENGTH + 1);
for (; idx < lw232PacketLen; idx++) {
lw232Buffer[idx] = HexHelper::parseFullByte(lw232Message[LW232_OFFSET_EXT_PKT_DATA + idx * 2], lw232Message[LW232_OFFSET_EXT_PKT_DATA + idx * 2 + 1]);
}
if (CAN_OK != sendMsgBuf(lw232CanId, 1, 0, lw232PacketLen, lw232Buffer)) {
ret = LW232_ERR;
} else if (lw232AutoPoll) {
ret = LW232_OK_BIG;
} else {
ret = LW232_OK;
}
}
break;
case LW232_CMD_RTR11:
// riiil[CR] Transmit an standard RTR (11bit) CAN frame.
if (lw232CanChannelMode == LW232_STATUS_CAN_OPEN_NORMAL) {
parseCanStdId();
lw232PacketLen = HexHelper::parseNibbleWithLimit(lw232Message[LW232_OFFSET_STD_PKT_LEN], LW232_FRAME_MAX_LENGTH + 1);
if (CAN_OK != sendMsgBuf(lw232CanId, 0, 1, lw232PacketLen, lw232Buffer)) {
ret = LW232_ERR;
}
else if (lw232AutoPoll) {
ret = LW232_OK_SMALL;
}
}
else {
ret = LW232_ERR;
}
break;
case LW232_CMD_RTR29:
// Riiiiiiiil[CR] Transmit an extended RTR (29bit) CAN frame.
if (lw232CanChannelMode == LW232_STATUS_CAN_OPEN_NORMAL) {
parseCanExtId();
lw232PacketLen = HexHelper::parseNibbleWithLimit(lw232Message[LW232_OFFSET_EXT_PKT_LEN], LW232_FRAME_MAX_LENGTH + 1);
if (CAN_OK != sendMsgBuf(lw232CanId, 1, 1, lw232PacketLen, lw232Buffer)) {
ret = LW232_ERR;
}
else if (lw232AutoPoll) {
ret = LW232_OK_SMALL; // not a typo. strangely can232_v3.pdf tells to return "z[CR]", not "Z[CR]" as in 29bit. todo: check if it is error in pdf???
}
} else {
ret = LW232_ERR;
}
break;
case LW232_CMD_POLL_ONE:
// P[CR] Poll incomming FIFO for CAN frames (single poll)
if (lw232CanChannelMode != LW232_STATUS_CAN_CLOSED && lw232AutoPoll == LW232_AUTOPOLL_OFF) {
if (CAN_MSGAVAIL == checkReceive()) {
ret = receiveSingleFrame();
}
} else {
ret = LW232_ERR;
}
break;
case LW232_CMD_POLL_MANY:
// A[CR] Polls incomming FIFO for CAN frames (all pending frames)
if (lw232CanChannelMode != LW232_STATUS_CAN_CLOSED && lw232AutoPoll == LW232_AUTOPOLL_OFF) {
while (CAN_MSGAVAIL == checkReceive()) {
ret = ret ^ receiveSingleFrame();
if (ret != CAN_OK)
break;
Serial.write(LW232_CR);
}
if (ret == CAN_OK)
Serial.print(LW232_ALL);
} else {
ret = LW232_ERR;
}
break;
case LW232_CMD_FLAGS:
// F[CR] Read Status Flags.
// LAWICEL CAN232 and CANUSB have some specific errors which differ from MCP2515/MCP2551 errors. We just return MCP2515 error.
Serial.print(LW232_FLAG);
if (lw232CAN && lw232CAN->checkError(&err) == CAN_OK)
err = 0;
HexHelper::printFullByte(err /*& MCP_EFLG_ERRORMASK*/);
break;
case LW232_CMD_AUTOPOLL:
// Xn[CR] Sets Auto Poll/Send ON/OFF for received frames.
if (lw232CanChannelMode == LW232_STATUS_CAN_CLOSED) {
lw232AutoPoll = (lw232Message[1] == LW232_ON_ONE) ? LW232_AUTOPOLL_ON : LW232_AUTOPOLL_OFF;
//todo: save to eeprom
} else {
ret = LW232_ERR;
}
break;
case LW232_CMD_FILTER:
// Wn[CR] Filter mode setting. By default CAN232 works in dual filter mode (0) and is backwards compatible with previous CAN232 versions.
ret = LW232_ERR_NOT_IMPLEMENTED; break;
case LW232_CMD_ACC_CODE:
// Mxxxxxxxx[CR] Sets Acceptance Code Register (ACn Register of SJA1000). // we use MCP2515,
ret = LW232_ERR_NOT_IMPLEMENTED; break;
case LW232_CMD_ACC_MASK:
// mxxxxxxxx[CR] Sets Acceptance Mask Register (AMn Register of SJA1000).
ret = LW232_ERR_NOT_IMPLEMENTED; break;
case LW232_CMD_UART:
// Un[CR] Setup UART with a new baud rate where n is 0-6.
idx = HexHelper::parseNibbleWithLimit(lw232Message[1], LW232_UART_BAUD_NUM);
Serial.begin(lw232SerialBaudRates[idx]);
break;
case LW232_CMD_VERSION1:
case LW232_CMD_VERSION2:
// V[CR] Get Version number of both CAN232 hardware and software
Serial.print(LW232_LAWICEL_VERSION_STR);
break;
case LW232_CMD_SERIAL:
// N[CR] Get Serial number of the CAN232.
Serial.print(LW232_LAWICEL_SERIAL_NUM);
break;
case LW232_CMD_TIMESTAMP:
// Zn[CR] Sets Time Stamp ON/OFF for received frames only. Z0 - OFF, Z1 - Lawicel's timestamp 2 bytes, Z2 - arduino timestamp 4 bytes.
if (lw232CanChannelMode == LW232_STATUS_CAN_CLOSED) {
// lw232TimeStamp = (lw232Message[1] == LW232_ON_ONE);
if (lw232Message[1] == LW232_ON_ONE) {
lw232TimeStamp = LW232_TIMESTAMP_ON_NORMAL;
}
else if (lw232Message[1] == LW232_ON_TWO) {
lw232TimeStamp = LW232_TIMESTAMP_ON_EXTENDED;
}
else {
lw232TimeStamp = LW232_TIMESTAMP_OFF;
}
}
else {
ret = LW232_ERR;
}
break;
case LW232_CMD_AUTOSTART:
// Qn[CR] Auto Startup feature (from power on).
if (lw232CanChannelMode != LW232_STATUS_CAN_CLOSED) {
if (lw232Message[1] == LW232_ON_ONE) {
lw232AutoStart = LW232_AUTOSTART_ON_NORMAL;
}
else if (lw232Message[1] == LW232_ON_TWO) {
lw232AutoStart = LW232_AUTOSTART_ON_LISTEN;
}
else {
lw232AutoStart = LW232_AUTOSTART_OFF;
}
//todo: save to eeprom
}
else {
ret = LW232_ERR;
}
break;
default:
ret = LW232_ERR_UNKNOWN_CMD;
}
return ret;
}
INT8U Can232::checkReceive() {
#ifndef _MCP_FAKE_MODE_
return lw232CAN? lw232CAN->checkReceive(): CAN_NOMSG;
#else
return CAN_MSGAVAIL;
#endif
}
INT8U Can232::readMsgBufID(INT32U *ID, INT8U *len, INT8U buf[]) {
#ifndef _MCP_FAKE_MODE_
return lw232CAN? lw232CAN->readMsgBufID(ID, len, buf): CAN_NOMSG;
#else
*ID = random(0x100, 0x110);
*len = 4;
buf[0] = random(0x01, 0x10);
buf[1] = random(0xa1, 0xf0);
buf[2] = 0x00;
buf[3] = 0x00;
return CAN_OK;
#endif
}
INT8U Can232::receiveSingleFrame() {
INT8U ret = LW232_OK;
INT8U idx = 0;
if (CAN_OK == readMsgBufID(&lw232CanId, &lw232PacketLen, lw232Buffer)) {
if (lw232CanId > 0x1FFFFFFF) {
ret = LW232_ERR; // address if totally wrong
}
else if (checkPassFilter(lw232CanId)) {// do we want to skip some addresses?
if (isExtendedFrame()) {
Serial.print(LW232_TR29);
HexHelper::printFullByte(HIGH_BYTE(HIGH_WORD(lw232CanId)));
HexHelper::printFullByte(LOW_BYTE(HIGH_WORD(lw232CanId)));
HexHelper::printFullByte(HIGH_BYTE(LOW_WORD(lw232CanId)));
HexHelper::printFullByte(LOW_BYTE(LOW_WORD(lw232CanId)));
}
else {
Serial.print(LW232_TR11);
HexHelper::printNibble(HIGH_BYTE(LOW_WORD(lw232CanId)));
HexHelper::printFullByte(LOW_BYTE(LOW_WORD(lw232CanId)));
}
//write data len
HexHelper::printNibble(lw232PacketLen);
//write data
for (idx = 0; idx < lw232PacketLen; idx++) {
HexHelper::printFullByte(lw232Buffer[idx]);
}
//write timestamp if needed
if (lw232TimeStamp != LW232_TIMESTAMP_OFF) {
INT32U time = millis();
if (lw232TimeStamp == LW232_TIMESTAMP_ON_NORMAL) {
// standard LAWICEL protocol. two bytes.
time %= 60000;
} else {
// non standard protocol - 4 bytes timestamp
HexHelper::printFullByte(HIGH_BYTE(HIGH_WORD(time)));
HexHelper::printFullByte(LOW_BYTE(HIGH_WORD(time)));
}
HexHelper::printFullByte(HIGH_BYTE(LOW_WORD(time)));
HexHelper::printFullByte(LOW_BYTE(LOW_WORD(time)));
}
}
}
else {
ret = LW232_ERR;
}
return ret;
}
INT8U Can232::isExtendedFrame() {
#ifndef _MCP_FAKE_MODE_
return lw232CAN? lw232CAN->isExtendedFrame(): 0;
#else
return lw232CanId > 0x7FF ? 1 : 0; //simple hack for fake mode
#endif
}
INT8U Can232::checkPassFilter(INT32U addr) {
if (userAddressFilterFunc == 0)
return LW232_FILTER_PROCESS;
return (*userAddressFilterFunc)(addr);
}
INT8U Can232::openCanBus() {
INT8U ret = LW232_OK;
#ifndef _MCP_FAKE_MODE_
if (!lw232CAN) {
return CAN_FAILINIT;
}
if (CAN_OK != lw232CAN->begin(lw232CanSpeedSelection, lw232McpModuleClock))
ret = LW232_ERR;
#endif
return ret;
}
INT8U Can232::sendMsgBuf(INT32U id, INT8U ext, INT8U rtr, INT8U len, INT8U *buf) {
#ifndef _MCP_FAKE_MODE_
if (!lw232CAN) {
return CAN_FAILTX;
}
return lw232CAN->sendMsgBuf(id, ext, rtr, len, buf);
#else
Serial.print("<sending:");
Serial.print(id, HEX);
Serial.print(',');
if (ext) Serial.print('+');
else Serial.print('-');
if (rtr) Serial.print('+');
else Serial.print('-');
Serial.print(',');
Serial.print(len, DEC);
Serial.print(',');
int i;
for (i = 0; i < len; i++) printFullByte(buf[i]);
return CAN_OK;
#endif
}
void Can232::parseCanStdId() {
lw232CanId = (((INT32U)HexHelper::parseNibble(lw232Message[1])) << 8)
+ (((INT32U)HexHelper::parseNibble(lw232Message[2])) << 4)
+ (((INT32U)HexHelper::parseNibble(lw232Message[3])));
lw232CanId &= 0x7FF;
}
void Can232::parseCanExtId() {
lw232CanId = (((INT32U)HexHelper::parseNibble(lw232Message[1])) << 28)
+ (((INT32U)HexHelper::parseNibble(lw232Message[2])) << 24)
+ (((INT32U)HexHelper::parseNibble(lw232Message[3])) << 20)
+ (((INT32U)HexHelper::parseNibble(lw232Message[4])) << 16)
+ (((INT32U)HexHelper::parseNibble(lw232Message[5])) << 12)
+ (((INT32U)HexHelper::parseNibble(lw232Message[6])) << 8)
+ (((INT32U)HexHelper::parseNibble(lw232Message[7])) << 4)
+ (((INT32U)HexHelper::parseNibble(lw232Message[8])));
lw232CanId &= 0x1FFFFFFF;
}
void HexHelper::printFullByte(INT8U b) {
if (b < 0x10) {
Serial.print('0');
// dbg0('0');
}
Serial.print(b, HEX);
//dbgH(b);
}
void HexHelper::printNibble(INT8U b) {
Serial.print(b & 0x0F, HEX);
//dbgH(b & 0x0F);
}
INT8U HexHelper::parseNibble(INT8U hex) {
INT8U ret = 0;
if (hex >= '0' && hex <= '9') {
ret = hex - '0';
} else if (hex >= 'a' && hex <= 'f') {
ret = hex - 'a' + 10;
} else if (hex >= 'A' && hex <= 'F') {
ret = hex - 'A' + 10;
} // else error, return 0
return ret;
}
INT8U HexHelper::parseFullByte(INT8U H, INT8U L) {
return (parseNibble(H) << 4) + parseNibble(L);
}
INT8U HexHelper::parseNibbleWithLimit(INT8U hex, INT8U limit) {
INT8U ret = parseNibble(hex);
if (ret < limit)
return ret;
else
return 0;
}
+234
View File
@@ -0,0 +1,234 @@
/*****************************************************************************************
* This is implementation of CAN BUS ASCII protocol based on LAWICEL v1.3 serial protocol
* of CAN232/CANUSB device (http://www.can232.com/docs/can232_v3.pdf)
*
* Made for Arduino with Seeduino/ElecFreaks CAN BUS Shield based on MCP2515
*
* Copyright (C) 2015 Anton Viktorov <latonita@yandex.ru>
* https://github.com/latonita/can-ascii
*
* This library is free software. You may use/redistribute it under The MIT License terms.
*
*****************************************************************************************/
#ifndef _CAN_SERIAL_H_
#define _CAN_SERIAL_H_
//#if defined(ARDUINO) && ARDUINO >= 100
// #include "arduino.h"
//#else
// #include "WProgram.h"
//#endif
#include "mcp_can.h"
#define LW232_LAWICEL_VERSION_STR "V1013"
#define LW232_LAWICEL_SERIAL_NUM "NA123"
#define LW232_CAN_BUS_SHIELD_CS_PIN 10
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Commands not supported/not implemented:
// s, W, M, m, U
//
// Commands modified:
// S - supports not declared 83.3 rate straight away (S9)
// refer to https://github.com/latonita/CAN_BUS_Shield fork with 83.3 support, easy to add.
// F - returns MCP2515 error flags
// Z - extra Z2 option enables 4 byte timestamp vs standard 2 byte (60000ms max)
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// CODE SUPPORTED SYNTAX DESCRIPTION
//
#define LW232_CMD_SETUP 'S' // YES+ Sn[CR] Setup with standard CAN bit-rates where n is 0-8.
// S0 10Kbit S4 125Kbit S8 1Mbit
// S1 20Kbit S5 250Kbit S9 83.3Kbit
// S2 50Kbit S6 500Kbit
// S3 100Kbit S7 800Kbit
#define LW232_CMD_SETUP_BTR 's' // - sxxyy[CR] Setup with BTR0/BTR1 CAN bit-rates where xx and yy is a hex value.
#define LW232_CMD_OPEN 'O' // YES O[CR] Open the CAN channel in normal mode (sending & receiving).
#define LW232_CMD_LISTEN 'L' // YES L[CR] Open the CAN channel in listen only mode (receiving).
#define LW232_CMD_CLOSE 'C' // YES C[CR] Close the CAN channel.
#define LW232_CMD_TX11 't' // YES tiiildd...[CR] Transmit a standard (11bit) CAN frame.
#define LW232_CMD_TX29 'T' // YES Tiiiiiiiildd...[CR] Transmit an extended (29bit) CAN frame
#define LW232_CMD_RTR11 'r' // YES riiil[CR] Transmit an standard RTR (11bit) CAN frame.
#define LW232_CMD_RTR29 'R' // YES Riiiiiiiil[CR] Transmit an extended RTR (29bit) CAN frame.
#define LW232_CMD_POLL_ONE 'P' // YES P[CR] Poll incomming FIFO for CAN frames (single poll)
#define LW232_CMD_POLL_MANY 'A' // YES A[CR] Polls incomming FIFO for CAN frames (all pending frames)
#define LW232_CMD_FLAGS 'F' // YES+ F[CR] Read Status Flags.
#define LW232_CMD_AUTOPOLL 'X' // YES Xn[CR] Sets Auto Poll/Send ON/OFF for received frames.
#define LW232_CMD_FILTER 'W' // - Wn[CR] Filter mode setting. By default CAN232 works in dual filter mode (0) and is backwards compatible with previous CAN232 versions.
#define LW232_CMD_ACC_CODE 'M' // - Mxxxxxxxx[CR] Sets Acceptance Code Register (ACn Register of SJA1000). // we use MCP2515, not supported
#define LW232_CMD_ACC_MASK 'm' // - mxxxxxxxx[CR] Sets Acceptance Mask Register (AMn Register of SJA1000). // we use MCP2515, not supported
#define LW232_CMD_UART 'U' // YES Un[CR] Setup UART with a new baud rate where n is 0-6.
#define LW232_CMD_VERSION1 'V' // YES v[CR] Get Version number of both CAN232 hardware and software
#define LW232_CMD_VERSION2 'v' // YES V[CR] Get Version number of both CAN232 hardware and software
#define LW232_CMD_SERIAL 'N' // YES N[CR] Get Serial number of the CAN232.
#define LW232_CMD_TIMESTAMP 'Z' // YES+ Zn[CR] Sets Time Stamp ON/OFF for received frames only. EXTENSION to LAWICEL: Z2 - millis() timestamp w/o standard 60000ms cycle
#define LW232_CMD_AUTOSTART 'Q' // YES todo Qn[CR] Auto Startup feature (from power on).
#define LOW_BYTE(x) ((unsigned char)((x)&0xFF))
#define HIGH_BYTE(x) ((unsigned char)(((x)>>8)&0xFF))
#define LOW_WORD(x) ((unsigned short)((x)&0xFFFF))
#define HIGH_WORD(x) ((unsigned short)(((x)>>16)&0xFFFF))
#ifndef INT32U
#define INT32U unsigned long
#endif
#ifndef INT16U
#define INT16U word
#endif
#ifndef INT8U
#define INT8U byte
#endif
#define LW232_OK 0x00
#define LW232_OK_SMALL 0x01
#define LW232_OK_BIG 0x02
#define LW232_ERR 0x03
#define LW232_ERR_NOT_IMPLEMENTED 0x04
#define LW232_ERR_UNKNOWN_CMD 0x05
#define LW232_FILTER_SKIP 0x00
#define LW232_FILTER_PROCESS 0x01
//#define LW232_IS_OK(x) ((x)==LW232_OK ||(x)==LW232_OK_NEW ? TRUE : FALSE)
#define LW232_CR '\r'
#define LW232_ALL 'A'
#define LW232_FLAG 'F'
#define LW232_TR11 't'
#define LW232_TR29 'T'
#define LW232_RET_ASCII_OK 0x0D
#define LW232_RET_ASCII_ERROR 0x07
#define LW232_RET_ASCII_OK_SMALL 'z'
#define LW232_RET_ASCII_OK_BIG 'Z'
#define LW232_STATUS_CAN_CLOSED 0x00
#define LW232_STATUS_CAN_OPEN_NORMAL 0x01
#define LW232_STATUS_CAN_OPEN_LISTEN 0x01
#define LW232_FRAME_MAX_LENGTH 0x08
#define LW232_FRAME_MAX_SIZE (sizeof("Tiiiiiiiildddddddddddddddd\r")+1)
#define LW232_INPUT_STRING_BUFFER_SIZE 200
#define LW232_OFF '0'
#define LW232_ON_ONE '1'
#define LW232_ON_TWO '2'
#define LW232_AUTOPOLL_OFF 0x00
#define LW232_AUTOPOLL_ON 0x01
#define LW232_AUTOSTART_OFF 0x00
#define LW232_AUTOSTART_ON_NORMAL 0x01
#define LW232_AUTOSTART_ON_LISTEN 0x02
#define LW232_TIMESTAMP_OFF 0x00
#define LW232_TIMESTAMP_ON_NORMAL 0x01
#define LW232_TIMESTAMP_ON_EXTENDED 0x02
#define LW232_OFFSET_STD_PKT_LEN 0x04
#define LW232_OFFSET_STD_PKT_DATA 0x05
#define LW232_OFFSET_EXT_PKT_LEN 0x09
#define LW232_OFFSET_EXT_PKT_DATA 0x0A
#define LW232_DEFAULT_BAUD_RATE 115200
#define LW232_DEFAULT_CAN_RATE CAN_500KBPS
#define LW232_DEFAULT_CLOCK_FREQ MCP_16MHz
#define LW232_CAN_BAUD_NUM 0x0a
#define LW232_UART_BAUD_NUM 0x07
const INT32U lw232SerialBaudRates[] //PROGMEM
= { 230400, 115200, 57600, 38400, 19200, 9600, 2400 };
const INT32U lw232CanBaudRates[] //PROGMEM
= { CAN_10KBPS, CAN_20KBPS, CAN_50KBPS, CAN_100KBPS, CAN_125KBPS, CAN_250KBPS, CAN_500KBPS, CAN_800KBPS, CAN_1000KBPS, CAN_83K3BPS };
class Can232
{
public:
static void init(INT8U defaultCanSpeed = LW232_DEFAULT_CAN_RATE, const INT8U clock = LW232_DEFAULT_CLOCK_FREQ);
static void attach(MCP_CAN *can);
static void setFilter(INT8U (*userFunc)(INT32U));
static void loop();
static void serialEvent();
private:
static MCP_CAN *MCP_OBJECT;
static Can232* _instance;
static Can232* instance();
void initFunc();
void setFilterFunc(INT8U (*userFunc)(INT32U));
void loopFunc();
void serialEventFunc();
INT8U (*userAddressFilterFunc)(INT32U addr) = 0;
/*
MCP_CAN lw232CAN = MCP_CAN(LW232_CAN_BUS_SHIELD_CS_PIN);
*/
INT8U lw232CanSpeedSelection = CAN_83K3BPS;
INT8U lw232McpModuleClock = MCP_16MHz;
INT8U lw232CanChannelMode = LW232_STATUS_CAN_CLOSED;
INT8U lw232LastErr = LW232_OK;
INT8U lw232AutoStart = LW232_AUTOSTART_OFF;
INT8U lw232AutoPoll = LW232_AUTOPOLL_OFF;
INT8U lw232TimeStamp = LW232_TIMESTAMP_OFF;
INT32U lw232CanId = 0;
INT8U lw232Buffer[8];
INT8U lw232PacketLen = 0;
INT8U lw232Message[LW232_FRAME_MAX_SIZE];
String inputString = ""; // a string to hold incoming data
boolean stringComplete = false; // whether the string is complete
INT8U parseAndRunCommand();
INT8U exec();
INT8U checkReceive();
INT8U readMsgBufID(INT32U *ID, INT8U *len, INT8U buf[]);
INT8U receiveSingleFrame();
INT8U isExtendedFrame();
INT8U checkPassFilter(INT32U addr);
INT8U openCanBus();
INT8U sendMsgBuf(INT32U id, INT8U ext, INT8U rtr, INT8U len, INT8U *buf);
void parseCanStdId();
void parseCanExtId();
};
class HexHelper {
public:
static void printFullByte(INT8U b);
static void printNibble(INT8U b);
static INT8U parseNibble(INT8U hex);
static INT8U parseFullByte(INT8U H, INT8U L);
static INT8U parseNibbleWithLimit(INT8U hex, INT8U limit);
};
class Can232Fake : Can232 {
};
#endif
+1662
View File
File diff suppressed because it is too large Load Diff
+160
View File
@@ -0,0 +1,160 @@
/*
mcp_can.h
2012 Copyright (c) Seeed Technology Inc. All right reserved.
Author:Loovee (loovee@seeed.cc)
2014-1-16
Contributor:
Cory J. Fowler
Latonita
Woodward1
Mehtajaghvi
BykeBlast
TheRo0T
Tsipizic
ralfEdmund
Nathancheek
BlueAndi
Adlerweb
Btetz
Hurvajs
ttlappalainen
The MIT License (MIT)
Copyright (c) 2013 Seeed Technology Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef _MCP2515_H_
#define _MCP2515_H_
#include "mcp_can.h"
#include "mcp2515_can_dfs.h"
#define MAX_CHAR_IN_MESSAGE 8
class mcp2515_can : public MCP_CAN
{
public:
mcp2515_can(byte _CS) : MCP_CAN(_CS), nReservedTx(0){};
/*
mcp2515 driver function
*/
public:
virtual void enableTxInterrupt(bool enable = true); // enable transmit interrupt
virtual void reserveTxBuffers(byte nTxBuf = 0)
{
nReservedTx = (nTxBuf < MCP_N_TXBUFFERS ? nTxBuf : MCP_N_TXBUFFERS - 1);
}
virtual byte getLastTxBuffer()
{
return MCP_N_TXBUFFERS - 1; // read index of last tx buffer
}
virtual byte begin(uint32_t speedset, const byte clockset = MCP_16MHz, const bool _initSPI = true); // init can
virtual byte init_Mask(byte num, byte ext, unsigned long ulData); // init Masks
virtual byte init_Filt(byte num, byte ext, unsigned long ulData); // init filters
virtual void setSleepWakeup(byte enable); // Enable or disable the wake up interrupt (If disabled the MCP2515 will not be woken up by CAN bus activity, making it send only)
virtual byte sleep(); // Put the MCP2515 in sleep mode
virtual byte wake(); // Wake MCP2515 manually from sleep
virtual byte setMode(byte opMode); // Set operational mode
virtual byte getMode(); // Get operational mode
virtual byte checkError(uint8_t* err_ptr = NULL); // if something error
virtual byte checkReceive(void); // if something received
virtual byte readMsgBufID(byte status, volatile unsigned long *id, volatile byte *ext, volatile byte *rtr, volatile byte *len, volatile byte *buf); // read buf with object ID
/* wrapper */
byte readMsgBufID(unsigned long *ID, byte *len, byte *buf) {
return readMsgBufID(readRxTxStatus(), ID, &ext_flg, &rtr, len, buf);
}
byte readMsgBuf(byte *len, byte *buf) {
return readMsgBufID(readRxTxStatus(), &can_id, &ext_flg, &rtr, len, buf);
}
virtual byte trySendMsgBuf(unsigned long id, byte ext, byte rtrBit, byte len, const byte *buf, byte iTxBuf = 0xff); // as sendMsgBuf, but does not have any wait for free buffer
virtual byte sendMsgBuf(byte status, unsigned long id, byte ext, byte rtrBit, byte len, volatile const byte *buf); // send message buf by using parsed buffer status
virtual byte sendMsgBuf(unsigned long id, byte ext, byte rtrBit, byte len, const byte *buf, bool wait_sent = true); // send buf
using MCP_CAN::sendMsgBuf; // make other overloads visible
virtual void clearBufferTransmitIfFlags(byte flags = 0); // Clear transmit flags according to status
virtual byte readRxTxStatus(void); // read has something send or received
virtual byte checkClearRxStatus(byte *status); // read and clear and return first found rx status bit
virtual byte checkClearTxStatus(byte *status, byte iTxBuf = 0xff); // read and clear and return first found or buffer specified tx status bit
virtual bool mcpPinMode(const byte pin, const byte mode); // switch supported pins between HiZ, interrupt, output or input
virtual bool mcpDigitalWrite(const byte pin, const byte mode); // write HIGH or LOW to RX0BF/RX1BF
virtual byte mcpDigitalRead(const byte pin);
private:
void mcp2515_reset(void); // reset mcp2515
byte mcp2515_readRegister(const byte address); // read mcp2515's register
void mcp2515_readRegisterS(const byte address,
byte values[],
const byte n);
void mcp2515_setRegister(const byte address, // set mcp2515's register
const byte value);
void mcp2515_setRegisterS(const byte address, // set mcp2515's registers
const byte values[],
const byte n);
void mcp2515_initCANBuffers(void);
void mcp2515_modifyRegister(const byte address, // set bit of one register
const byte mask,
const byte data);
byte mcp2515_readStatus(void); // read mcp2515's Status
byte mcp2515_setCANCTRL_Mode(const byte newmode); // set mode
byte mcp2515_requestNewMode(const byte newmode); // Set mode
byte mcp2515_configRate(const byte canSpeed, const byte clock); // set baudrate
byte mcp2515_init(const byte canSpeed, const byte clock); // mcp2515init
void mcp2515_write_id(const byte mcp_addr, // write can id
const byte ext,
const unsigned long id);
void mcp2515_read_id(const byte mcp_addr, // read can id
byte *ext,
unsigned long *id);
void mcp2515_write_canMsg(const byte buffer_sidh_addr, unsigned long id, byte ext, byte rtr, byte len,
volatile const byte *buf); // read can msg
void mcp2515_read_canMsg(const byte buffer_load_addr, volatile unsigned long *id, volatile byte *ext,
volatile byte *rtr, volatile byte *len, volatile byte *buf); // write can msg
void mcp2515_start_transmit(const byte mcp_addr); // start transmit
byte mcp2515_getNextFreeTXBuf(byte *txbuf_n); // get Next free txbuf
byte mcp2515_isTXBufFree(byte *txbuf_n, byte iBuf); // is buffer by index free
/*
can operator function
*/
byte sendMsg(unsigned long id, byte ext, byte rtrBit, byte len, const byte *buf, bool wait_sent = true); // send message
private:
byte nReservedTx; // Count of tx buffers for reserved send
};
#endif
/*********************************************************************************************************
END FILE
*********************************************************************************************************/
+159 -73
View File
@@ -1,49 +1,49 @@
/*
mcp_can_dfs.h
2012 Copyright (c) Seeed Technology Inc. All right reserved.
mcp_can_dfs.h
2012 Copyright (c) Seeed Technology Inc. All right reserved.
Author:Loovee (loovee@seeed.cc)
2014-1-16
Author:Loovee (loovee@seeed.cc)
2014-1-16
Contributor:
Contributor:
Cory J. Fowler
Latonita
Woodward1
Mehtajaghvi
BykeBlast
TheRo0T
Tsipizic
ralfEdmund
Nathancheek
BlueAndi
Adlerweb
Btetz
Hurvajs
xboxpro1
ttlappalainen
Cory J. Fowler
Latonita
Woodward1
Mehtajaghvi
BykeBlast
TheRo0T
Tsipizic
ralfEdmund
Nathancheek
BlueAndi
Adlerweb
Btetz
Hurvajs
xboxpro1
ttlappalainen
The MIT License (MIT)
The MIT License (MIT)
Copyright (c) 2013 Seeed Technology Inc.
Copyright (c) 2013 Seeed Technology Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef _MCP2515DFS_H_
#define _MCP2515DFS_H_
@@ -54,7 +54,9 @@
// if print debug information
#define DEBUG_EN 1
#ifndef DEBUG_EN
#define DEBUG_EN 1
#endif
// Begin mt
@@ -126,6 +128,8 @@
#define MCP_RXF2SIDL 0x09
#define MCP_RXF2EID8 0x0A
#define MCP_RXF2EID0 0x0B
#define MCP_BFPCTRL 0x0C
#define MCP_TXRTSCTRL 0x0D
#define MCP_CANSTAT 0x0E
#define MCP_CANCTRL 0x0F
#define MCP_RXF3SIDH 0x10
@@ -249,10 +253,23 @@
#define MCP_WAKIF 0x40
#define MCP_MERRF 0x80
// clock
// BFPCTRL Register Bits
#define MCP_16MHz 1
#define MCP_8MHz 2
#define B1BFS 0x20
#define B0BFS 0x10
#define B1BFE 0x08
#define B0BFE 0x04
#define B1BFM 0x02
#define B0BFM 0x01
// TXRTCTRL Register Bits
#define B2RTS 0x20
#define B1RTS 0x10
#define B0RTS 0x08
#define B2RTSM 0x04
#define B1RTSM 0x02
#define B0RTSM 0x01
// speed 16M
@@ -260,6 +277,14 @@
#define MCP_16MHz_1000kBPS_CFG2 (0xD0)
#define MCP_16MHz_1000kBPS_CFG3 (0x82)
#define MCP_16MHz_800kBPS_CFG1 (0x40)
#define MCP_16MHz_800kBPS_CFG2 (0x92)
#define MCP_16MHz_800kBPS_CFG3 (0x02)
#define MCP_16MHz_666kBPS_CFG1 (0x00)
#define MCP_16MHz_666kBPS_CFG2 (0xA0)
#define MCP_16MHz_666kBPS_CFG3 (0x04)
#define MCP_16MHz_500kBPS_CFG1 (0x00)
#define MCP_16MHz_500kBPS_CFG2 (0xF0)
#define MCP_16MHz_500kBPS_CFG3 (0x86)
@@ -324,9 +349,73 @@
#define MCP_16MHz_5kBPS_CFG2 (0xFF)
#define MCP_16MHz_5kBPS_CFG3 (0x87)
#define MCP_16MHz_666kBPS_CFG1 (0x00)
#define MCP_16MHz_666kBPS_CFG2 (0xA0)
#define MCP_16MHz_666kBPS_CFG3 (0x04)
// speed 12M
#define MCP_12MHz_1000kBPS_CFG1 (0x00)//
#define MCP_12MHz_1000kBPS_CFG2 (0x88)//
#define MCP_12MHz_1000kBPS_CFG3 (0x01)//
#define MCP_12MHz_666kBPS_CFG1 (0x00)//
#define MCP_12MHz_666kBPS_CFG2 (0x92)//
#define MCP_12MHz_666kBPS_CFG3 (0x01)//
#define MCP_12MHz_500kBPS_CFG1 (0x00)
#define MCP_12MHz_500kBPS_CFG2 (0x9B)
#define MCP_12MHz_500kBPS_CFG3 (0x02)
#define MCP_12MHz_250kBPS_CFG1 (0x00)//
#define MCP_12MHz_250kBPS_CFG2 (0xBF)//
#define MCP_12MHz_250kBPS_CFG3 (0x06)///
#define MCP_12MHz_200kBPS_CFG1 (0x01)//
#define MCP_12MHz_200kBPS_CFG2 (0xA4)//
#define MCP_12MHz_200kBPS_CFG3 (0x03)//
#define MCP_12MHz_125kBPS_CFG1 (0x01)//
#define MCP_12MHz_125kBPS_CFG2 (0xBF)//
#define MCP_12MHz_125kBPS_CFG3 (0x06)//
#define MCP_12MHz_100kBPS_CFG1 (0x02)//
#define MCP_12MHz_100kBPS_CFG2 (0xB6)//
#define MCP_12MHz_100kBPS_CFG3 (0x04)//
#define MCP_12MHz_95kBPS_CFG1 (0x02)//
#define MCP_12MHz_95kBPS_CFG2 (0xBE)//
#define MCP_12MHz_95kBPS_CFG3 (0x04)//
#define MCP_12MHz_83k3BPS_CFG1 (0x03)//
#define MCP_12MHz_83k3BPS_CFG2 (0xB5)//
#define MCP_12MHz_83k3BPS_CFG3 (0x03)//
#define MCP_12MHz_80kBPS_CFG1 (0x04)//
#define MCP_12MHz_80kBPS_CFG2 (0xA4)//
#define MCP_12MHz_80kBPS_CFG3 (0x03)//
#define MCP_12MHz_50kBPS_CFG1 (0x05)//
#define MCP_12MHz_50kBPS_CFG2 (0xB6)//
#define MCP_12MHz_50kBPS_CFG3 (0x04)//
#define MCP_12MHz_40kBPS_CFG1 (0x09)//
#define MCP_12MHz_40kBPS_CFG2 (0xA4)//
#define MCP_12MHz_40kBPS_CFG3 (0x03)//
#define MCP_12MHz_33kBPS_CFG1 (0x0C)//
#define MCP_12MHz_33kBPS_CFG2 (0xA4)//
#define MCP_12MHz_33kBPS_CFG3 (0x02)//
#define MCP_12MHz_31k25BPS_CFG1 (0x0B)//
#define MCP_12MHz_31k25BPS_CFG2 (0xAC)//
#define MCP_12MHz_31k25BPS_CFG3 (0x03)//
#define MCP_12MHz_25kBPS_CFG1 (0X0B)//
#define MCP_12MHz_25kBPS_CFG2 (0XB6)//
#define MCP_12MHz_25kBPS_CFG3 (0X04)//
#define MCP_12MHz_20kBPS_CFG1 (0x0C)//
#define MCP_12MHz_20kBPS_CFG2 (0xBF)//
#define MCP_12MHz_20kBPS_CFG3 (0x05)//
// speed 8M
@@ -335,6 +424,10 @@
#define MCP_8MHz_1000kBPS_CFG2 (0x80)
#define MCP_8MHz_1000kBPS_CFG3 (0x00)
#define MCP_8MHz_800kBPS_CFG1 (0x00)
#define MCP_8MHz_800kBPS_CFG2 (0x80)
#define MCP_8MHz_800kBPS_CFG3 (0x01)
#define MCP_8MHz_500kBPS_CFG1 (0x00)
#define MCP_8MHz_500kBPS_CFG2 (0x90)
#define MCP_8MHz_500kBPS_CFG3 (0x02)
@@ -355,10 +448,18 @@
#define MCP_8MHz_100kBPS_CFG2 (0xb4)
#define MCP_8MHz_100kBPS_CFG3 (0x06)
#define MCP_8MHz_95k2BPS_CFG1 (0x01)
#define MCP_8MHz_95k2BPS_CFG2 (0xBB)
#define MCP_8MHz_95k2BPS_CFG3 (0x07)
#define MCP_8MHz_80kBPS_CFG1 (0x01)
#define MCP_8MHz_80kBPS_CFG2 (0xbf)
#define MCP_8MHz_80kBPS_CFG3 (0x07)
#define MCP_8MHz_83k3BPS_CFG1 (0x01)
#define MCP_8MHz_83k3BPS_CFG2 (0xBE)
#define MCP_8MHz_83k3BPS_CFG3 (0x07)
#define MCP_8MHz_50kBPS_CFG1 (0x03)
#define MCP_8MHz_50kBPS_CFG2 (0xb4)
#define MCP_8MHz_50kBPS_CFG3 (0x06)
@@ -403,6 +504,17 @@
#define CANSENDTIMEOUT (200) // milliseconds
#define MCP_PIN_HIZ (0)
#define MCP_PIN_INT (1)
#define MCP_PIN_OUT (2)
#define MCP_PIN_IN (3)
#define MCP_RX0BF (0)
#define MCP_RX1BF (1)
#define MCP_TX0RTS (2)
#define MCP_TX1RTS (3)
#define MCP_TX2RTS (4)
// initial value of gCANAutoProcess
@@ -414,38 +526,12 @@
#define CANDEFAULTIDENT (0x55CC)
#define CANDEFAULTIDENTEXT (CAN_EXTID)
#define CAN_5KBPS 1
#define CAN_10KBPS 2
#define CAN_20KBPS 3
#define CAN_25KBPS 4
#define CAN_31K25BPS 5
#define CAN_33KBPS 6
#define CAN_40KBPS 7
#define CAN_50KBPS 8
#define CAN_80KBPS 9
#define CAN_83K3BPS 10
#define CAN_95KBPS 11
#define CAN_100KBPS 12
#define CAN_125KBPS 13
#define CAN_200KBPS 14
#define CAN_250KBPS 15
#define CAN_500KBPS 16
#define CAN_666KBPS 17
#define CAN_1000KBPS 18
#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
*********************************************************************************************************/
END FILE
*********************************************************************************************************/
File diff suppressed because it is too large Load Diff
+293
View File
@@ -0,0 +1,293 @@
#ifndef _MCP2518FD_H_
#define _MCP2518FD_H_
#include "mcp2518fd_can_dfs.h"
#include "mcp_can.h"
#include <Arduino.h>
#include <SPI.h>
// *****************************************************************************
// *****************************************************************************
//! Reset DUT
// Code anchor for break points
#define Nop() asm("nop")
// Index to SPI channel
// Used when multiple MCP25xxFD are connected to the same SPI interface, but
// with different CS
#define SPI_DEFAULT_BUFFER_LENGTH 96
// extern SPIClass* pSPI;
#define spi_readwrite pSPI->transfer
#define spi_read() spi_readwrite(0x00)
#define spi_write(spi_val) spi_readwrite(spi_val)
#define SPI_BEGIN() \
pSPI->beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0))
#define SPI_END() pSPI->endTransaction();
// *****************************************************************************
// *****************************************************************************
// Section: Defines
#define CRCBASE 0xFFFF
#define CRCUPPER 1
//! Reverse order of bits in byte
const uint8_t BitReverseTable256[256] = {
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0,
0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4,
0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC,
0x3C, 0xBC, 0x7C, 0xFC, 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA,
0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6,
0x36, 0xB6, 0x76, 0xF6, 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1,
0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9,
0x39, 0xB9, 0x79, 0xF9, 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD,
0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3,
0x33, 0xB3, 0x73, 0xF3, 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7,
0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF,
0x3F, 0xBF, 0x7F, 0xFF};
//! Look-up table for CRC calculation
const uint16_t crc16_table[256] = {
0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011, 0x8033,
0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022, 0x8063, 0x0066,
0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072, 0x0050, 0x8055, 0x805F,
0x005A, 0x804B, 0x004E, 0x0044, 0x8041, 0x80C3, 0x00C6, 0x00CC, 0x80C9,
0x00D8, 0x80DD, 0x80D7, 0x00D2, 0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB,
0x00EE, 0x00E4, 0x80E1, 0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE,
0x00B4, 0x80B1, 0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087,
0x0082, 0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192,
0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1, 0x01E0,
0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1, 0x81D3, 0x01D6,
0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2, 0x0140, 0x8145, 0x814F,
0x014A, 0x815B, 0x015E, 0x0154, 0x8151, 0x8173, 0x0176, 0x017C, 0x8179,
0x0168, 0x816D, 0x8167, 0x0162, 0x8123, 0x0126, 0x012C, 0x8129, 0x0138,
0x813D, 0x8137, 0x0132, 0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E,
0x0104, 0x8101, 0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317,
0x0312, 0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321,
0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371, 0x8353,
0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342, 0x03C0, 0x83C5,
0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1, 0x83F3, 0x03F6, 0x03FC,
0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2, 0x83A3, 0x03A6, 0x03AC, 0x83A9,
0x03B8, 0x83BD, 0x83B7, 0x03B2, 0x0390, 0x8395, 0x839F, 0x039A, 0x838B,
0x038E, 0x0384, 0x8381, 0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E,
0x0294, 0x8291, 0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7,
0x02A2, 0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2,
0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1, 0x8243,
0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252, 0x0270, 0x8275,
0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261, 0x0220, 0x8225, 0x822F,
0x022A, 0x823B, 0x023E, 0x0234, 0x8231, 0x8213, 0x0216, 0x021C, 0x8219,
0x0208, 0x820D, 0x8207, 0x0202};
class SPIClass;
class mcp2518fd : public MCP_CAN {
public:
mcp2518fd(byte _CS) : MCP_CAN(_CS), nReservedTx(0){};
public:
virtual void
enableTxInterrupt(bool enable = true); // enable transmit interrupt
virtual void reserveTxBuffers(byte nTxBuf = 0) {
nReservedTx = (nTxBuf < 3 ? nTxBuf : 3 - 1);
}
virtual byte getLastTxBuffer() {
return 3 - 1; // read index of last tx buffer
}
/*
* speedset could be in MCP_BITTIME_SETUP,
* or fill by CANFD::BITRATE()
*/
virtual byte begin(uint32_t speedset,
const byte clockset = MCP2518FD_40MHz,
const bool _initSPI = true); // init can
virtual byte init_Mask(byte num, byte ext, unsigned long ulData);
virtual byte init_Filt(byte num, byte ext,
unsigned long ulData); // init filters
virtual void setSleepWakeup(const byte enable);
virtual byte sleep();
virtual byte wake();
virtual byte setMode(const byte opMode);
virtual byte getMode();
virtual byte checkError(uint8_t* err_ptr = NULL);
/* ---- receiving ---- */
virtual byte checkReceive(void);
virtual byte readMsgBufID(byte status, volatile unsigned long *id,
volatile byte *ext, volatile byte *rtr,
volatile byte *len,
volatile byte *buf); // read buf with object ID
/* wrapper */
byte readMsgBufID(unsigned long *ID, byte *len, byte *buf) {
return readMsgBufID(readRxTxStatus(), ID, &ext_flg, &rtr, len, buf);
}
byte readMsgBuf(byte *len, byte *buf) {
return readMsgBufID(readRxTxStatus(), &can_id, &ext_flg, &rtr, len, buf);
}
/* ---- sending ---- */
/* dlc = CAN_DLC_0..CAN_DLC_64(0..15)
* CAN_DLC_0..CAN_DLC_8(0..8) = data bytes count, compatible to MCP2515 APIs
* CAN_DLC_12(9) = 12 bytes
* CAN_DLC_16(10) = 16 bytes
* CAN_DLC_20(11) = 20 bytes
* CAN_DLC_24(12) = 24 bytes
* CAN_DLC_32(13) = 32 bytes
* CAN_DLC_48(14) = 48 bytes
* CAN_DLC_64(15) = 64 bytes
*/
virtual byte trySendMsgBuf(unsigned long id, byte ext, byte rtr, byte dlc,
const byte *buf, byte iTxBuf = 0xff);
virtual byte sendMsgBuf(byte status, unsigned long id, byte ext, byte rtr,
byte dlc, volatile const byte *buf);
virtual byte sendMsgBuf(unsigned long id, byte ext, byte rtr, byte dlc,
const byte *buf, bool wait_sent = true);
using MCP_CAN::sendMsgBuf; // make other overloads visible
virtual void clearBufferTransmitIfFlags(byte flags = 0);
virtual byte readRxTxStatus(void);
virtual byte checkClearRxStatus(byte *status);
virtual byte checkClearTxStatus(byte *status, byte iTxBuf = 0xff);
virtual bool mcpPinMode(const byte pin, const byte mode);
virtual bool mcpDigitalWrite(const byte pin, const byte mode);
virtual byte mcpDigitalRead(const byte pin);
private:
byte mcp2518fd_readMsgBufID(volatile byte *len, volatile byte *buf);
byte mcp2518fd_sendMsg(const byte *buf, byte len, unsigned long id, byte ext,
byte rtr, bool wait_sent);
int8_t mcp2518fd_receiveMsg();
private:
uint8_t mcp2518fd_init(uint32_t speedset, const byte clock); // mcp2518fdinit
int8_t mcp2518fd_reset(void); // reset mcp2518fd
int8_t mcp2518fd_EccEnable(void); // Section: ECC
int8_t mcp2518fd_RamInit(uint8_t d);
int8_t mcp2518fd_ConfigureObjectReset(CAN_CONFIG *config);
int8_t mcp2518fd_Configure(CAN_CONFIG *config);
int8_t
mcp2518fd_TransmitChannelConfigureObjectReset(CAN_TX_FIFO_CONFIG *config);
int8_t mcp2518fd_TransmitChannelConfigure(CAN_FIFO_CHANNEL channel,
CAN_TX_FIFO_CONFIG *config);
int8_t
mcp2518fd_ReceiveChannelConfigureObjectReset(CAN_RX_FIFO_CONFIG *config);
int8_t mcp2518fd_ReceiveChannelConfigure(CAN_FIFO_CHANNEL channel,
CAN_RX_FIFO_CONFIG *config);
int8_t mcp2518fd_FilterObjectConfigure(CAN_FILTER filter,
CAN_FILTEROBJ_ID *id);
int8_t mcp2518fd_FilterMaskConfigure(CAN_FILTER filter, CAN_MASKOBJ_ID *mask);
int8_t mcp2518fd_FilterToFifoLink(CAN_FILTER filter, CAN_FIFO_CHANNEL channel,
bool enable);
int8_t mcp2518fd_BitTimeConfigure(uint32_t speedset,
CAN_SSP_MODE sspMode, CAN_SYSCLK_SPEED clk);
int8_t mcp2518fd_GpioModeConfigure(GPIO_PIN_MODE gpio0, GPIO_PIN_MODE gpio1);
int8_t mcp2518fd_TransmitChannelEventEnable(CAN_FIFO_CHANNEL channel,
CAN_TX_FIFO_EVENT flags);
int8_t mcp2518fd_ReceiveChannelEventEnable(CAN_FIFO_CHANNEL channel,
CAN_RX_FIFO_EVENT flags);
int8_t mcp2518fd_ModuleEventEnable(CAN_MODULE_EVENT flags);
int8_t mcp2518fd_OperationModeSelect(CAN_OPERATION_MODE opMode);
CAN_OPERATION_MODE mcp2518fd_OperationModeGet();
void mcp2518fd_TransmitMessageQueue();
int8_t mcp2518fd_TransmitChannelEventGet(CAN_FIFO_CHANNEL channel,
CAN_TX_FIFO_EVENT *flags);
int8_t mcp2518fd_ErrorCountStateGet(uint8_t *tec, uint8_t *rec,
CAN_ERROR_STATE *flags);
int8_t mcp2518fd_TransmitChannelLoad(CAN_FIFO_CHANNEL channel,
CAN_TX_MSGOBJ *txObj, uint8_t *txd,
uint32_t txdNumBytes, bool flush);
int8_t mcp2518fd_ReceiveChannelEventGet(CAN_FIFO_CHANNEL channel,
CAN_RX_FIFO_EVENT *flags);
int8_t mcp2518fd_ReceiveMessageGet(CAN_FIFO_CHANNEL channel,
CAN_RX_MSGOBJ *rxObj, uint8_t *rxd,
uint8_t nBytes);
int8_t mcp2518fd_ReceiveChannelUpdate(CAN_FIFO_CHANNEL channel);
int8_t mcp2518fd_TransmitChannelUpdate(CAN_FIFO_CHANNEL channel, bool flush);
int8_t mcp2518fd_ReceiveChannelStatusGet(CAN_FIFO_CHANNEL channel,
CAN_RX_FIFO_STATUS *status);
int8_t mcp2518fd_ErrorStateGet(CAN_ERROR_STATE *flags);
int8_t mcp2518fd_ModuleEventRxCodeGet(CAN_RXCODE *rxCode);
int8_t mcp2518fd_ModuleEventTxCodeGet(CAN_TXCODE *txCode);
int8_t mcp2518fd_TransmitChannelEventAttemptClear(CAN_FIFO_CHANNEL channel);
int8_t mcp2518fd_LowPowerModeEnable();
int8_t mcp2518fd_LowPowerModeDisable();
int8_t mcp2518fd_ReadByte(uint16_t address, uint8_t *rxd);
int8_t mcp2518fd_WriteByte(uint16_t address, uint8_t txd);
int8_t mcp2518fd_ReadWord(uint16_t address, uint32_t *rxd);
int8_t mcp2518fd_WriteWord(uint16_t address, uint32_t txd);
int8_t mcp2518fd_ReadHalfWord(uint16_t address, uint16_t *rxd);
int8_t mcp2518fd_WriteHalfWord(uint16_t address, uint16_t txd);
int8_t mcp2518fd_ReadByteArray(uint16_t address, uint8_t *rxd,
uint16_t nBytes);
int8_t mcp2518fd_WriteByteArray(uint16_t address, uint8_t *txd,
uint16_t nBytes);
int8_t mcp2518fd_WriteByteSafe(uint16_t address, uint8_t txd);
int8_t mcp2518fd_WriteWordSafe(uint16_t address, uint32_t txd);
int8_t mcp2518fd_ReadByteArrayWithCRC(uint16_t address, uint8_t *rxd,
uint16_t nBytes, bool fromRam,
bool *crcIsCorrect);
int8_t mcp2518fd_WriteByteArrayWithCRC(uint16_t address, uint8_t *txd,
uint16_t nBytes, bool fromRam);
int8_t mcp2518fd_ReadWordArray(uint16_t address, uint32_t *rxd,
uint16_t nWords);
int8_t mcp2518fd_WriteWordArray(uint16_t address, uint32_t *txd,
uint16_t nWords);
private:
int8_t
mcp2518fd_BitTimeConfigureNominal(void);
int8_t mcp2518fd_BitTimeConfigureData(CAN_SSP_MODE sspMode);
byte nReservedTx; // Count of tx buffers for reserved send
CAN_OPERATION_MODE mcpMode = CAN_CLASSIC_MODE; // Current controller mode
uint32_t bittime_compat_to_mcp2518fd(uint32_t speedset);
int calcBittime(const uint32_t inDesiredArbitrationBitRate,
const uint32_t inTolerancePPM = 10000/* 1% */);
uint32_t mSysClock; // PLL disabled, mSysClock = Oscillator Frequency
uint32_t mDesiredArbitrationBitRate; // desired ArbitrationBitRate
uint8_t mDataBitRateFactor; // multiplier between ArbitrationBitRate and DataBitrate
//--- Data bit rate; if mDataBitRateFactor==1, theses properties are not used for configuring the MCP2517FD.
uint8_t mDataPhaseSegment1 = 0 ; // if mDataBitRateFactor > 1: 2...32, else equal to mArbitrationPhaseSegment1
uint8_t mDataPhaseSegment2 = 0 ; // if mDataBitRateFactor > 1: 1...16, else equal to mArbitrationPhaseSegment2
uint8_t mDataSJW = 0 ; // if mDataBitRateFactor > 1: 1...16, else equal to mArbitrationSJW
//--- Bit rate prescaler is common to arbitration and data bit rates
uint16_t mBitRatePrescaler = 0 ; // 1...256
//--- Arbitration bit rate
uint16_t mArbitrationPhaseSegment1 = 0 ; // 2...256
uint8_t mArbitrationPhaseSegment2 = 0 ; // 1...128
uint8_t mArbitrationSJW = 0 ; // 1...128
bool mArbitrationBitRateClosedToDesiredRate = false ; // The above configuration is not correct
//--- Transmitter Delay Compensation Offset
int8_t mTDCO = 0 ; // -64 ... +63
};
/* CANFD Auxiliary helper */
class CANFD {
public:
static byte dlc2len(byte dlc);
static byte len2dlc(byte len);
static uint32_t BITRATE(uint32_t arbitration, uint8_t factor) {
return ((uint32_t)factor << 24) | (arbitration & 0xFFFFFUL);
}
};
#endif
File diff suppressed because it is too large Load Diff
+31
View File
@@ -0,0 +1,31 @@
#include "mcp_can.h"
/*********************************************************************************************************
** Function name: MCP_CAN
** Descriptions: Constructor
*********************************************************************************************************/
MCP_CAN::MCP_CAN(byte _CS)
{
pSPI = &SPI;
init_CS(_CS);
}
/*********************************************************************************************************
** Function name: init_CS
** Descriptions: init CS pin and set UNSELECTED
*********************************************************************************************************/
void MCP_CAN::init_CS(byte _CS)
{
if (_CS == 0)
{
return;
}
SPICS = _CS;
pinMode(SPICS, OUTPUT);
digitalWrite(SPICS, HIGH);
}
void MCP_CAN::setSPI(SPIClass *_pSPI)
{
pSPI = _pSPI; // define SPI port to use before begin()
}
+139
View File
@@ -0,0 +1,139 @@
#ifndef _MCP_CAN_H_
#define _MCP_CAN_H_
#include <Arduino.h>
#include <SPI.h>
#include <inttypes.h>
#ifndef SERIAL_PORT_MONITOR
#ifdef SEEED_XIAO_M0
#define SERIAL_PORT_MONITOR Serial
#elif defined(ARDUINO_SAMD_VARIANT_COMPLIANCE)
#define SERIAL_PORT_MONITOR SerialUSB
#else
#define SERIAL_PORT_MONITOR Serial
#endif
#endif
#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)
// clock
typedef enum {
MCP_NO_MHz,
/* apply to MCP2515 */
MCP_16MHz,
MCP_12MHz,
MCP_8MHz,
/* apply to MCP2518FD */
MCP2518FD_40MHz = MCP_16MHz /* To compatible MCP2515 shield */,
MCP2518FD_20MHz,
MCP2518FD_10MHz,
} MCP_CLOCK_T;
typedef enum {
CAN_NOBPS,
CAN_5KBPS,
CAN_10KBPS,
CAN_20KBPS,
CAN_25KBPS,
CAN_31K25BPS,
CAN_33KBPS ,
CAN_40KBPS ,
CAN_50KBPS ,
CAN_80KBPS ,
CAN_83K3BPS ,
CAN_95KBPS ,
CAN_95K2BPS ,
CAN_100KBPS ,
CAN_125KBPS ,
CAN_200KBPS ,
CAN_250KBPS ,
CAN_500KBPS ,
CAN_666KBPS ,
CAN_800KBPS ,
CAN_1000KBPS
} MCP_BITTIME_SETUP;
class MCP_CAN
{
public:
virtual void enableTxInterrupt(bool enable = true) = 0; // enable transmit interrupt
virtual void reserveTxBuffers(byte nTxBuf = 0) = 0;
virtual byte getLastTxBuffer() = 0;
/*
* speedset be in MCP_BITTIME_SETUP
* clockset be in MCP_CLOCK_T
*/
virtual byte begin(uint32_t speedset, const byte clockset, const bool _initSPI = true) = 0; // init can
virtual byte init_Mask(byte num, byte ext, unsigned long ulData) = 0; // init Masks
virtual byte init_Filt(byte num, byte ext, unsigned long ulData) = 0; // init filters
virtual void setSleepWakeup(byte enable) = 0; // Enable or disable the wake up interrupt
// (If disabled the MCP2515 will not be woken up by CAN bus activity, making it send only)
virtual byte sleep() = 0; // Put the MCP2515 in sleep mode
virtual byte wake() = 0; // Wake MCP2515 manually from sleep
virtual byte setMode(byte opMode) = 0; // Set operational mode
virtual byte getMode() = 0; // Get operational mode
virtual byte checkError(uint8_t* err_ptr = NULL) = 0; // if something error
/* ---- receiving ---- */
virtual byte checkReceive(void) = 0; // if something received
virtual byte readMsgBufID(byte status,
volatile unsigned long *id, volatile byte *ext, volatile byte *rtr,
volatile byte *len, volatile byte *buf) = 0; // read buf with object ID
/* wrapper */
virtual byte readMsgBufID(unsigned long *ID, byte *len, byte *buf) = 0;
virtual byte readMsgBuf(byte *len, byte *buf) = 0;
/* could be called after a successful readMsgBufID() */
unsigned long getCanId(void) { return can_id; }
byte isRemoteRequest(void) { return rtr; }
byte isExtendedFrame(void) { return ext_flg;}
/* ---- sending ---- */
virtual byte trySendMsgBuf(unsigned long id, byte ext, byte rtr,
byte len, const byte *buf, byte iTxBuf = 0xff) = 0; // as sendMsgBuf, but does not have any wait for free buffer
virtual byte sendMsgBuf(byte status, unsigned long id, byte ext, byte rtr,
byte len, volatile const byte *buf) = 0; // send message buf by using parsed buffer status
virtual byte sendMsgBuf(unsigned long id, byte ext, byte rtrBit,
byte len, const byte *buf, bool wait_sent = true) = 0; // send message with wait
/* wrapper */
inline byte sendMsgBuf(unsigned long id, byte ext, byte len, const byte *buf) {
return sendMsgBuf(id, ext, 0, len, buf, true);
}
virtual void clearBufferTransmitIfFlags(byte flags = 0) = 0; // Clear transmit flags according to status
virtual byte readRxTxStatus(void) = 0; // read has something send or received
virtual byte checkClearRxStatus(byte *status) = 0; // read and clear and return first found rx status bit
virtual byte checkClearTxStatus(byte *status, byte iTxBuf = 0xff) = 0; // read and clear and return first found or buffer specified tx status bit
virtual bool mcpPinMode(const byte pin, const byte mode) = 0; // switch supported pins between HiZ, interrupt, output or input
virtual bool mcpDigitalWrite(const byte pin, const byte mode) = 0; // write HIGH or LOW to RX0BF/RX1BF
virtual byte mcpDigitalRead(const byte pin) = 0; // read HIGH or LOW from supported pins
public:
MCP_CAN(byte _CS);
void init_CS(byte _CS); // define CS after construction before begin()
void setSPI(SPIClass *_pSPI);
protected:
byte ext_flg; // identifier xxxID
// either extended (the 29 LSB) or standard (the 11 LSB)
unsigned long can_id; // can id
byte rtr; // is remote frame
byte SPICS;
SPIClass *pSPI;
byte mcpMode; // Current controller mode
};
#endif