mirror of
https://github.com/Seeed-Studio/Seeed_Arduino_CAN.git
synced 2026-07-28 12:15:53 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb607da7da | ||
|
|
fc19066027 | ||
|
|
ca8fcc7fe3 | ||
|
|
31438c426b | ||
|
|
ad48756e56 | ||
|
|
c8556d5c1b | ||
|
|
23b23eff5c | ||
|
|
6f556e2ac8 | ||
|
|
491283753f | ||
|
|
23666a81df | ||
|
|
6dcfabc65e | ||
|
|
02d18fb3b3 | ||
|
|
7328966ef0 | ||
|
|
adceb9b415 | ||
|
|
eb6887ba3c | ||
|
|
b946ae7c24 | ||
|
|
58a38c9387 | ||
|
|
e2cbc7bb07 | ||
|
|
06e6e163a9 | ||
|
|
9226a0ae6b | ||
|
|
6acaf5a258 | ||
|
|
b517530d07 | ||
|
|
c991cacd9a | ||
|
|
5a41853758 | ||
|
|
4080671c63 | ||
|
|
c110bf10c0 | ||
|
|
1351334686 | ||
|
|
f579f66402 | ||
|
|
1b63d26adc | ||
|
|
e9adda5cea | ||
|
|
bb92e93e9b | ||
|
|
efbcf196f8 | ||
|
|
14f1e98a12 | ||
|
|
78173b3225 | ||
|
|
f8a04fd600 | ||
|
|
5863c67c70 | ||
|
|
f3ae9d0f10 | ||
|
|
7ba9b7deff | ||
|
|
d756ec0980 | ||
|
|
ef05384659 | ||
|
|
66305bbf5d | ||
|
|
d315924485 | ||
|
|
85648cd0fc | ||
|
|
8b82b6ef89 | ||
|
|
240bb4de04 | ||
|
|
438ae2bb21 | ||
|
|
8920835971 | ||
|
|
7cb25da245 | ||
|
|
feeb26e4e1 | ||
|
|
d73add5f0a | ||
|
|
b2247a8436 | ||
|
|
9826a04cae | ||
|
|
e1047f27e3 | ||
|
|
d89af776af | ||
|
|
3dea108ee3 | ||
|
|
7c195a14ed | ||
|
|
c45e7935ff | ||
|
|
300c1c4a4b | ||
|
|
3dff8e3d20 | ||
|
|
39d55dc608 | ||
|
|
cfd840cd23 | ||
|
|
92597cb97d | ||
|
|
efad5bb364 | ||
|
|
6dc4e7d197 | ||
|
|
c522d7842f | ||
|
|
0677b13bfc | ||
|
|
544d2c8eeb | ||
|
|
e3834de29c | ||
|
|
1fc462f2b2 | ||
|
|
3a35904217 | ||
|
|
4577e4fa7b | ||
|
|
36a70d5cdc | ||
|
|
d8ecb0ddcc | ||
|
|
6ad2ba8c4b | ||
|
|
dad91a1dba | ||
|
|
cf1fbfaddf | ||
|
|
06cf5a136d | ||
|
|
fc04762c9e | ||
|
|
4e171d138e | ||
|
|
9a153768ee | ||
|
|
69791769cf | ||
|
|
8c8500aa8c | ||
|
|
c11356b4e5 | ||
|
|
3ff9e1b4c3 | ||
|
|
fc85852e2e | ||
|
|
0838960cdd | ||
|
|
57d8f936b2 | ||
|
|
c31b9fbbd6 | ||
|
|
7d08979ce1 | ||
|
|
0a1883947a | ||
|
|
a899ff745b | ||
|
|
62f484a4b4 | ||
|
|
bfc70f2099 | ||
|
|
3c78368258 | ||
|
|
cbe5bf3af0 | ||
|
|
576e6c9548 | ||
|
|
1007209ac4 | ||
|
|
41b900754c | ||
|
|
2ef6a99dd2 | ||
|
|
bc014ccbd8 | ||
|
|
68da38c24b | ||
|
|
81ecabba1c | ||
|
|
c26bfa704b | ||
|
|
c72a842c31 | ||
|
|
a827db4891 | ||
|
|
d310e299c6 | ||
|
|
a1dbce2513 | ||
|
|
e2d0f87918 | ||
|
|
d50624c15a | ||
|
|
da74297193 | ||
|
|
1a927343eb | ||
|
|
391a4891b0 | ||
|
|
6e9112c4f1 | ||
|
|
1e5d371fe2 | ||
|
|
7eda1c5315 | ||
|
|
ed18dd50ad | ||
|
|
4a9eb41389 | ||
|
|
fd0d620578 | ||
|
|
dc2fb92dad | ||
|
|
22d5092c4b | ||
|
|
cec72bf65a | ||
|
|
edaba2d87e | ||
|
|
055c0024ea | ||
|
|
dc03e48b66 | ||
|
|
33bb082ecf | ||
|
|
bea2f9dd4d | ||
|
|
54030c8ced | ||
|
|
cab016e7d5 | ||
|
|
7d30ccccc8 | ||
|
|
7d41ceb28a | ||
|
|
1935258e58 | ||
|
|
34de82b7ec | ||
|
|
81a975210b | ||
|
|
ad54af425f | ||
|
|
6ff126f5ba | ||
|
|
05124b74b9 | ||
|
|
5020428581 | ||
|
|
f2946d199b | ||
|
|
19203a365d | ||
|
|
ee45ed5eae | ||
|
|
962660f3e8 | ||
|
|
3594a57299 | ||
|
|
75df0a0e9b | ||
|
|
00ef33618b | ||
|
|
7b7c780451 | ||
|
|
7368740360 | ||
|
|
8dc685cedc | ||
|
|
7a35c12770 | ||
|
|
d7ce9e6779 | ||
|
|
cefe36904e | ||
|
|
6f25bcddb9 |
@@ -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.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: Custom issue template
|
||||
about: Describe this issue template's purpose here.
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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 }}
|
||||
@@ -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 }}
|
||||
@@ -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
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -1,168 +1,31 @@
|
||||
# CAN BUS Shield
|
||||
---
|
||||

|
||||
# Seeed Arduino CAN [](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
|
||||
:-------------------------:|:-------------------------:
|
||||
[](https://www.seeedstudio.com/CAN-BUS-Shield-V2-p-2921.html) | [](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/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>
|
||||
|
||||
|
||||
[](https://github.com/igrigorik/ga-beacon)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
# arduino-canbus-monitor [](https://travis-ci.org/latonita/arduino-canbus-monitor) [](https://scan.coverity.com/projects/latonita-arduino-canbus-monitor) [](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) [](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).
|
||||
|
||||
```
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
|
||||
*********************************************************************************************************/
|
||||
|
||||
@@ -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
|
||||
*********************************************************************************************************/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
*********************************************************************************************************/
|
||||
|
||||
@@ -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
|
||||
*********************************************************************************************************/
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
*********************************************************************************************************/
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
*********************************************************************************************************/
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
Reference in New Issue
Block a user