编译软件工具KEIL篇

软件开发篇

基本说明

已适配的无线模块

IO口定义

序号 模块IO MCU IO 转接板排针 模块功能 必需 备注
1 IRQ PB0 IO0 收发状态中断信号输出 输出高电平,外部可做上升沿触发检测
2 NRST PB1 IO1 芯片复位脚 N 可以不控制,悬空或者置高
3 DIO03 PC5 IO2 N
4 DIO11 PA2 IO3 N
5 NC X
6 NC X
7 VCC VCC
8 GND G
9 GND G
10 NSS PA4 NSS NSS 从机SPI片选脚
11 MOSI PA7 DO MOSI 主机SPI数据发送,从机SPI数据接收
12 MISO PA6 DI MISO P 主机SPI数据接收,从机SPI数据发送,3线SPI可以不接
13 SCK PA5 SCK SCK 主机SPI时钟输出
14 NC X
15 GND G
16 ANT

说明:

SPI驱动接口

工程文件架构

..\adapterBoardDriver_xxxxxxxxxxxxxxx_Vxx
├──app \\常用应用模块封装
|  └──
├──core    \\MCU内核文件
|  └──
├──STM32F10x_FWLib \\MCU官方库函数
   └──
├──image   \\md文件显示用的图片
|  └──
├──keil_v5 \\keil编译器工程文件,包含编译生成的HEX文件
|  └──Object  \\编译生成的HEX文件在此文件夹
├──peripheral  \\项目用到的MCU外设
|  └──
├──project \\项目的主函数和GPIO定义包含文件
|  └──
├──radio   \\射频底层驱动文件
|  ├──myRadio_gpio.c  \\射频驱动接口硬件初始化
|  └──myRadio.c   \\为无线应用通用封装API
|  └──...

无线通讯开发注意事项

硬件篇

  1. 无线模组转接板插槽,带金手指,可以适配不同的模块转接板
  2. 普通 LED 指示灯
  3. 显示屏,显示工作状态以及工作使用参数
  4. MCU 预留 I/O 口
  5. 主板 MCU 复位按键
  6. SWD 主板 MCU 程序下载调与调试接口
  7. 供电电源 3 档开关,可以用于切换选择测试板的供电电源,切换到 BT 档,
    测试板为底部的 3 节 5 号电池供电,切换到 USB 档,测试板为⑧的 Micro-B 座子
    供电,打在中间档关闭供电
  8. Micro-B USB 座子,可以用于测试板的供电;连接电脑可以做 TTL 转 USB 功
    能,测试板内含 CP2102N 芯片

编译软件工具KEIL篇

编译参数选择

keil工程已经设置了4个选项:

模块演示板出厂默认烧录projecet_ST_APP工程,该工程是带boot功能的,默认选择的Debug工具是CMSIS-DAP Debugger工具,在Option->Debug->Setting->Flash Download->Programming Algorithm->Start中设置了起始地址,如果更换了Debug工具,起始地址会恢复默认,需要重新设置起始地址。

更新固件方式

  1. 使用Debug工具通过keil的Download下载,需要注意编译参数选择。
  2. 使用串口下载,通过USB数据线连接电脑,通过vollgoKit-update.exe工具升级

软件开发篇

1、进入低功耗

调用./radio/myRadio.c/myRadio_abort()函数,将射频模块进入低功耗模式,进入低功耗模式后,射频模块将不接收任何无线信号,只有当射频模块进入接收状态后,才能再次接收无线信号,具体测试参数见PAN3029_470-510MHz指标测试报告.pdf

void myRadio_abort(void)
{
    if (rf_handle == 0)
    {
        return;
    }
    RF_EXT_PA_TO_IDLE();
    // rf_deepsleep();
    rf_sleep();
}

2、射频模块进入接收状态

调用./radio/myRadio.c/myRadio_receiver()函数,将射频模块进入接收状态,进入接收状态后,射频模块将接收周围环境中的无线信号,并可以接收数据包。在接收状态或者发送过程不能重新调用该函数,发送需要等待发送完成才能再次调用该函数,不然会打断无线发送。接收到无线数据后,射频模块会通过IRQ引脚产生输出个信号,然后再./radio/myRadio.c/myRadio_process(void)函数中读取fifo中的数据包。

void myRadio_receiver(void)
{ 
    if (rf_handle == 0)
    {
        return;
    }
    RF_EXT_PA_TO_RX();
    if (rf_get_mode() == PAN3029_MODE_DEEP_SLEEP)
    {
        rf_deepsleep_wakeup();
        myRadio_setFrequency(rfFrequence);
        myRadio_setTxPower(rfTxPower);
        myRadio_setRfParams(rf_sf, rf_bw, rf_cr);
        myRadio_delay(10);
    }
    if (rf_get_mode() == PAN3029_MODE_SLEEP)
    {
        rf_sleep_wakeup();
        myRadio_delay(10);
    }
    rf_enter_continous_rx();
    rf_workProcess = RF_PRC_RX;
}

3、射频模块发送数据包

调用./radio/myRadio.c/myRadio_transmit(rfTxPacket_ts *packet)函数,将射频模块进入发送状态,进入发送状态后,射频模块将发送数据包,发送完成后才可以调用接收函数进入接收状态,发送完成后,射频模块会通过IRQ引脚产生输出个信号,然后再./radio/myRadio.c/myRadio_process(void)函数中读取发送完成状态。

void myRadio_transmit(rfTxPacket_ts *packet)
{
    if (rf_handle == 0)
    {
        return;
    }
    RF_EXT_PA_TO_TX();
    uint32_t getTxtime;
    if (rf_get_mode() == PAN3029_MODE_DEEP_SLEEP)
    {
        rf_deepsleep_wakeup();
        myRadio_setFrequency(rfFrequence);
        myRadio_setTxPower(rfTxPower);
        myRadio_setRfParams(rf_sf, rf_bw, rf_cr);
        myRadio_delay(10);
    }
    if (rf_get_mode() == PAN3029_MODE_SLEEP)
    {
        rf_sleep_wakeup();
        myRadio_delay(10);
    }
    
    if(rf_single_tx_data(packet->payload, packet->len, &packet->absTime) != OK)	
    {
    }
    else
    {
    }
    rf_workProcess = RF_PRC_TX;
}

4、射频初始化

调用./radio/myRadio.c/myRadio_init(int agr0, void *agr1_ptr)函数,将射频模块初始化,初始化完成后,射频模块将进入接收状态,该函数会初始化一个默认的参数,如果需要自定义参数,比如频率信道,发射功率,无线波特率等参数,可以调用相关函数接口重新设置,如果不需要自定义参数,也可以通过修改rf_set_default_para();中的默认参数:

初始化完成后就可以进入接收状态或者发送无线数据包了,具体使用方法可以参考示例代码。

void myRadio_init(int agr0, void *agr1_ptr)
{
    myRadio_gpio_init(myRadio_gpioCallback);
    
/**-------------------------radio init----------------------------------**/
    uint32_t ret = 0;
#ifdef SPI_SOFT_3LINE
    PAN3029_write_reg(REG_SYS_CTL, 0x03);
    PAN3029_write_reg(0x1A, 0x83);
#endif

	ret = rf_init();
	if(ret != OK)
	{
		// printf("  RF Init Fail");
		while(1);
	}

	rf_set_default_para();

    rf_set_dcdc_mode(regulatorMode);
/**-------------------------radio init end----------------------------------**/
    myRadio_delay(10);
    RF_EXT_PA_TO_IDLE();
    if ((rfRxCallBack )agr1_ptr)
    {
        rxCb = (rfRxCallBack )agr1_ptr;
    }
    rf_handle = 0xe5;
}

5、射频底层执行

调用./radio/myRadio.c/myRadio_process(void)函数,该函数需要放在主函数中不断判断检测是否有中断触发,然后根据中断标志来解析处理。状态处理可以直接在相应的位置处理,或者通过回调函数rxCb将结果返回上一层处理

void myRadio_process(void)
{
    rfRxPacket_ts rfRxPacket;
    if (rf_handle == 0)
    {
        return;
    }
    if (rf_ifq == false)
    {
        return;
    }
    rf_ifq = false;
    if (!((rf_workProcess == RF_PRC_TX) || (rf_workProcess == RF_PRC_RX)))
    {
        return;
    }

    uint8_t plhd_len;
    uint8_t irq = rf_get_irq();

    if(irq & REG_IRQ_RX_PLHD_DONE)
    {
        plhd_len = rf_get_plhd_len();
        rf_set_recv_flag(RADIO_FLAG_PLHDRXDONE);
        RxDoneParams.PlhdSize = rf_plhd_receive(RxDoneParams.PlhdPayload,plhd_len);
        //PAN3029_rst();//stop it

    }
    if(irq & REG_IRQ_RX_DONE)
    {
        RxDoneParams.Snr = rf_get_snr();
        RxDoneParams.Rssi = rf_get_rssi();
        rf_set_recv_flag(RADIO_FLAG_RXDONE);
        RxDoneParams.Size = rf_receive(RxDoneParams.Payload);
        rf_set_recv_flag(RADIO_FLAG_IDLE); 
        if (rxCb)
        {
            rfRxPacket.rssi = RxDoneParams.Rssi;
            rfRxPacket.len = RxDoneParams.Size;
            memcpy(rfRxPacket.payload, RxDoneParams.Payload, RxDoneParams.Size);
            rxCb(RX_STA_SECCESS, rfRxPacket);
        }
        
    }
    if(irq & REG_IRQ_CRC_ERR)
    {
        rf_set_recv_flag(RADIO_FLAG_RXERR);
        rf_clr_irq();

    }
    if(irq & REG_IRQ_RX_TIMEOUT)
    {
        rf_set_refresh();
        rf_set_recv_flag(RADIO_FLAG_RXTIMEOUT);
        rf_clr_irq();
        rf_set_recv_flag(RADIO_FLAG_IDLE); 
        RF_EXT_PA_TO_IDLE();
        if (rxCb)
        {
            rxCb(RX_STA_TIMEOUT, rfRxPacket);
        }
    }
    if(irq & REG_IRQ_TX_DONE)
    {
        rf_set_transmit_flag(RADIO_FLAG_TXDONE);
        rf_clr_irq();

        RF_EXT_PA_TO_IDLE();
        if (rxCb)
        {
            rxCb(TX_STA_SECCESS, rfRxPacket);
        }
    }
}

6、无线波特率设置

可以通过void myRadio_setBaudrate(uint32_t br)或者void myRadio_setRfParams(uint8_t sf, uint8_t bw, uint8_t cr)来设置。

版本更新

免责说明

1、本工程驱动软件只提供做演示项目使用,未经过大批量项目验证,客户需谨慎使用,如果使用在正式项目中引发的所有问题,本司概不负责。使用过程若发现任何问题,可及时与本司相关人员联系。
2、本工程所有文件可以用于商业性项目移植,无需向本司申请。