STC8H开发(十六): GPIO驱动XL2400无线模块
阅读原文时间:2023年07月10日阅读:6

目录

XL2400 简介

小众的2.4G射频收发芯片, 和 Ci24R1, XN297L 一样, 都属于 nRF24L01 派生的 SOP8 版本. 在寄存器和操作上类似于nRF24L01, 但是寄存器中存在大量多字节的设置, 没有中断, 完全靠轮询工作, 这是这个型号的特点.

在兼容性上, 和XN297L管脚布局一致但是寄存器不一样, 比XN297L的外围电路元件更少, 只需要一个16MHz晶振, 两个电容就能工作. 和Ci24R1比管脚和寄存器都不一样.

具体的参数可以查看官网上的产品介绍 和手册 XL2400规格书V2.0a.pdf, XL240X应用说明v2.1a.pdf, 市场上还有型号为 WL2400 的芯片, 看手册应该是同一个芯片.

直接看电路和代码

管脚定义

PIN

Name

I/O

说明

1

CSN

DI

SPI 片选信号

2

SCK

DI

SPI 时钟信号

3

DATA/IRQ

IO

SPI 数据输入/输出/中断信号

4

VDD

Power

电源(+2.1 ~ +3.6V,DC)

5

XC1

AI

晶振输入

6

XC2

AO

晶振输出

8

VSS

GND

7

ANT

RF

天线接口

可以和 Ci24R1 对比一下, 仅仅是管脚位置不同

电路

电路非常简单, C3可以省略, C7可以用1pF至3pF.

没有现成的模块, 在立创打的板子, 成品图, 兼容XN297, 因此多预留了一些焊盘

STC8H 驱动 XL2400

从测试的过程看, 基于GPIO模拟SPI驱动比较稳妥, 如果用硬件SPI, 收发的通信成功率太低. STC8H对三线SPI半双工通信没有说明, 还需要进一步尝试. 因此以下仅说明基于GPIO模拟SPI驱动的方式.

示例代码中, 使用了与硬件SPI一样的Pin, 实际上换成其他Pin也一样, 因为都是通过GPIO模拟驱动.

 *    Pin connection:
 *    P35              => CSN
 *    P34              => DATA
 *    P32              => SCK
 *                        VDD1     => 3.3V
 *                        XC1,XC2  => 16MHz OSC
 *                        GND      => GND

代码下载地址

在SPI目录下也有硬件SPI驱动方式的代码, 通信效果较差, 有兴趣的可以试一下.

基础宏定义

切换收发模式, 通过main.c中的XL2400_MODE设置

// 0:TX, 1:RX
#define XL2400_MODE 1

宏定义和Ci24R1是一样的, 只是XL2400的CE操作更复杂一点, 需要读写两个字节所以没放到宏定义里

#define XL2400_CSN  P35
#define XL2400_SCK  P32
#define XL2400_MOSI P34

#define XL2400_PLOAD_WIDTH       32   // Payload width

#define XL2400_DATA_OUT()        GPIO_P3_SetMode(GPIO_Pin_4, GPIO_Mode_Output_PP)
#define XL2400_DATA_IN()         GPIO_P3_SetMode(GPIO_Pin_4, GPIO_Mode_Input_HIP)
#define XL2400_DATA_LOW()        XL2400_MOSI = 0
#define XL2400_DATA_HIGH()       XL2400_MOSI = 1
#define XL2400_DATA_READ()       XL2400_MOSI

#define XL2400_CLK_LOW()         XL2400_SCK = 0
#define XL2400_CLK_HIGH()        XL2400_SCK = 1

#define XL2400_NSS_LOW()         XL2400_CSN = 0
#define XL2400_NSS_HIGH()        XL2400_CSN = 1

SPI基础通信, 寄存器读写和多字节读写

SPI基本读写和 Ci24R1 完全一致, 可以参考 Ci24R1 的对应部分. 从官方的代码样例移植时, 并没有使用官方提供的操作方式, 因为相对比之下, 现在这种写法更稳妥. XL2400 没有单字节命令, 只有普通的双字节命令读写, 其它的多字节读写也和 Ci24R1 是一样的.

XL2400的CE操作

void XL2400_CE_Low(void)
{
    XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_CFG_TOP, cbuf, 2);
    *(cbuf + 1) &= 0xBF;
    XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_CFG_TOP, cbuf, 2);
}

void XL2400_CE_High(void)
{
    XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_CFG_TOP, cbuf, 2);
    *(cbuf + 1) |= 0x40;
    XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_CFG_TOP, cbuf, 2);
}

XL2400 的初始化

void XL2400_Init(void)
{
    // Analog config
    XL2400_ReadToBuf(XL2400_CMD_R_REGISTER | XL2400_REG_ANALOG_CFG0, xbuf, 13);
    *(xbuf + 4) &= ~0x04;
    *(xbuf + 12) |= 0x40;
    XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_ANALOG_CFG0, xbuf, 13);
    // Switch to software CE control, wake up RF
    XL2400_WakeUp();
    // Enable Auto ACK Pipe 0
    XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_EN_AA, 0x3F);
    // Enable Pipe 0
    XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_EN_RXADDR, 0x3F);
    // Address Width, 5 bytes
    XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_SETUP_AW, 0xAF);
    // Retries and interval
    XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_SETUP_RETR, 0x33);
    // RF Data Rate 1Mbps
    XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_RF_SETUP, 0x22);
    // Number of bytes in RX payload, pipe 0 and pipe 1
    *(cbuf + 0) = XL2400_PLOAD_WIDTH;
    *(cbuf + 1) = XL2400_PLOAD_WIDTH;
    XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RX_PW_PX, cbuf, 2);
    // Dynamic payload width: off
    XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_DYNPD, 0x00);
    // Other features
    //bit7&6=00 return status when send register address
    //bit5=0 long data pack off
    //bit4=1 FEC off
    //bit3=1 FEATURE on
    //bit2=0 Dynamic length off
    //bit1=0 ACK without payload
    //bit0=0 W_TX_PAYLOAD_NOACK off
    XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_FEATURE, 0x18);
    // Enable RSSI
    *(cbuf + 0) = 0x10;
    *(cbuf + 1) = 0x00;
    XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RSSI, cbuf, 2);
}

XL2400 发送

发送沿用了官方例子, 在写入发送内容, 拉高CE后, 轮询状态等待发送结果. 如果是MAX_RT或TX_DS_FLAG 则返回结果.

uint8_t XL2400_Tx(uint8_t *ucPayload, uint8_t length)
{
    uint8_t y = 100, status = 0;
    XL2400_ClearStatus();
    XL2400_WriteFromBuf(XL2400_CMD_W_TX_PAYLOAD, ucPayload, length);
    XL2400_CE_High();
    // Retry until timeout
    while (y--)
    {
        SYS_DelayUs(100);
        status = XL2400_ReadStatus();
        // If TX successful or retry timeout, exit
        if ((status & (MAX_RT_FLAG | TX_DS_FLAG)) != 0)
        {
            break;
        }
    }
    XL2400_CE_Low();
    return status;
}

XL2400 接收

也沿用了官方例子, 轮询等待待接收结果状态, 并读出接收到的字节

uint8_t XL2400_Rx(void)
{
    uint8_t i, status, rxplWidth;
    status = XL2400_ReadStatus();
    if (status & RX_DR_FLAG)
    {
        XL2400_CE_Low();
        rxplWidth = XL2400_ReadReg(XL2400_CMD_R_RX_PL_WID);
        XL2400_ReadToBuf(XL2400_CMD_R_RX_PAYLOAD, xbuf, rxplWidth);
        XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_STATUS, status);
        // UART1_TxChar('>');
        // for (i = 0; i < rxplWidth; i++)
        // {
        //     UART1_TxHex(*(xbuf + i));
        // }
    }
    return status;
}

每次在调用 之前, 需要设置一下RX状态, 否则不会接收

void XL2400_SetRxMode(void)
{
    XL2400_CE_Low();
    XL2400_ClearStatus();
    XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_CFG_TOP, 0x7F);
    // XL2400_RxCalibrate();
    XL2400_CE_High();
    SYS_Delay(1);
}

XL2400通信速率

时间有限没有充分测试, 仅测试了1Mbps速率开启ACK情况下的通信情况. 接收不设间隔, 发送间隔为2 - 3 毫秒时达到最高速率, 大约每1.7秒发送256组, 每组32个字节, 速率为2.7K 字节每秒, 这样看速度只有同等设置下nRF24L01的1/8, 可能和软件模拟的SPI有关.

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章