
小众的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, 因此多预留了一些焊盘


从测试的过程看, 基于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
代码下载地址
在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基本读写和 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的初始化, 有一部分和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);
}
发送沿用了官方例子, 在写入发送内容, 拉高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;
}
也沿用了官方例子, 轮询等待待接收结果状态, 并读出接收到的字节
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);
}
时间有限没有充分测试, 仅测试了1Mbps速率开启ACK情况下的通信情况. 接收不设间隔, 发送间隔为2 - 3 毫秒时达到最高速率, 大约每1.7秒发送256组, 每组32个字节, 速率为4.8K 字节每秒, 这样看速度只有同等设置下nRF24L01的1/5, 可能和软件模拟的SPI有关.
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。问题1)我想知道rubyonrails是否有功能类似于primefaces的gem。我问的原因是如果您使用primefaces(http://www.primefaces.org/showcase-labs/ui/home.jsf),开发人员无需担心javascript或jquery的东西。据我所知,JSF是一个规范,基于规范的各种可用实现,prim
本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01 客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02 数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit
MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO
注意:本文主要掌握DCN自研无线产品的基本配置方法和注意事项,能够进行一般的项目实施、调试与运维AP基本配置命令AP登录用户名和密码均为:adminAP默认IP地址为:192.168.1.10AP默认情况下DHCP开启AP静态地址配置:setmanagementstatic-ip192.168.10.1AP开启/关闭DHCP功能:setmanagementdhcp-statusup/downAP设置默认网关:setstatic-ip-routegeteway192.168.10.254查看AP基本信息:getsystemgetmanagementgetmanaged-apgetrouteAP配
我使用的是最新版本的Chrome(32.0.1700.107)和Chrome驱动程序(V2.8)。但是当我在Ruby中使用以下代码运行示例测试时:require'selenium-webdriver'WAIT=Selenium::WebDriver::Wait.new(timeout:100)$driver=Selenium::WebDriver.for:chrome$driver.manage.window.maximize$driver.navigate.to'https://www.google.co.in'defapps_hoverele_hover=$driver.find_
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。多年来,我一直在使用多种语言进行编程,并且认为自己总体上相当擅长。但是,我从未编写过任何自动化测试:没有单元测试,没有TDD,没有BDD,什么都没有。我已经尝试开始为我的项目编写适当的测试套件。我可以看到在进行任何更改后能够自动测试项目中所有代码的理论值(value)。我可以看到像RSpec和Mocha这样的测试框架应该如何使设置和运行所述测试变得相当容易
如果我在功能规范中调用url_for,它会返回一个以http://www.example.com/开头的绝对URL.Capybara会很乐意尝试加载该站点上的页面,但这与我的应用程序无关。以下是重现该问题的最少步骤:从这个Gemfile开始:source'https://rubygems.org'gem"sqlite3"gem"jquery-rails"gem"draper"gem"rails",'4.1.0'gem"therubyracer"gem"uglifier"gem"rspec-rails"gem"capybara"gem"poltergeist"gem"launchy"运行
在笔者前面有一篇文章《驱动开发:断链隐藏驱动程序自身》通过摘除驱动的链表实现了断链隐藏自身的目的,但此方法恢复时会触发PG会蓝屏,偶然间在网上找到了一个作者介绍的一种方法,觉得有必要详细分析一下他是如何实现的进程隐藏的,总体来说作者的思路是最终寻找到MiProcessLoaderEntry的入口地址,该函数的作用是将驱动信息加入链表和移除链表,运用这个函数即可动态处理驱动的添加和移除问题。MiProcessLoaderEntry(pDriverObject->DriverSection,1)添加MiProcessLoaderEntry(pDriverObject->DriverSection,
我有一个适用于事件/监听器模型的应用程序。发布了几种不同类型的数据(事件),然后许多不同的事情可能需要也可能不需要对该数据(监听器)采取行动。监听器的发生没有特定的顺序,每个监听器将决定是否需要对事件采取行动。Rails应用程序有哪些工具可以完成此任务?我希望自己不必这样做(尽管我可以。这没什么大不了的。)编辑:观察者模式可能是更好的选择 最佳答案 查看EventMachine.它是一个非常流行的Ruby事件处理库。它看起来相当不错,而且很多其他库似乎都在利用它(Cramp)。这是一个很好的介绍:http://rubylearnin
一、概述在之前的一篇博文中,记录了AT24C01、AT24C02芯片的读写驱动,先将之前的相关文章include一下:1.IIC驱动:4位数码管显示模块TM1637芯片C语言驱动程序2.AT24C01/AT24C02读写:AT24C01/AT24C02系列EEPROM芯片单片机读写驱动程序本文记录分享AT24C04、AT24C08、AT24C16芯片的单片机C语言读写驱动程序。二、芯片对比介绍型号容量bit容量byte页数字节/页器件寻址位可寻址器件数WordAddress位数/字节数备注AT24C044k5123216A2A149/1WordAddress使用P0位AT24C088k1024