4
STM32F407的SPI1外设可以提供高达84MHz的时钟控制,可以应用到绝大部分的SPI项目中,因为在实际应用中,像W5500模块,SX1278 LORA模块,都不需要用到这么高的时钟,一般是0.5MHz左右的速率就够了,再快就反应不过来,SPI1在256分频下的波形如下:
- uint8_t SPI1_Read_Write_Byte(uint8_t txdata)
- {
- while ((SPI1->SR & SPI_FLAG_TXE) == 0);
- SPI1->DR = txdata;
- while ((SPI1->SR & SPI_FLAG_RXNE) == 0);
- return SPI1->DR;
- }
- while(1)
- {
- SPI1_Read_Write_Byte(0xab);
- Delay_ms(1);
- }
复制代码
然后是SX1278驱动的移植:
- typedef struct sLoRaSettings
- {
- uint32_t RFFrequency;
- int8_t Power;
- uint8_t SignalBw;
- uint8_t SpreadingFactor;
- uint8_t ErrorCoding;
- bool CrcOn;
- bool ImplicitHeaderOn;
- bool RxSingleOn;
- bool FreqHopOn;
- uint8_t HopPeriod;
- uint32_t TxPacketTimeout;
- uint32_t RxPacketTimeout;
- uint8_t PayloadLength;
- }tLoRaSettings;
- tLoRaSettings LoRaSettings =
- {
- 400000000,
- 20,
- 8, // BW [0:7.8kHz, 1:10.4kHz, 2:15.6kHz, 3:20.8kHz, 4:31.2kHz, 5:41.6kHz, 6: 62.5kHz, 7:125kHz, 8:250kHz, 9:500kHz, other: Reserved]
- // 432MHZ~434MHZ
- 11, // SF [6:64, 7:128, 8:256, 9:512, 10:1024, 11:2048, 12:4096 chips]
- //
- 1, // [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
- true, // CRC[0: OFF, 1: ON]
- false, // [0: OFF, 1: ON]
- 0, // [0: Continuous, 1 Single]
- 0, // FreqHopOn[0: OFF, 1: ON]
- 4, // HopPeriod
- 100000, //
- 1000000, //
- 128, //
- };
- struct _SX1276
- {
- uint8_t InitOK;
- uint8_t Busy;
- uint8_t RxMode;
- uint8_t TxMode;
- }xLORA;
- void RA02_GPIO_Init(void)
- {
- GPIO_InitTypeDef gpio_init_struct;
- __HAL_RCC_GPIOB_CLK_ENABLE();
- gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;
- gpio_init_struct.Pull = GPIO_PULLUP;
- gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
-
- gpio_init_struct.Pin = LORA_NSS_PIN;
- HAL_GPIO_Init(LORA_NSS_GPIO , &gpio_init_struct);
-
- gpio_init_struct.Pin = LORA_SPI_RESET_PIN;
- HAL_GPIO_Init(LORA_SPI_RESET_GPIO , &gpio_init_struct);
- }
- void SX1276_Reset(void)
- {
- LORA_SPI_RESET_GPIO ->BSRR |= LORA_SPI_RESET_PIN << 16;
- Delay_ms (1);
-
- LORA_SPI_RESET_GPIO ->BSRR |= LORA_SPI_RESET_PIN;
- Delay_ms (6);
- }
- void SX1276Write( uint8_t addr, uint8_t *buffer, uint8_t size )
- {
- int i = 0;
- LORA_NSS_LOW;
- SPI1_Read_Write_Byte( addr | 0x80 );
- for(i = 0 ; i < size ; i++)
- {
- SPI1_Read_Write_Byte( buffer[i] );
- }
- LORA_NSS_HIGH;
- }
- void SX1276Read(uint8_t addr, uint8_t *buffer, uint8_t size)
- {
- int i = 0;
- LORA_NSS_LOW;
- SPI1_Read_Write_Byte( addr & 0x7F );
-
- for(i = 0; i < size; i++ )
- {
- buffer[i] = SPI1_Read_Write_Byte(0);
- }
- LORA_NSS_HIGH;
- }
- uint8_t regTemp;
- void SX1276_SetOpMode( uint8_t opMode )
- {
- SX1276Read( 0x01, ®Temp, 1 );
- printf("SX1276_SetOpMode read 0x01 regTemp = 0x%x\n" , regTemp);
- regTemp &= 0xF8;
- regTemp |= (uint8_t)opMode ;
- printf("SX1276_SetOpMode write 0x01 regTemp = 0x%x\n" , regTemp);
- SX1276Write( 0x01, ®Temp , 1 );
- SX1276Read( 0x01, ®Temp, 1 );
- printf("SX1276_SetOpMode read 0x01 regTemp = 0x%x\n" , regTemp);
- }
- void SX1276LoRaSetRFFrequency(uint32_t freq)
- {
- uint8_t F[3];
- freq = ( uint32_t )( ( double )freq / ( double )61.03515625f );
- F[0] = ( uint8_t )( ( freq >> 16 ) & 0xFF );
- F[1] = ( uint8_t )( ( freq >> 8 ) & 0xFF );
- F[2] = ( uint8_t )( freq & 0xFF );
- printf("SX1276LoRaSetRFFrequency write 0x06 F = 0x%x 0x%x 0x%x\n" , F[0] , F[1] , F[2]);
- SX1276Write(0x06 , F , 3);
- SX1276Read(0x06 , F , 3);
- printf("SX1276LoRaSetRFFrequency read 0x06 F = 0x%x 0x%x 0x%x\n" , F[0] , F[1] , F[2]);
- }
- void SX1276LoRaSetErrorCoding( uint8_t value )
- {
- SX1276Read( 0x1D, ®Temp , 1 );
- regTemp = ( regTemp & 0xF1 ) | ( value << 1 );
- SX1276Write( 0x1D, ®Temp ,1 );
- }
- void SX1276LoRaSetSpreadingFactor( uint8_t factor )
- {
- if( factor > 12 ) factor = 12;
- if( factor < 6 ) factor = 6;
-
- SX1276Read (0x31, ®Temp ,1);
- if( factor == 6 )
- regTemp = (regTemp & 0xF8) | 5;
- else
- regTemp = (regTemp & 0xF8) | 3;
- SX1276Write (0x31, ®Temp , 1);
- SX1276Read ( 0x1E, ®Temp , 1);
- regTemp = (regTemp & 0x0F) | (factor << 4);
- SX1276Write (0x1E, ®Temp , 1);
- }
- void SX1276LoRaSetPacketCrcOn( bool enable )
- {
- SX1276Read( REG_LR_MODEMCONFIG2, ®Temp ,1 );
- regTemp = ( regTemp & 0xFB ) | ( enable << 2);
- SX1276Write( REG_LR_MODEMCONFIG2, ®Temp , 1);
- }
- void SX1276LoRaSetSignalBandwidth(uint8_t bw)
- {
- SX1276Read( 0x1D, ®Temp , 1 );
- regTemp = ( regTemp & 0x0F ) | ( bw << 4 );
- SX1276Write( 0x1D, ®Temp , 1);
- //LoRaSettings.SignalBw = bw;
- }
- void SX1276LoRaSetImplicitHeaderOn( bool enable )
- {
- SX1276Read( 0x1D, ®Temp ,1 );
- regTemp = ( regTemp & 0xFE) | ( enable );
- SX1276Write(0x1D, ®Temp ,1 );
- }
- void SX1276LoRaSetLowDatarateOptimize( bool enable )
- {
- SX1276Read( REG_LR_MODEMCONFIG3, ®Temp, 1 );
- regTemp = ( regTemp & 0xF7 ) | ( enable << 3 );
- SX1276Write( REG_LR_MODEMCONFIG3, ®Temp,1 );
- }
- void SX1276LoRaSetSymbTimeout( uint16_t value )
- {
- uint8_t reg[2];
- SX1276Read( 0x1E, reg, 2 );
- reg[0] = ( reg[0] & 0xFC ) | ( ( value >> 8 ) & ~0xFC );
- reg[1] = value & 0xFF;
- SX1276Write( 0x1E, reg, 2);
- }
- void SX1276LoRaSetPAOutput( uint8_t outputPin )
- {
- SX1276Read( REG_LR_PACONFIG, ®Temp ,1 );
- regTemp = (regTemp & 0x7F ) | outputPin;
- SX1276Write(REG_LR_PACONFIG, ®Temp, 1 );
- }
- void Lora_RxMode()
- {
- if(xLORA.InitOK == 0)
- {
- printf("LORA\n");
- return;
- }
- SX1276_SetOpMode( RFLR_OPMODE_STANDBY );
- regTemp = 0;
- SX1276Write( REG_LR_HOPPERIOD, ®Temp , 1);
-
- regTemp = RFLR_IRQFLAGS_RXTIMEOUT |
- //RFLR_IRQFLAGS_RXDONE |
- //RFLR_IRQFLAGS_PAYLOADCRCERROR |
- RFLR_IRQFLAGS_VALIDHEADER |
- RFLR_IRQFLAGS_TXDONE |
- RFLR_IRQFLAGS_CADDONE |
- RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL|
- RFLR_IRQFLAGS_CADDETECTED;
- SX1276Write( REG_LR_IRQFLAGSMASK, ®Temp ,1 );
- regTemp = RFLR_DIOMAPPING1_DIO0_00 | RFLR_DIOMAPPING1_DIO1_00 | RFLR_DIOMAPPING1_DIO2_00 | RFLR_DIOMAPPING1_DIO3_00;
- SX1276Write ( 0x40, ®Temp ,1);
- //SX1276LR->RegFifoAddrPtr = SX1276LR->RegFifoRxBaseAddr;
- //sx1276_SpiWriteByte( REG_LR_FIFOADDRPTR, SX1276LR->RegFifoAddrPtr );
-
- regTemp = 0xFF;
- SX1276Write(REG_LR_IRQFLAGS , ®Temp , 1);
- SX1276_SetOpMode( RFLR_OPMODE_RECEIVER );
- xLORA.RxMode =1;
- }
- void SX1276_Init(uint32_t fre , uint8_t bw)
- {
- xLORA.InitOK = 0;
- LoRaSettings.RFFrequency = fre * 1000 * 1000;
- LoRaSettings.SpreadingFactor = 11;
- LoRaSettings.SignalBw = bw;
- SX1276_Reset();
- SX1276Read(0x06, ®Temp ,1);
- while(regTemp != 0x6C)
- {
- printf("SX1276_Init error.\n");
- Delay_ms(300);
- }
-
- SX1276_SetOpMode(RFLR_OPMODE_SLEEP);
- SX1276Read(0x01, ®Temp , 1);
- printf("read 0x01 regTemp = 0x%x\n" , regTemp);
- regTemp |= 0x80 ;
- SX1276Write( 0x01, ®Temp , 1);
- printf("write 0x01 regTemp = 0x%x\n" , regTemp);
- SX1276Read (0x01, ®Temp , 1);
- printf("read 0x01 regTemp = 0x%x\n" , regTemp);
-
- regTemp = RFLR_LNA_GAIN_G1;
- printf("write 0x%x regTemp = 0x%x\n" , REG_LR_LNA , regTemp);
- SX1276Write ( REG_LR_LNA , ®Temp , 1);
- SX1276Read (REG_LR_LNA, ®Temp , 1);
- printf("read 0x%x regTemp = 0x%x\n" , REG_LR_LNA , regTemp);
-
- SX1276LoRaSetRFFrequency(LoRaSettings.RFFrequency);
- SX1276LoRaSetSpreadingFactor(LoRaSettings.SpreadingFactor);
- SX1276LoRaSetErrorCoding(LoRaSettings.ErrorCoding);
- SX1276LoRaSetPacketCrcOn(LoRaSettings.CrcOn);
- SX1276LoRaSetSignalBandwidth(LoRaSettings.SignalBw);
- SX1276LoRaSetImplicitHeaderOn(LoRaSettings.ImplicitHeaderOn );
- SX1276LoRaSetSymbTimeout(0x3FF);
-
- SX1276Write( 0x22, &LoRaSettings.PayloadLength , 1 );
- SX1276LoRaSetLowDatarateOptimize( true );
- SX1276LoRaSetPAOutput( RFLR_PACONFIG_PASELECT_PABOOST );
- regTemp = 0x87;
- SX1276Write(REG_LR_PADAC , ®Temp , 1);
- regTemp = 0x8F;
- SX1276Write(REG_LR_PACONFIG , ®Temp , 1);
- //SX1276Read (0x26, ®Temp , 1);
- //regTemp = (regTemp & 0xF7) | ( 1<<3);
- //SX1276Write (0x26, ®Temp, 1);
- regTemp = 0xFF;
- SX1276Write(REG_LR_IRQFLAGS ,®Temp, 1);
- xLORA.InitOK = 1;
- printf("SX1276_Init OK.\n");
- Lora_RxMode();
- printf("SX1276 RxMode.\n");
- }
复制代码
非常简单,直接参考例程可,初始化打印序列如图:
然后,LORA模块收发是需要检测DIO0状态的,无论是发送端还是接收端,输入方式都是上升沿事件,因此可以用外部中断检测实现,也是非常简单:
- #define RF_BUFFER_SIZE 256
- static uint8_t RxSize;
- static uint8_t RxBuffer[RF_BUFFER_SIZE];
- void RA02_DIO0_IRQHandler(void)
- {
- __HAL_GPIO_EXTI_CLEAR_IT(RA02_DIO0_PIN);
-
- printf("LORA_DIO0_HANDLER xLORA.TxMode = %d xLORA.RxMode = %d\n" , xLORA.TxMode , xLORA.RxMode);
- if(xLORA.RxMode == 1)
- {
- regTemp = 0xFF;
- SX1276Write( 0x12, ®Temp ,1 );
- if( LoRaSettings.ImplicitHeaderOn == true )
- RxSize = LoRaSettings.PayloadLength ;
- else
- SX1276Read( REG_LR_NBRXBYTES, &RxSize, 1 );
-
- SX1276Read( REG_LR_FIFORXCURRENTADDR, ®Temp ,1);
- SX1276Write( REG_LR_FIFOADDRPTR, ®Temp ,1 );
- SX1276Read(0, RxBuffer, RxSize );
-
- printf("RxSize %d RxBuffer: %s\r" , RxSize , RxBuffer);
- }
- }
复制代码
我这边将DIO0引脚接到PF9上,PF9接了一个板载的LED灯,可以直接通过观察灯的状态来检测DIO0状态:
运行效果:
0
|
|
|
|