首页 > 其他分享 >STM32F105双路隔离型CAN总线转4G控制板 - 把CAN数据发送到TCP服务器,实现通过TCP透传通信

STM32F105双路隔离型CAN总线转4G控制板 - 把CAN数据发送到TCP服务器,实现通过TCP透传通信

时间:2024-03-15 13:44:06浏览次数:25  
标签:00 CanTxMsgValue read 双路 tcp TCP client 控制板 data

<p><iframe name="ifd" src="https://mnifdv.cn/resource/cnblogs/product/STM32F105_2CAN/index.html" frameborder="0" scrolling="auto" width="100%" height="1500"></iframe></p>

<iframe frameborder="0" height="1500" name="ifd" scrolling="auto" src="https://mnifdv.cn/resource/cnblogs/product/STM32F105_2CAN/index.html" width="100%"></iframe>

 

说明

这节是把设备从CAN总线接收的数据发送到TCP服务器, 设备从TCP服务器接收的数据通过CAN总线输出;

 

测试

1,打开工程

 

2,根据自己的设备设置CAN波特率

 

3,默认连接这边的服务器进行测试,用户如果要测试需要修改为连接自己的服务器

 

4,设备日志打印如下说明连接成功

 

5,我在我的服务器上打开调试助手进行测试

 

6,接上CAN总线设备

 

7,如果设备接收到CAN数据,将会发送到TCP调试助手上

 

数据格式说明: 01   00 00 01 02   55 55 55 55 55 55 55 55

最前面一位是0x01; 最前面的0代表这个数据是数据帧,后面的1代表第一路CAN数据,;

中间  00 00 01 02 四位是帧 ID;  最后 55 55 55 55 55 55 55 55 8位是数据

 

数据格式说明: 11   00 00 01 02   00 00 00 00 00 00 00 00

最前面一位是0x11; 最前面的1代表这个数据是遥控帧,后面的1代表第一路CAN数据,;

中间  00 00 01 02 四位是帧 ID;  最后 00 00 00 00 00 00 00 00  8位是数据

 

如果是第二路:

 

 

7,通过TCP调试助手发送数据给设备

由于网络通信接收数据有可能出现数据分包和粘包,所以数据格式改了下

测试1:

假设给第一路CAN发送一个数据帧, 然后ID是 0x1234  数据是 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07

实际发送的数据: 55 AA  00 0E 01 00 00 12 34 00 01 02 03 04 05 06 07 70

55 AA为固定头;  00 0E代表后面的数据个数;  01 00 00 12 34 00 01 02 03 04 05 06 07 是实际数据;  最后的70是前面所有数据累加和 然后%256

实际数据和上面的格式是一样的, 最前面的 01 代表第一路; 00 00 12 34 是ID;  00 01 02 03 04 05 06 07 是CAN数据

 

这边用了CAN分析仪监测的设备数据

 

测试2:

假设给第一路CAN发送一个遥控帧, 然后ID是 0x1234

实际发送的数据为: 55 AA  00 0E 11 00 00 12 34 00 01 02 03 04 05 06 07 80

 

 

测试3:

假设给第二路CAN发送一个数据帧, 然后ID是 0x1234  数据是 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07

实际发送的数据: 55 AA  00 0E 02 00 00 12 34 00 01 02 03 04 05 06 07 71

 

 

 

测试4:

假设给第二路CAN发送一个遥控帧, 然后ID是 0x1234 ,后面的数据随意

实际发送的数据为: 55 AA  00 0E 12 00 00 12 34 00 01 02 03 04 05 06 07 81

 

程序说明

1,串口2接收模组数据的时候,单独使用一个缓存,缓存了TCP/IP接收的数据

 

2,连接TCP服务器

 

 

3,CAN接收的数据是存储到了环形队列

 

4,把接收的CAN数据发送到TCP服务器

 

 

5.从TCP服务器收到的消息通过CAN总线输出

 

 

int  tcp_client_read_data_timeout=0;
uint8_t tcp_client_read_data_switch=0;
uint8_t tcp_client_read_data[1460];
uint16_t tcp_client_read_data_len=0;
/**
* @brief   设备接收数据(高速处理模式,可以处理分包和粘包)
* @param   None
* @retval  None
* @warning None
* @example
**/
void tcp_client_data_while(void)
{
    int len=0,i=0,sum=0;
    uint32_t CAN_IDE=0;
    
    if(tcp_client_read_data_switch==0)
    {
        len = rbCanRead(&rb_t_net_read);//获取模组返回的TCP数据
        if(len>0)
        {
            memset(tcp_client_read_data,0,sizeof(tcp_client_read_data));
            rbRead(&rb_t_net_read, &tcp_client_read_data[0], 1);
            
            if(tcp_client_read_data[0]==0x55)
            {
                tcp_client_read_data_switch=1;
                tcp_client_read_data_timeout=0;
            }
        }
    }
    else if(tcp_client_read_data_switch==1)
    {
        len = rbCanRead(&rb_t_net_read);//获取模组返回的TCP数据
        
        if(len>0)
        {
            rbRead(&rb_t_net_read, &tcp_client_read_data[1], 1);
            if(tcp_client_read_data[1]==0xAA)
            {
                tcp_client_read_data_switch=2;
            }
            else
            {
                if(tcp_client_read_data[1]==0x55)
                {
                    tcp_client_read_data_switch=1;
                }
                else
                {
                    tcp_client_read_data_switch=0;
                }
            }
            tcp_client_read_data_timeout=0;
        }
        else
        {
            if(tcp_client_read_data_timeout>=5000)
            {
                tcp_client_read_data_timeout=0;
                tcp_client_read_data_switch=0;
            }
        }
    }
    else if(tcp_client_read_data_switch==2)
    {
        len = rbCanRead(&rb_t_net_read);//获取模组返回的TCP数据
        if(len>1)
        {
            rbRead(&rb_t_net_read, &tcp_client_read_data[2], 2);
            tcp_client_read_data_len = tcp_client_read_data[2];
            tcp_client_read_data_len = tcp_client_read_data_len<<8;
            tcp_client_read_data_len = tcp_client_read_data_len+tcp_client_read_data[3];
            
            tcp_client_read_data_switch=3;
            tcp_client_read_data_timeout=0;
        }
        else
        {
            if(tcp_client_read_data_timeout>=5000)
            {
                tcp_client_read_data_timeout=0;
                tcp_client_read_data_switch=0;
            }
        }
    }
    else if(tcp_client_read_data_switch==3)
    {
        len = rbCanRead(&rb_t_net_read);//获取模组返回的TCP数据
        if(len>=tcp_client_read_data_len)
        {
            rbRead(&rb_t_net_read, &tcp_client_read_data[4], tcp_client_read_data_len);
            sum=0;
            for(i=0;i<(tcp_client_read_data_len+3);i++)
            {
                sum = sum+tcp_client_read_data[i];
            }
            sum = sum%256;
            
            if(sum == tcp_client_read_data[tcp_client_read_data_len+3])
            {
                memset(tcp_client_buff,0,sizeof(tcp_client_buff));
                memcpy(tcp_client_buff, &tcp_client_read_data[4], tcp_client_read_data_len-1);
                
                debug_printf("\r\ncan data:");
                for(i=0;i<len;i++)
                {
                debug_printf("%02x,",tcp_client_buff[i]);
                }
                debug_printf("\r\n");
                
                CAN_IDE = tcp_client_buff[1]; CAN_IDE = CAN_IDE<<8;
                CAN_IDE = CAN_IDE + tcp_client_buff[2]; CAN_IDE = CAN_IDE<<8;
                CAN_IDE = CAN_IDE + tcp_client_buff[3]; CAN_IDE = CAN_IDE<<8;
                CAN_IDE = CAN_IDE + tcp_client_buff[4];//ID
                if(CAN_IDE>0x7FF)//扩展帧
                {
                    CanTxMsgValue.IDE = CAN_ID_EXT;
                    CanTxMsgValue.ExtId = CAN_IDE;
                    debug_printf("CAN_ID_EXT\r\n");
                }
                else//标准帧
                {
                    CanTxMsgValue.IDE = CAN_ID_STD;
                    CanTxMsgValue.StdId = CAN_IDE;
                    debug_printf("CAN_ID_STD\r\n");
                }
                CanTxMsgValue.RTR=CAN_RTR_DATA;
                if((tcp_client_buff[0]&0x10) == 0x10)//遥控帧
                {
                    CanTxMsgValue.RTR = CAN_RTR_REMOTE;
                    debug_printf("CAN_RTR_REMOTE\r\n");
                }
                
                CanTxMsgValue.DLC = 8;
                memcpy(CanTxMsgValue.Data, &tcp_client_buff[5], 8);//拷贝数据
                
                if((tcp_client_buff[0]&0x01) == 0x01)//发送给CAN1口
                {
                    debug_printf("CAN_SendData(CAN1, &CanTxMsgValue)\r\n");
                    
                    CAN_SendData(CAN1, &CanTxMsgValue);//发送CAN数据
                }
                else if((tcp_client_buff[0]&0x02) == 0x02)//发送给CAN2口
                {
                    debug_printf("CAN_SendData(CAN2, &CanTxMsgValue)\r\n");
                    CAN_SendData(CAN2, &CanTxMsgValue);//发送CAN数据
                }
        
                tcp_client_read_data_switch=0;
            }
            else
            {
                tcp_client_read_data_switch=0;
            }
            
        }
        else
        {
            if(tcp_client_read_data_timeout>=5000)
            {
                tcp_client_read_data_timeout=0;
                tcp_client_read_data_switch=0;
            }
        }
    }
}

/**
* @brief   设备接收数据
* @param   None
* @retval  None
* @warning None
* @example
**/
void tcp_client_into_data(char *data, int length)
{    
    int len = length;
    uint32_t CAN_IDE=0;
    int i=0;
    
    debug_printf("\r\ntcp read:");
    for(i=0;i<len;i++)
    {
        debug_printf("%02x,",data[i]);
    }
    debug_printf("\r\n");
    
    memset(tcp_client_buff,0,sizeof(tcp_client_buff));
    if(len> sizeof(tcp_client_buff))
    {
        len = sizeof(tcp_client_buff);
        memcpy(tcp_client_buff, data, sizeof(tcp_client_buff));
    }
    else{ memcpy(tcp_client_buff, data, len); }
    
    if(length==13)
    {
        CAN_IDE = tcp_client_buff[1]; CAN_IDE = CAN_IDE<<8;
        CAN_IDE = CAN_IDE + tcp_client_buff[2]; CAN_IDE = CAN_IDE<<8;
        CAN_IDE = CAN_IDE + tcp_client_buff[3]; CAN_IDE = CAN_IDE<<8;
        CAN_IDE = CAN_IDE + tcp_client_buff[4];//ID
        if(CAN_IDE>0x7FF)//扩展帧
        {
            CanTxMsgValue.IDE = CAN_ID_EXT;
            CanTxMsgValue.ExtId = CAN_IDE;
            debug_printf("CAN_ID_EXT\r\n");
        }
        else//标准帧
        {
            CanTxMsgValue.IDE = CAN_ID_STD;
            CanTxMsgValue.StdId = CAN_IDE;
            debug_printf("CAN_ID_STD\r\n");
        }
        CanTxMsgValue.RTR=CAN_RTR_DATA;
        if((tcp_client_buff[0]&0x10) == 0x10)//遥控帧
        {
            CanTxMsgValue.RTR = CAN_RTR_REMOTE;
            debug_printf("CAN_RTR_REMOTE\r\n");
        }
        
        CanTxMsgValue.DLC = 8;
        memcpy(CanTxMsgValue.Data, &tcp_client_buff[5], 8);//拷贝数据
        
        if((tcp_client_buff[0]&0x01) == 0x01)//发送给CAN1口
        {
            debug_printf("CAN_SendData(CAN1, &CanTxMsgValue)\r\n");
            
            CAN_SendData(CAN1, &CanTxMsgValue);//发送CAN数据
        }
        else if((tcp_client_buff[0]&0x02) == 0x02)//发送给CAN2口
        {
            debug_printf("CAN_SendData(CAN2, &CanTxMsgValue)\r\n");
            CAN_SendData(CAN2, &CanTxMsgValue);//发送CAN数据
        }
    }
}

 

6,程序里面默认还获取了 IMEI,ICCID,CSQ,时间等,都解析好了,用户可以直接选择对应的变量使用

 

 用户可以在这里更改定时获取时间参数

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

.

 

标签:00,CanTxMsgValue,read,双路,tcp,TCP,client,控制板,data
From: https://www.cnblogs.com/yangfengwu/p/18075230

相关文章

  • 在Linux中,TCP/IP协议栈的工作原理是什么?
    在Linux中,TCP/IP协议栈是操作系统内核的一部分,负责处理所有网络通信并遵循InternetProtocolSuite标准。它由一组相互协作的协议组成,这些协议定义了数据在网络中的传输方式。TCP/IP协议栈的核心工作原理可以从以下几个层面来详细说明:1.四层模型概述TCP/IP协议栈按照经典的四层......
  • 3月14-第五讲复习回顾和第六讲TCP协议
    结合gpt和其他方面的资料,对于昨天的网络层和链路层做出补充:1.数据传输时两层基本都经过,网络层规划路由表(路由器跳转路径),装配ip地址(用来规划线路),封装和传输数据包在节点与目标设备之间,把链路层的数据帧转换为数据包。链路层则是节点之间的,物理层面,使用Mac这种物理地址定位。2.注......
  • Qt TCP (小型聊天窗口)
    实现的具体功能为:服务器端需要主动监听,可以主动断开连接,可以发送信息给客户端客户端需要输入主机,端口号,需要主动连接,可以主动断开连接,可以发送信息给服务器端服务器端和客户端都能看到聊天记录服务器端的搭建:创建一个TCP_Server项目1.首先在.Pro文件中添加:QT+=network......
  • Qt TcpSocket的掉线解决方法
    1、tcpip协议没什么好说的,号称保证传输准确可靠,使命必达。协议很大一坨,实际应用上用得上的很少。2、问题所在在使用tcp协议跟服务器连接后(分别测试过windows系统,ubuntu系统单片机带tcpip协议的通讯模块)都发现不能及时反馈或反馈网络已断;(在同一个局域网内和公共网络上......
  • Qt TCP通信客户端断开连接有哪些方法
    在QT中,可以使用以下方法来处理TCP通信客户端断开连接的情况:使用QAbstractSocket::disconnected信号:当客户端与服务器断开连接时,该信号会被触发。你可以连接这个信号到一个槽函数,在槽函数中处理断开连接的逻辑。QObject::connect(socket,&QTcpSocket::disconnected,this,&You......
  • 一文彻底搞懂OSI七层模型和TCP/IP四层模型
    文章目录1.OSI七层模型2.TCP/IP四层模型1.OSI七层模型OSI(OpenSystemInterconnect)七层模型是一种将计算机网络通信协议划分为七个不同层次的标准化框架。每一层都负责不同的功能,从物理连接到应用程序的处理。这种模型有助于不同的系统之间进行通信时,更好地理解和......
  • TCP协议
    TCP协议TCP协议的头部为20ByteTCP头部的数据格式端口号:各占2个字节,端口号与IP首部中的源端IP地址和目的端IIP地址唯一确定一个TCP连接。序号:占4字节,整个要传送的字节流的起始序号必须在连接建立时设置确认号:占4字节,是期望收到对方下一个报文段的第一个数据字节......
  • TCP和UDP
    计算机网络的七层协议计算机网络体系可以大致分为一下三种,OSI七层模型、TCP/IP四层模型和五层模型。七层协议的功能:物理层:负责处理网络通信的物理传输和传输介质的细节。物理层的主要任务是将比特流(bitstream)从发送方传输到接收方,确保数据能够在网络中进行可靠的物理传输。......
  • QT TCP通信介绍
    QT是一个跨平台的C++应用程序开发框架,它提供了一套完整的工具和库,用于开发各种类型的应用程序,包括图形用户界面(GUI)应用程序、命令行工具、网络应用程序等。QT提供了丰富的功能和类来简化网络通信的开发,其中包括TCP通信。TCP通信是一种可靠的、面向连接的通信协议,它在网络中......
  • 详解Go程序添加远程调用tcpdump功能,exec.Command("sh", "-c", "ps -elf | grep xxx |
    摘自:https://www.jb51.net/article/249001.htm这篇文章主要介绍了go程序添加远程调用tcpdump功能,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下 最近开发的telemetry采集系统上线了。听起来高大上,简单来说就是一个grpc/udp服务端,用......