WIFI&蓝牙(ESP32)转CAN总线&串口TTL模块-A1-蓝牙和CAN总线透传通信(经典蓝牙从机)
<p><iframe name="ifd" src="https://mnifdv.cn/resource/cnblogs/ESP32_CAN" frameborder="0" scrolling="auto" width="100%" height="1500"></iframe></p>
实现的功能说明
设备作为经典蓝牙从机, 使用蓝牙调试助手作为蓝牙主机;
蓝牙调试助手和经典蓝牙设备配对并连接,然后通过蓝牙发送数据给设备,设备接收到数据通过CAN总线发送;
设备从CAN总线接收的数据通过蓝牙发送给蓝牙调试助手;
测试
1,安装CAN支持库(如果已经安装了不需要安装)
主题选择通信,然后输入 CAN, 往下找到对应的库,然后点击安装
2,打开这节的工程(放到非中文目录打开)
3,使用Type-C数据线连接上设备
4,选择设备对应的端口号(根据自己的选择)
5,当前设置的CAN速率为250K, 设备蓝牙的名字为 ESP32_SLAVE_BT
6,点击下载
7,连接CAN设备(我使用的CAN数据测试仪)
8,打开手机蓝牙页面, 点击连接配对设备的蓝牙
9,安装手机蓝牙调试助手APP
10,点击这个(这边这个是测试经典蓝牙)
11,点击
12,蓝牙调试助手通过蓝牙发送数据给设备
把16进制数据 01 01 02 03 04 通过蓝牙发送给设备
可以在CAN 总线上接收到数据, 说明设备把蓝牙接收的数据转发到了CAN
13,使用CAN测试仪, 通过CAN总线发送数据给设备
可以在手机蓝牙APP上接收到数据, 说明设备把CAN接收的数据转发到了蓝牙上
程序说明
程序都有注释,只说下注意的地方
CAN总线最多一次传8字节数据,所以这里做了限制
#include "BluetoothSerial.h" #include <esp_bt_device.h> #include <CAN.h> #define LEDPIN 5 //LED /*设置CAN引脚*/ #define CanRxPin GPIO_NUM_16 #define CanTxPin GPIO_NUM_17 /*设置CAN 比特率*/ #define CanBitrate 250E3 //500E3, 250E3, 200E3, 125E3, 100E3, 80E3, 50E3, 40E3, 20E3, 10E3, 5E3 #define CanExPacket 0 //0:标准帧 1:扩展帧 BluetoothSerial SerialBT; //定义一个蓝牙对象 uint8_t CanRcvBuf[8]; uint8_t CanRcvBufCnt=0; void setup() { pinMode(LEDPIN, OUTPUT); Serial.begin(9600); /*BT*/ SerialBT.onData(RecvData); //注册接收回调函数 SerialBT.begin("ESP32_SLAVE_BT"); //蓝牙的名字 /*CAN*/ CAN.setPins(CanRxPin, CanTxPin); if (!CAN.begin(CanBitrate*2)) { Serial.println("Starting CAN failed!"); while (1); } CAN.onReceive(onReceive);//注册CAN数据接收回调函数 /*日志打印*/ Serial.println("start"); } void loop() { if(SerialBT.hasClient())//蓝牙处于连接中 { digitalWrite(LEDPIN, LOW); } else { digitalWrite(LEDPIN, HIGH); } } /*蓝牙数据接收回调函数*/ void RecvData(const uint8_t *buffer, size_t size) { if(size > 0 && size<=8) { Serial.write(buffer, size); //打印出来 /*使用CAN总线发送*/ #if (CanExPacket==0) //使用标准帧 CAN.beginPacket(0x12);//设置标准帧ID CAN.write(buffer, size);//设置要发送的数据 CAN.endPacket();//发送 #else CAN.beginExtendedPacket(0xabcdef);//设置扩展帧ID CAN.write(buffer, size);//设置要发送的数据 CAN.endPacket();//发送 #endif } } /*CAN数据接收回调函数*/ void onReceive(int packetSize) { /*日志打印*/ Serial.println("CAN Rceive:"); if (CAN.packetExtended())//接收的是扩展帧 { /*日志打印*/ Serial.println("extended"); } if (CAN.packetRtr())//判断有没有RTR { /*日志打印*/ Serial.println("RTR"); } /*获取ID*/ char id = CAN.packetId(); /*日志打印*/ Serial.print("packet id 0x"); Serial.print(id, HEX); Serial.println(); if (CAN.packetRtr())//远程帧没有数据只打印数据长度 { /*日志打印*/ Serial.print("requested length:"); Serial.print(CAN.packetDlc());//打印DLC Serial.println(); } else//打印数据 { /*日志打印*/ Serial.print("data length:"); Serial.print(packetSize); Serial.println(); Serial.print("data:"); CanRcvBufCnt=0; while (CAN.available())//如果有可读的字节数 { /*把Can数据拷贝到数组*/ CanRcvBuf[CanRcvBufCnt] = CAN.read(); /*日志打印*/ Serial.print(CanRcvBuf[CanRcvBufCnt],HEX);//读取一个数据并打印(打印16进制数) Serial.print(" "); CanRcvBufCnt++; } //把接收的CAN 数据通过蓝牙发送出去 if(SerialBT.hasClient())//蓝牙处于连接中 { SerialBT.write((const uint8_t*)CanRcvBuf, packetSize);//发送数据 } } /*日志打印*/ Serial.println(); } //SerialBT.println("..");
.