dropLin 9aacf9997a 修复了一些bug | 2 mesiacov pred | |
---|---|---|
STM32F10x_FWLib | 7 mesiacov pred | |
app | 7 mesiacov pred | |
core | 7 mesiacov pred | |
keil_v5 | 7 mesiacov pred | |
peripheral | 7 mesiacov pred | |
project | 3 mesiacov pred | |
radio | 2 mesiacov pred | |
.gitignore | 7 mesiacov pred | |
README.md | 2 mesiacov pred | |
keilkilll.bat | 7 mesiacov pred |
[toc]
软件开发移植,先看这里 跳转
VG239xS240N0M1系列、VG239xS240X0M1系列
序号 | 模块IO | MCU IO | 转接板排针 | 模块功能 | 必需 | 备注 |
---|---|---|---|---|---|---|
14 | ANT | ✓ | ||||
13 | GND | G | ✓ | |||
5 | NSS | PA4 | NSS | NSS | ✓ | 从机SPI片选脚 |
4 | SCK | PA5 | SCK | SCK | ✓ | 主机SPI时钟输出 |
6 | VCC | VCC | ✓ | |||
3 | MOSI | PA7 | DO | MOSI | ✓ | 主机SPI数据发送,从机SPI数据接收 |
2 | MISO | PA6 | DI | MISO | ✓ | 主机SPI数据接收,从机SPI数据发送,3线SPI可以不接 |
1 | RST | PC5 | RST | ✓ | ||
11 | BUSY | PA2 | BUSY | ✓ | ||
10 | DIO1 | PB0 | IO0 | 收发状态中断信号输出 | ✓ | 输出高电平,外部可做上升沿触发检测 |
8 | DIO2 | PB1 | IO2 | N | ||
8 | DIO3 | PB1 | IO3 | N | ||
4 | TXEN\NC | PB11 | TE | 内部PA使能 | P | 高电平使能,VG239xS240N0M1系列为NC |
3 | RXEN\NC | PB10 | RE | 内部LNA使能 | P | 高电平使能,VG239xS240N0M1系列为NC |
7 | GND | G | ✓ | |||
9 | NC | G | X |
说明:
✓
:表示必须连接N
:表示可以根据实际需要选择是否连接P
:表示根据SPI模式选择是否连接X
:表示不需要连接..\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
| └──...
448MHz
的中心频点radio\sx1280-hal.c\void SX1280HalWaitOnBusy( void )
这个函数的busy脚的状态,如果无法往下执行,则表示spi操作失败,需要检查硬件连接或者spi的时序是否正确。LoRa Calculator.exe
计算得到最终的波特率
Micro-B USB 座子,可以用于测试板的供电;连接电脑可以做 TTL 转 USB 功 能,测试板内含 CP2102N 芯片
keil工程已经设置了4个选项:
projecet_AT
:表示该工程的MCU型号选择的是雅特力AT32F413RCT7单片机,不带自定义boot功能,即不设置偏移地址projecet_ST
:表示该工程的MCU型号选择的是ST意法半导体STM32F103RCT6单片机,不带自定义boot功能,即不设置偏移地址projecet_AT_1W
:表示该工程的MCU型号选择的是雅特力AT32F413RCT7单片机,不带自定义boot功能,即不设置偏移地址,适配1W大功率模块projecet_ST_1W
:表示该工程的MCU型号选择的是ST意法半导体STM32F103RCT6单片机,不带自定义boot功能,即不设置偏移地址,适配1W大功率模块projecet_AT_APP
:表示该工程的MCU型号选择的是雅特力AT32F413RCT7单片机,带自定义boot功能,设置偏移地址为0x000C800
projecet_ST_APP
:表示该工程的MCU型号选择的是ST意法半导体STM32F103RCT6单片机,带自定义boot功能,设置偏移地址为0x000C800
projecet_AT_1W_APP
:表示该工程的MCU型号选择的是雅特力AT32F413RCT7单片机,带自定义boot功能,设置偏移地址为0x000C800
,适配1W大功率模块projecet_ST_1W_APP
:表示该工程的MCU型号选择的是ST意法半导体STM32F103RCT6单片机,带自定义boot功能,设置偏移地址为0x000C800
,适配1W大功率模块模块演示板出厂默认烧录projecet_ST_APP
工程,该工程是带boot功能的,默认选择的Debug工具是CMSIS-DAP Debugger
工具,在Option->Debug->Setting->Flash Download->Programming Algorithm->Start
中设置了起始地址,如果更换了Debug工具,起始地址会恢复默认,需要重新设置起始地址。
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)
中断入口函数直接拿来用,注册回调的方式只是为了方便调用。
SPI_HARD
来选择,具体见./radio/myRadio_gpio.c/void myRadio_gpio_init(RADIO_GPIO_CALLBACK cb)
RF_EXT_PA_TE
和RF_EXT_PA_RE
,如果使用的是小功率模块,这两个引脚可以不用控制myRadio_setTxPower(power);
设置,再去发送数据。调用./radio/myRadio.c/myRadio_abort()
函数,将射频模块进入低功耗模式,进入低功耗模式后,射频模块将不接收任何无线信号,只有当射频模块进入接收状态后,才能再次接收无线信号。
void myRadio_abort(void)
{
if (rf_handle == 0)
{
return;
}
RF_EXT_PA_TO_IDLE();
SleepParams_t SleepParams;
SleepParams.DataBufferRetention = 1;
SleepParams.DataRamRetention = 1;
SleepParams.InstructionRamRetention = 1;
SleepParams.WakeUpRTC = 0;
// Radio.SetSleep( SleepParams );
Radio.SetStandby( STDBY_RC );
}
调用./radio/myRadio.c/myRadio_receiver()
函数,将射频模块进入接收状态,进入接收状态后,射频模块将接收周围环境中的无线信号,并可以接收数据包。在接收状态或者发送过程不能重新调用该函数,发送需要等待发送完成才能再次调用该函数,不然会打断无线发送。接收到无线数据后,射频模块会通过DIO1
引脚产生输出个信号,然后在./radio/myRadio.c/myRadio_process(void)
函数中读取fifo中的数据包。
void myRadio_receiver(void)
{
if (rf_handle == 0)
{
return;
}
RF_EXT_PA_TO_RX();
TickTime_t TickTime ={ RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE };
Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
Radio.SetRx( TickTime );
}
调用./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();
if (Radio.GetOpMode() == MODE_SLEEP)
{
myRadio_delay(1);
}
TickTime_t TickTime ={ RX_TIMEOUT_TICK_SIZE, TX_TIMEOUT_VALUE };
Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE );
packet->len = 64;
if(rfModuleMode == RF_MM_MODE_GFSK)
{
packetParams.Params.Gfsk.PayloadLength = packet->len;
}
else if (rfModuleMode == RF_MM_MODE_LORA)
{
packetParams.Params.LoRa.PayloadLength = packet->len;
}
else if (rfModuleMode == RF_MM_MODE_FLRC)
{
packetParams.Params.Flrc.PayloadLength = packet->len;
}
else
{
packetParams.Params.Flrc.PayloadLength = packet->len;
}
Radio.SetPacketParams( &packetParams );
Radio.SendPayload( packet->payload, packet->len, TickTime);
}
调用./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/void myRadio_setBaudrate(uint32_t br)
:设置射频模块无线波特率
初始化完成后就可以进入接收状态或者发送无线数据包了,具体使用方法可以参考示例代码。
void myRadio_init(int agr0, void *agr1_ptr)
{
myRadio_gpio_init(myRadio_gpioCallback);
/**-------------------------radio init----------------------------------**/
uint16_t ver = 0;
myRadio_delay(1000);
Radio.Init( &Callbacks );
Radio.SetRegulatorMode( USE_DCDC ); // Can also be set in LDO mode but consume more power
{
ver = Radio.GetFirmwareVersion();//获取芯片信息 0xA9B5 可用于测试SPI的读写情况
}
if (rfModuleMode == RF_MM_MODE_BLE)
{
modulationParams.PacketType = PACKET_TYPE_BLE;
modulationParams.Params.Ble.BitrateBandwidth = GFS_BLE_BR_1_000_BW_1_2;
modulationParams.Params.Ble.ModulationIndex = GFS_BLE_MOD_IND_0_50;
modulationParams.Params.Ble.ModulationShaping = RADIO_MOD_SHAPING_BT_0_5;
packetParams.PacketType = PACKET_TYPE_BLE;
packetParams.Params.Ble.BlePacketType = BLE_EYELONG_1_0;
packetParams.Params.Ble.ConnectionState = BLE_ADVERTISER;
packetParams.Params.Ble.CrcField = BLE_CRC_3B;
packetParams.Params.Ble.Whitening = RADIO_WHITENING_ON;
}
else if(rfModuleMode == RF_MM_MODE_LORA)
{
modulationParams.PacketType = PACKET_TYPE_LORA;
modulationParams.Params.LoRa.SpreadingFactor = LORA_SF5;//
modulationParams.Params.LoRa.Bandwidth = LORA_BW_0400;
modulationParams.Params.LoRa.CodingRate = LORA_CR_LI_4_5;
packetParams.PacketType = PACKET_TYPE_LORA;
packetParams.Params.LoRa.PreambleLength = 12;
packetParams.Params.LoRa.HeaderType = LORA_PACKET_VARIABLE_LENGTH;
packetParams.Params.LoRa.PayloadLength = BUFFER_SIZE;
packetParams.Params.LoRa.CrcMode = LORA_CRC_ON;
packetParams.Params.LoRa.InvertIQ = LORA_IQ_NORMAL;
}
else if(rfModuleMode == RF_MM_MODE_GFSK)
{
modulationParams.PacketType = PACKET_TYPE_GFSK;
modulationParams.Params.Gfsk.BitrateBandwidth = GFS_BLE_BR_0_125_BW_0_3;
modulationParams.Params.Gfsk.ModulationIndex = GFS_BLE_MOD_IND_1_00;
modulationParams.Params.Gfsk.ModulationShaping = RADIO_MOD_SHAPING_BT_1_0;
packetParams.PacketType = PACKET_TYPE_GFSK;
packetParams.Params.Gfsk.PreambleLength = PREAMBLE_LENGTH_24_BITS;
packetParams.Params.Gfsk.SyncWordLength = GFS_SYNCWORD_LENGTH_5_BYTE;
packetParams.Params.Gfsk.SyncWordMatch = RADIO_RX_MATCH_SYNCWORD_1_2_3;
packetParams.Params.Gfsk.HeaderType = RADIO_PACKET_FIXED_LENGTH;
packetParams.Params.Gfsk.PayloadLength = BUFFER_SIZE;
packetParams.Params.Gfsk.CrcLength = RADIO_CRC_OFF;
packetParams.Params.Gfsk.Whitening = RADIO_WHITENING_OFF;
// packetParams.PacketType = PACKET_TYPE_GFSK;
// packetParams.Params.Gfsk.PreambleLength = PREAMBLE_LENGTH_32_BITS;
// packetParams.Params.Gfsk.SyncWordLength = GFS_SYNCWORD_LENGTH_5_BYTE;
// packetParams.Params.Gfsk.SyncWordMatch = RADIO_RX_MATCH_SYNCWORD_1;
// packetParams.Params.Gfsk.HeaderType = RADIO_PACKET_VARIABLE_LENGTH;
// packetParams.Params.Gfsk.PayloadLength = BUFFER_SIZE;
// packetParams.Params.Gfsk.CrcLength = RADIO_CRC_3_BYTES;
// packetParams.Params.Gfsk.Whitening = RADIO_WHITENING_ON;
}
else if(rfModuleMode == RF_MM_MODE_FLRC)
{
modulationParams.PacketType = PACKET_TYPE_FLRC;
modulationParams.Params.Flrc.BitrateBandwidth = FLRC_BR_0_325_BW_0_3;
modulationParams.Params.Flrc.CodingRate = FLRC_CR_1_2;
modulationParams.Params.Flrc.ModulationShaping = RADIO_MOD_SHAPING_BT_1_0;
packetParams.PacketType = PACKET_TYPE_FLRC;
packetParams.Params.Flrc.PreambleLength = PREAMBLE_LENGTH_32_BITS;
packetParams.Params.Flrc.SyncWordLength = FLRC_SYNCWORD_LENGTH_4_BYTE;
packetParams.Params.Flrc.SyncWordMatch = RADIO_RX_MATCH_SYNCWORD_1;
packetParams.Params.Flrc.HeaderType = RADIO_PACKET_VARIABLE_LENGTH;
packetParams.Params.Flrc.PayloadLength = BUFFER_SIZE;
packetParams.Params.Flrc.CrcLength = RADIO_CRC_3_BYTES;
packetParams.Params.Flrc.Whitening = RADIO_WHITENING_OFF;
}
else
{
modulationParams.PacketType = PACKET_TYPE_FLRC;
modulationParams.Params.Flrc.BitrateBandwidth = FLRC_BR_0_325_BW_0_3;
modulationParams.Params.Flrc.CodingRate = FLRC_CR_1_2;
modulationParams.Params.Flrc.ModulationShaping = RADIO_MOD_SHAPING_BT_1_0;
packetParams.PacketType = PACKET_TYPE_FLRC;
packetParams.Params.Flrc.PreambleLength = PREAMBLE_LENGTH_32_BITS;
packetParams.Params.Flrc.SyncWordLength = FLRC_SYNCWORD_LENGTH_4_BYTE;
packetParams.Params.Flrc.SyncWordMatch = RADIO_RX_MATCH_SYNCWORD_1;
packetParams.Params.Flrc.HeaderType = RADIO_PACKET_VARIABLE_LENGTH;
packetParams.Params.Flrc.PayloadLength = BUFFER_SIZE;
packetParams.Params.Flrc.CrcLength = RADIO_CRC_3_BYTES;
packetParams.Params.Flrc.Whitening = RADIO_WHITENING_OFF;
}
// #elif defined( MODE_GFSK )
// #elif defined( MODE_LORA )
// #elif defined( MODE_FLRC )
// #else
// #error "Please select the mode of operation for the Ping Ping demo"
// #endif
Radio.SetStandby( STDBY_RC );
Radio.SetPacketType( modulationParams.PacketType );
Radio.SetModulationParams( &modulationParams );
Radio.SetPacketParams( &packetParams );
Radio.SetRfFrequency( RF_FREQUENCY );//频点设置
Radio.SetBufferBaseAddresses( 0x00, 0x00 );
Radio.SetTxParams( TX_OUTPUT_POWER, RADIO_RAMP_02_US );//功率设置
// Radio.SetInterruptMode();
Radio.SetPollingMode();
if(rfModuleMode == RF_MM_MODE_GFSK)
{
//接收灵敏度测试
Radio.SetSyncWord( 1, ( uint8_t[] ){ 0xDD, 0xA0, 0x96, 0x69, 0xDD } );
}
if(rfModuleMode == RF_MM_MODE_BLE)
{
// only used in GENERIC and BLE mode
Radio.WriteRegister(0x9c7, 0x55 );
Radio.WriteRegister(0x9c8, 0x55 );
Radio.WriteRegister(0x9c9, 0x55 );
//Radio.WriteRegister( 0x9c5, 0x33 );
Radio.SetBleAdvertizerAccessAddress( );
Radio.SetWhiteningSeed( 0x33 );
ble_header_adv.Fields.length = PINGPONGSIZE + 2;
ble_header_adv.Fields.pduType = 2;
}
AppState = APP_LOWPOWER;
/**-------------------------radio init end----------------------------------**/
RF_EXT_PA_TO_IDLE();
if ((rfRxCallBack )agr1_ptr)
{
rxCb = (rfRxCallBack )agr1_ptr;
}
rf_handle = 0xe5;
}
调用./radio/myRadio.c/myRadio_process(void)
函数,该函数需要放在主函数中不断判断检测是否有中断触发(可以放在while循环中执行),然后根据中断标志来解析处理。状态处理可以直接在相应的位置处理,或者通过回调函数rxCb
将结果返回上一层处理
void myRadio_process(void)
{
if (rf_handle == 0)
{
return;
}
SX1280ProcessIrqs();
}
在初始化的时候已经通过回调注册了几个回调函数
RadioEvents.TxDone = OnTxDone;
RadioEvents.RxDone = OnRxDone;
RadioEvents.TxTimeout = OnTxTimeout;
RadioEvents.RxTimeout = OnRxTimeout;
RadioEvents.RxError = OnRxError;
当有相关状态触发时,会通过回调函数将状态回调到./radio/myRadio.c
中对应的函数中执行。
可以通过void myRadio_setBaudrate(uint32_t br)
来设置。
void myRadio_setBaudrate(uint32_t br)
:通过数组选择定义好的几组扩频因子、带宽、码率的组合即可V11 2024年6月24日
V12 2024年11月15日
1、本工程驱动软件只提供做演示项目使用,未经过大批量项目验证,客户需谨慎使用,如果使用在正式项目中引发的所有问题,本司概不负责。使用过程若发现任何问题,可及时与本司相关人员联系。 2、本工程所有文件可以用于商业性项目移植,无需向本司申请。