146_Arduino使用MCP2515实现CAN收发

整个Arduino系列的学习汇总链接如下: https://github.com/GreyZhang/g_arduino 感觉Arduino做一个小工具实现起来特别容易,逐渐成了我的一个测试小助手。也很容易做成小的快速原型机,做一些功能测试。 工作中CAN使用的比较多,但是我的Arduino小板子上没有,

         整个Arduino系列的学习汇总链接如下:

         https://github.com/GreyZhang/g_arduino

         感觉Arduino做一个小工具实现起来特别容易,逐渐成了我的一个测试小助手。也很容易做成小的快速原型机,做一些功能测试。

         工作中CAN使用的比较多,但是我的Arduino小板子上没有,找了一下找到一款SPI转CAN的工具。使用的是MCP2515的一个转换工具,砍了下Arduino的库中也有相应的支持。测试了一下,功能实现比较容易。

         首先直接运行了CAN的loopback模式,运行比较顺利。接着找了CAN分析仪,我使用的是Kvaser的一个CAN卡,测试了一下收发功能。

         测试代码如下:

//——————————————————————————————————————————————————————————————————————————————
//  ACAN2515 Demo in loopback mode
//——————————————————————————————————————————————————————————————————————————————

#include <ACAN2515.h>

//——————————————————————————————————————————————————————————————————————————————
//  MCP2515 connections:
//    - standard SPI pins for SCK, MOSI and MISO
//    - a digital output for CS
//    - interrupt input pin for INT
//——————————————————————————————————————————————————————————————————————————————
// If you use CAN-BUS shield (http://wiki.seeedstudio.com/CAN-BUS_Shield_V2.0/) with Arduino Uno,
// use B connections for MISO, MOSI, SCK, #9 or #10 for CS (as you want),
// #2 or #3 for INT (as you want).
//——————————————————————————————————————————————————————————————————————————————

static const byte MCP2515_CS = 10; // CS input of MCP2515 (adapt to your design)
static const byte MCP2515_INT = 3; // INT output of MCP2515 (adapt to your design)

//——————————————————————————————————————————————————————————————————————————————
//  MCP2515 Driver object
//——————————————————————————————————————————————————————————————————————————————

ACAN2515 can(MCP2515_CS, SPI, MCP2515_INT);

//——————————————————————————————————————————————————————————————————————————————
//  MCP2515 Quartz: adapt to your design
//——————————————————————————————————————————————————————————————————————————————

static const uint32_t QUARTZ_FREQUENCY = 8UL * 1000UL * 1000UL; // 8 MHz

//——————————————————————————————————————————————————————————————————————————————
//   SETUP
//——————————————————————————————————————————————————————————————————————————————

void setup()
{
    //--- Start serial
    Serial.begin(38400);
    //--- Wait for serial (blink led at 10 Hz during waiting)
    while (!Serial)
    {
        delay(50);
    }
    //--- Begin SPI
    SPI.begin();
    //--- Configure ACAN2515
    Serial.println("Configure ACAN2515");
    ACAN2515Settings settings(QUARTZ_FREQUENCY, 500UL * 1000UL); // CAN bit rate 500 kb/s
    settings.mRequestedMode = ACAN2515Settings::NormalMode;      // Select Normal mode
    const uint16_t errorCode = can.begin(settings, [] { can.isr(); });
    if (errorCode == 0)
    {
        Serial.print("Bit Rate prescaler: ");
        Serial.println(settings.mBitRatePrescaler);
        Serial.print("Propagation Segment: ");
        Serial.println(settings.mPropagationSegment);
        Serial.print("Phase segment 1: ");
        Serial.println(settings.mPhaseSegment1);
        Serial.print("Phase segment 2: ");
        Serial.println(settings.mPhaseSegment2);
        Serial.print("SJW: ");
        Serial.println(settings.mSJW);
        Serial.print("Triple Sampling: ");
        Serial.println(settings.mTripleSampling ? "yes" : "no");
        Serial.print("Actual bit rate: ");
        Serial.print(settings.actualBitRate());
        Serial.println(" bit/s");
        Serial.print("Exact bit rate ? ");
        Serial.println(settings.exactBitRate() ? "yes" : "no");
        Serial.print("Sample point: ");
        Serial.print(settings.samplePointFromBitStart());
        Serial.println("%");
    }
    else
    {
        Serial.print("Configuration error 0x");
        Serial.println(errorCode, HEX);
    }
}

//------------------------------------------------------------------------------
#define DEBUG_MODE 1

CANMessage frame_tx;
CANMessage frame_rx;
char putc_char;
int counter = 0;
//——————————————————————————————————————————————————————————————————————————————

void loop()
{
#if DEBUG_MODE
    frame_tx.len = 8;
    frame_tx.ext = false;
    frame_tx.rtr = false;
    frame_tx.idx = 0x0;
    frame_tx.data[0] += 1U;
    if (can.tryToSend(frame_tx))
    {
        Serial.println(counter++);
    }
    delay(100);
    if (can.available())
    {
        can.receive(frame_rx);
        {
            frame_tx.id = frame_rx.id;
        }
    }
#endif
}

         运行情况如下:

         代码设计的功能,把接收到的报文的ID再次发送出来。接下来测几个报文:

         测试了一下,功能正常。

         Arduino有一个很好的串口功能,这样我就能够实现一个CAN通信版本的printf了,这个功能后面尝试一下。

知秋君
上一篇 2024-07-22 17:36
下一篇 2024-07-22 17:02

相关推荐