串口通信程序中十六进制格式发送和接收实现

本文介绍MFC上位机程序中串口通信的十六进制与二进制转换方法。通过HexChar和Str2Hex函数实现十六进制字符串到二进制数组的转换,并展示如何将二进制数据转换为十六进制字符串显示。

       最近要用MFC开发一个上位机监控程序,上位机和控制板之间使用RS232/485协议通信。其中一个问题是MFC对于串口收发事件处理函数中需要对发送和接收的数据进行进制转换。处理函数中对串口的读写是以二进制字节流形式,而上位机界面控件中输入和回显的都是十进制,所以涉及到字符串的十进制到二进制转换的问题。

       设置的参数经过包装后成为十六进制的字符串,如“66 03 0C 00 01 00 01 00 00 00 00 00 3C 00 3E F5 94“,发送和接收缓冲区均为char型的数组,发送时如何将字符串类型十六进制串转换为二进制数组呢?下面的函数可以实现转换过程:

HexChar函数的功能是将十六进制字符由ASCII码转为相应大小的数值:

char HexChar(char c)
{
    if((c>='0')&&(c<='9'))
        return c-'0';     //将0-9的数字字符转为十六进制格式
    else if((c>='A')&&(c<='F'))
        return c-'A'+10;  //将A-F的字符转为十六进制格式,例如字符'C'-'A'+10=12=0x0C
    else if((c>='a')&&(c<='f'))
        return c-'a'+10;   //将a-f的字符转为十六进制格式
    else
        return 0x10;
}

Str2Hex函数的功能则是将如“66 03 ...”形式的字符串以空格为间隔转换为对应的二进制存放在BYTE型(typdef unsigned char BYTE)数组中,data数组作为发送缓冲数组写入串口即可。

int Str2Hex(CString str, BYTE *data)
{
    int t,t1;
    int rlen=0,len=str.GetLength();
    if(len==1)
    {
        char h=str[0];
        t=HexChar(h);
        data[0]=(BYTE)t;
        rlen++;
    }
    //data.SetSize(len/2);
    for(int i=0;i<len;)
    {
        char l,h=str[i];
        if(h==' ')
        {
            i++;
            continue;
        }
        i++;
        if(i>=len)
            break;
        l=str[i];
        t=HexChar(h);
        t1=HexChar(l);
        if((t==16)||(t1==16))//判断为非法的16进制数
            break;
        else
            t=t*16+t1;
        i++;
        data[rlen]=(BYTE)t;
        rlen++;
    }
    return rlen;
}

      对于接收到的数据,位于接收缓冲区的BYTE数组RecBuf中,如果要以相应大小的16进制形式显示,刚可以将数组中每一个元素以下列格式转换并放入字符串RecText中,即可实现以16进制显示。

CString RecText,str;
for(int i=0;i<Rlen;i++)
{
     str.Format("%02X ",RecBuf[i]);//将接收到的BYTE型数据转换为对应的十六进制
     RecText.Append(str);
}

 

<think> 我们使用C#进行串口通信时,主要使用System.IO.Ports命名空间下的SerialPort类。 需求:发送十六进制的31(即ASCII字符'1'),并接收十六进制的30(即ASCII字符'0')。 步骤: 1. 创建SerialPort对象,配置串口参数(如端口名、波特率、数据位、停止位、校验位等)。 2. 打开串口。 3. 发送数据:将十六进制的31(即字节0x31)发送出去。注意,SerialPort.Write方法可以发送字节数组。 4. 接收数据:通过事件触发或同步读取方式接收数据。这里我们使用事件方式(DataReceived事件)来异步接收数据。 5. 解析接收到的数据,判断是否包含十六进制的30(即0x30)。 6. 关闭串口(在不需要时)。 注意:实际使用中,需要根据硬件设备的串口参数进行配置。 下面是一个示例代码,展示了如何配置串口并发送接收数据。 </think> 在C#中实现串口通信发送十六进制数据(0x31)并接收十六进制数据(0x30),需要使用`System.IO.Ports`命名空间。以下是完整解决方案: ### 解决方案代码 ```csharp using System; using System.IO.Ports; using System.Text; class SerialCommunication { static SerialPort serialPort; public static void Main() { // 配置串口参数(根据实际设备修改) serialPort = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One) { Handshake = Handshake.None, ReadTimeout = 500, // 读取超时500ms WriteTimeout = 500 // 写入超时500ms }; // 注册数据接收事件 serialPort.DataReceived += DataReceivedHandler; try { serialPort.Open(); Console.WriteLine("串口已连接"); // 发送十六进制0x31 (ASCII字符'1') byte[] sendData = { 0x31 }; serialPort.Write(sendData, 0, 1); Console.WriteLine($"已发送: 0x{sendData[0]:X2}"); Console.WriteLine("等待接收数据... (按任意键退出)"); Console.ReadKey(); } catch (Exception ex) { Console.WriteLine($"错误: {ex.Message}"); } finally { if (serialPort.IsOpen) serialPort.Close(); } } // 数据接收事件处理 private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) { SerialPort sp = (SerialPort)sender; int bytesToRead = sp.BytesToRead; byte[] buffer = new byte[bytesToRead]; sp.Read(buffer, 0, bytesToRead); // 打印接收到的十六进制数据 Console.WriteLine($"收到 {bytesToRead} 字节数据:"); foreach (byte b in buffer) { Console.WriteLine($"0x{b:X2} {(b == 0x30 ? "<-- 检测到目标值0x30" : "")}"); // 此处可添加业务逻辑处理 } } } ``` ### 代码详解 1. **串口配置** - `SerialPort("COM3", 9600...)`:设置端口号(需改为实际端口)、波特率9600、无校验位、8数据位、1停止位 - `ReadTimeout/WriteTimeout`:防止通信阻塞的超时设置(单位:毫秒) 2. **发送十六进制数据** - 创建字节数组 `{ 0x31 }` 对应十六进制值 - `serialPort.Write()` 发送原始字节数据(非字符串编码) 3. **异步接收处理** - `DataReceived` 事件在数据到达时自动触发 - `BytesToRead` 获取缓冲区数据长度 - `Read()` 方法读取原始字节数据 - `0x{b:X2}` 格式化输出十六进制值 4. **特殊值检测** - `b == 0x30` 判断是否收到目标值0x30 - 可在该条件分支内添加业务逻辑(如触发动作、记录日志等) ### 使用注意事项 1. **端口修改**:将代码中的`"COM3"`替换为实际端口号(Windows设备管理器查看) 2. **权限问题**:首次运行时可能需要管理员权限 3. **设备匹配**:确保波特率/数据位等参数与通信设备一致 4. **数据触发**:小数据量可能合并触发事件,建议启用`ReceivedBytesThreshold`设置触发阈值 ### 运行示例输出 ``` 串口已连接 已发送: 0x31 等待接收数据... (按任意键退出) 收到 1 字节数据: 0x30 <-- 检测到目标值0x30 ```
评论 9
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值