提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、软硬件使用
- 二、官网固件支持包下载
- 三、SPI通讯
- 四、LoRa驱动移植步骤
- 1. 移植官方的LoRa驱动前需要明确LoRa芯片与主芯片的引脚接线:
- 2.双击打开STM32CubeMX,选择File—>New Project
- 3.搜索STM32l151芯片型号,点击Strat Project
- 4.选择System Core下的 SYS 选择 Debug—>Serial Write
- 5.选择System Core下的 RCC 选择 HSE—>CCR 和 LSE—>CCR
- 6.配置时钟树为(32MHz)
- 7.SPI配置,模式为全双工主站(Full-Duplex Master),分频(Prescale)为8,波特率Baud Rate 为4MBits/s(其波特率和时钟树的主时钟频率有关)。CPOL = Low.表示SCLK = 0时处于空闲态,所以有效状态就是SCLK处于高电平有效。CPHA = 1 Edge 表示数据采样是在第一个边沿,数据发送是在第二个边沿。其通讯模式为 Mode:0。
- 8.GPIO配置 PA3和PB8为LED灯。
- 9.点击Project Manager—>Project,需要自己命名项目名称和设置项目路径(尽量不要出现汉字)
- 10.勾选Code Generator 下的每次都重新生成一个外设的 /.c/ .h文件 和 只复制必要的库文件。
- 11.点击GENERATE CODE,生成工程文件。
- 12.点击 Open Project.
- 13.生成如下工程,先点击编译(首次编译时间较长请耐心等待)![在这里插入图片描述](https://img-blog.csdnimg.cn/e8a1752c0f6b456ab9c5392fff454a00.png)编译后无警告无错误即为工程新建成功。
- 14.先把Keil5最小化打开工程文件所在的文件夹位置
- 15.新建一个LoRa的文件夹,并且把从官网下载的固件加压下的radio和platform拷贝在此文件夹下。
- 16.此时需要把platform—>sx12xxEiger—>spi.c和spi.h删掉。因为会与STM32CubeMx自动生成的spi.c和spi.h冲突。
- 17.点击Manage Project Items —>Groups新建连个文件夹LoRa/radio和LoRa/platform并添加相应的/.c文件,添加完毕点击OK。
- 18.添加/.c对应的/.h文件。
- 19.修改platform.h,在MDK的project的Options选项卡中的C/C++的Preprocessor Symbols Define中添加PLATFORM=SX12xxEiger。
- 20.将sx12xxEiger.c 下的BoardInit()函数内容删掉或屏蔽掉。
- 21.sx12xxEiger.h的屏蔽如图所示。
- 22.更改较多的是sx1276-Hal.c文件,整体代码如下。
- 23.更改sx1276-Hal.h 下的#define GET_TICK_COUNT( ) ( TickCounter ) 替换为 HAL_GetTick()。
- 24.点击编译,如果错误为:0,就说明工程移植成功了。
前言
最近想实现长距离无线通讯,使用LoRa模块,其芯片采用的SX1278SEMTECH射频集成芯片SX127X的射频模块,这是一款高性能物联网无线收发器.为了方便今后的温故与学习,写一篇小文章记录一下。
一、软硬件使用
- Keil5
- STM32CubeMx
- STM32L151C8 + LoRa模块(SX1278)
二、官网固件支持包下载
SEMTECH官网的链接 :https://www.semtech.com/
三、SPI通讯
LoRa芯片与MCU通过SPI进行通信。SPI(Serial Peripheral Interface Bus),是由摩托罗拉公司开发的高速全双工同步串行通信协议。SPI支持一主多从,这点类似于I2C,但是又与I2C选通从设备的方式不同,I2C是通过发送从机地址来选通从机,而SPI则是通过拉低连接到从机的NSS引脚对从机进行选通的。
SPI一般应用由四个引脚组成(一主一从):
- NSS (CS) :选择信号,由主机发出,一般是低电位有效
- SCLK:串行时钟,由主机发出
- MOSI:主机输出从机输入信号,由主机发出
- MISO:主机输入从机输出信号,由从机发出
SPI主要特点有:
- 全双工
- 提供频率可编程时钟
- 写冲突保护,总线竞争保护
- 发送结束中断标志
- 可以当作主机或从机工作等
以上是对LoRa通讯的简单描述,主要是进行移植详细步骤的说明。
四、LoRa驱动移植步骤
1. 移植官方的LoRa驱动前需要明确LoRa芯片与主芯片的引脚接线:
- DIO0和DIO1为lora模块的输出引脚,连接的单片机引脚需要对应配置为输入模式进行检测。
- NSS,SCK,MISO.MOSI为STM32与LoRa模块的SPI接口
- DIO0——PB11
- DIO1——PB10
- SPI_SCK——PA4
- SPI_MISO——PA5
- SPI_MOSI——PA6
2.双击打开STM32CubeMX,选择File—>New Project
3.搜索STM32l151芯片型号,点击Strat Project
4.选择System Core下的 SYS 选择 Debug—>Serial Write
5.选择System Core下的 RCC 选择 HSE—>CCR 和 LSE—>CCR
6.配置时钟树为(32MHz)
7.SPI配置,模式为全双工主站(Full-Duplex Master),分频(Prescale)为8,波特率Baud Rate 为4MBits/s(其波特率和时钟树的主时钟频率有关)。CPOL = Low.表示SCLK = 0时处于空闲态,所以有效状态就是SCLK处于高电平有效。CPHA = 1 Edge 表示数据采样是在第一个边沿,数据发送是在第二个边沿。其通讯模式为 Mode:0。
8.GPIO配置 PA3和PB8为LED灯。
9.点击Project Manager—>Project,需要自己命名项目名称和设置项目路径(尽量不要出现汉字)
10.勾选Code Generator 下的每次都重新生成一个外设的 /.c/ .h文件 和 只复制必要的库文件。
11.点击GENERATE CODE,生成工程文件。
12.点击 Open Project.
13.生成如下工程,先点击编译(首次编译时间较长请耐心等待)
编译后无警告无错误即为工程新建成功。
14.先把Keil5最小化打开工程文件所在的文件夹位置
15.新建一个LoRa的文件夹,并且把从官网下载的固件加压下的radio和platform拷贝在此文件夹下。
16.此时需要把platform—>sx12xxEiger—>spi.c和spi.h删掉。因为会与STM32CubeMx自动生成的spi.c和spi.h冲突。
17.点击Manage Project Items —>Groups新建连个文件夹LoRa/radio和LoRa/platform并添加相应的/.c文件,添加完毕点击OK。
18.添加/.c对应的/.h文件。
19.修改platform.h,在MDK的project的Options选项卡中的C/C++的Preprocessor Symbols Define中添加PLATFORM=SX12xxEiger。
20.将sx12xxEiger.c 下的BoardInit()函数内容删掉或屏蔽掉。
21.sx12xxEiger.h的屏蔽如图所示。
22.更改较多的是sx1276-Hal.c文件,整体代码如下。
/*
* THE FOLLOWING FIRMWARE IS PROVIDED: (1) "AS IS" WITH NO WARRANTY; AND
* (2)TO ENABLE ACCESS TO CODING INFORMATION TO GUIDE AND FACILITATE CUSTOMER.
* CONSEQUENTLY, SEMTECH SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR
* CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT
* OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION
* CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* Copyright (C) SEMTECH S.A.
*/
/*!
* \file sx1276-Hal.c
* \brief SX1276 Hardware Abstraction Layer
*
* \version 2.0.B2
* \date Nov 21 2012
* \author Miguel Luis
*
* Last modified by Miguel Luis on Jun 19 2013
*/
#include <stdint.h>
#include <stdbool.h>
#include "platform.h"
#if defined( USE_SX1276_RADIO )
#include "ioe.h"
#include "spi.h"
#include "../../radio/sx1276-Hal.h"
void SX1276InitIo( void )
{
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);
// GPIO_InitTypeDef GPIO_InitStructure;
//#if defined( STM32F4XX ) || defined( STM32F2XX ) || defined( STM32F429_439xx )
// RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB |
// RCC_AHB1Periph_GPIOG, ENABLE );
//#else
// RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB |
// RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE );
//#endif
//#if defined( STM32F4XX ) || defined( STM32F2XX ) || defined( STM32F429_439xx )
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
// GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
// GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
//#else
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//#endif
//
// // Configure NSS as output
// GPIO_WriteBit( NSS_IOPORT, NSS_PIN, Bit_SET );
// GPIO_InitStructure.GPIO_Pin = NSS_PIN;
// GPIO_Init( NSS_IOPORT, &GPIO_InitStructure );
// // Configure radio DIO as inputs
//#if defined( STM32F4XX ) || defined( STM32F2XX ) || defined( STM32F429_439xx )
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
//#else
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
//#endif
// // Configure DIO0
// GPIO_InitStructure.GPIO_Pin = DIO0_PIN;
// GPIO_Init( DIO0_IOPORT, &GPIO_InitStructure );
//
// // Configure DIO1
// GPIO_InitStructure.GPIO_Pin = DIO1_PIN;
// GPIO_Init( DIO1_IOPORT, &GPIO_InitStructure );
//
// // Configure DIO2
// GPIO_InitStructure.GPIO_Pin = DIO2_PIN;
// GPIO_Init( DIO2_IOPORT, &GPIO_InitStructure );
//
// // REAMARK: DIO3/4/5 configured are connected to IO expander
// // Configure DIO3 as input
//
// // Configure DIO4 as input
//
// // Configure DIO5 as input
}
void SX1276SetReset( uint8_t state )
{
// GPIO_InitTypeDef GPIO_InitStructure;
// if( state == RADIO_RESET_ON )
// {
// // Set RESET pin to 0
// GPIO_WriteBit( RESET_IOPORT, RESET_PIN, Bit_RESET );
// // Configure RESET as output
//#if defined( STM32F4XX ) || defined( STM32F2XX ) || defined( STM32F429_439xx )
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
// GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
//#else
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
//#endif
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
// GPIO_InitStructure.GPIO_Pin = RESET_PIN;
// GPIO_Init( RESET_IOPORT, &GPIO_InitStructure );
// }
// else
// {
//#if FPGA == 0
// // Configure RESET as input
//#if defined( STM32F4XX ) || defined( STM32F2XX ) || defined( STM32F429_439xx )
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
//#else
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
//#endif
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
// GPIO_InitStructure.GPIO_Pin = RESET_PIN;
// GPIO_Init( RESET_IOPORT, &GPIO_InitStructure );
//#else
// GPIO_WriteBit( RESET_IOPORT, RESET_PIN, Bit_RESET );
//#endif
// }
}
uint8_t SpiInOut(uint8_t outData)
{
uint8_t RxData;
HAL_SPI_TransmitReceive(&hspi1,&outData,&RxData,1,1000);
return RxData;
}
void SX1276Write( uint8_t addr, uint8_t data )
{
SX1276WriteBuffer( addr, &data, 1 );
}
void SX1276Read( uint8_t addr, uint8_t *data )
{
SX1276ReadBuffer( addr, data, 1 );
}
void SX1276WriteBuffer( uint8_t addr, uint8_t *buffer, uint8_t size )
{
uint8_t i;
//NSS = 0;
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);
SpiInOut( addr | 0x80 );
for( i = 0; i < size; i++ )
{
SpiInOut( buffer[i] );
}
//NSS = 1;
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);
}
void SX1276ReadBuffer( uint8_t addr, uint8_t *buffer, uint8_t size )
{
uint8_t i;
//NSS = 0;
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);
SpiInOut( addr & 0x7F );
for( i = 0; i < size; i++ )
{
buffer[i] = SpiInOut( 0 );
}
//NSS = 1;
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);
}
void SX1276WriteFifo( uint8_t *buffer, uint8_t size )
{
SX1276WriteBuffer( 0, buffer, size );
}
void SX1276ReadFifo( uint8_t *buffer, uint8_t size )
{
SX1276ReadBuffer( 0, buffer, size );
}
inline uint8_t SX1276ReadDio0( void )
{
return HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_11);
}
inline uint8_t SX1276ReadDio1( void )
{
return HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_10);
}
23.更改sx1276-Hal.h 下的#define GET_TICK_COUNT( ) ( TickCounter ) 替换为 HAL_GetTick()。
24.点击编译,如果错误为:0,就说明工程移植成功了。
以上就是LoRa官方固件移植的全部步骤。
接下来就可以进行LoRa点对点相关实验的进行了。