08_pingpong 乒乓通信例程

一、简介

本例程演示 PAN211 芯片的乒乓通信功能,包含发送转接收和接收转发送两种模式。

二、条件说明

频点:2478MHz
芯片工作模式:PAN211_CHIPMODE_XN297
CRC:2字节
数据速率:1Mbps
SPI类型:3线SPI
通信地址:{0xcc,0xcc,0xcc,0xcc,0xcc}
数据长度:32字节
工作模式:普通型
发送功率:9dBm
接收超时:1000ms

三、接口(移植)实现

  1. 根据硬件实现以下配置:

  • SPI_CS引脚配置为推挽输出

  • SPI_SCK引脚配置为推挽输出

  • SPI_DATA引脚配置为推挽输出或输入模式,低功耗模式下需配置为输入模式并启用上拉电阻

#define SPI_CS_HIGH      CS_PIN = 1      /* 将SPI_CS引脚设置为高电平 */
#define SPI_CS_LOW       CS_PIN = 0      /* 将SPI_CS引脚设置为低电平 */
#define SPI_SCK_HIGH     SCK_PIN = 1     /* 将SPI_SCK引脚设置为高电平 */
#define SPI_SCK_LOW      SCK_PIN = 0     /* 将SPI_SCK引脚设置为低电平 */
#define SPI_DATA_HIGH    DATA_PIN = 1    /* 将SPI_DATA引脚设置为高电平 */
#define SPI_DATA_LOW     DATA_PIN = 0    /* 将SPI_DATA引脚设置为低电平 */
#define SPI_DATA_STATUS  DATA_PIN        /* 读取SPI_DATA引脚状态 */
#define SPI_DATA_OUTPUT  GPIO_SetModeByPin(P4_3, GPIO_MODE_OUTPUT)  /* 配置SPI_DATA引脚为输出模式 */
#define SPI_DATA_INPUT   GPIO_SetModeByPin(P4_3, GPIO_MODE_INPUT)   /* 配置SPI_DATA引脚为输入模式 */
  1. 根据实际使用的MCU修改SPI接口初始化代码:

/**
 * @brief 初始化PAN211 3线SPI接口
 * @param 无
 * @return 无
 * @note 该函数配置SPI_SCK、SPI_CS和SPI_DATA引脚为GPIO模式,并设置为输出模式
 * @note PAN211没有独立中断引脚,可开启SPI_DATA引脚中断复用功能
 * @note PAN216具有独立中断引脚,可通过P4_5来检测PAN216的中断事件
 */
void BSP_3LineSPIInit(void)
{
    CLK_AHBPeriphClockCmd(CLK_AHBPeriph_GPIO, ENABLE);

    // 将引脚配置为GPIO模式,以软件SPI实现
    SYS_ConfigMFP(P4_0, SYS_MFP_GPIO); // SPI_SCK
    SYS_ConfigMFP(P4_1, SYS_MFP_GPIO); // SPI_CS
    SYS_ConfigMFP(P4_3, SYS_MFP_GPIO); // SPI_DATA
    SYS_ConfigMFP(P4_5, SYS_MFP_GPIO); // IRQ引脚,PAN211未使用

    GPIO_SetModeByPin(P4_1, GPIO_MODE_OUTPUT); // 配置SPI_CS为输出模式
    GPIO_SetModeByPin(P4_0, GPIO_MODE_OUTPUT); // 配置SPI_SCK为输出模式
    GPIO_SetModeByPin(P4_3, GPIO_MODE_OUTPUT); // 配置SPI_DATA为输出模式,后续根据时序需要设置为输入模式
    GPIO_SetModeByPin(P4_5, GPIO_MODE_INPUT);  // PAN211没有中断引脚,PAN216有中断引脚,配置为输入模式

    P41 = 1; // SPI_CS置高,表示未选中
    P40 = 0; // SPI_SCK置低,SPI时钟极性为低电平有效
    P43 = 0; // SPI_DATA置低

    GPIO_EnablePullupPath(P4, BIT3); // 将SPI_DATA引脚设置为输入模式,并启用上拉电阻
}

四、应用范例

  1. 发送转接收模式(TXRX_TEST_MODE = 0):

    /* 读取P30引脚电平,决定是发送还是接收,P30连接至EVB板的P6接口*/
    if(P30 == TXRX_TEST_MODE) /* P30 == 0: 发送转接收测试模式,EVB板的P6接口选择RFTX */
    {
Start:
        /*====================发送数据开始=====================*/
        PAN211_EnterStandby(); /* 进入待机模式,准备发送数据 */
        BSP_DelayMs(500);      /* 延时500ms后再发送数据包 */

        PAN211_WriteFIFO(TxBuf, sizeof(TxBuf)); /* 将待发送的数据写入PAN211 TX FIFO */
        PAN211_TxStart();            /* PAN211进入发送状态并开始送数据 */

        while(!IRQDetected());       /* 等待SPI_DATA/IIC_SDA引脚变低,指示发送完成 */

        IRQFlag = PAN211_GetIRQFlags(); /* 获取中断标志 */
        if(IRQFlag & RF_IT_TX_IRQ)      /* 如果是发送完成中断 */
        {
            printf("发送完成!发送计数:%d\r\n", ++TxCount); /* 打印发送计数 */
            BSP_Led2Toggle();                     /* 切换LED2状态 */
        }
        printf("中断标志1: 0x%02X \r\n", IRQFlag);
        PAN211_ClearIRQFlags(0xFF);  /* 清除所有PAN211中断标志 */
        /*====================发送数据结束=====================*/

        /*====================接收数据开始=====================*/
        PAN211_RxStart();  /* 进入接收模式 */     
        
        CurrentSystemTime = g_SystemTick; /* 获取当前系统时间 */
        while(!IRQDetected())
        {
            if(g_SystemTick - CurrentSystemTime >= 1000) /* 超过1000ms,还没有收到任何中断 */
            {
                goto Start;  /* 接收超时,跳出循环,继续发送下一包数据 */
            }
        }
        IRQFlag = PAN211_GetIRQFlags(); /* 获取中断标志 */
        if(IRQFlag & RF_IT_RX_IRQ)      /* 如果是接收完成中断 */
        { 
            PAN211_ReadFIFO(RxBuf, sizeof(RxBuf));/* 读取FIFO数据到RxBuf缓冲区,
                                                     注意:FIFO数据长度不能超过RxBuf大小 */
            printf("接收数据包完成!接收数据包计数:%d\r\n", ++RxCount); /* 打印接收计数 */
            PrintHex(RxBuf, sizeof(RxBuf));  /* 以十六进制方式打印接收数据 */
            BSP_Led3Toggle();  /* 切换LED3状态 */
        }
        printf("中断标志2: 0x%02X \r\n", IRQFlag);
        PAN211_ClearIRQFlags(0xFF); /* 清除所有PAN211中断标志 */
        /*====================接收数据结束=====================*/
    }
  1. 接收转发送模式(RXTX_TEST_MODE = 1):

    else    /* P30 == 1: 接收转发送测试模式,EVB板的P6接口选择RFRX */
    {
        /*====================接收数据开始=====================*/
        PAN211_RxStart();               /* 进入接收模式 */
        while(!IRQDetected());          /* 等待SPI_DATA/IIC_SDA引脚变低,指示接收完成 */
        IRQFlag = PAN211_GetIRQFlags(); /* 获取中断标志 */
        if(IRQFlag & RF_IT_RX_IRQ)      /* 如果是接收完成中断 */
        { 
            PAN211_ReadFIFO(RxBuf, sizeof(RxBuf)); /* 读取FIFO数据到RxBuf缓冲区,
                                                      注意:FIFO数据长度不能超过RxBuf大小 */
            printf("接收数据包完成!接收数据包计数:%d\r\n", ++RxCount); /* 打印接收计数 */
            PrintHex(RxBuf, sizeof(RxBuf)); /* 以十六进制方式打印接收数据 */
            BSP_Led3Toggle(); /* 切换LED3状态 */
        }
        printf("中断标志1: 0x%02X \r\n", IRQFlag);
        PAN211_ClearIRQFlags(0xFF); /* 清除所有PAN211中断标志 */
        /*====================接收数据结束=====================*/

        /*====================发送数据开始=====================*/
        PAN211_WriteFIFO(TxBuf, sizeof(TxBuf)); /* 将待发送的数据写入PAN211 TX FIFO */
        PAN211_TxStart();      /* PAN211进入发送状态并开始送数据 */
        while(!IRQDetected()); /* 等待SPI_DATA/IIC_SDA引脚变低,指示发送完成 */
        IRQFlag = PAN211_GetIRQFlags(); /* 获取中断标志 */
        if(IRQFlag & RF_IT_TX_IRQ)   /* 如果是发送完成中断 */
        {
            printf("发送应答完成!发送应答计数:%d\r\n", ++TxCount); /* 打印发送计数 */
            BSP_Led2Toggle();                     /* 切换LED2状态 */
        }
        printf("中断标志2: 0x%02X \r\n", IRQFlag);
        PAN211_ClearIRQFlags(0xFF);  /* 清除所有PAN211中断标志 */
        
        PAN211_WriteReg(0x02, 0x74); /* 进入待机状态 */
        
        BSP_DelayMs(1); /* 延时1ms,避免发送数据过快,导致接收数据错误 */
        /*====================发送数据结束=====================*/
    }