码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • STC8H开发(十六): GPIO驱动XL2400无线模块


    目录

    • STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解)
    • STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解)
    • STC8H开发(三): 基于FwLib_STC8的模数转换ADC介绍和演示用例说明
    • STC8H开发(四): FwLib_STC8 封装库的介绍和使用注意事项
    • STC8H开发(五): SPI驱动nRF24L01无线模块
    • STC8H开发(六): SPI驱动ADXL345三轴加速度检测模块
    • STC8H开发(七): I2C驱动MPU6050三轴加速度+三轴角速度检测模块
    • STC8H开发(八): NRF24L01无线传输音频(对讲机原型)
    • STC8H开发(九): STC8H8K64U模拟USB HID外设
    • STC8H开发(十): SPI驱动Nokia5110 LCD(PCD8544)
    • STC8H开发(十一): GPIO单线驱动多个DS18B20数字温度计
    • STC8H开发(十二): I2C驱动AT24C08,AT24C32系列EEPROM存储
    • STC8H开发(十三): I2C驱动DS3231高精度实时时钟芯片
    • STC8H开发(十四): I2C驱动RX8025T高精度实时时钟芯片
    • STC8H开发(十五): GPIO驱动Ci24R1无线模块
    • STC8H开发(十六): GPIO驱动XL2400无线模块

    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晶振输出
    7VSSGND地
    8ANTRF天线接口

    可以和 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    示例代码

    代码下载地址

    • GitHub https://github.com/IOsetting/FwLib_STC8/tree/master/demo/gpio/xl2400
    • Gitee https://gitee.com/iosetting/fw-lib_-stc8/tree/master/demo/gpio/xl2400

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

    基础宏定义

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

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

    宏定义和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

    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

    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);
    }
    
    • 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

    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

    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

    每次在调用 之前, 需要设置一下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

    XL2400通信速率

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

  • 相关阅读:
    图解LeetCode——1796. 字符串中第二大的数字(难度:简单)
    高频数据分析:使用数据透视
    考试周刊杂志考试周刊杂志社考试周刊编辑部2022年第24期目录
    杰哥教你面试之一百问系列:java中高级多线程concurrent的使用
    机器学习笔记 - 生成代理的架构框架
    C++ Qt开发:StringListModel字符串列表映射组件
    架构学习之通用定时器
    解放你的双手----WIN7设置自动化任务
    JAVA基于Netty实现内网穿透功能【设计实践】
    C/C++如何避免“野指针”
  • 原文地址:https://blog.csdn.net/michaelchain/article/details/126450279
  • 最新文章
  • 【JVM】编译执行与解释执行的区别是什么?JVM 使用哪种方式?
    用 Hashids 优雅解决 C 端自增 ID 暴露问题
    V8引擎 精品漫游指南--Ignition篇(上) 指令 栈帧 槽位 调用约定 内存布局 基础内容
    LLVM Pass快速入门(四):代码插桩
    milkup:桌面端 markdown AI续写和即时渲染
    基于项目工程构建SBOM(软件物料清单)的研究
    鸿蒙应用开发UI基础第二节:鸿蒙应用程序框架核心解析与实操
    .NET 中如何快速实现 List 集合去重?
    扣子Coze实战:从0到1打造抖音+小红书热点监控智能体
    浅谈数据访问层
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
小工具 小游戏
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1

京公网安备 11010502049817号