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 变量来选择主机发送还是从机接收。
声明:
本文采用
BY-NC-SA
协议进行授权,如无注明均为原创,转载请注明转自
走着的小站
本文地址: 基于stm32CubeMX控制LORA芯片SX1280 SPI通信
本文地址: 基于stm32CubeMX控制LORA芯片SX1280 SPI通信