目录

  • 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晶振输出
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              => CSNP34              => DATAP32              => SCK                    VDD1     => 3.3V                    XC1,XC2  => 16MHz OSC                    GND      => GND

示例代码

代码下载地址

  • 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驱动方式的代码, 通信效果较差, 有兴趣的可以试一下. 如果能改进为硬件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 的初始化

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

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个字节, 速率为4.8K 字节每秒, 这样看速度只有同等设置下nRF24L01的1/5, 可能和软件模拟的SPI有关.