LORA-B1 官方LORA驱动移植
基于前面针对LORA-B1开发板基础教程,本节终于可以到正式的对lora的操作。我们制作的教程力求每一步都可以方便快速的进行验证,这样即便出现问题也好分析。所以本节虽然是移植lora的驱动,但是我们实现的目的很简单:stm32通过SPI接口对sx1278芯片的操作成功。我们最终会读取sx1278内部的一个固定寄存器的值,看读回来的值是否和手册上面的相同。相同即证明我们的驱动移植基本没有问题。
开发环境准备:
硬件:
- Lora-B1开发板一块
- DAPLINK(或STLINK、Jlink)调试器
软件:
- stm32cubemx
- MDK5
- Semtech官方Lora驱动代码(sx12xxDrivers-V2.1.0.zip)
原理图:
如下原理图所示,DIO0-DIO3为lora模块的输出引脚,连接的单片机引脚需要对应配置为输入模式进行检测。SPI_MOSI、SPI_MISO、SPI_SCK、CS脚为lora模块和stm32之间的spi接口引脚。L_RST是lora模块的复位引脚,对应stm32的IO口要配置为输出模式。
移植步骤:
一、打开stm32cubemx新建工程,
选择stm32f030f4,配置各个引脚,如下图所示。Stm32主时钟频率设定为48mhz,这里略过。
- DIO0-DIO3为GPIO_INPUT模式
- SPI1_CS和LRST配置为GPIO_OUTPUT模式(注意CS脚这里是作为普通输出)
- SPI1_MOSI、SPI1_MISO、SPI1_CLK为标准SPI接口。
二、配置SPI参数:
参数配置主要涉及如下几个,其他默认值不用修改
这里需要注意的就是spi的极性相位的设置,在sx1278的手册中可以得到如下信息:
所以stm32的CPOL和CPHA要和sx1278的相同,这里CPOL=Low即CPOL=0,
CPHA=1Edge即CPHA=0(如果这里还有疑问请查看stm32f030的参考手册的SPI章节)
三、生成MDK工程
Stm32cubemx的各个参数配置好以后就可以生成MDK工程,mdk工程结构如下:
在mdk的工程目录中添加两个文件夹:lora/radio、lora/platform用于后面添加lora驱动的代码,添加后如下所示:
四、添加lora驱动源代码
在工程目录下新建lora文件夹,并把从官方源码中解压出来的src下的platform和radio文件夹拷贝进来。
这样我们需要的驱动源代码就有了。之后就可以往mdk的工程添加了。现在应该也可以理解了我们前面在mdk的project下建立的lora/radio、lora/platform也就是和这里的源码文件对应起来的。
这时候你又会惊讶的发现在这两个文件夹里面存放很多文件,但是真用我们用到的不多,其他的可以暂时先不管。添加完以后我们的MDK工程结构是这个样子的:
添加c文件以后别忘了添加mdk的h文件路径。
五、编译排错修改
- 删除\lora\platform\sx12xxEiger\spi.c和spi.h文件(该文件没用,但是名称和cubemx生成的spi初始化文件名相同会造成后面编译失败)
- 打开platform.h文件,打开这条宏定义
#define PLATFORM SX12xxEiger
- 打开sx12xxEiger.c文件,屏蔽或删除掉该文件内所有函数
- 打开sx12xxEiger.h文件,修改#include “stm32f10x.h” 为 #include “stm32f0xx_hal.h”
- 修改sx1276-Hal.h中#define GET_TICK_COUNT( ) HAL_GetTick()
- 接下来的错误都集中在sx1276-Hal.c文件,该文件也是实现移植的主要接口。修改该文件代码接口如下:
- MDK的编译会强制每个c或h文件最后都要空一行,根据提示把警告的文件后面回车多添加一行新行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
/* * 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 "main.h" #include "spi.h" #include "gpio.h" #include "platform.h" #include "../../radio/sx1276-Hal.h" uint8_t SpiInOut( uint8_t outData ) { uint8_t Rxdata; HAL_SPI_TransmitReceive(&hspi1,&outData,&Rxdata,1, 1000); return Rxdata; } void SX1276InitIo( void ) { } void SX1276SetReset( uint8_t state ) { if(state==RADIO_RESET_ON) { HAL_GPIO_WritePin(LRST_GPIO_Port,LRST_Pin,GPIO_PIN_RESET); } else { HAL_GPIO_WritePin(LRST_GPIO_Port,LRST_Pin,GPIO_PIN_SET); } } 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 ) { HAL_GPIO_WritePin(SPI1_CS_GPIO_Port,SPI1_CS_Pin,GPIO_PIN_RESET); SpiInOut( addr | 0x80 ); for(uint8_t i = 0; i < size; i++ ) { SpiInOut( buffer[i] ); } HAL_GPIO_WritePin(SPI1_CS_GPIO_Port,SPI1_CS_Pin,GPIO_PIN_SET); } void SX1276ReadBuffer( uint8_t addr, uint8_t *buffer, uint8_t size ) { HAL_GPIO_WritePin(SPI1_CS_GPIO_Port,SPI1_CS_Pin,GPIO_PIN_RESET); SpiInOut( addr & 0x7F ); for(uint8_t i = 0; i < size; i++ ) { buffer[i] = SpiInOut( 0 ); } HAL_GPIO_WritePin(SPI1_CS_GPIO_Port,SPI1_CS_Pin,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(DIO0_GPIO_Port,DIO0_Pin); } inline uint8_t SX1276ReadDio1( void ) { return HAL_GPIO_ReadPin(DIO1_GPIO_Port,DIO1_Pin); } inline uint8_t SX1276ReadDio2( void ) { return 0; } inline uint8_t SX1276ReadDio3( void ) { return HAL_GPIO_ReadPin(DIO3_GPIO_Port,DIO3_Pin); } inline uint8_t SX1276ReadDio4( void ) { return 1; } inline uint8_t SX1276ReadDio5( void ) { return 1; } inline void SX1276WriteRxTx( uint8_t txEnable ) { } |
- 验证移植驱动
经过上面的移植,如果编译没有错误,移植工作就算完成了。之后我们就可以基于lora的驱动编写我们的应用代码。
打开sx127x的手册,看0x42地址的寄存器描述,该寄存器读取回来的值是固定的0X12。那我们就基于写好的驱动读取该寄存器的值,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_SPI1_Init(); /* USER CODE BEGIN 2 */ tRadioDriver *radio; radio = RadioDriverInit( ); radio->Init(); radio->StartRx(); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { uint8_t ver=0; SX1276Read(REG_LR_VERSION,&ver); if(ver==0x12) { HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin); } HAL_Delay(300); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } */ } |
radio里面有个sys.h头文件,这个怎么更改啊