适用于升特的SX1262、SX1268、llcc68射频芯片以及相关射频模块

dropLin 9289661b55 优化myRadio_init中的初始化 3 сар өмнө
STM32F10x_FWLib 71c63c8477 first commit 5 сар өмнө
app 3fb2cc0e6f V13,增加信噪比显示 3 сар өмнө
core 71c63c8477 first commit 5 сар өмнө
keil_v5 9289661b55 优化myRadio_init中的初始化 3 сар өмнө
peripheral d117279c34 V12,更新界面显示 3 сар өмнө
project 9289661b55 优化myRadio_init中的初始化 3 сар өмнө
radio 9289661b55 优化myRadio_init中的初始化 3 сар өмнө
.gitignore 71c63c8477 first commit 5 сар өмнө
README.md 9289661b55 优化myRadio_init中的初始化 3 сар өмнө
keilkilll.bat 71c63c8477 first commit 5 сар өмнө

README.md

[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. 无线模组转接板插槽,带金手指,可以适配不同的模块转接板
  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_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工具升级,升级固件文件: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的中断函数回调:

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_RERF_SX126x_EXT_PA_TE,如果使用的是小功率模块,这两个引脚可以不用控制
    • 软件:大功率模块的最大发射功率为15dbm,小功率的没有限制。大功率模块初始化完成后需要调用myRadio_setTxPower(power);设置,再去发送数据。
  • 射频芯片IO使用:DIO2默认用于射频天线开关控制,软件调用SX126xSetDio2AsRfSwitchCtrl( true );设置即可。如果是有源晶体模块,需要设置如下:

    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()函数,将射频模块进入低功耗模式,进入低功耗模式后,射频模块将不接收任何无线信号,只有当射频模块进入接收状态后,才能再次接收无线信号。

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进入接收状态。

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发送无线数据

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):设置射频模块无线波特率

有源晶体参数设置:

if ((chipType >= DVTP_VG2379S433N0SA) && (chipType <= DVTP_VGdd79S915N0SA))
{
    SX126xEnableTxco(true);
}

用户可以直接调用SX126xEnableTxco(true);设置即可。 初始化完成后就可以进入接收状态或者发送无线数据包了,具体使用方法可以参考示例代码。

    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将结果返回上一层处理

void myRadio_process(void)
{
    if (rf_handle == 0)
    {
        return;
    }
    Radio.IrqProcess();
}

在初始化的时候已经通过回调注册了几个回调函数

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、本工程所有文件可以用于商业性项目移植,无需向本司申请。