• STC8H开发(十六): GPIO驱动XL2400无线模块


    🚀 优质资源分享 🚀

    学习路线指引(点击解锁)知识定位人群定位
    🧡 Python实战微信订餐小程序 🧡进阶级本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。
    💛Python量化交易实战💛入门级手把手带你打造一个易扩展、更安全、效率更高的量化交易系统

    目录

    XL2400 简介

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

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

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

    XL2400 管脚和典型电路

    管脚定义

    PINNameI/O说明
    1CSNDISPI 片选信号
    2SCKDISPI 时钟信号
    3DATA/IRQIOSPI 数据输入/输出/中断信号
    4VDDPower电源(+2.1 ~ +3.6V,DC)
    5XC1AI晶振输入
    6XC2AO晶振输出
    8VSSGND
    7ANTRF天线接口

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

    电路

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

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

    STC8H 驱动 XL2400

    驱动说明

    从测试的过程看, 基于GPIO模拟SPI驱动比较稳妥, 如果用硬件SPI, 收发的通信成功率太低, 主要遇到的问题是SPI读取时, 有30%概率会读到全为0xFF的内容, 猜测是XL2400的驱动能力较弱, 无法拉低读周期的电平?

    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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    示例代码

    代码下载地址

    在SPI目录下也有硬件SPI驱动方式的代码, 通信效果较差, 有兴趣的可以试一下. 如果能改进为硬件SPI收发就更好.

    基础宏定义

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

    // 0:TX, 1:RX
    #define XL2400\_MODE 1
    
    
    • 1
    • 2
    • 3

    宏定义和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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    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);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    XL2400 的初始化

    XL2400的初始化, 有一部分和nRF24L01一致, 另一部分是特有的

    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();
        // 开启所有 Pipe 的 Auto ACK
        XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_EN_AA, 0x3F);
        // 启用所有 Pipe
        XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_EN_RXADDR, 0x3F);
        // 地址宽度 5 bytes
        XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_SETUP_AW, 0xAF);
        // 重试次数和间隔
        XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_SETUP_RETR, 0x33);
        // 无线速率 1Mbps
        XL2400_WriteReg(XL2400_CMD_W_REGISTER | XL2400_REG_RF_SETUP, 0x22);
        // 接收通道0和通道1的接收字节数
        *(cbuf + 0) = XL2400_PLOAD_WIDTH;
        *(cbuf + 1) = XL2400_PLOAD_WIDTH;
        XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RX_PW_PX, cbuf, 2);
        // 关闭动态接收大小
        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);
        // 开启 RSSI
        *(cbuf + 0) = 0x10;
        *(cbuf + 1) = 0x00;
        XL2400_WriteFromBuf(XL2400_CMD_W_REGISTER | XL2400_REG_RSSI, cbuf, 2);
    }
    
    
    • 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

    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;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    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;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    每次在调用 之前, 需要设置一下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);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    XL2400通信速率

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

  • 相关阅读:
    Debezium报错处理系列之六十八:No resolvable bootstrap urls given in bootstrap.servers
    SAP 销售订单审批状态参数设置
    nginx 的使用
    NoSQL之 Redis配置与优化
    【JavaSE】函数or方法?方法的重载讲解
    GFS分布式文件系统
    C#下WinForm多语种切换
    MySQL汉字转拼音方案
    【2022硬件设计开源盛宴】一年一度的hackaday大赛结束,冠军便携式风力涡轮机,共提交326个电子作品,奖金池15万美元
    无人机红外相机的畸变矫正
  • 原文地址:https://blog.csdn.net/u012804784/article/details/126458091