接收到的数据在遇到第一个字节等于零后清零

Received Data Zeroed Out After Encountering First Byte Equal to Zero

  1. 总结问题:

我在 linux 中为 NRF24L01+ 收发器编写了一个用户空间 SPI 驱动程序。我的目标是将文件发送到服务器。 jetson nano 是发送者,raspberry pi 3b+ 是接收者。 spi 和 nano 都是 运行 Linux.

我可以始终如一地发送数据包和接收确认。

但是,问题是每当我发送 0x ff ee dd 00 cc bb aa 等数据包时,接收方只收到数据包 0x ff ee dd 00 00 00 00。所以发生的事情是,只要遇到的第一个字节为零,数据包的其余部分就会变为零。这会导致我发送的文件损坏。

我能够使用具有类似模式的字符数组重现此错误。当我打印出我在发送器和接收器上发送的文件内容时,我注意到了这种趋势。

  1. 我尝试过的:

我试过更改我的 SPI 读取功能。我认为正在发生的事情是筹码 select 线被提早翻转了。这没有用,我得到了相同的结果。

我在从发送器调用 ioctl() 函数之前打印了数据包,数据包保持完好无损。

我打印了 ioctl() 函数的 return 值,以查看我接收和发送了多少字节。我从发送器发送 31 个字节,从接收器接收 32 个字节。所以看起来我的读取和发送没有失败。

如果我有逻辑分析仪,我的下一步将是检查发送器上的 SPI 引脚,但遗憾的是我没有。

我在收发器上添加了一个 10uF 去耦电容器,这加快了通信速度。

  1. 显示一些代码:

接收方:

/**
 *      Reads the payload when data pipe
 *      is available.
 *
 *      spi_dev_fd: file descriptor for spi device.
 * */
int nrf_rx_read(int spi_dev_fd, char * payload, int * pipe, int * bytes)
{
        int pipe_temp, rtn;

        // TODO: Add timeout.
        do
        {
                rtn = nrf_rx_pipe_available(spi_dev_fd, &pipe_temp);

        }while(rtn != 0);

        if(rtn == 0)
        {
                char status;

                if(bytes != NULL)
                {
                        char size;
                        spi_read_msg(spi_dev_fd, R_RX_PL_WID, &status, &size, 1);
                        *bytes = (int) size;
                }


                spi_read_msg(spi_dev_fd, R_RX_PAYLOAD , &status, payload, (int) NUM_PAYLOAD_BYTES);

                *pipe = pipe_temp;

                char msg;
                msg = RX_DR;
                spi_send_msg(spi_dev_fd, W_REGISTER | STATUS, &msg, 1);

                return 0;
        }

        return 1;
}

bool nrf_rx_pipe_available(int spi_dev_fd, int * pipe)
{

        char addr = NOP;
        char status;
        spi_read_msg(spi_dev_fd, addr, &status, NULL, 0);

        if((status & RX_DR) > 0)
        {
                *pipe = (status >> RX_P_NO) & 0x07;

                if(*pipe > 5)
                {
                        return 1;
                }

                return 0;
        }

        return 1;
}

int spi_read_msg(int spi_dev_fd, char addr, char * status, char * copy_to, int len)
{
        char data_buffer;
        char recv_buffer[len + 1];
        struct spi_ioc_transfer xfer;

        memset(&xfer, 0, sizeof(xfer));
        memset(&recv_buffer, 0, sizeof(recv_buffer));

        data_buffer = addr;
        xfer.tx_buf = (unsigned long) &data_buffer;
        xfer.rx_buf = (unsigned long) recv_buffer;
        xfer.len = len + 2;
        xfer.bits_per_word = 8;
        xfer.speed_hz = 1000000;
        xfer.cs_change = 0;
        xfer.rx_nbits = len * 8;
        xfer.tx_nbits = 8;

        int res = ioctl(spi_dev_fd, SPI_IOC_MESSAGE(1), xfer);

        if(res > 0)
        {
                status[0] = recv_buffer[0];
                if(copy_to != NULL)
                {
                        string temp = string(recv_buffer);
                        temp = temp.substr(1);
                        strncpy(copy_to, temp.c_str(), len);
                }

                // debug code
                for(int i = 0; i < len; ++i)
                {
                        printf("copy_to: %x \n ", copy_to[i]);
                }
                // end debug code.
        }

        return res;

}

发射端:

/**
 *      Function to load a payload and send a packet.
 *
 *
 *      spi_dev_fd: file descriptor for spi device.
 * */
int nrf_tx_send_packet(int spi_dev_fd, char * payload, int len)
{
        int rtn;
        // Put low so we can add the payload.
        gpio_set_value((unsigned int) GPIO_CE, (unsigned int) GPIO_LVL_LOW);
        // Set a new payload.
        nrf_tx_new_payload(spi_dev_fd, payload, len);

        // Start tx transmission.
        gpio_set_value((unsigned int) GPIO_CE, (unsigned int) GPIO_LVL_HIGH);


        do
        {
                rtn = nrf_tx_pending_send(spi_dev_fd);

                if(rtn == 2)
                {
                        char clr = MAX_RT;
                        spi_send_msg(spi_dev_fd, W_REGISTER | STATUS, &clr, 1);
                }
        }while(rtn != 1);

        // Go back to standby mode
        gpio_set_value((unsigned int) GPIO_CE, (unsigned int) GPIO_LVL_LOW);    // Setting chip enable to 0.

        char reg = W_REGISTER | STATUS;
        char val = RX_DR | TX_DS | MAX_RT;
        spi_send_msg(spi_dev_fd, reg, &val, 1);

        return 0;
}

int spi_send_msg(int spi_dev_fd, char addr, char * data, int len)
{
        char data_buffer[len + 1];
        char recv_buffer;
        struct spi_ioc_transfer xfer;

        memset(&xfer, 0, sizeof(xfer));
        memset(&recv_buffer, 0, sizeof(recv_buffer));

        data_buffer[0] = addr;
        for(int i = 1; i < len + 1; ++i)
        {
                data_buffer[i] = data[i-1];

                printf("databuffer[i]: %x \n", data_buffer[i]);
        }
        xfer.tx_buf = (unsigned long) data_buffer;
        xfer.rx_buf = (unsigned long) NULL;
        xfer.len = len + 1;
        xfer.bits_per_word = 8;
        xfer.speed_hz = 1000000;
        xfer.cs_change = 0;
        //xfer.rx_nbits = 8;
        xfer.rx_nbits = 0;
        xfer.tx_nbits = (8 * len) + 8;

        int res = ioctl(spi_dev_fd, SPI_IOC_MESSAGE(1), xfer);

        printf("res: %i \n", res);

        return res;

}

我试着添加了所有相关代码,如果有点多请见谅。主要看的是发送和接收函数。它们都按预期工作,直到我遇到清零字节。

如果我遗漏了任何可以帮助某人的信息,请告诉我,我可以添加。然而,我认为发送和接收功能是最重要的。我能够设置和读取收发器的寄存器。

我现在可以发送文件了!

已在 spi_read_msg() 函数中完成修复。

问题是我将接收到的缓冲区转换为字符串,这导致在遇到字节 0x00 时数据被修剪。这也等同于空终止符。

收件人代码:

int spi_read_msg(int spi_dev_fd, char addr, char * status, char * copy_to, int len)
{
        char data_buffer;
        char recv_buffer[len + 1];
        struct spi_ioc_transfer xfer;

        memset(&xfer, 0, sizeof(xfer));
        memset(&recv_buffer, 0, sizeof(recv_buffer));

        data_buffer = addr;
        xfer.tx_buf = (unsigned long) &data_buffer;
        xfer.rx_buf = (unsigned long) recv_buffer;
        xfer.len = len + 2;
        xfer.bits_per_word = 8;
        xfer.speed_hz = 1000000;
        xfer.cs_change = 0;
        xfer.rx_nbits = len * 8;
        xfer.tx_nbits = 8;

        int res = ioctl(spi_dev_fd, SPI_IOC_MESSAGE(1), xfer);

        if(res > 0)
        {
                status[0] = recv_buffer[0];
                if(copy_to != NULL)
                {
                        for(int i = 0; i < len; ++i)
                        {
                                copy_to[i] = recv_buffer[i + 1];
                        }
                }

        }

        return res;

}