[toc]
软件开发移植,先看这里
跳转
## 基本说明
- 编程语言:C99
- 开发环境:MDK-ARM Standard Version: 5.14.0.0
- 芯片型号:AT32F413RCT7 或 STM32F103RCT6,这两个型号软硬件兼容
- 软件LIB版本:STM32F10x_StdPeriph_Lib_V3.5.0
- 射频驱动官方库版本:
- 烧录仿真接口:SWD
- 烧录仿真器:J-Link 或 DAP
- 文档编写日期:2024年5月14日
## 已适配的无线模块
- VGdd79SxxxN0S1系列
- VG237xSxxxN0Sx系列
- VGdd79SxxxX0Mx系列
- VG237xSxxxX0Mx系列
## IO口定义
- VGdd79SxxxN0S1系列、VG237xSxxxN0Sx系列
| 序号 | 模块IO | MCU IO| 转接板排针 | 模块功能 | 必需 | 备注 |
|:----:|:----:|:----:|:----:|:----:|:----:|----|
| 1 | RST | PC5 | RST | | ✓ | |
| 2 | MISO | PA6 | DI | MISO | ✓ | 主机SPI数据接收,从机SPI数据发送,3线SPI可以不接 |
| 3 | MOSI | PA7 | DO | MOSI | ✓ | 主机SPI数据发送,从机SPI数据接收 |
| 4 | SCK | PA5 | SCK | SCK | ✓ | 主机SPI时钟输出 |
| 5 | NSS | PA4 | NSS | NSS | ✓ | 从机SPI片选脚 |
| 6 | VCC | | VCC | | ✓ | |
| 7 | GND | | G | | ✓ | |
| 8 | DIO3\NC | PB1 | IO3 | | N | VG237xSxxxN0SA系列为有源晶体模块,DIO3脚用于内部晶体控制 |
| 9 | GND | | G | | ✓ | |
| 10| DIO1 | PB0 | IO0 | 收发状态中断信号输出 | ✓ | 输出高电平,外部可做上升沿触发检测 |
| 11| BUSY | PA2 | BUSY | | ✓ | |
| 12| GND | | G | | ✓ | |
| 13| GND | | G | | ✓ | |
| 14| ANT | | | | ✓ | |
- VGdd79SxxxX0Mx系列、VG237xSxxxX0Mx系列
| 序号 | 模块IO | MCU IO| 转接板排针 | 模块功能 | 必需 | 备注 |
|:----:|:----:|:----:|:----:|:----:|:----:|----|
| 1 | GND | | G | | ✓ | |
| 2 | GND | | G | | ✓ | |
| 3 | RXEN | PB10 | RE | 内部LNA使能 | ✓ | 高电平使能 |
| 4 | TXEN | PB11 | TE | 内部PA使能 | ✓ | 高电平使能 |
| 5 | DIO3 | PA2 | IO3 | | N | |
| 6 | DIO1 | PB0 | IO0 | 收发状态中断信号输出 | ✓ | 输出高电平,外部可做上升沿触发检测 |
| 7 | GND | | G | | ✓ | |
| 8 | VCC | | VCC | | ✓ | |
| 9 | BUSY | PC5 | IO2 | | ✓ | |
| 10| RST | PB1 | IO1 | | ✓ | |
| 11 | MISO | PA6 | DI | MISO | ✓ | 主机SPI数据接收,从机SPI数据发送,3线SPI可以不接 |
| 12 | MOSI | PA7 | DO | MOSI | ✓ | 主机SPI数据发送,从机SPI数据接收 |
| 13 | SCK | PA5 | SCK | SCK | ✓ | 主机SPI时钟输出 |
| 14 | NSS | PA4 | NSS | NSS | ✓ | 从机SPI片选脚 |
| 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. 一定要根据规格书规定的供电电压选择合适电压,同时还要关注射频发送时的电流问题,防止有些电源的电流驱动能力不足导致压降,电压过低会影响射频信号的辐射,最终影响通讯距离,也有可能导致模块无法正常工作。
- 无线频率
1. 避免使用中心频率为射频芯片使用的晶体频率整数倍的,比如晶体频率为32MHz,就需要避免使用`448MHz`的中心频点
- SPI驱动调试
1. 首先保证SPI通讯正常,具体SPI时序需根据射频芯片要求设置,可通过示波器或者逻辑分析仪进行硬件分析
2. SPI通讯正常后,进一步调试查看寄存器操作,读写寄存器,若能正常操作,基本可判定移植成功了
3. 直观判断可以看寄存器操作`radio\sx126x-board.c\void SX126xWaitOnBusy( void )`这个函数的busy脚的状态,如果无法往下执行,则表示spi操作失败,需要检查硬件连接或者spi的时序是否正确。
- 通讯距离
影响无线传输距离的因素
1. 无线电频谱,包括使用的无线频段和无线波特率,原则上无线波特率越低,无线信号传播距离越远,但是时间延迟也越大,由于模块的射频芯片使用的是扩频调制技术,其无线波特率主要有扩频因子、带宽、容错率三个参数控制,根据这个三个参数不同组合可以得到不同的无线波特率,可以通过计算器`LoRa Calculator.exe`计算得到最终的波特率
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)工具升级,升级固件文件:`keil_v5\Listings\*.bin`
## 软件开发篇
**软件功能框图**
软件开发主要就是涉及`射频模块驱动`,与硬件相关的主要就是SPI接口和一些辅助IO口(比如中断信号脚),这部分软件主要放在`./radio/myRadio_gpio.c`中。
中断信号是通过回调函数`RADIO_GPIO_CALLBACK`的方式从`./radio/myRadio_gpio.c`回调到`./radio/myRadio.c`中处理,回调函数的方式只是为了方便软件编写,用户可以直接把外部中断函数直接放在`./radio/myRadio.c`中处理。
所有的中断入口函数放在`.\project\stm32f10x_it.c`,在需要的地方通过回调注册的方式回调中断状态,比如注册回调PB0的中断函数回调:
```c
void rfIrq_callback(uint8_t status, uint32_t param)
{
}
myIrqCallback_rfIrq.thisCb = rfIrq_callback;
EXTILINE0_callbackRegiste(&myIrqCallback_rfIrq);
```
也可以把`void EXTI0_IRQHandler(void)`中断入口函数直接拿来用,注册回调的方式只是为了方便调用。
### 注意事项
- 4线spi接口的硬件和软件模拟方式切换
通过宏定义`SPI_HARD`来选择,具体见`./radio/myRadio_gpio.c/void myRadio_gpio_init(RADIO_GPIO_CALLBACK cb)`
- 大功率(VGdd79SxxxX0Mx系列、VG237xSxxxX0Mx系列)小功率(VGdd79SxxxN0S1系列、VG237xSxxxN0Sx系列)模块操作区别
本项目工程对这两种模块做了兼容,在移植时软件和硬件操作都需要注意区别,
- 引脚控制:大功率模块需增加两个控制脚,`RF_SX126x_EXT_PA_RE`和`RF_SX126x_EXT_PA_TE`,如果使用的是小功率模块,这两个引脚可以不用控制
- 软件:大功率模块的最大发射功率为15dbm,小功率的没有限制。大功率模块初始化完成后需要调用`myRadio_setTxPower(power);`设置,再去发送数据。
- 射频芯片IO使用:DIO2默认用于射频天线开关控制,软件调用`SX126xSetDio2AsRfSwitchCtrl( true );`设置即可。如果是有源晶体模块,需要设置如下:
```c
SX126xSetStandby( STDBY_XOSC );
OperatingMode = MODE_STDBY_XOSC;
SX126xSetDio3AsTcxoCtrl( TCXO_CTRL_3_3V, 1 << 6 ); // convert from ms to SX126x time base
calibParam.Value = 0x7F;
SX126xCalibrate( calibParam );
```
### 1、进入低功耗
调用`./radio/myRadio.c/myRadio_abort()`函数,将射频模块进入低功耗模式,进入低功耗模式后,射频模块将不接收任何无线信号,只有当射频模块进入接收状态后,才能再次接收无线信号。
```c
void myRadio_abort(void)
{
if (rf_handle == 0)
{
return;
}
RF_SX126x_EXT_PA_TO_IDLE();
State = LOWPOWER;
rf_workProcess = RF_PRC_SLEEP;
Radio.Sleep();
}
```
### 2、射频模块进入接收状态
调用`./radio/myRadio.c/myRadio_receiver()`函数,将射频模块进入接收状态,进入接收状态后,射频模块将接收周围环境中的无线信号,并可以接收数据包。在接收状态或者发送过程不能重新调用该函数,发送需要等待发送完成才能再次调用该函数,不然会打断无线发送。接收到无线数据后,射频模块会通过`DIO1`引脚产生输出个信号,然后在`./radio/myRadio.c/myRadio_process(void)`函数中读取fifo中的数据包。
休眠唤醒已在底层实现`.\radio\sx126x.c\void SX126xCheckDeviceReady( void )`,每次操作`SX126xWriteCommand(...)`或者`SX126xReadCommand(...)`都会调用`SX126xCheckDeviceReady`,休眠状态下可以直接调用`myRadio_receiver`进入接收状态。
```c
void myRadio_receiver(void)
{
if (rf_handle == 0)
{
return;
}
RF_SX126x_EXT_PA_TO_RX();
Radio.Rx( rf_rxTimeout );
rf_workProcess = RF_PRC_RX;
}
```
### 3、射频模块发送数据包
调用`./radio/myRadio.c/myRadio_transmit(rfTxPacket_ts *packet)`函数,将射频模块进入发送状态,进入发送状态后,射频模块将发送数据包,发送完成后才可以调用接收函数进入接收状态,发送完成后,射频模块会通过`IRQ`引脚产生输出个信号,然后在`./radio/myRadio.c/myRadio_process(void)`函数中读取发送完成状态。
休眠唤醒已在底层实现`.\radio\sx126x.c\void SX126xCheckDeviceReady( void )`,每次操作`SX126xWriteCommand(...)`或者`SX126xReadCommand(...)`都会调用`SX126xCheckDeviceReady`。休眠状态下可以直接调用`myRadio_transmit`发送无线数据
```c
void myRadio_transmit(rfTxPacket_ts *packet)
{
if (rf_handle == 0)
{
return;
}
RF_SX126x_EXT_PA_TO_TX();
rf_workProcess = RF_PRC_TX;
Radio.Send( packet->payload, packet->len );
}
```
### 4、射频初始化
调用`./radio/myRadio.c/myRadio_init(int agr0, void *agr1_ptr)`函数,将射频模块初始化,初始化完成后,射频模块将进入接收状态,该函数会初始化一个默认的参数,如果需要自定义参数,比如频率信道,发射功率,无线波特率等参数,可以调用相关函数接口重新设置:
- `./radio/myRadio.c/myRadio_setFrequency(uint32_t freq)`:设置射频模块工作频率
- `./radio/myRadio.c/myRadio_setTxPower(uint8_t power)`:设置射频模块发射功率
- `./radio/myRadio.c/void myRadio_setBaudrate(uint32_t br)`:设置射频模块无线波特率
有源晶体参数设置:
```c
if ((chipType >= DVTP_VG2379S433N0SA) && (chipType <= DVTP_VGdd79S915N0SA))
{
SX126xEnableTxco(true);
}
```
用户可以直接调用`SX126xEnableTxco(true);`设置即可。
初始化完成后就可以进入接收状态或者发送无线数据包了,具体使用方法可以参考示例代码。
```c
myRadio_gpio_init(myRadio_gpioCallback);
/**-------------------------radio init----------------------------------**/
// Radio initialization
RadioEvents.TxDone = OnTxDone;
RadioEvents.RxDone = OnRxDone;
RadioEvents.TxTimeout = OnTxTimeout;
RadioEvents.RxTimeout = OnRxTimeout;
RadioEvents.RxError = OnRxError;
if ((chipType >= DVTP_VG2379S433N0SA) && (chipType <= DVTP_VGdd79S915N0SA))
{
SX126xEnableTxco(true);
}
Radio.Init( &RadioEvents );
Radio.SetChannel( RF_FREQUENCY );
// #if defined( USE_MODEM_LORA )
if (getLoRaSta())
{
Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
LORA_SPREADING_FACTOR, LORA_CODINGRATE,
LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
true, 0, 0, LORA_IQ_INVERSION_ON, 3000 );
Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR,
LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH,
LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON,
0, true, 0, 0, LORA_IQ_INVERSION_ON, false );
}
// #elif defined( USE_MODEM_FSK )
else
{
Radio.SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0,
FSK_DATARATE, 0,
FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON,
true, 0, 0, 0, 3000 );
Radio.SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE,
0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH,
0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, false,
0, 0,false, false);
// #else
}
// #error "Please define a frequency band in the compiler options."
// #endif
RF_SX126x_EXT_PA_TO_IDLE();
/**-------------------------radio init end----------------------------------**/
if ((rfRxCallBack )agr1_ptr)
{
rxCb = (rfRxCallBack )agr1_ptr;
}
rf_handle = 0xe5;
```
### 5、射频底层执行
调用`./radio/myRadio.c/myRadio_process(void)`函数,该函数需要放在主函数中不断判断检测是否有中断触发(可以放在while循环中执行),然后根据中断标志来解析处理。状态处理可以直接在相应的位置处理,或者通过回调函数`rxCb`将结果返回上一层处理
```c
void myRadio_process(void)
{
if (rf_handle == 0)
{
return;
}
Radio.IrqProcess();
}
```
在初始化的时候已经通过回调注册了几个回调函数
```c
RadioEvents.TxDone = OnTxDone;
RadioEvents.RxDone = OnRxDone;
RadioEvents.TxTimeout = OnTxTimeout;
RadioEvents.RxTimeout = OnRxTimeout;
RadioEvents.RxError = OnRxError;
```
当有相关状态触发时,会通过回调函数将状态回调到`./radio/myRadio.c`中对应的函数中执行。
### 6、无线波特率设置
可以通过`void myRadio_setBaudrate(uint32_t br)`来设置。
- `void myRadio_setBaudrate(uint32_t br)`:通过数组选择定义好的几组扩频因子、带宽、码率的组合即可
## 版本更新
- V12
2024年6月21日
- 更新界面显示
- V13
2024年6月21日
- 增加信噪比显示
- V14
2024年6月25日
- 优化myRadio_init中的初始化
## 免责说明
1、本工程驱动软件只提供做演示项目使用,未经过大批量项目验证,客户需谨慎使用,如果使用在正式项目中引发的所有问题,本司概不负责。使用过程若发现任何问题,可及时与本司相关人员联系。
2、本工程所有文件可以用于商业性项目移植,无需向本司申请。