最近在项目止采用SI4438作为无线通信。采用的是wds内的长包发送模板,用的中断为TX_FIFO_EMPTY和RX_FIFO_FULL两个中断。但是在实际应用中却出现了问题。程序内包长设置的是255字节(项目需要最长为255字节)。由于数据发送较为频繁,即使主机发送7字节数据,从机也会进入5次RX_FIFO_FULL中断,已经影响到了从机其它任务的正常运行。
经分析,此问题存在的根源是,从机每次均按255字节接收,不知道主机所实际传输的字节是多少。后面经查资料,WDS内有可变长包发送的这个功能,所以就进行了程序修改和测试。
具体实现方法如下:
首先配置好WDS的软件,按界面生成如下的工程模板,将radio_config_Si4438.h生成。具体配置如下(具体配置情况以个人为准,此截图仅为本人用):
WDS配置好了,生成了radio_config_Si4438.h这个文件,放到工程里替换。
接下来是程序的配置:
一、变长包数据收发格式
/*第一字节是长度,后面是数据。实际写入到TX FIFO发送的数据是9字节 = 负载数据8字节+数据长度1字节*/
变长包的格式是:0x08,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08;
二、接收
SI4438的接收和发送是相对独立的,同一时间内只能接收或者只能发送。
转换到接收状态部分程序
void vRadio_StartRX(U8 channel)
{
/*清除中断标记*/
si446x_get_int_status(0u, 0u, 0u);
/*清空RX FIFO*/
si446x_fifo_info(SI446X_CMD_FIFO_INFO_ARG_FIFO_RX_BIT);
/*由于start TX和 start RX命令中的length长度不再起作用,实际需要收发的数据长度由对应的field length寄存器来控制,field1一直代表数据包的长度,收发都是一个字节来表示长度,因此不需要修改field1 length寄存器。修改field2 length的代码如下 */
/*以下程序为指定最长的接收长度 最后一位为目前的长度,设置为255(尽量设置长,目前自测试最长到255,此为最长接收字节。实际接收字节由filed2自动获取)*/
si446x_set_property(0x12,0x02,0x11,0x00,0xFF);
/* Start Receiving packet, channel 0, START immediately, Packet length according to PH */}
接收部分中断
在接收及长包中断处理中,以LongPacket Rx为模板为准,完成接收部分的长包接收部分的程序
三、发送
发送函数如下构成,主要是参照LongPacket Tx模板实现的,主要是对发送的数据长度进行实际区分。如果大于TX FIFO,则分包传输。小于TX FIFO,则一次性传输。
void SI4438_Send(uint8_t *dat,uint8_t length)
{
PacketTxData.length = length+1;
PacketTxData.buf[0] = length;
memcpy(PacketTxData.buf+1,dat,length); //将数据结构按照无线传输结构去打包
/*复位TX FIFO*/
si446x_fifo_info(SI446X_CMD_FIFO_INFO_ARG_FIFO_TX_BIT);
/*清除中断标记*/
si446x_get_int_status(0u, 0u, 0u);
/*将所传数据的首地址给指针*/
LongPacketData.pTxPositionInPayload = PacketTxData.buf; /*从数据的首地址开始*/
LongPacketData.NumTxPositionInPayload = 0; /*长度从0开始计算*/
/*要发送的字节长度 大于当前FIFO的空间(64字节)*/
if( RADIO_MAX_PACKET_LENGTH < PacketTxData.length)
{
/* 第一包发送FIFO定长的数据 */
si446x_write_tx_fifo(RADIO_MAX_PACKET_LENGTH, LongPacketData.pTxPositionInPayload);
/*计算发送了多少字节 */
LongPacketData.NumTxPositionInPayload += RADIO_MAX_PACKET_LENGTH;
/* 计算数组偏移 */
LongPacketData.pTxPositionInPayload += RADIO_MAX_PACKET_LENGTH;
/*长度>64*/
LongPacketData.TxlengthGet = 0;
}
else
{
/*未超过FIFO最大值(64字节) 则将所有字节发送出去*/
si446x_write_tx_fifo(PacketTxData.length,LongPacketData.pTxPositionInPayload);
/*长度<64*/
LongPacketData.TxlengthGet = 1;
}
/*需要发送的长度,放到field2 length寄存器中 要发送的长度由这里给出*/
si446x_set_property(0x12,0x02,0x11,0x00,PacketTxData.length);
/*立即发送 长度由field2 length决定*/
si446x_start_tx(SI4438Configure.Radio_TX_ChannelNumber, 0x00, 0x00);
}
发送部分中断处理
在发送及长包处理中断程序,以LongPacket Tx为模板为准,完成接收部分的长包接收部分中断的程序
经过以上调试,接收方在接收数据时,能够知道接收字节的长度。433模块会根据字节长度,进入中断。中断次数得到有效的控制。