[toc]
软件开发移植,先看这里 跳转
## 基本说明 - 编程语言:C99 - 开发环境:MDK-ARM Standard Version: 5.14.0.0 - 芯片型号:AT32F413RCT7 或 STM32F103RCT6,这两个型号软硬件兼容 - 软件LIB版本:STM32F10x_StdPeriph_Lib_V3.5.0 - 射频驱动官方库版本:V0.7 - 烧录仿真接口:SWD - 烧录仿真器:J-Link 或 DAP - 文档编写日期:2024年5月14日 ## 已适配的无线模块 - VG4130SxxxN0S1系列 ## 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 | | | | ✓ | | 说明: - `✓`:表示必须连接 - `N`:表示可以根据实际需要选择是否连接 - `P`:表示根据SPI模式选择是否连接 - `X`:表示不需要连接 ## SPI驱动接口 - 固件已适配3线和4线SPI接口 - 支持SPI时钟频率范围:最大10MHz - 支持SPI时钟极性:低电平,空闲状态下SCK为低电平 - 支持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. 避免使用中心频率为射频芯片使用的晶体频率整数倍的,比如晶体频率为32MHz,就需要避免使用`448MHz`的中心频点 - SPI驱动调试 1. 首先保证SPI通讯正常,具体SPI时序需根据射频芯片要求设置,可通过示波器或者逻辑分析仪进行硬件分析 2. SPI通讯正常后,进一步调试查看寄存器操作,读写寄存器,若能正常操作,基本可判定移植成功了 3. 直观判断可以看射频初始化的时候`ret = rf_init();`这个返回值是否等于`OK` - 通讯距离 影响无线传输距离的因素 1. 无线电频谱,包括使用的无线频段和无线波特率,原则上无线波特率越低,无线信号传播距离越远,但是时间延迟也越大,由于PAN3029射频芯片使用的是扩频调制技术,其无线波特率主要有扩频因子、带宽、容错率三个参数控制,根据这个三个参数不同组合可以得到不同的无线波特率,可以通过计算器`磐启微电子PAN3029计算器.xlsx`计算得到最终的波特率 2. 发射功率,原则上发射功率越大,无线信号传播距离越远 3. 天线增益,不同增益的天线对无线信号的接收效果影响很大 4. 路径损耗,主要是包括无线使用的周围环境,比如楼宇、树木山峰遮挡 5. 其他的无线信号干扰 ## 硬件篇
1. 无线模组转接板插槽,带金手指,可以适配不同的模块转接板 1. 普通 LED 指示灯 1. 显示屏,显示工作状态以及工作使用参数 1. MCU 预留 I/O 口 1. 主板 MCU 复位按键 1. SWD 主板 MCU 程序下载调与调试接口 1. 供电电源 3 档开关,可以用于切换选择测试板的供电电源,切换到 BT 档, 测试板为底部的 3 节 5 号电池供电,切换到 USB 档,测试板为⑧的 Micro-B 座子 供电,打在中间档关闭供电 1. Micro-B USB 座子,可以用于测试板的供电;连接电脑可以做 TTL 转 USB 功 能,测试板内含 CP2102N 芯片 ## 编译软件工具KEIL篇 ### 编译参数选择
keil工程已经设置了4个选项: - `projecet_AT`:表示该工程的MCU型号选择的是雅特力AT32F413RCT7单片机,不带自定义boot功能,即不设置偏移地址 - `projecet_ST`:表示该工程的MCU型号选择的是ST意法半导体STM32F103RCT6单片机,不带自定义boot功能,即不设置偏移地址 - `projecet_AT_APP`:表示该工程的MCU型号选择的是雅特力AT32F413RCT7单片机,带自定义boot功能,设置偏移地址为`0x000C800` - `projecet_ST_APP`:表示该工程的MCU型号选择的是ST意法半导体STM32F103RCT6单片机,带自定义boot功能,设置偏移地址为`0x000C800` 模块演示板出厂默认烧录`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](http://git.cloudpeaks.cn/droplin/vollgoKit-update)工具升级 ## 软件开发篇
**软件功能框图**
软件开发主要就是涉及`射频模块驱动`,与硬件相关的主要就是SPI接口和一些辅助IO口(比如中断信号脚),这部分软件主要放在`./radio/myRadio_gpio.c`中。 中断信号是通过回调函数`RADIO_GPIO_CALLBACK`的方式从`./radio/myRadio_gpio.c`回调到`./radio/myRadio.c`中处理,回调函数的方式只是为了方便软件编写,用户可以直接把外部中断函数直接放在`./radio/myRadio.c`中处理。 ### 注意事项 - 4线spi接口的硬件和软件模拟方式切换 通过宏定义`SPI_HARD`来选择,具体见`./radio/myRadio_gpio.c/void myRadio_gpio_init(RADIO_GPIO_CALLBACK cb)` ### 1、进入低功耗 调用`./radio/myRadio.c/myRadio_abort()`函数,将射频模块进入低功耗模式,进入低功耗模式后,射频模块将不接收任何无线信号,只有当射频模块进入接收状态后,才能再次接收无线信号。 - 调用`rf_deepsleep();`可进入超低功耗模式,电流功耗400na左右,唤醒后需要重新初始化 - 调用`rf_sleep();`可进入低功耗模式,电流功耗1ua左右 ```c 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中的数据包。 ```c 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)`函数中读取发送完成状态。 ```c 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();`中的默认参数: - `./radio/myRadio.c/myRadio_setFrequency(uint32_t freq)`:设置射频模块工作频率 - `./radio/myRadio.c/myRadio_setTxPower(uint8_t power)`:设置射频模块发射功率 - `./radio/myRadio.c/myRadio_setRfParams(uint8_t sf, uint8_t bw, uint8_t cr)`:设置射频模块无线波特率,信道带宽,编码速率 初始化完成后就可以进入接收状态或者发送无线数据包了,具体使用方法可以参考示例代码。 ```c 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)`函数,该函数需要放在主函数中不断判断检测是否有中断触发(可以放在while循环中执行),然后根据中断标志来解析处理。状态处理可以直接在相应的位置处理,或者通过回调函数`rxCb`将结果返回上一层处理 - `REG_IRQ_RX_DONE`:表示接收到无线数据包 - `REG_IRQ_TX_DONE`:表示无线数据包发送成功 ```c 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)`来设置。 - `void myRadio_setBaudrate(uint32_t br)`:通过数组选择定义好的几组扩频因子、带宽、码率的组合即可 - `void myRadio_setRfParams(uint8_t sf, uint8_t bw, uint8_t cr)`:通过参数设置具体的扩频因子、带宽、码率 ## 版本更新 - V10 - 优化发射功率设置 ## 免责说明 1、本工程驱动软件只提供做演示项目使用,未经过大批量项目验证,客户需谨慎使用,如果使用在正式项目中引发的所有问题,本司概不负责。使用过程若发现任何问题,可及时与本司相关人员联系。 2、本工程所有文件可以用于商业性项目移植,无需向本司申请。