找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4340|回复: 4
收起左侧

CAN Bootloader协议介绍与C++源码

[复制链接]
ID:210626 发表于 2018-10-21 20:53 | 显示全部楼层 |阅读模式
CAN Bootloader命令列表
命令名称    命令值(Hex)    说明
GET_ADDR(1)    000    向主机请求本机地址
ERASE(2)    XX1    擦除应用程序
WRITE(3)    XX2    将程序写入Flash
READ(4)    XX3    将程序从Flash中读出
GO(5)    XX4    执行应用程序
SET_WRITE_ADDR    XX5    设置写数据起始地址
WRITE_CONTINUOUS    XX6    连续写数据,写数据地址自动递增
SET_READ_ADDR    XX7    设置读数据起始地址
READ_CONTINUOUS    XX8    连续读数据,读数据起始地址递增
GET_VERSION    XX9    获取Bootloader固件版本
ADDR_OK    XXC    请求地址可用
ADDR_ERROR    XXD    请求地址不可用
CMD_OK    XXE    命令执行成功
CMD_ERROR    XXF    命令执行失败
1、本机地址为7bit,所以在CAN总线上最多只能连接128个节点,本命令由从机发出,主机会给从机分配一个临时地址并回复CMD_OK,如果主机地址使用完毕则回复CMD_ERROR,从机可以根据接收到的主机反馈判断本机地址设置是否成功;
2、擦除应用程序命令会带擦除起始地址和擦除结束地址;
3、写数据命令带4字节写数据地址参数和4字节的数据;
4、读数据命令会携带4字节地址,从机返回4字节数据;
5、执行应用程序;

命令详解
GET_ADDR:
该命令由从机发送给主机,主机接收到该命令后会分配一个地址给从机,如果主机无法分配地址则发送ADDR_ERROR回复从机,此时从机应进入无法获取地址的错误处理程序中。主机和从机在发送命令的时候必须携带8字节物理地址,也就是说DLC为8。从机如果正确获取到地址后可以设置过滤器为只接收和自己地址匹配的数据,这样可以减少CPU的负担。
ERASE:
擦除应用程序储存地址区域的数据,该命令由主机发送给从机,命令携带8字节数据,前4字节数据为擦出起始地址,后4字节为擦出结束地址,从机接收到该命令后可回复CMD_OK或CMD_ERROR给主机。
WRITE:
将一个字(4Byte)的数据写入指定的Flash地址,该命令由主机发送给从机,命令携带8字节数据,前4字节为数据写入地址,后4字节为准备写入的数据。
READ:
从指定的Flash地址读取4字节的数据,该命令由主机发送给从机或者从机发送给主机,主机发送给从机的时候携带4字节地址参数,从机发送给主机的时候携带4字节的数据。
GO:
执行应用程序,该命令由主机发送给从机,命令携带4字节的地址参数,从机接收到该命令后从指定的地址开始执行程序。
SET_WRITE_ADDR:
设置连续写数据的起始地址,该命令由主机发送给从机,命令携带4字节的地址参数。
WRITE_CONTINUOUS:
连续写数据到Flash中,该命令由主机发送给从机,从机根据SET_WRITE_ADDR命令设置的起始地址将程序数据写入Flash中,该命令携带最多8字节的程序数据。
SET_READ_ADDR:
设置连续读数据起始地址,该命令由主机发送给从机,命令携带4字节的地址参数。
READ_CONTINUOUS:
连续读数据,该命令由主机发送给从机或者由从机发送给主机,由主机发送给从机时DLC为0,从机接收到这个命令后将该命令携带最多8字节数据返回给主机。
GET_VERSION:
获取Bootloader固件版本号,版本号由两字节组成,第一字节为主版本号,第二字节为从版本号。
ADDR_OK:
返回合法的从机地址。
ADDR_ERROR:
不能正常分配从机地址。
CMD_OK:
命令支持成功。
CMD_ERROR:
命令执行失败。

单片机源程序如下:
  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"

  3. typedef  struct {
  4.   unsigned char   SJW;
  5.   unsigned char   BS1;
  6.   unsigned char   BS2;
  7.   unsigned short  PreScale;
  8. } tCAN_BaudRate;

  9. #define GET_ADDR                        0x0        //向主机请求本机地址,XX为本机地址,一共7bit
  10. #define ERASE                                0x1        //擦除应用程序
  11. #define WRITE                                0x2        //将程序写入Flash
  12. #define READ                                0x3        //将程序从Flash中读出
  13. #define GO                                        0x4        //执行应用程序
  14. #define SET_WRITE_ADDR                0x5        //设置写数据起始地址
  15. #define WRITE_CONTINUOUS        0x6        //连续写数据,写数据地址自动递增
  16. #define SET_READ_ADDR                0x7        //设置读数据起始地址
  17. #define READ_CONTINUOUS                0x8        //连续读数据,读数据起始地址递增
  18. #define GET_VERSION                        0x9        //获取Bootloader固件版本
  19. #define        ONLINE_CHECK                0xA        //检测CAN节点是否在线
  20. #define ADDR_OK                                0xC        //请求地址可用
  21. #define ADDR_ERROR                        0xD        //请求地址不可用
  22. #define CMD_OK                                0xE        //命令执行成功
  23. #define CMD_ERROR                        0xF        //命令执行失败

  24. MainWindow::MainWindow(QWidget *parent) :
  25.     QMainWindow(parent),
  26.     ui(new Ui::MainWindow)
  27. {
  28.     int ret;
  29.     ui->setupUi(this);
  30.     for(int i=0;i<128;i++){
  31.         can_addr.local_addr[i]=0;
  32.     }
  33.     nodeTableInit();
  34.     ret = VCI_ScanDevice(1);
  35.     if(ret<=0){
  36.         QMessageBox::warning(this,"Warning","No device Connected!");
  37.         return;
  38.     }
  39.     ret = VCI_OpenDevice(VCI_USBCAN2,ui->deviceIndexComboBox->currentIndex(),0);
  40.     if(ret!=STATUS_OK){
  41.         QMessageBox::warning(this,"Warning","Open device Error!");
  42.         return;
  43.     }
  44.     if(canInit()){
  45.         ret = VCI_StartCAN(VCI_USBCAN2,
  46.                            ui->deviceIndexComboBox->currentIndex(),
  47.                            ui->channelIndexComboBox->currentIndex());
  48.         if(ret!=STATUS_OK){
  49.             QMessageBox::warning(this,"Warning","Start CAN Error!");
  50.             return;
  51.         }
  52.     }
  53.     scanNodeTimerID = startTimer(100);
  54. }

  55. MainWindow::~MainWindow()
  56. {
  57.     VCI_ResetCAN(VCI_USBCAN2,
  58.                  ui->deviceIndexComboBox->currentIndex(),
  59.                  ui->channelIndexComboBox->currentIndex());
  60.     VCI_CloseDevice(VCI_USBCAN2,ui->deviceIndexComboBox->currentIndex());
  61.     delete ui;
  62. }

  63. void MainWindow::nodeTableInit(void)
  64. {
  65.     QStringList strList;
  66.     strList << "Addr" << "MAC(Hex)" << "Version";
  67.     model = new QStandardItemModel;
  68.     model->setColumnCount(strList.count());
  69.     model->setRowCount(127);
  70.     model->setHorizontalHeaderLabels(strList);
  71.     ui->nodeListTableView->setModel(model);
  72.     ui->nodeListTableView->setColumnWidth(0, 50);
  73.     ui->nodeListTableView->setColumnWidth(1, 160);
  74.     ui->nodeListTableView->setColumnWidth(2, 60);
  75.     ui->nodeListTableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
  76.     ui->nodeListTableView->setSelectionBehavior(QAbstractItemView::SelectRows); //整行选中的方式
  77.     ui->nodeListTableView->verticalHeader()->setDefaultSectionSize(20);
  78.     ui->nodeListTableView->verticalHeader()->hide();
  79.     for(int r=0;r<model->rowCount();r++){
  80.         for(int c = 0; c < model->columnCount(); c++)
  81.         {
  82.             QStandardItem *item = new QStandardItem("");
  83.             model->setItem(r,c,item);
  84.         }
  85.     }
  86. }
  87. int MainWindow::CAN_GetBaudRateNum(unsigned int BaudRate)
  88. {
  89.     switch(BaudRate){
  90.         case 1000000 :return 0;
  91.         case 900000 :return 1;
  92.         case 800000 :return 2;
  93.         case 666000 :return 3;
  94.         case 600000 :return 4;
  95.         case 500000 :return 5;
  96.         case 400000 :return 6;
  97.         case 300000 :return 7;
  98.         case 250000 :return 8;
  99.         case 225000:return 9;
  100.         case 200000 :return 10;
  101.         case 160000:return 11;
  102.         case 150000 :return 12;
  103.         case 144000:return 13;
  104.         case 125000 :return 14;
  105.         case 120000:return 15;
  106.         case 100000 :return 16;
  107.         case 90000 :return 17;
  108.         case 80000 :return 18;
  109.         case 75000:return 19;
  110.         case 60000 :return 20;
  111.         case 50000 :return 21;
  112.         case 40000 :return 22;
  113.         case 30000 :return 23;
  114.         case 20000 :return 24;
  115.         default:return 0;
  116.     }
  117. }
  118. bool MainWindow::canInit(void)
  119. {
  120.     int ret;
  121.     tCAN_BaudRate  CAN_BaudRateInitTab[]= {      // CLK=36MHz
  122.        1,5,3,4,     // 1M
  123.        1,4,3,5,     // 900K
  124.        1,5,3,5,     // 800K
  125.        1,5,3,6,     // 666K
  126.        1,6,3,6,     // 600K
  127.        1,5,2,9,     // 500K
  128.        1,7,2,9,     // 400K
  129.        1,16,3,6,    // 300K
  130.        1,4,3,18,    // 250K
  131.        1,6,3,16,        // 225K
  132.        1,8,3,15,    // 200K
  133.        1,4,4,25,        // 160K
  134.        1,5,4,24,    // 150K
  135.        1,5,4,25,        // 144K
  136.        1,13,4,16,   // 125K
  137.        1,10,4,20,        // 120K
  138.        1,9,5,24,    // 100K
  139.        1,10,5,25,   // 90K
  140.        1,12,5,25,   // 80K
  141.        1,9,6,30,        // 75K
  142.        1,7,7,40,    // 60K
  143.        1,8,7,45,    // 50K
  144.        1,9,8,50,    // 40K
  145.        1,6,3,120,   // 30K
  146.        1,3,2,300,   // 20K
  147.     };
  148.     VCI_INIT_CONFIG_EX CAN_InitConfig;
  149.     QString str = ui->baudRateComboBox->currentText();
  150.     str.resize(str.length()-4);
  151.     int baud = str.toInt(NULL,10)*1000;
  152.     CAN_InitConfig.CAN_BRP = CAN_BaudRateInitTab[CAN_GetBaudRateNum(baud)].PreScale;
  153.     CAN_InitConfig.CAN_SJW = CAN_BaudRateInitTab[CAN_GetBaudRateNum(baud)].SJW;
  154.     CAN_InitConfig.CAN_BS1 = CAN_BaudRateInitTab[CAN_GetBaudRateNum(baud)].BS1;
  155.     CAN_InitConfig.CAN_BS2 = CAN_BaudRateInitTab[CAN_GetBaudRateNum(baud)].BS2;
  156.     CAN_InitConfig.CAN_ABOM = 1;
  157.     CAN_InitConfig.CAN_Mode = 0;
  158.     CAN_InitConfig.CAN_NART = 0;
  159.     CAN_InitConfig.CAN_RELAY = 0;
  160.     CAN_InitConfig.CAN_RFLM = 0;
  161.     CAN_InitConfig.CAN_TXFP = 1;
  162.     ret = VCI_InitCANEx(VCI_USBCAN2,
  163.                         ui->deviceIndexComboBox->currentIndex(),
  164.                         ui->channelIndexComboBox->currentIndex(),
  165.                         &CAN_InitConfig);
  166.     if(ret!=STATUS_OK){
  167.         QMessageBox::warning(this,"Warning","Initialize device Error!");
  168.         return false;
  169.     }
  170.     VCI_FILTER_CONFIG CAN_Filter;
  171.     CAN_Filter.Enable = 1;
  172.     CAN_Filter.ExtFrame = 0;
  173.     CAN_Filter.FilterIndex = 0;
  174.     CAN_Filter.FilterMode = 0;
  175.     CAN_Filter.ID_IDE = 0;
  176.     CAN_Filter.ID_RTR = 0;
  177.     CAN_Filter.ID_Std_Ext = 0;
  178.     CAN_Filter.MASK_IDE = 0;
  179.     CAN_Filter.MASK_RTR = 0;
  180.     CAN_Filter.MASK_Std_Ext = 0;
  181.     ret = VCI_SetFilter(VCI_USBCAN2,
  182.                         ui->deviceIndexComboBox->currentIndex(),
  183.                         ui->channelIndexComboBox->currentIndex(),
  184.                         &CAN_Filter);
  185.     if(ret!=STATUS_OK){
  186.         QMessageBox::warning(this,"Warning","Set filter Error!");
  187.         return false;
  188.     }
  189.     return true;
  190. }

  191. void MainWindow::logMessage(QString str)
  192. {
  193.     ui->logTextEdit->moveCursor(QTextCursor::End);
  194.     ui->logTextEdit->append(str);
  195. }
  196. bool MainWindow::setStartAddr(unsigned char can_node_addr,unsigned int startAddr)
  197. {
  198.     VCI_CAN_OBJ CAN_SendData;
  199.     VCI_CAN_OBJ CAN_ReadData;
  200.     int ret,retry;
  201.     CAN_SendData.Data[0] = startAddr>>24;
  202.     CAN_SendData.Data[1] = startAddr>>16;
  203.     CAN_SendData.Data[2] = startAddr>>8;
  204.     CAN_SendData.Data[3] = startAddr>>0;
  205.     CAN_SendData.DataLen = 4;
  206.     CAN_SendData.ID = (can_node_addr<<4)|SET_WRITE_ADDR;
  207.     CAN_SendData.ExternFlag = 0;
  208.     CAN_SendData.RemoteFlag = 0;
  209.     CAN_SendData.SendType = 0;
  210.     ret = VCI_Transmit(VCI_USBCAN2,
  211.                        ui->deviceIndexComboBox->currentIndex(),
  212.                        ui->channelIndexComboBox->currentIndex(),
  213.                        &CAN_SendData,
  214.                        1);
  215.     if(ret!=1){
  216.         logMessage("Set start address error!");
  217.         QMessageBox::warning(this,"Warning","Set start address error!");
  218.         return false;
  219.     }
  220.     retry = 0;
  221.     while(1){
  222.         Sleep(10);
  223.         ret = VCI_Receive(VCI_USBCAN2,
  224.                           ui->deviceIndexComboBox->currentIndex(),
  225.                           ui->channelIndexComboBox->currentIndex(),
  226.                           &CAN_ReadData,
  227.                           1);
  228.         if((ret==1)&&(can_node_addr==(CAN_ReadData.ID>>4))&&((CAN_ReadData.ID&0xF)==CMD_OK)){
  229.             break;
  230.         }else{
  231.             Sleep(10);
  232.             retry++;
  233.             if(retry>5){
  234.                 logMessage("Set start address error!");
  235.                 QMessageBox::warning(this,"Warning","Set start address error!");
  236.                 return false;
  237.             }
  238.             QCoreApplication::processEvents(QEventLoop::AllEvents);
  239.         }
  240.     }
  241.     logMessage("Set start success!");
  242.     return true;
  243. }

  244. bool MainWindow::eraseSectors(unsigned char can_node_addr,unsigned int startAddr,unsigned int EndAddr)
  245. {
  246.     VCI_CAN_OBJ CAN_SendData;
  247.     VCI_CAN_OBJ CAN_ReadData;
  248.     int ret,retry;
  249.     if(startAddr>EndAddr){
  250.         QMessageBox::warning(this,"Warning","Address error!");
  251.         return false;
  252.     }else{
  253.         CAN_SendData.Data[0] = startAddr>>24;
  254.         CAN_SendData.Data[1] = startAddr>>16;
  255.         CAN_SendData.Data[2] = startAddr>>8;
  256.         CAN_SendData.Data[3] = startAddr>>0;
  257.         CAN_SendData.Data[4] = EndAddr>>24;
  258.         CAN_SendData.Data[5] = EndAddr>>16;
  259.         CAN_SendData.Data[6] = EndAddr>>8;
  260.         CAN_SendData.Data[7] = EndAddr>>0;
  261.         CAN_SendData.DataLen = 8;
  262.         CAN_SendData.ID = (can_node_addr<<4)|ERASE;
  263.         CAN_SendData.ExternFlag = 0;
  264.         CAN_SendData.RemoteFlag = 0;
  265.         CAN_SendData.SendType = 0;
  266.         ret = VCI_Transmit(VCI_USBCAN2,
  267.                            ui->deviceIndexComboBox->currentIndex(),
  268.                            ui->channelIndexComboBox->currentIndex(),
  269.                            &CAN_SendData,
  270.                            1);
  271.         if(ret!=1){
  272.             logMessage("Erase sectors error!");
  273.             QMessageBox::warning(this,"Warning","Send Data Error!");
  274.             return false;
  275.         }
  276.         logMessage("Start erase sectors,please wait...");
  277.         retry = 0;
  278.         while(1){
  279.             Sleep(10);
  280.             ret = VCI_Receive(VCI_USBCAN2,
  281.                               ui->deviceIndexComboBox->currentIndex(),
  282.                               ui->channelIndexComboBox->currentIndex(),
  283.                               &CAN_ReadData,
  284.                               1);
  285.             if((ret==1)&&(can_node_addr==(CAN_ReadData.ID>>4))&&((CAN_ReadData.ID&0xF)==CMD_OK)){
  286.                 break;
  287.             }else{
  288.                 Sleep(10);
  289.                 retry++;
  290.                 if(retry>200){
  291.                     logMessage("Erase sectors error!");
  292.                     QMessageBox::warning(this,"Warning","Erase sector error!");
  293.                     return false;
  294.                 }
  295.                 QCoreApplication::processEvents(QEventLoop::AllEvents);
  296.             }
  297.         }
  298.         logMessage("Erase sector success!");
  299.         return true;
  300.     }
  301. }

  302. void MainWindow::on_updatePushButton_clicked()
  303. {
  304.     int ret,retry;
  305.     QString str;
  306.     uint32_t startAddr = ui->startAddrLineEdit->text().toInt(NULL,16);
  307.     VCI_CAN_OBJ CAN_SendData;
  308.     VCI_CAN_OBJ CAN_ReadData;
  309.     QFile firmwareFile(ui->fileLineEdit->text());
  310.     if(model->item(ui->nodeListTableView->currentIndex().row(),0)->text().isEmpty()){
  311.         QMessageBox::warning(this,"Warning","Please select online can node!");
  312.         return;
  313.     }
  314.     uint8_t can_node_addr = ui->nodeListTableView->currentIndex().row()+1;
  315.     if (firmwareFile.open(QFile::ReadOnly)){
  316.         killTimer(scanNodeTimerID);
  317.         //擦出程序扇区
  318.         if(!eraseSectors(can_node_addr,startAddr,startAddr+firmwareFile.size())){
  319.             scanNodeTimerID = startTimer(100);
  320.             return;
  321.         }
  322.         //设置程序起始地址
  323.         if(!setStartAddr(can_node_addr,startAddr)){
  324.             scanNodeTimerID = startTimer(50);
  325.             return;
  326.         }
  327.         logMessage("Start write firmware data...");
  328.         str.sprintf("CAN node address:%d",can_node_addr);
  329.         logMessage(str);
  330.         str.sprintf("Firmware start address(Hex):%08X",startAddr);
  331.         logMessage(str);
  332.         str.sprintf("Firmware size:%d Byte",firmwareFile.size());
  333.         logMessage(str);
  334.         str.sprintf("Current Progress:%3d%%",0);
  335.         logMessage(str);
  336.         for(int i=0;i<firmwareFile.size();i+=8){
  337.             firmwareFile.read((char*)(&CAN_SendData.Data[0]),8);
  338.             CAN_SendData.DataLen = 8;
  339.             CAN_SendData.ExternFlag = 0;
  340.             CAN_SendData.RemoteFlag = 0;
  341.             CAN_SendData.SendType = 0;
  342.             CAN_SendData.ID = (can_node_addr<<4)|WRITE_CONTINUOUS;
  343.             ret = VCI_Transmit(VCI_USBCAN2,
  344.                                ui->deviceIndexComboBox->currentIndex(),
  345.                                ui->channelIndexComboBox->currentIndex(),
  346.                                &CAN_SendData,
  347.                                1);
  348.             if(ret!=1){
  349.                 logMessage("Write firmware data error!");
  350.                 QMessageBox::warning(this,"Warning","Send Data Error!");
  351.                 scanNodeTimerID = startTimer(100);
  352.                 return;
  353.             }
  354.             //设置更新进度
  355.             QTextCursor cursor = ui->logTextEdit->textCursor();
  356.             cursor.deletePreviousChar();
  357.             cursor.deletePreviousChar();
  358.             cursor.deletePreviousChar();
  359.             cursor.deletePreviousChar();
  360.             str.sprintf("%3d%%",i*100/firmwareFile.size());
  361.             ui->logTextEdit->insertPlainText(str);
  362.             retry = 0;
  363.             while(1){
  364.                 ret = VCI_Receive(VCI_USBCAN2,
  365.                                   ui->deviceIndexComboBox->currentIndex(),
  366.                                   ui->channelIndexComboBox->currentIndex(),
  367.                                   &CAN_ReadData,
  368.                                   1);
  369.                 if((ret==1)&&(can_node_addr==(CAN_ReadData.ID>>4))&&((CAN_ReadData.ID&0xF)==CMD_OK)){
  370.                     break;
  371.                 }else{
  372.                     Sleep(10);
  373.                     retry++;
  374.                     if(retry>10){
  375.                         logMessage("Write firmware data error!");
  376.                         QMessageBox::warning(this,"Warning","Get ACK error!");
  377.                         scanNodeTimerID = startTimer(100);
  378.                         return;
  379.                     }
  380.                 }
  381.             }
  382.             QCoreApplication::processEvents(QEventLoop::AllEvents);
  383.         }
  384.         //设置更新进度
  385.         QTextCursor cursor = ui->logTextEdit->textCursor();
  386.         cursor.deletePreviousChar();
  387.         cursor.deletePreviousChar();
  388.         cursor.deletePreviousChar();
  389.         cursor.deletePreviousChar();
  390.         str.sprintf("%3d%%",100);
  391.         ui->logTextEdit->insertPlainText(str);
  392.         logMessage("Write firmware data success!");
  393.         QMessageBox::information(this,"Information","Update firmware success!");
  394.         scanNodeTimerID = startTimer(100);
  395.         firmwareFile.close();
  396.     }else{
  397.         QMessageBox::warning(this,"Warning","Open file error!");
  398.     }
  399. }

  400. void MainWindow::timerEvent(QTimerEvent * event)
  401. {
  402.     if(event->timerId() == scanNodeTimerID){
  403.         onlineCheck();
  404.     }

  405. }

  406. void MainWindow::onlineCheck(void)
  407. {
  408.     VCI_CAN_OBJ CAN_ReadData[200];
  409.     VCI_CAN_OBJ CAN_SendData;
  410.     int ret,i,k;
  411.     QString mac_str;
  412.     QString str;
  413.     ret = VCI_Receive(VCI_USBCAN2,
  414.                       ui->deviceIndexComboBox->currentIndex(),
  415.                       ui->channelIndexComboBox->currentIndex(),
  416.                       &CAN_ReadData[0],
  417.                       200);
  418.     for(k=0;k<ret;k++){
  419.         if((CAN_ReadData[k].ID&0xF)==GET_ADDR){
  420.             mac_str.sprintf("%02X%02X%02X%02X%02X%02X%02X%02X",
  421.                             CAN_ReadData[k].Data[0],CAN_ReadData[k].Data[1],
  422.                             CAN_ReadData[k].Data[2],CAN_ReadData[k].Data[3],
  423.                             CAN_ReadData[k].Data[4],CAN_ReadData[k].Data[5],
  424.                             CAN_ReadData[k].Data[6],CAN_ReadData[k].Data[7]);
  425.             for(i=1;i<128;i++){
  426.                 if(can_addr.local_addr[i]==0){
  427.                     can_addr.local_addr[i] = i;
  428.                     for(int j=0;j<8;j++){
  429.                         can_addr.mac_addr[i][j] = CAN_ReadData[k].Data[j];
  430.                         CAN_SendData.Data[j] = CAN_ReadData[k].Data[j];
  431.                     }
  432.                     CAN_SendData.DataLen = 8;
  433.                     CAN_SendData.ExternFlag = 0;
  434.                     CAN_SendData.RemoteFlag = 0;
  435.                     CAN_SendData.SendType = 0;
  436.                     CAN_SendData.ID = (i<<4)|ADDR_OK;//设置从机地址
  437.                     break;
  438.                 }else if(mac_str==model->item(i-1,1)->text()){
  439.                     for(int j=0;j<8;j++){
  440.                         CAN_SendData.Data[j] = CAN_ReadData[k].Data[j];
  441.                     }
  442.                     CAN_SendData.DataLen = 8;
  443.                     CAN_SendData.ExternFlag = 0;
  444.                     CAN_SendData.RemoteFlag = 0;
  445.                     CAN_SendData.SendType = 0;
  446.                     CAN_SendData.ID = (i<<4)|ADDR_OK;//设置从机地址
  447.                     break;
  448.                 }else{
  449.                     continue;
  450.                 }
  451.             }
  452.             if(i==128){
  453.                 CAN_SendData.DataLen = 0;
  454.                 CAN_SendData.ExternFlag = 0;
  455.                 CAN_SendData.RemoteFlag = 0;
  456.                 CAN_SendData.SendType = 0;
  457.                 CAN_SendData.ID = ADDR_ERROR;
  458.             }
  459.             ret = VCI_Transmit(VCI_USBCAN2,
  460.                                ui->deviceIndexComboBox->currentIndex(),
  461.                                ui->channelIndexComboBox->currentIndex(),
  462.                                &CAN_SendData,
  463.                                1);
  464.             if(ret!=1){
  465.                 QMessageBox::warning(this,"Warning","Send Data Error!");
  466.                 killTimer(scanNodeTimerID);
  467.             }else{
  468.                 //将正确获取到设备地址的节点在界面列表里面显示出来
  469.                 if((CAN_SendData.ID&0xF)!=ADDR_ERROR){
  470.                     str.sprintf("%d",i);
  471.                     model->item(i-1,0)->setText(str);
  472.                     model->item(i-1,1)->setText(mac_str);
  473.                 }
  474.             }
  475.         }
  476.     }
  477.     QCoreApplication::processEvents(QEventLoop::AllEvents);
  478.     //检测在线状态
  479.     for(i=0;i<model->rowCount();i++){
  480.         uint32_t local_addr,retry=0;
  481.         if(!model->item(i,0)->text().isEmpty()){
  482.             //清除之前接收的数据
  483.             VCI_ClearBuffer(VCI_USBCAN2,
  484.                             ui->deviceIndexComboBox->currentIndex(),
  485.                             ui->channelIndexComboBox->currentIndex());
  486.             local_addr = model->item(i,0)->text().toInt(NULL,0);
  487.             //发送在线检测命令
  488.             CAN_SendData.DataLen = 0;
  489.             CAN_SendData.ExternFlag = 0;
  490.             CAN_SendData.RemoteFlag = 0;
  491.             CAN_SendData.SendType = 0;
  492.             CAN_SendData.ID = (local_addr<<4)|ONLINE_CHECK;
  493.             ret = VCI_Transmit(VCI_USBCAN2,
  494.                                ui->deviceIndexComboBox->currentIndex(),
  495.                                ui->channelIndexComboBox->currentIndex(),
  496.                                &CAN_SendData,
  497.                                1);
  498.             if(ret!=1){
  499.                 QMessageBox::warning(this,"Warning","Send Data Error!");
  500.             }
  501.             retry = 0;
  502.             while(1){
  503.                 ret = VCI_Receive(VCI_USBCAN2,
  504.                                   ui->deviceIndexComboBox->currentIndex(),
  505.                                   ui->channelIndexComboBox->currentIndex(),
  506.                                   &CAN_ReadData[0],
  507.                                   1);
  508.                 if((ret==1)&&(local_addr==(CAN_ReadData[0].ID>>4))&&((CAN_ReadData[0].ID&0xF)==CMD_OK)){
  509.                     mac_str.sprintf("%02X%02X%02X%02X%02X%02X%02X%02X",
  510.                                     CAN_ReadData[0].Data[0],CAN_ReadData[0].Data[1],
  511.                                     CAN_ReadData[0].Data[2],CAN_ReadData[0].Data[3],
  512.                                     CAN_ReadData[0].Data[4],CAN_ReadData[0].Data[5],
  513.                                     CAN_ReadData[0].Data[6],CAN_ReadData[0].Data[7]);
  514.                     model->item(i,1)->setText(mac_str);
  515.                     break;
  516.                 }else{
  517.                     if(retry<10){
  518.                         Sleep(10);
  519.                         retry++;
  520.                     }else{
  521.                         for(int c=0;c<model->columnCount();c++){
  522.                             model->item(i,c)->setText("");
  523.                         }
  524.                         can_addr.local_addr[i+1]=0;
  525.                         break;
  526.                     }
  527.                 }
  528.             }
  529.         }
  530.     }
  531.     QCoreApplication::processEvents(QEventLoop::AllEvents);
  532.     //获取版本信息
  533.     for(i=0;i<model->rowCount();i++){
  534.         uint32_t local_addr,retry=0;
  535.         if(!model->item(i,0)->text().isEmpty()){
  536.             //清除之前接收的数据
  537.             VCI_ClearBuffer(VCI_USBCAN2,
  538.                             ui->deviceIndexComboBox->currentIndex(),
  539.                             ui->channelIndexComboBox->currentIndex());
  540.             local_addr = model->item(i,0)->text().toInt(NULL,0);
  541.             //发送在线检测命令
  542.             CAN_SendData.DataLen = 0;
  543.             CAN_SendData.ExternFlag = 0;
  544.             CAN_SendData.RemoteFlag = 0;
  545.             CAN_SendData.SendType = 0;
  546.             CAN_SendData.ID = (local_addr<<4)|GET_VERSION;
  547.             ret = VCI_Transmit(VCI_USBCAN2,
  548.                                ui->deviceIndexComboBox->currentIndex(),
  549.                                ui->channelIndexComboBox->currentIndex(),
  550.                                &CAN_SendData,
  551.                                1);
  552.             if(ret!=1){
  553.                 QMessageBox::warning(this,"Warning","Send Data Error!");
  554.             }
  555.             retry = 0;
  556.             while(1){
  557.                 ret = VCI_Receive(VCI_USBCAN2,
  558.                                   ui->deviceIndexComboBox->currentIndex(),
  559.                                   ui->channelIndexComboBox->currentIndex(),
  560.                                   &CAN_ReadData[0],
  561.                                   1);
  562.                 if((ret==1)&&(local_addr==(CAN_ReadData[0].ID>>4))&&((CAN_ReadData[0].ID&0xF)==GET_VERSION)){
  563.                     str.sprintf("V%d.%d",CAN_ReadData[0].Data[0],CAN_ReadData[0].Data[1]);
  564.                     model->item(local_addr-1,2)->setText(str);
  565.                     break;
  566.                 }else{
  567.                     if(retry<10){
  568.                         Sleep(10);
  569.                         retry++;
  570.                     }else{
  571.                         break;
  572.                     }
  573.                 }
  574.             }
  575.         }
  576.     }
  577. }

  578. void MainWindow::on_openFilePushButton_clicked()
  579. {
  580.     QString fileName;
  581.     fileName=QFileDialog::getOpenFileName(this,
  582.                                           tr("Open files"),
  583.                                           "",
  584. ……………………

  585. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
0.png

所有资料51hei提供下载:
CAN Bootloader.rar (440.04 KB, 下载次数: 65)
回复

使用道具 举报

ID:624979 发表于 2019-10-16 13:03 | 显示全部楼层
很实用!
回复

使用道具 举报

ID:505032 发表于 2019-11-12 20:12 | 显示全部楼层
我下载了以后,解压不了,显示‘文件格式未知或者数据已经损坏’

请发一份我QQ邮箱:号871854638
谢!

回复

使用道具 举报

ID:650811 发表于 2019-12-4 16:09 | 显示全部楼层
正在学习CAN总线,学习一下
回复

使用道具 举报

ID:700459 发表于 2020-3-19 19:42 | 显示全部楼层
thank you
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表