BasicRF之中断接收basicRfRxFrmDoneIsr
由于appLight()的主循环一直在等待 接收中断完成,一旦有接收中断并接收完成则进行后续的数据处理,因此这里主要介绍一下接收中断服务子函数basicRfRxFrmDoneIsr(该函数指针在basicRfInit()被声明,详细介绍参看上一篇),具体代码如下:
/***********************************************************************************
* @fn basicRfRxFrmDoneIsr
*
* @brief Interrupt service routine for received frame from radio
* (either data or acknowlegdement)
* //当无线信号有接收帧时执行中断服务子程序;
* @param rxi - file scope variable info extracted from the last incoming
* frame
* //最近一次接收帧信息;
* txState - file scope variable that keeps tx state info
* //发送状态信息,在中断服务子程序中主要在接收ACK中涉及;
* @return none
*/
static void basicRfRxFrmDoneIsr(void)
{
basicRfPktHdr_t *pHdr; //帧头结构体指针;
uint8 *pStatusWord; //存储读RSSI和CRC信息;
#ifdef SECURITY_CCM
uint8 authStatus=0;
#endif
// Map header to packet buffer
//帧头指针指向 所接收的MPDU数据单元;
//结构体间的强制类型转换,起始地址的指向;
pHdr= (basicRfPktHdr_t*)rxMpdu;
// Clear interrupt and disable new RX frame done interrupt
//关闭通用RF中断 和 RXPKTDONE中断;
halRfDisableRxInterrupt();
// Enable all other interrupt sources (enables interrupt nesting)
//始能总中断;(考虑默认优先级 其他中断)
halIntOn();
// Read payload length.
//读取长度域的值;
halRfReadRxBuf(&pHdr->packetLength,1);
pHdr->packetLength &= BASIC_RF_PLD_LEN_MASK; // Ignore MSB
//最大程度为127字节,故忽略最高有效位;
// Is this an acknowledgment packet?
// Only ack packets may be 5 bytes in total.
//由于只有ACK帧的数据长度为5,所以可以通过 帧 长度来判断该帧的类型:数据帧 or 应答帧;
if (pHdr->packetLength == BASIC_RF_ACK_PACKET_SIZE) {
// Read the packet
//将接收数据 通过RFD从缓存中一个字节一个字节读出;
halRfReadRxBuf(&rxMpdu[1], pHdr->packetLength);
// Make sure byte fields are changed from network to host byte order
//将网络参数的高4位和低4位交换 ,由 无线网络格式 转换为 本地格式;
UINT16_NTOH(pHdr->panId);
UINT16_NTOH(pHdr->destAddr);
UINT16_NTOH(pHdr->srcAddr);
#ifdef SECURITY_CCM
UINT32_NTOH(pHdr->frameCounter);
#endif
//读取应答帧帧的应答位信息,对于应答帧的FCF该位应该为0;
rxi.ackRequest = !!(pHdr->fcf0 & BASIC_RF_FCF_ACK_BM_L);
// Read the status word and check for CRC OK
//指向该帧的FCS;
pStatusWord= rxMpdu + 4;
// Indicate the successful ACK reception if CRC and sequence number OK
//若CRC校验位和帧序号无误,则将txState.ackReceived 设置为 TRUE,表示数据发送及对方节点接收完成;
if ((pStatusWord[1] & BASIC_RF_CRC_OK_BM) && (pHdr->seqNumber == txState.txSeqNumber)) {
txState.ackReceived = TRUE;
}
// No, it is data
} else {
// It is assumed that the radio rejects packets with invalid length.
// Subtract the number of bytes in the frame overhead to get actual payload.
//在灯开关例程中,默认 非应答帧长度的数据 皆为有效数据,即:假定非有效数据都被拒绝(假定很恶劣= =!);如果传输的数据长度是固定的可以更换 固定的长度条件,其他 长度的无线数据都不进行处理;
//长度域的值减去(MHR+MFR)获得有效负载长度;
rxi.length = pHdr->packetLength - BASIC_RF_PACKET_OVERHEAD_SIZE;
#ifdef SECURITY_CCM
rxi.length -= (BASIC_RF_AUX_HDR_LENGTH + BASIC_RF_LEN_MIC);
authStatus = halRfReadRxBufSecure(&rxMpdu[1], pHdr->packetLength, rxi.length,
BASIC_RF_LEN_AUTH, BASIC_RF_SECURITY_M);
#else
halRfReadRxBuf(&rxMpdu[1], pHdr->packetLength); //将接收数据 通过RFD从缓存中一个字节一个字节读出;
#endif
// Make sure byte fields are changed from network to host byte order
//将网络参数的高4位和低4位交换 ,由 无线网络格式 转换为 本地格式;
UINT16_NTOH(pHdr->panId);
UINT16_NTOH(pHdr->destAddr);
UINT16_NTOH(pHdr->srcAddr);
#ifdef SECURITY_CCM
UINT32_NTOH(pHdr->frameCounter);
#endif
//读取该帧的应答位信息;
rxi.ackRequest = !!(pHdr->fcf0 & BASIC_RF_FCF_ACK_BM_L);
// Read the source address
//读取源地址;
rxi.srcAddr= pHdr->srcAddr;
// Read the packet payload
//读取净载荷数据;
rxi.pPayload = rxMpdu + BASIC_RF_HDR_SIZE;
// Read the FCS to get the RSSI and CRC
//读取帧校验中的RSSI和CRC相关信息;
pStatusWord= rxi.pPayload+rxi.length;
#ifdef SECURITY_CCM
pStatusWord+= BASIC_RF_LEN_MIC;
#endif
//读取RSSI的值;
rxi.rssi = pStatusWord[0];
// Notify the application about the received data packet if the CRC is OK
// Throw packet if the previous packet had the same sequence number
//根据CRC校验位来判定是否 为有效数据帧;
//其中,还要求对 帧序号 进行验证,如果该数据帧 要求有应答的情况下 在数据帧发送接收流程上不完整,帧序号连续两次相同的那么不对重复数据帧进行后续的处理,需要被丢弃;
//另外如果发送节点 确定数据被正确接收 可以采用连续发送两次,并根据 应答是否成功 来判断程序是否进行二次重复发送;
if( (pStatusWord[1] & BASIC_RF_CRC_OK_BM) && (rxi.seqNumber != pHdr->seqNumber) ) {
// If security is used check also that authentication passed
#ifdef SECURITY_CCM
if( authStatus==SUCCESS ) {
if ( (pHdr->fcf0 & BASIC_RF_FCF_BM_L) ==
(BASIC_RF_FCF_NOACK_L | BASIC_RF_SEC_ENABLED_FCF_BM_L)) {
rxi.isReady = TRUE;
}
}
#else
if ( ((pHdr->fcf0 & (BASIC_RF_FCF_BM_L)) == BASIC_RF_FCF_NOACK_L) ) {
rxi.isReady = TRUE; //如果接收到的FCF满足无ACK位的条件,说明正确接收,将接收节点状态 设置为TRUE;
//其中BASIC_RF_FCF_NOACK_L = 0x61表示PANID一致而且该帧类型为 数据帧;
//数据帧的通过验证的判断条件:1.CRC = OK ;2.SeqNumber和上一次的不同;3.保持PANID 和 帧类型 一致;
}
#endif
}
//帧序号在灯开关例程作用:
//数据帧要求有应答的情况,应答成功→下一帧SeqNumber自加→(PANID 和 帧类型一致的条件下)下一帧进行的后期操作;然而 应答不成功→下一帧SeqNumber保持→rxi.isReady始终为FALSE下一帧无法进行后期处理,表现现象为对应节点发送的数据始终无法接收!
//数据帧要求无应答的情况,下一帧SeqNumber始终自加,不会造成对应节点发送的数据无法接收的问题;
//SeqNumber在灯开关例程作用始终是 ACK的成功与否来决定的,因此应该善于利用 ACK是否成功完成的条件!
rxi.seqNumber = pHdr->seqNumber;
}
// Enable RX frame done interrupt again
//关闭总中断,会在 basicRfReceive()中 复制完接收数据 后重新始能;
halIntOff(); //调用函数HAL_INT_OFF();
//#define HAL_INT_OFF(x) st( EA = 0; )
//x的指向可以是空?
//始能通用RF中断 和 RXPKTDONE中断;
halRfEnableRxInterrupt();
}
BasicRF之中断接收basicRfRxFrmDoneIsr相关推荐
- STM32串口中断接收方式详细比较
本例程通过PC机的串口调试助手将数据发送至STM32,STM32通过SP3232芯片采用中断接收方式完成,然后接收数据后将所接收的数据又发送至PC机. 实例一: void USART1_IRQHand ...
- STM32 HAL库 串口DMA(收发)和STM32串口中断接收(接收时间管理机制)+ESP8266 wifi模组通信问题
一.HAL库 串口 DMA+ESP8266模组通信问题 用STM32 HAL库串口的DMA发送和空闲中断接收处理数据,单片机发送AT指令给ESP8266 wifi模组问题:单片机连续几次给wifi模组 ...
- bufferedreader接收不到数据_FreeRTOS例程3-串口中断接收不定长的数据与二值信号量的使用
1 基础知识点 1.1 串口中断种类 串口中断属于STM32本身的资源,不涉及到FreeRTOS,但可与FreeRTOS配合使用. 串口接收中断 中断标志为:USART_IT_RXNE,即rx non ...
- STM32串口的使用(原理、结构体、库函数、串口发送字符(串)、重定向printf串口发送、串口中断接收控制灯)
参考:串口的结构体 重定向printf串口发送stm32等博文 作者:点灯小哥 发布时间: 2021-03-06 21:46:33 网址:https://blog.csdn.net/weixin_46 ...
- STM32H743+CubeMX-串口非空闲中断接收
文章目录 一.前言 二.CubeMX 2.1.选择串口 三.代码 3.1.main.c 3.2.stm32f7xx_it.c 相关笔记: STM32H743-串口重定向printf 一.前言 在实际工 ...
- stm32串口空闲中断接收不定长数据
串口空闲中断接收不定长数据 空闲中断是接受数据后出现一个byte的高电平(空闲)状态,就会触发空闲中断.并不是空闲就会一直中断,准确的说应该是上升沿(停止位)后一个byte,如果一直是低电平是不会触发 ...
- STM32 利用空闲中断接收数据
STM32 利用串口空闲中断接收不定长数据 利用cubeMX打开DMA串口接收中断 利用CubeMX打开串口中断 HAL_NVIC_SetPriority(USART2_IRQn, 0, 0); HA ...
- stc 串口收发 c语言,STC12C5A60S2 串口中断接收程序
原标题:STC12C5A60S2 串口中断接收程序 #define UART0_BUF_LEN 32 int UART1_Recv_count; //接收计数 bit UART1_Overflow_F ...
- STM32使用串口中断接收HWT101的数据
因研究生阶段项目需求,需要采用HWT101给单片机提供角度信息. HWT101是维特智能公司下的一款角度传感器,它可以通过计算角速度测量绕Z轴旋转的水平方向的偏航角,具有高精度.几乎无漂移.不受磁场干 ...
最新文章
- 【2018-01-22】HTML-表单及表单元素
- easyui的combobox下拉框初始化默认值以及保持该值一直显示的方法
- android edittext标签,TagEditText,类似微博标签的文本控件
- Selenium java环境搭建
- javaScript实现字符串首字母大写
- 安徽省2019年普通高校招生文史、理工类最低控制分数线一览表
- [转]有关IIS的虚拟目录的控制总结
- 小型的网站服务器配置,中小型网站服务器配置参考
- RabbitMQ脑裂
- OpenShift安装
- selenium操作cookies实现免密登录,自动发微博
- 如何通过RFID开发来迎接第四次工业革命(转)
- Nginx访问403异常问题处理
- 使用 JavaScript,也能在 Web 应用中实现人脸检测功能?!
- 计算机二级b5纸是多大尺寸,两张b5纸是多大
- 利用R语言做可重复性报告研究
- 非晶金属模型建模:Ovito方法
- linux 中的3类驱动程序
- 数字信号处理原理及实现一书的思维导图
- (连载0.1)实践报告:在深度系统用Python3对上市公司年度报告财务报表进行提取