arduino - Arduino SPI接口读取随机值?(尝试使用 CAN 总线屏蔽)
问题描述
我在设置 Arduino CAN 总线通信时遇到了一个奇怪的问题。
描述如下,该视频显示了结果:https ://www.youtube.com/watch?v=NnMyC23Fe9s&feature=youtu.be
(备注:我尝试过的每块板都会出现这种效果)
硬件:
- 不同的 Arduino 或 Arduino-Equal 板(目前是 AZ-Delivery UNO,也尝试使用 Arduino Mega 和 Arduino UNO。
- SeedStudio 的 CAN 总线屏蔽 (V1.2)(请参阅https://github.com/Seeed-Studio/CAN_BUS_Shield)
使用的软件: https ://github.com/Seeed-Studio/CAN_BUS_Shield/blob/master/examples/send/send.ino
我从我的 2 个 Arduinos(不是 Mega,它不兼容)和 2 个 CAN 总线屏蔽开始完整设置,我想知道初始化失败然后突然成功。我猜这是关于焊接引脚的,所以我重新设计了它,但它并没有变得更好。
经过大量测试,我得出了您在视频中看到的结果:我什至不需要 CAN Bus Shield 来初始化 CAN Bus Shield O_o。如果我触摸 SPI 接口,它会将我识别为 CAN Bus Shield。
通过 CAN BUS 库,我检查了函数 CAN.begin。它使用 ISP 引脚(2 行中的 6 个引脚)来:
- 通过 SPI 将值写入地址
- 通过 SPI 从另一个地址读取两个值
通过 SPI 读取的代码(全部来自库,没有自己的代码!)
uint8_t MCP2515Class::readRegister(uint8_t address)
{
uint8_t value;
SPI.beginTransaction(_spiSettings);
digitalWrite(_csPin, LOW);
SPI.transfer(0x03);
SPI.transfer(address);
value = SPI.transfer(0x00);
digitalWrite(_csPin, HIGH);
SPI.endTransaction();
return value;
}
CAN.begin 函数
int MCP2515Class::begin(long baudRate)
{
CANControllerClass::begin(baudRate);
pinMode(_csPin, OUTPUT);
// start SPI
SPI.begin();
reset();
writeRegister(REG_CANCTRL, 0x80);
if (readRegister(REG_CANCTRL) != 0x80) {
return 0;
}
const struct {
long clockFrequency;
long baudRate;
uint8_t cnf[3];
} CNF_MAPPER[] = {
{ (long)8E6, (long)1000E3, { 0x00, 0x80, 0x00 } },
{ (long)8E6, (long)500E3, { 0x00, 0x90, 0x02 } },
{ (long)8E6, (long)250E3, { 0x00, 0xb1, 0x05 } },
{ (long)8E6, (long)200E3, { 0x00, 0xb4, 0x06 } },
{ (long)8E6, (long)125E3, { 0x01, 0xb1, 0x05 } },
{ (long)8E6, (long)100E3, { 0x01, 0xb4, 0x06 } },
{ (long)8E6, (long)80E3, { 0x01, 0xbf, 0x07 } },
{ (long)8E6, (long)50E3, { 0x03, 0xb4, 0x06 } },
{ (long)8E6, (long)40E3, { 0x03, 0xbf, 0x07 } },
{ (long)8E6, (long)20E3, { 0x07, 0xbf, 0x07 } },
{ (long)8E6, (long)10E3, { 0x0f, 0xbf, 0x07 } },
{ (long)8E6, (long)5E3, { 0x1f, 0xbf, 0x07 } },
{ (long)16E6, (long)1000E3, { 0x00, 0xd0, 0x82 } },
{ (long)16E6, (long)500E3, { 0x00, 0xf0, 0x86 } },
{ (long)16E6, (long)250E3, { 0x41, 0xf1, 0x85 } },
{ (long)16E6, (long)200E3, { 0x01, 0xfa, 0x87 } },
{ (long)16E6, (long)125E3, { 0x03, 0xf0, 0x86 } },
{ (long)16E6, (long)100E3, { 0x03, 0xfa, 0x87 } },
{ (long)16E6, (long)80E3, { 0x03, 0xff, 0x87 } },
{ (long)16E6, (long)50E3, { 0x07, 0xfa, 0x87 } },
{ (long)16E6, (long)40E3, { 0x07, 0xff, 0x87 } },
{ (long)16E6, (long)20E3, { 0x0f, 0xff, 0x87 } },
{ (long)16E6, (long)10E3, { 0x1f, 0xff, 0x87 } },
{ (long)16E6, (long)5E3, { 0x3f, 0xff, 0x87 } },
};
const uint8_t* cnf = NULL;
for (unsigned int i = 0; i < (sizeof(CNF_MAPPER) / sizeof(CNF_MAPPER[0])); i++) {
if (CNF_MAPPER[i].clockFrequency == _clockFrequency && CNF_MAPPER[i].baudRate == baudRate) {
cnf = CNF_MAPPER[i].cnf;
break;
}
}
if (cnf == NULL) {
return 0;
}
writeRegister(REG_CNF1, cnf[0]);
writeRegister(REG_CNF2, cnf[1]);
writeRegister(REG_CNF3, cnf[2]);
writeRegister(REG_CANINTE, FLAG_RXnIE(1) | FLAG_RXnIE(0));
writeRegister(REG_BFPCTRL, 0x00);
writeRegister(REG_TXRTSCTRL, 0x00);
writeRegister(REG_RXBnCTRL(0), FLAG_RXM1 | FLAG_RXM0);
writeRegister(REG_RXBnCTRL(1), FLAG_RXM1 | FLAG_RXM0);
writeRegister(REG_CANCTRL, 0x00);
if (readRegister(REG_CANCTRL) != 0x00) {
return 0;
}
return 1;
}
2个问题:
- 这怎么可能,系统应该区分正确的阅读和简单的错误,不是吗?
- 我该怎么做才能让这件事运行起来?
解决方案
我怀疑屏蔽演示程序不起作用,因为您没有将屏蔽插入汽车总线。
看一下屏蔽的示意图,在屏蔽上 Seeedstudio 页面的 Documents 选项卡下(https://www.seeedstudio.com/CAN-BUS-Shield-V2.html),看起来屏蔽是一个适配器,没有硬件可以对 arduino 说太多。我相信它需要插入汽车才能工作。
正如您所展示的,can 总线的软件检测并不是对插入汽车的屏蔽的可靠测试。
在防护罩的学习选项卡下,有一个演示链接。虽然演示视频不是英文的,但您可以在大约https://youtu.be/Y-1AFyOP-tk?t=565看到该板已插入汽车。
祝你的项目好运!
推荐阅读
- kubernetes - AWS EKS 组 NLB 作为 ALB,但具有不同的端口
- javascript - Gatsby 构建失败,因为 postcss 和 css-minimizer-webpack-plugin 上的 CSS minimzer 出现“未知单词”错误
- haskell - 值在 Haskell 中被丢弃
- c++ - 没有 RTTI 的内存高效 dynamic_cast
- r - 如何对一个数据集中的缺失数据进行 wilcoxon 符号秩检验
- django - 您如何控制模型中存储的语言?
- android-source - 如何使用 Android.bp 解决依赖项缺少的变体 arch:common?
- c# - C# - 检查句柄是否处于活动状态
- scala - 如何防范“选项”论点?
- r - 如何解决数据集变量的问题