【问题标题】:UART Communication In C language (Hex)C语言的UART通信(十六进制)
【发布时间】:2021-11-17 10:34:45
【问题描述】:

我想向写入函数发送一个十六进制值。 (例如,0×90)。 这是因为需要通信的设备以十六进制数字接收命令。 未使用的变量在测试和注释时出现,丢失十六进制值,稍后将被删除。 怎么写除String以外的十六进制值的写函数?

对于初学者, 请告诉我们如何通过读写函数交换十六进制值。

#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <time.h>
#include <pthread.h>

int main(void)
{
    int fd;
    fd=open("/dev/ttyHSL6", O_RDWR|O_NOCTTY );
    struct termios newtio;

    char buffer[2000];
    int bytes_read=0;
    char *data;
    //int *a=0x90;

    char *a="0X90";
    const int *num1;
    
    if (fd == -1)
    {
        printf("Error! in opening port");
        exit(-100);
    }

    memset(&newtio, 0, sizeof(struct termios));
    newtio.c_cflag = B9600 | CS8 | CLOCAL | CREAD;

    newtio.c_iflag = IGNPAR;

    newtio.c_oflag = 0;
    newtio.c_lflag = 0;
    newtio.c_cc[VTIME] = 0; 
    newtio.c_cc[VMIN] = 1; 
    tcflush(fd, TCIFLUSH);

    tcsetattr(fd, TCSANOW, &newtio);
    data=malloc(sizeof(char)*140);
    while(1){
        const char *str ="0x91";
        
        //write(fd, str, strlen(str)+1);

        bytes_read = read(fd,buffer,sizeof(buffer));

        if (bytes_read > 0)
        {
            buffer[bytes_read]=0;
            printf("%s", buffer);
        }
        usleep(100000);

        
    }
    close(fd);
    return 0;
}

目前进展:

我设置了发送和接收变量,并使用unsigned char编译了代码,但是出现了这样的错误。

./serial.c:48:10: warning: format ‘%x’ expects argument of type ‘unsigned int’, but argument 2 has type ‘unsigned char *’ [-Wformat=]
   printf("%x\n",str);

如果我使用%p,没有编译错误,但是如你所知,地址值是打印出来的,所以和我想要的结果不一样。我是初学者,不知道怎么做。

修改部分如下。

    while(1){
        //const char *str ="0x91";
        unsigned char str[13] = {0xA5,0x80,0x90,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBD};
        write(fd, str, strlen(str));
        printf("%x\n",str);
        bytes_read = read(fd,buffer,sizeof(buffer));

    //  printf("%x\n",*str);
        if (bytes_read > 0)
        {
            buffer[bytes_read]=0;
            

            printf("%p\n", buffer);
        }
        usleep(100000);

        //printf("%s\r\n",buffer);      

    }
    close(fd);
    return 0;

【问题讨论】:

  • "我怎样才能写一个除字符串以外的十六进制值的写函数"。十六进制不是数据格式。那只是一个数据表示。如果您的意思是发送二进制数据而不是文本数据,则类似于:int val = 0x91; write(fd, &amp;val, sizeof(val));。但实际上你问的不是很清楚。
  • 如果你提到十六进制数字,你是在说字符串吗?您要将 字符串 "x90" 发送到设备还是要将与 0220144 相同的 0x90 发送到设备?如果只讲值,“十六进制”没有任何意义。
  • 您的 termios 初始化不可靠。请参阅Setting Terminal Modes Properly 和示例代码:stackoverflow.com/questions/12437593/…
  • 如果要将字节数组显示为十六进制值,则必须单独转换每个字节。没有单一的 printf() 说明符可以为您执行此操作。见stackoverflow.com/questions/6947413/…

标签: c serial-port uart unistd.h


【解决方案1】:

您只想发送二进制而不是文本数据,但是,二进制数据不能以与文本字符串相同的方式处理,因为 0 (0x00) 是合法的二进制值,而它充当字符串终止符这就是为什么二进制数据的协议通常在一个字节中有一个长度指示符,如果消息可以是可变长度的,或者是特定的消息分隔符(消息开头和结尾处的唯一值,不能在消息数据)。

关于您的代码的指针: 在可能的情况下始终初始化值,尤其是要存储字符串的数组,例如char buffer[2000] = {0} 如果编译器允许,否则 memset(buffer, 0, sizeof(buffer); 在使用之前。

    unsigned char str[13] = {0xA5,0x80,0x90,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBD};

这里有一个从 signed intunsigned char 的隐式转换,用于初始化数组的值,例如0x90 默认为int

    write(fd, str, strlen(str));

正如所指出的 0x00 (null) 是一个合法的二进制值,但恰好是 C 中的文本字符串终止符,因此 strlen(str) 将返回 4,因为它将 0xA5, 0x80, 0x90, 0x08, 0x00 作为您的字符串,包含 4 个数据字节和一个终止符。对于存储字符串的数组,您必须允许在其中放置空终止符的额外字节。

你应该使用类似的东西:

write(fd, str, sizeof(str)/sizeof(str[0]));

这会计算数组中元素的数量。由于sizeof 将返回正在调整大小的项目占用的内存字节数(八位字节),我们还需要将其除以数组元素的大小以确定元素的数量。

char 将返回 1 的大小,int 在 16 位处理器上编译时可以返回 2,如果是 32 位,则返回 4 等等。

最后,您需要转换正在打印的值,因此请尝试使用:(编辑:进行代码更正)

unsigned char str[13] = {0xA5,0x80,0x90,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xBD};

for (int i=0; i< sizeof(str)/sizeof(str[0]); i++) 
{ 
    printf("%X",(int)str[i]); 
} 
printf("\n"); 

会给

A58090800000000BD

【讨论】:

  • 感谢您的友好回答。我修改了答案中的代码,但是写入时的打印只打印在空间中,读取函数结果仅返回a5 ...请问您检查出了什么问题吗?对不起,我是初学者。
  • while(1){ memset(buffer, 0, sizeof(buffer));写(fd,str,sizeof(str)/sizeof(str[0])); for (int i=0; i 0) { 缓冲区[bytes_read]=0; for (int j=0; j
  • 嗨 - 我看到 for (int i=0; i&lt; sizeof(str)/str[0]; i++) 应该是 for (int i=0; i&lt; sizeof(str)/sizeof(str[0]); i++)for (int j=0; j&lt; sizeof(buffer)/buffer[0]; j++) 应该是 for (int j=0; j&lt; sizeof(buffer)/sizeof(buffer[0]); j++)
  • 我发现我在最后一段代码中犯了一个错误,虽然之前是正确的 - 现在我已经更正了。
【解决方案2】:

如果您想发送 0x90 值,就像它的 int 值 144 一样,您应该使用

unsigned char hex = 0x90

有了这个你可以发送价值144

【讨论】:

  • 参考相关资料修改后尝试编译源代码,但出现错误。请参考上面的答案。我是初学者,所以很抱歉我很笨拙。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-21
  • 2017-04-27
  • 1970-01-01
  • 2011-06-01
  • 2011-12-09
相关资源
最近更新 更多