embedded 原文存档
基于stm32CubeMX控制LORA芯片SX1280 SPI通信
1,资源
sx1280芯片官网:https://www.semtech.cn/products/wireless-rf/lora-connect/sx1280
下载后的压缩包名为:SX1280_DemoApp_V1_0.zip
解压后在:如下目录下找到SX1280_DemoApp\SMTC_Drivers\sx1280-driver-c

其中。radio.h是抽象头文件,里面都是函数指针,这里面的函数就是官方手册的实际调用函数。
sx1280-hal.c h是spi实现的读写函数,属于底层。(最要这里面修改我们自己的板子)
sx1280.c h是sx1280芯片的业务逻辑函数,不用动。
2,开始施工
1,stm32cbumx里面正常
我新建了比sx1280-hal还底层的文件mybase.c h,主要实现SpiInOut,SpiIn,GpioWrite,GpioRead
2,硬件驱动
mybase.c
`#include "mybase.h" void SpiInit(void) { // RadioSpiHandle = hspi2; } void GpioWrite( GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, uint32_t value ) { HAL_GPIO_WritePin( GPIOx, GPIO_Pin , ( GPIO_PinState ) value ); } uint32_t GpioRead( GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin ) { return HAL_GPIO_ReadPin( GPIOx, GPIO_Pin ); } void HAL_GPIO_EXTI_Callback( uint16_t GPIO_Pin ) { // GpioLaunchIrqHandler( GPIO_Pin ); } void SpiInOut( uint8_t *txBuffer, uint8_t *rxBuffer, uint16_t size ) { #ifdef STM32L4XX_FAMILY HAL_SPIEx_FlushRxFifo( &hspi2 ); // Comment For STM32L0XX and STM32L1XX Int間ration, uncomment for STM32L4XX Int間ration #endif #ifdef USE_DMA blockingDmaFlag = true; HAL_SPI_TransmitReceive_DMA( &SpiHandle, txBuffer, rxBuffer, size ); WAIT_FOR_BLOCKING_FLAG #else HAL_SPI_TransmitReceive( &hspi2, txBuffer, rxBuffer, size, HAL_MAX_DELAY ); #endif } void SpiIn( uint8_t *txBuffer, uint16_t size ) { #ifdef USE_DMA blockingDmaFlag = true; HAL_SPI_Transmit_DMA( &SpiHandle, txBuffer, size ); WAIT_FOR_BLOCKING_FLAG #else HAL_SPI_Transmit( &hspi2, txBuffer, size, HAL_MAX_DELAY ); #endif }`
mybase.h
`#ifndef __MYBASE_H__ #define __MYBASE_H__ #include <stdint.h> #include <stdbool.h> #include <math.h> #include "main.h" #include "gpio.h" #include "spi.h" #include "sx1280.h" /***** * 说明:这个函数实现sx1280官方库的底层硬件函数 * */ extern SPI_HandleTypeDef hspi2; #define RADIO_nRESET_PORT SX1280_RST_GPIO_Port #define RADIO_nRESET_PIN SX1280_RST_Pin #define RADIO_NSS_PORT SPI2_NSS_GPIO_Port #define RADIO_NSS_PIN SPI2_NSS_Pin #define RADIO_DIO1_GPIO_Port SX1280_DIO1_GPIO_Port #define RADIO_DIO1_Pin SX1280_DIO1_Pin #define RADIO_BUSY_PORT SX1280_BUSY_GPIO_Port #define RADIO_BUSY_PIN SX1280_BUSY_Pin void GpioWrite( GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, uint32_t value ); uint32_t GpioRead( GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin ); void SpiInit( void ); void SpiInOut( uint8_t *txBuffer, uint8_t *rxBuffer, uint16_t size ); void SpiIn( uint8_t *txBuffer, uint16_t size ); #endif`
main.h
`#define SX1280_RST_Pin GPIO_PIN_7 #define SX1280_RST_GPIO_Port GPIOA #define SX1280_RXEN_Pin GPIO_PIN_4 #define SX1280_RXEN_GPIO_Port GPIOC #define SX1280_TXEN_Pin GPIO_PIN_5 #define SX1280_TXEN_GPIO_Port GPIOC #define SX1280_BUSY_Pin GPIO_PIN_2 #define SX1280_BUSY_GPIO_Port GPIOB #define SX1280_DIO1_Pin GPIO_PIN_10 #define SX1280_DIO1_GPIO_Port GPIOB`
3,上层APP
my1280app.c
`#include "my1280app.h" const uint8_t PingMsg[] = "PING"; const uint8_t PongMsg[] = "PONG"; RadioCallbacks_t Callbacks = { &OnTxDone, // txDone &OnRxDone, // rxDone NULL, // syncWordDone NULL, // headerDone &OnTxTimeout, // txTimeout &OnRxTimeout, // rxTimeout &OnRxError, // rxError NULL, // rangingDone &OnCadDone, // cadDone }; uint8_t BufferSize = BUFFER_SIZE; uint8_t Buffer[BUFFER_SIZE]; uint16_t RxIrqMask = IRQ_RX_DONE | IRQ_RX_TX_TIMEOUT; uint16_t TxIrqMask = IRQ_TX_DONE | IRQ_RX_TX_TIMEOUT; AppStates_t AppState = APP_LOWPOWER; PacketParams_t packetParams; PacketStatus_t packetStatus; ModulationParams_t modulationParams; bool isMaster = true; // bool isMaster = false; void LoRa_init() { HAL_GPIO_WritePin(SX1280_RST_GPIO_Port, SX1280_RST_Pin, GPIO_PIN_RESET); HAL_Delay(100); HAL_GPIO_WritePin(SX1280_RST_GPIO_Port, SX1280_RST_Pin, GPIO_PIN_SET); printf( "Radio firmware version 0x%x\r\n", SX1280GetFirmwareVersion() ); if(isMaster==true) { printf( "Master LORA mode\n\r" ); } else { printf( "Slaver LORA mode\n\r" ); } Radio.Init( &Callbacks ); Radio.SetRegulatorMode( USE_DCDC ); modulationParams.PacketType = PACKET_TYPE_LORA; modulationParams.Params.LoRa.SpreadingFactor = LORA_SF12; modulationParams.Params.LoRa.Bandwidth = LORA_BW_1600; modulationParams.Params.LoRa.CodingRate = LORA_CR_LI_4_7; 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; Radio.SetStandby( STDBY_RC ); switch(modulationParams.Params.LoRa.SpreadingFactor){ case LORA_SF5: case LORA_SF6: Radio.WriteRegister(0x0925,0x1E); break; case LORA_SF7: case LORA_SF8: Radio.WriteRegister(0x0925,0x37); break; case LORA_SF9: case LORA_SF10: case LORA_SF11: case LORA_SF12: Radio.WriteRegister(0x0925,0x32); break; } 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 ); //SX1280SetPollingMode( ); SX1281SetInterruptMode(); if(isMaster==true) { //发送 HAL_GPIO_WritePin(SX1280_TXEN_GPIO_Port,SX1280_TXEN_Pin,GPIO_PIN_SET); Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); Radio.SendPayload((uint8_t*)"123456",6, ( TickTime_t ){ RX_TIMEOUT_TICK_SIZE, TX_TIMEOUT_VALUE }); } else { HAL_GPIO_WritePin(SX1280_RXEN_GPIO_Port,SX1280_RXEN_Pin,GPIO_PIN_SET); Radio.SetDioIrqParams( RxIrqMask, RxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); //Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE } ); Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, 0xFFFF } );//RX_TIMEOUT_VALUE } AppState = APP_LOWPOWER; } void LoRa_process() { SX1280ProcessIrqs( ); HAL_Delay(1000); } void OnTxDone( void ) { AppState = APP_TX; printf( "<>>>>>>>>OnTxDone\n\r" ); Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); Radio.SendPayload((uint8_t*)"123456",6, ( TickTime_t ){ RX_TIMEOUT_TICK_SIZE, TX_TIMEOUT_VALUE }); } void OnRxDone( void ) { AppState = APP_RX; printf( "<>>>>>>>>OnRxDone\n\r" ); BufferSize = 0; Radio.GetPayload( Buffer, &BufferSize, BUFFER_SIZE ); Buffer[BufferSize+1] = 0; printf("size = %d ,%s",BufferSize,Buffer); // printf("OnRxDone\r\n",Buffer,BufferSize); //Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE } ); } void OnTxTimeout( void ) { AppState = APP_TX_TIMEOUT; printf( "<>>>>>>>>TXE\n\r" ); Radio.SetDioIrqParams( TxIrqMask, TxIrqMask, IRQ_RADIO_NONE, IRQ_RADIO_NONE ); Radio.SendPayload((uint8_t*)"12345",5, ( TickTime_t ){ RX_TIMEOUT_TICK_SIZE, TX_TIMEOUT_VALUE }); } void OnRxTimeout( void ) { AppState = APP_RX_TIMEOUT; printf( "<>>>>>>>>OnRxTimeout\n\r" ); //Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE } ); Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, 0xFFFF } ); } void OnRxError(int error) { AppState = APP_RX_ERROR; printf( "RXE<>>>>>>>>error code=%d\n\r",error); Radio.SetRx( ( TickTime_t ) { RX_TIMEOUT_TICK_SIZE, RX_TIMEOUT_VALUE } ); } void OnCadDone( bool channelActivityDetected ) { printf( "<>>OnCadDone CAD code=%d\n\r",channelActivityDetected); }`
my1280app.h
`#ifndef __MY1280APP_H #define __MY1280APP_H #include "sx1280-hal.h" #include "sx1280.h" #include "radio.h" /*! * Select mode of operation for the Ping Ping application */ //#define MODE_BLE #define MODE_LORA //#define MODE_GFSK //#define MODE_FLRC #define RF_BL_ADV_CHANNEL_38 2426000000 // Hz #define RF_BL_ADV_CHANNEL_0 2404000000 // Hz /*! * \brief Defines the nominal frequency */ #define RF_FREQUENCY RF_BL_ADV_CHANNEL_0 // Hz /*! * \brief Defines the output power in dBm * * \remark The range of the output power is [-18..+13] dBm */ #define TX_OUTPUT_POWER 13 /*! * \brief Defines the buffer size, i.e. the payload size */ #define BUFFER_SIZE 6 /*! * \brief Number of tick size steps for tx timeout */ #define TX_TIMEOUT_VALUE 10000 // ms /*! * \brief Number of tick size steps for rx timeout */ #define RX_TIMEOUT_VALUE 1000 // ms /*! * \brief Size of ticks (used for Tx and Rx timeout) */ #define RX_TIMEOUT_TICK_SIZE RADIO_TICK_SIZE_1000_US /*! * \brief Defines the size of the token defining message type in the payload */ #define PINGPONGSIZE 4 /*! * \brief Defines the states of the application */ typedef enum { APP_LOWPOWER, APP_RX, APP_RX_TIMEOUT, APP_RX_ERROR, APP_TX, APP_TX_TIMEOUT, }AppStates_t; /*! * \brief Function to be executed on Radio Tx Done event */ void OnTxDone( void ); /*! * \brief Function to be executed on Radio Rx Done event */ void OnRxDone( void ); /*! * \brief Function executed on Radio Tx Timeout event */ void OnTxTimeout( void ); /*! * \brief Function executed on Radio Rx Timeout event */ void OnRxTimeout( void ); /*! * \brief Function executed on Radio Rx Error event */ void OnRxError(int error); void OnCadDone( bool channelActivityDetected ); void LoRa_init(void); void LoRa_process(void); #endif`
3,控制逻辑梳理
1,上电要手动RST复位sx1280芯片,否则不正常(低电平有效)
2,TXEN和RXEN,在使用前要打开(高电平有效)(只开一个)
3,每次接收和每次发送,都要新设置SetDioIrqParams中断源
4,控制:
可以循环读取寄存器SX1280GetIrqStatus判断收发数据
可以使用EXTI GPIO中断读取
5,在app文件里面,使用 isMaster 变量来选择主机发送还是从机接收。