当前位置: 首页 > news >正文

做网站需要字体授权网站建设武清

做网站需要字体授权,网站建设武清,广州网站的优化,logo网站免费文章目录 原启UART 走CAN收发器CH343 模拟CAN发送CPP ASIO SocketCANVXCANGithub Link 原启 早些年自动驾驶激光雷达还不支持PTP之类的时间同步, 很多都是用PPS时间同步, 激光雷达一般装的离控制器或者GNSS天线较远, 车上的线束一般数据电源各种都包在一起的, 如果3.3V直接从域… 文章目录 原启UART 走CAN收发器CH343 模拟CAN发送CPP ASIO SocketCANVXCANGithub Link 原启 早些年自动驾驶激光雷达还不支持PTP之类的时间同步, 很多都是用PPS时间同步, 激光雷达一般装的离控制器或者GNSS天线较远, 车上的线束一般数据电源各种都包在一起的, 如果3.3V直接从域控制器出, 信号将惨不忍睹, 为了解决长距离3.3V PPS传输受干扰的问题, 各种骚操作都整出来: 同轴线, 走SMA或者FAKRA接口出高电压大电流, 最简单的拿个三极管反相, 12V出, 接收端再反过来, 同时增大传输线中的电流, 抗干扰效果不错 直到看到某家域控制器居然是拿CANFD收发器来传输PPS, 顿时三观炸裂, 直呼卧槽. CAN收发器通俗讲只是电平转换, 和串口分TTL, RS232, RS485类似, 协议大体相似, 只是传输电平不同. 传PPS自然没有问题. 那大胆一点, UART远距离传输直接走CAN收发器是不是也行. 毕竟国产的CAN收发器价格上和RS232的电平转换芯片也相差不多了. UART 走CAN收发器 那就这样测试一下 实物图 果然可以 需要注意的地方: UART收发独立, 是全双工的, 如果收发不能时间上错开, 那收发引脚就各自接一片CAN收发器 那再扩展一下, B站上都能拿CH340来当音频设备放歌了, 这CH343能到6Mbps, 模拟下500Kbit/s的CAN发送, 和CAN分析仪通信好像问题不大. CH343 模拟CAN发送 串口通常的帧格式为 空闲高, 1低电平起始位 5到9数据位 0或1校验位 1到2停止位 以CAN标准数据帧为例, 刚好也是空闲高电平, 1bit帧起始(0), 11bitID, 1bit远程帧, 1bit扩展帧, 1bit占位符(0), 4位的数据长度代码, 0~8字节的数据, 151bit的CRC, 11bit的ACK(01), 7bit帧结束(1111111), 7bit帧间隔(1111111), 来源 Introduction to the Controller Area Network (CAN) (Rev. B) 还要注意填充位: 在相同逻辑电平的五个连续位之后, 需要插入1bit相反电平, 不然会被认为错误帧. 逻辑分析仪抓出来的波形: CH343模拟CAN发送 的原理分析: 串口助手上可以设置数据位5 6 7 8, 校验位None Even Mark Odd Space, 停止位 1 1.5 2, 也就是串口一个字节最少是1起始位5数据位0校验位1停止位, 也就是7bit, 最多1-8-1-2, 也就是14bit这里500Kbit/s进行CAN测试, CAN或CANFD的位的采样点一般在 75% ~ 87.5%, 串口的起始位和停止位控制不了, 所以要尽量让CAN的采样点落在串口的数据位, 把数据位搞的多多的, 停止位和校验位搞的少少的给串口4Mbps, 要想串口一字节(一帧的意思)对应500Kbit/s的CAN的一位, 那串口一个字节8bit, 对应 1起始位 0停止位 1停止位 搞到最小, 剩下最多的 6bit 都给数据, CAN采样点 80% 会落在 8 * 80% 6.4, 刚好在数据的最后1bit, 能控制就挺好 上面逻辑分析仪抓出来的CAN Bits行数据 000100100011000001010101011111001101110010001011111111 1bit膨胀成UART的1帧(字节), 直接翻译成十六进制串口数据, 0 翻译成00, 1翻译成全1, 6bit数据对应0b111111, 也就是0x3F, 这里测试发现直接写成0xFF也没有问题 00 00 00 FF 00 00 FF 00 00 00 FF FF 00 00 00 00 00 FF 00 FF 00 FF 00 FF 00 FF FF FF FF FF 00 00 FF FF 00 FF FF FF 00 00 FF 00 00 00 FF 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF因为串口空闲也是高电平, 所以最后的FF都不发了, ACK是其它收发器回的, 也不用发, 最终发的是 00 00 00 FF 00 00 FF 00 00 00 FF FF 00 00 00 00 00 FF 00 FF 00 FF 00 FF 00 FF FF FF FF FF 00 00 FF FF 00 FF FF FF 00 00 FF 00 00 00 FF连线 实物 先打开CAN分析仪 500Kbit/s, 80%采样点, 开启内部终端电阻. 再打开逻辑分析仪, 给通道同时配置UART和CAN协议解析. 最后打开串口调试助手, 4Mbps, 数据位6, 校验位None, 停止位1, 十六进制定时发送, 周期10ms 在CAN分析仪上位机中可以看到收到了数据(指示灯有几秒一次的闪红错误帧, 大概有1/19~1/20的错误帧) 逻辑分析仪的抓取 放大一下 功能上好像还点效果的. 至于偶发的错误帧, 大概是下图这样某帧发送32字节后, 没有连续发送的情形, 导致CAN的CRC算出来不正确, 可能是串口4M高速率的整包被USB截断了? 串口定时发送周期从 10ms 改成 100ms 后, 错误帧出现的概率依然不太变化, 情况并没有改善. 如果不用USB的包传输, 直接使用MCU的串口模拟CAN发送, 应该不会出现这样的问题? 但也要注意MCU的串口一般16字节FIFO, 可能要用DMA来搬数据, 不要出现传16字节断一会的情况. 换成 2Mbps, 数据位6, 校验位None, 停止位1, 十六进制定时发送, 周期10ms, 对应的CAN速率250kbit/s, 效果好了很多, 几乎不出现错误帧了: 下面用 Cpp Asio SocketCAN 写下任意帧发送的代码试试, 在WSL里面测试一下. CPP ASIO SocketCAN 先把CH343挂载进WSL里面: 下面的代码先把SocketCAN的数据的每1bit, 扩充成串口的每一个字节, bit 0对应0x00, bit1 对应0xFF, 然后计算CRC15, 最后插入填充位, 进行发送: #include linux/can.h#include asio.hpp #include chrono #include cstdbool #include cstdint #include iostream #include thread #include vectorint main(int argc, char *argv[]) {asio::io_context iocxt;// serial, 1 start bit, 8 data bits, 1 stop bit, no parity, 2.5M baud// CAN 100K, Serial 1M, 1 start bit, 8 data bits, 1 stop bit, no parity// CAN 250K, Serial 2M, 1 start bit, 6 data bits, 1 stop bit, no parity// CAN 500K, Serial 4M, 1 start bit, 6 data bits, 1 stop bit, no parityasio::serial_port ser(iocxt, /dev/ttyACM0);ser.set_option(asio::serial_port::baud_rate(2000000));ser.set_option(asio::serial_port::character_size(6));ser.set_option(asio::serial_port::stop_bits(asio::serial_port::stop_bits::one));ser.set_option(asio::serial_port::parity(asio::serial_port::parity::none));ser.set_option(asio::serial_port::flow_control(asio::serial_port::flow_control::none));if (!ser.is_open()) {std::cerr Failed to open serial port std::endl;return -1;}constexpr uint8_t Bit0 0x00;constexpr uint8_t Bit1 0xFF;// can crc15 calculationauto crc15 [](const std::vectoruint8_t data) {bool crc[15] {0};for (int i 0; i data.size(); i) {bool inv (data[i] Bit1) ^ crc[14];crc[14] crc[13] ^ inv;crc[13] crc[12];crc[12] crc[11];crc[11] crc[10];crc[10] crc[9] ^ inv;crc[9] crc[8];crc[8] crc[7] ^ inv;crc[7] crc[6] ^ inv;crc[6] crc[5];crc[5] crc[4];crc[4] crc[3] ^ inv;crc[3] crc[2] ^ inv;crc[2] crc[1];crc[1] crc[0];crc[0] inv;}uint16_t res 0;for (int i 0; i 15; i) {res | crc[i] i;}return res;};// fill stuff bitsauto fsb_insert [](std::vectoruint8_t data) {uint8_t count 0;bool last true;std::vectoruint8_t newdata;for (auto it data.begin(); it ! data.end(); it) {bool current *it Bit0 ? false : true;newdata.push_back(*it);if (current last) {count;} else {count 1;}if (count 5) {newdata.push_back(current ? Bit0 : Bit1);count 1;last !current;} else {last current;}}return newdata;};// socketcan frame to serial frameauto can2ser [](const can_frame frame) {std::vectoruint8_t data;uint32_t id 0;bool is_extended frame.can_id CAN_EFF_FLAG ? true : false;bool is_remote frame.can_id CAN_RTR_FLAG;uint8_t dlc frame.len;data.push_back(Bit0); // SOF, Start of frameif (is_extended) {id frame.can_id CAN_EFF_MASK;// High 11 bits idfor (uint8_t i 0; i 11; i) {uint8_t tmp ((uint8_t)(id (28 - i)) 0x01) ? Bit1 : Bit0;data.push_back(tmp);}data.push_back(Bit1); // SRR, Substitute remote requestdata.push_back(Bit1); // IDE, Identifier extension// Low 18 bits idfor (uint8_t i 0; i 18; i) {uint8_t tmp ((uint8_t)(id (17 - i)) 0x01) ? Bit1 : Bit0;data.push_back(tmp);}// RTRif (is_remote) {data.push_back(Bit1);} else {data.push_back(Bit0);}data.push_back(Bit0); // RB1, reserved bit 1} else {id frame.can_id CAN_SFF_MASK;for (uint8_t i 0; i 11; i) {uint8_t tmp ((uint8_t)(id (10 - i)) 0x01) ? Bit1 : Bit0;data.push_back(tmp);}// RTRif (is_remote) {data.push_back(Bit1);} else {data.push_back(Bit0);}data.push_back(Bit0); // IDE, Identifier extension}data.push_back(Bit0); // RB0, reserved bit 0// 4 bits DLCfor (uint8_t i 0; i 4; i) {uint8_t tmp ((uint8_t)(dlc (3 - i)) 0x01) ? Bit1 : Bit0;data.push_back(tmp);}// 0~64 bits datafor (uint8_t i 0; i frame.len; i) {for (uint8_t j 0; j 8; j) {uint8_t tmp ((frame.data[i] (7 - j)) 0x01) ? Bit1 : Bit0;data.push_back(tmp);}}// CRC15uint16_t crc crc15(data);for (uint8_t i 0; i 15; i) {uint8_t tmp ((crc (14 - i)) 0x01) ? Bit1 : Bit0;data.push_back(tmp);}data.push_back(Bit1); // CRC Delimiter// ACK, ACK Delimiter, EOF, IFS will not be caredreturn data;};// test can2serauto test []() {static uint8_t cnt 0;can_frame frame;// use 0x92345678, 8 bytes of 0x3C to test fill stuff bitsframe.can_id 0x12345678 | CAN_EFF_FLAG;frame.len 8;frame.__pad 0;frame.__res0 0;frame.len8_dlc 0;for (uint8_t i 0; i 8; i) {frame.data[i] cnt i;}cnt;auto data0 can2ser(frame);auto data fsb_insert(data0);// asio::write(ser, asio::buffer(data));asio::async_write(ser, asio::buffer(data),[](const asio::error_code ec, std::size_t bytes_transferred) {if (ec) {std::cerr Write error: ec.message() std::endl;}});};// timerauto ms std::chrono::milliseconds(10);asio::steady_timer t(iocxt, ms);std::functionvoid(const asio::error_code ) timer [](const asio::error_code ec) {if (ec) {std::cerr Timer error: ec.message() std::endl;} else {test();}t.expires_at(t.expiry() ms);t.async_wait(timer);};t.async_wait(timer);iocxt.run();return 0; }对应的cmake文件 cmake_minimum_required(VERSION 3.15 FATAL_ERROR) project(chcan LANGUAGES CXX)add_executable(${PROJECT_NAME} main.cpp)# https://github.com/cpm-cmake/CPM.cmake include(CPM.cmake)# https://github.com/chriskohlhoff/asio CPMAddPackage(gh:chriskohlhoff/asio#asio-1-28-21.28.2) find_package(Threads REQUIRED) if(asio_ADDED)add_library(asio INTERFACE)target_include_directories(asio SYSTEM INTERFACE ${asio_SOURCE_DIR}/asio/include)target_compile_definitions(asio INTERFACE ASIO_STANDALONE ASIO_NO_DEPRECATED)target_link_libraries(asio INTERFACE Threads::Threads) endif()target_link_libraries(${PROJECT_NAME} PRIVATE asio ) target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17)编译测试: $ mkdir build cd build $ cmake .. $ make $ sudo ./chcan如图 VXCAN 为了更实用一点, 如直接使用can_utils的cansend等命令, 用VXCAN虚拟出一对SocketCAN: #!/bin/sh sudo modprobe can_raw sudo modprobe vxcanif ip link show can0 /dev/null 21; thensudo ip link delete dev can0 type vxcan fisudo ip link add dev can0 type vxcan sudo ip link set up can0 sudo ip link set dev vxcan0 up运行检测: $ chmod 777 vxcan.sh $ ./vxcan.sh $ ifconfig下面编写 chvxcan, 使用对内的vxcan0进行收发. (这里在Ubuntu20测试, 里面 frame.len 写成了 frame.can_dlc) #include linux/can.h #include linux/can/raw.h#include asio.hpp #include chrono #include cstdbool #include cstdint #include cstring #include iostream #include thread #include vectorint main(int argc, char *argv[]) {asio::io_context iocxt;// serial, 1 start bit, 8 data bits, 1 stop bit, no parity, 2.5M baud// CAN 100K, Serial 1M, 1 start bit, 8 data bits, 1 stop bit, no parity// CAN 250K, Serial 2M, 1 start bit, 6 data bits, 1 stop bit, no parity// CAN 500K, Serial 4M, 1 start bit, 6 data bits, 1 stop bit, no parityasio::serial_port ser(iocxt, /dev/ttyACM0);ser.set_option(asio::serial_port::baud_rate(2000000));ser.set_option(asio::serial_port::character_size(6));ser.set_option(asio::serial_port::stop_bits(asio::serial_port::stop_bits::one));ser.set_option(asio::serial_port::parity(asio::serial_port::parity::none));ser.set_option(asio::serial_port::flow_control(asio::serial_port::flow_control::none));if (!ser.is_open()) {std::cerr Failed to open serial port std::endl;return -1;}// canint dev socket(PF_CAN, SOCK_RAW, CAN_RAW);if (dev 0) {std::cerr Failed to open can std::endl;return -1;}struct ifreq ifr;std::strcpy(ifr.ifr_name, vxcan0);if (ioctl(dev, SIOCGIFINDEX, ifr) 0) {std::cerr Failed to ioctl can std::endl;return -1;}struct sockaddr_can addr;addr.can_family AF_CAN;addr.can_ifindex ifr.ifr_ifindex;int enable_canfd 1;if (setsockopt(dev, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, enable_canfd,sizeof(enable_canfd)) 0) {std::cerr Failed to setsockopt canfd std::endl;return -1;}if (bind(dev, (struct sockaddr *)addr, sizeof(addr)) 0) {std::cerr Failed to bind can std::endl;return -1;}asio::posix::stream_descriptor can(iocxt, dev);constexpr uint8_t Bit0 0x00;constexpr uint8_t Bit1 0xFF;// can crc15 calculationauto crc15 [](const std::vectoruint8_t data) {bool crc[15] {0};for (int i 0; i data.size(); i) {bool inv (data[i] Bit1) ^ crc[14];crc[14] crc[13] ^ inv;crc[13] crc[12];crc[12] crc[11];crc[11] crc[10];crc[10] crc[9] ^ inv;crc[9] crc[8];crc[8] crc[7] ^ inv;crc[7] crc[6] ^ inv;crc[6] crc[5];crc[5] crc[4];crc[4] crc[3] ^ inv;crc[3] crc[2] ^ inv;crc[2] crc[1];crc[1] crc[0];crc[0] inv;}uint16_t res 0;for (int i 0; i 15; i) {res | crc[i] i;}return res;};// fill stuff bitsauto fsb_insert [](std::vectoruint8_t data) {uint8_t count 0;bool last true;std::vectoruint8_t newdata;for (auto it data.begin(); it ! data.end(); it) {bool current *it Bit0 ? false : true;newdata.push_back(*it);if (current last) {count;} else {count 1;}if (count 5) {newdata.push_back(current ? Bit0 : Bit1);count 1;last !current;} else {last current;}}return newdata;};// socketcan frame to serial frameauto can2ser [](const can_frame frame) {std::vectoruint8_t data;uint32_t id 0;bool is_extended frame.can_id CAN_EFF_FLAG ? true : false;bool is_remote frame.can_id CAN_RTR_FLAG;uint8_t dlc frame.can_dlc;data.push_back(Bit0); // SOF, Start of frameif (is_extended) {id frame.can_id CAN_EFF_MASK;// High 11 bits idfor (uint8_t i 0; i 11; i) {uint8_t tmp ((uint8_t)(id (28 - i)) 0x01) ? Bit1 : Bit0;data.push_back(tmp);}data.push_back(Bit1); // SRR, Substitute remote requestdata.push_back(Bit1); // IDE, Identifier extension// Low 18 bits idfor (uint8_t i 0; i 18; i) {uint8_t tmp ((uint8_t)(id (17 - i)) 0x01) ? Bit1 : Bit0;data.push_back(tmp);}// RTRif (is_remote) {data.push_back(Bit1);} else {data.push_back(Bit0);}data.push_back(Bit0); // RB1, reserved bit 1} else {id frame.can_id CAN_SFF_MASK;for (uint8_t i 0; i 11; i) {uint8_t tmp ((uint8_t)(id (10 - i)) 0x01) ? Bit1 : Bit0;data.push_back(tmp);}// RTRif (is_remote) {data.push_back(Bit1);} else {data.push_back(Bit0);}data.push_back(Bit0); // IDE, Identifier extension}data.push_back(Bit0); // RB0, reserved bit 0// 4 bits DLCfor (uint8_t i 0; i 4; i) {uint8_t tmp ((uint8_t)(dlc (3 - i)) 0x01) ? Bit1 : Bit0;data.push_back(tmp);}// 0~64 bits datafor (uint8_t i 0; i frame.can_dlc; i) {for (uint8_t j 0; j 8; j) {uint8_t tmp ((frame.data[i] (7 - j)) 0x01) ? Bit1 : Bit0;data.push_back(tmp);}}// CRC15uint16_t crc crc15(data);for (uint8_t i 0; i 15; i) {uint8_t tmp ((crc (14 - i)) 0x01) ? Bit1 : Bit0;data.push_back(tmp);}data.push_back(Bit1); // CRC Delimiter// ACK, ACK Delimiter, EOF, IFS will not be caredreturn data;};// read socketcan frame and write to serialuint8_t can_buffer[1024];std::functionvoid(const asio::error_code , std::size_t) can2ser_read [](const asio::error_code ec, std::size_t bytes_transferred) {if (ec) {std::cerr Read error: ec.message() std::endl;} else {if (bytes_transferred CAN_MTU) {struct can_frame frame;std::memcpy(frame, can_buffer, sizeof(can_frame));auto data0 can2ser(frame);auto data fsb_insert(data0);asio::async_write(ser, asio::buffer(data),[](const asio::error_code ec, std::size_t bytes_transferred) {if (ec) {std::cerr Write error: ec.message() std::endl;}});}}can.async_read_some(asio::buffer(can_buffer), can2ser_read);};can.async_read_some(asio::buffer(can_buffer), can2ser_read);iocxt.run();return 0; }测试如图 到这里, 就可以用你喜欢的语言, 如Python, Rust, C等对can0进行发送了. Github Link domain_controller_orin_x2_tc397/ch343_can at main · weifengdq/domain_controller_orin_x2_tc397 (github.com)
http://www.pierceye.com/news/463510/

相关文章:

  • 网站如何做实名验证码深圳企业网站推广
  • 傻瓜式大型网站开发工具餐饮业手机php网站
  • 网站建设小细节图片东阳网站建设yw126
  • 为什么找不到做网站的软件怎么做音乐mp3下载网站
  • 做一个网站需要什么网络营销方式分析论文
  • 可以做3d电影网站企业网站优化应该怎么做
  • 中山做网站联系电话app客户端开发公司
  • 秦皇岛网站推广价钱南京建设网站制作
  • 2018钓鱼网站建设邢台seo公司
  • 深圳建设交易中心网站域名网站建设
  • 做网站色弱可以吗一个网址多少钱
  • 如何查询网站接入信息产品营销网站
  • 常用博客建站程序遂溪网站开发公司
  • 网站开发软件系统安徽通皖建设工程有限公司网站
  • 意派网站开发新手篇做平面常用的网站
  • 广州网站设计费用深圳室内设计师网
  • 有什么可以做兼职的网站吗建设网站的需求分析
  • 专门做进口产品的网站6wordpress赚钱方法
  • 长兴网站建设公司郫县城乡规划建设管理局网站
  • 天津建设工程信息网站搜索引擎推广是什么工作
  • 网站的系统建设方式网站建设报价表格
  • 商城展示网站建设我劝大家不要学android
  • 官网的建站过程云南网站建设营销
  • 那个网站上有打码的任务做台州做网站的公司
  • 做公司网站 需要注意什么汕尾市住房和城建设局网站
  • 建立音乐网站网络媒体设计是什么
  • html网站怎么进入后台网站建设完成之后要索取哪些
  • 做炭化料的网站国外可以做非法网站吗
  • 厦门 网站建设 网站开发 未来网络做百科专用参考链接的网站
  • 手机网站友情链接怎么做网站轮播图