• 芯片:ESP32-S3(v0.2)
  • IDF 版本:ESP-IDF-v5.5.0

一、SX125x

SX125x 指的是 SX1255 和 SX1257。

1. SPI 通信格式

在硬件上,SX125x 的 SPI 引脚连接的是 SX1302 Radio A/B 的 SPI 接口,所以主控是通过 SX1302 来控制 SX125x 的。

  • 对于 SX1302

    未提供。

  • 对于 SX125x

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    
    NSS  -----+                                                     +-----
              |                                                     |
              +-----------------------------------------------------+
    
    SCK  ...
    
    MOSI      +-----+-----------+-----------------+-----------------+-----+
              | W/R | Addr[6:0] | Data Write[7:0] | Data Write[7:0] | ... |
         -----+-----+-----------+-----------------+-----------------+-----+-----
    
    MISO      +-----------------+-----------------+-----------------+-----+
              |       xxx       | Data Read[7:0]  | Data Read[7:0]  | ... |
         -----+-----------------+-----------------+-----------------+-----+-----
    
    • 寄存器地址范围在 0x00 - 0x13

2. SPI 通信函数

  • 单字节的写操作

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    
    /**
     * @brief SX125x 单字节的读操作
     * @param spi spi 句柄
     * @param traget 操作的目标, 0x01 - Radio A, 0x02 - Radio B
     * @param op_code 寄存器地址
     * @param buf 发送缓冲区
     * @param buf_len 发送缓冲区长度
     * @return
     *   - 0 : success
     *   - -1: failed
     */
    int sx125x_spi_wb(spi_device_handle_t *spi, uint8_t target, uint8_t op_code, uint8_t *buf, uint16_t buf_len)
    {
        esp_err_t err = ESP_OK;
    
        spi_transaction_ext_t trans = {0};
    
        if (buf_len != 1) {
            return -1;
        }
    
        err = spi_device_acquire_bus(*spi, portMAX_DELAY);
        if (err != ESP_OK) {
            return -1;
        }
    
        trans.base.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA;
    
        trans.base.tx_data[0] = target;
        trans.base.tx_data[1] = 0x80 | (op_code & 0x7f);
        trans.base.tx_data[2] = *buf;
    
        trans.base.length = 3 * 8;
        trans.base.rxlength = 3 * 8;
    
        err = spi_device_polling_transmit(*spi, (spi_transaction_t *)&trans);
    
        spi_device_release_bus(*spi);
    
        if (err != ESP_OK) {
            return -1;
        }
    
        return 0;
    }
    
  • 单字节的读操作

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    
    /**
     * @brief SX125x 单字节的读操作
     * @param spi spi 句柄
     * @param traget 操作的目标, 0x01 - Radio A, 0x02 - Radio B
     * @param op_code 寄存器地址
     * @param buf 接收缓冲区
     * @param buf_len 接收缓冲区长度
     * @return
     *   - 0 : success
     *   - -1: failed
     */
    int sx125x_spi_rb(spi_device_handle_t *spi, uint8_t target, uint8_t op_code, uint8_t *buf, uint16_t buf_len)
    {
        esp_err_t err = ESP_OK;
    
        spi_transaction_ext_t trans = {0};
    
        if (buf_len != 1) {
            return -1;
        }
    
        err = spi_device_acquire_bus(*spi, portMAX_DELAY);
        if (err != ESP_OK) {
            return -1;
        }
    
        trans.base.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA;
    
        trans.base.tx_data[0] = target;
        trans.base.tx_data[1] = 0x00 | (op_code & 0x7f);
        trans.base.tx_data[2] = 0x00;
    
        trans.base.length = 3 * 8;
        trans.base.rxlength = 3 * 8;
    
        err = spi_device_polling_transmit(*spi, (spi_transaction_t *)&trans);
        if (err != ESP_OK) {
            spi_device_release_bus(*spi);
            return -1;
        }
    
        *buf = trans.base.rx_data[2];
    
        spi_device_release_bus(*spi);
    
        return 0;
    }
    

二、SX1261

1. SPI 通信格式

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
BUSY ----+                                  +----
         |                                  |
         +----------------------------------+

NSS  ----+                                  +----
         |                                  |
         +----------------------------------+

SPI      +--------+---------+---------+-----+
         | opcode | param 1 | param 2 | ... |
     ----+--------+---------+---------+-----+---------------------
  • opcode

    大小是一个字节,类型是 uint8_t

  • param

    每个 param 的大小是一个字节,param 的个数取决于 opcode。

2. SPI 通信函数

  • 多字节的写操作

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    
    /**
     * @brief SX1261 多字节的写操作
     * @param spi spi 句柄
     * @param op_code 寄存器地址
     * @param buf 发送缓冲区
     * @param buf_len 发送缓冲区长度
     * @return
     *   - 0 : success
     *   - -1: failed
     */
    int sx1261_spi_w(spi_device_handle_t *spi, uint8_t op_code, uint8_t *buf, uint16_t buf_len)
    {
        esp_err_t err = ESP_OK;
    
        spi_transaction_ext_t trans = {0};
    
        uint8_t rx_buf[256] = {0};
    
        if (buf_len > 256) {
            return -1;
        }
    
        err = spi_device_acquire_bus(*spi, portMAX_DELAY);
        if (err != ESP_OK) {
            return -1;
        }
    
        trans.address_bits = 1 * 8;
        trans.base.addr = op_code;
        trans.base.flags = SPI_TRANS_VARIABLE_ADDR;
    
        trans.base.tx_buffer = buf;
        trans.base.rx_buffer = rx_buf;
        trans.base.length = buf_len * 8;
        trans.base.rxlength = buf_len * 8;
    
        err = spi_device_polling_transmit(*spi, (spi_transaction_t *)&trans);
    
        spi_device_release_bus(*spi);
    
        if (err != ESP_OK) {
            return -1;
        }
    
        return 0;
    }
    
  • 多字节的读操作

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    
    /**
     * @brief SX1261 多字节的读操作
     * @param spi spi 句柄
     * @param op_code 寄存器地址
     * @param buf 接收缓冲区
     * @param buf_len 接收缓冲区长度
     * @return
     *   - 0 : success
     *   - -1: failed
     */
    int sx1261_spi_r(spi_device_handle_t *spi, uint8_t op_code, uint8_t *buf, uint16_t buf_len)
    {
        esp_err_t err = ESP_OK;
    
        spi_transaction_ext_t trans = {0};
    
        uint8_t tx_buf[256] = {0};
    
        if (buf_len > 256) {
            return -1;
        }
    
        memcpy(tx_buf, buf, buf_len);
    
        err = spi_device_acquire_bus(*spi, portMAX_DELAY);
        if (err != ESP_OK) {
            return -1;
        }
    
        trans.address_bits = 1 * 8;
        trans.base.addr = op_code;
        trans.base.flags = SPI_TRANS_VARIABLE_ADDR;
    
        trans.base.tx_buffer = tx_buf;
        trans.base.rx_buffer = buf;
        trans.base.length = buf_len * 8;
        trans.base.rxlength = buf_len * 8;
    
        err = spi_device_polling_transmit(*spi, (spi_transaction_t *)&trans);
    
        spi_device_release_bus(*spi);
    
        if (err != ESP_OK) {
            return -1;
        }
    
        return 0;
    }
    

版权声明

本文为「Zeepunt 日常随笔」的原创文章,遵循 CC BY-NC-ND 4.0 许可协议。允许在署名作者、注明原文链接且不作任何更改的前提下非商业性地分享本文。

原文链接:https://zeepunt.github.io/article/lora/gateway%E5%B0%84%E9%A2%91%E8%8A%AF%E7%89%87%E9%80%9A%E4%BF%A1/