LORA驅動移植
移植前先嘮嗑嘮嗑:
在網上買了幾塊LORA-B1的開發板,開發板的LORA芯片用的是SX1278,微控制器是STM32F030F4P6,我這人底子薄沒怎麼用過STM32也沒用過LORA,就玩過ZigBee用過IAR,所以就一邊百度一邊學STM32CubeMX和Keil5 MDK的基本使用。點了點燈再跑下例程的按鈕點燈,不亦樂乎。
然後到移植LORA驅動這裏時,犯難了,碰到了很多問題,雖然有現成移植好LORA驅動的例程,但我就是想自己試一試。店家給的教程對我這種菜雞太不友好了,我腦抽沒看懂,問到店家都怕了我吧?(學習的過程中臉皮一定要厚,嗯嗯~)鼓搗一兩天終於弄出來了,還做了個筆記跟大家分享一下。這教程應該是非常適合像我這樣一臉懵逼一無所知的小白了。
附上參考教程鏈接:
http://www.eemaker.com/lora-b1-qudongyizhi.html
下面就是我用的LORA-B1開發板:
(我這算是幫別人打廣告嗎?不過這篇文章估計看的人也不多)
一、移植官方LORA驅動前需知:
1.DIO0-DIO3爲lora模塊的輸出引腳,連接的單片機引腳需要對應配置爲輸入模式進行檢測。
2.SPI_MOSI、SPI_MISO、SPI_SCK、CS腳爲lora模塊和stm32之間的spi接口引腳。
3.L_RST是lora模塊的復位引腳,對應stm32的IO口要配置爲輸出模式。
二、移植步驟:
1.打開STM32CubeMX,選擇ACCESS TO MCU SELECTOR
2.搜索自己的芯片型號,雙擊
3.按照上述原理圖配置各管腳
①DIO0-DIO3爲GPIO_INPUT模式
②SPI1_CS和LRST配置爲GPIO_OUTPUT模式(注意CS腳這裏是作爲普通輸出)
③SPI1_MOSI、SPI1_MISO、SPI1_CLK爲標準SPI接口。
④然後再對相應管腳進行命名和SPI管腳設置:展開System Core,雙擊GPIO,在User Label處改標籤名(注意:PB1管腳標籤改爲LRST,不是L_RST)
⑤展開Connectivity,點擊SPI1,選擇Full-Duplex Master模式(全雙工主機),在Parameter Settings裏將Data Size設爲8 Bits,Prescaler(for Baud Rate)設爲4,(注:灰色部分的Baud Rate與設置的Prescaler(for Baud Rate)和STM32的主時鐘頻率有關,下一步設置STM32的主時鐘頻率)其他參數默認不變,如圖所示:
4.設置STM32的主時鐘頻率爲48MHz
此時的SPI1參數如下:
5.在Project Manager的Project裏,自行命名項目名稱和設置項目路徑,Toolchain/IDE選擇MDK-ARM V5。
6.勾選,這個選項使每個外設對應產生一個.c和.h文件,讓代碼結構更加清晰。
7.點擊GENERATE CODE
再點擊Open Project自動生成工程。
自動生成的工程如下:
先關閉工程,下一步是代碼移植。
三、代碼移植
1.解壓官方源碼
解壓後在src下找到並複製platform和radio文件夾
再找到自動生成的工程路徑
在自動生成的工程下,新建一個命名爲lora的文件夾,在lora下黏貼platform和radio文件夾
2.打開LoraDrive工程並新建兩個文件夾lora/radio和lora/platform(若是新建過程中卡住了,就關閉工程再重新打開工程新建一次,還是卡就重啓電腦)
新建後工程視圖如下:
3.分別給新建的兩個文件夾Add Files…
(添加的.c文件是分別從工程下的lora文件夾下複製黏貼過來的platform和radio文件夾下選取的。)
添加文件後的工程視圖如下:
4.添加.c文件後添加mdk的.h文件路徑
5.最關鍵的地方來了!!!
①刪除\lora\platform\sx12xxEiger\spi.c和spi.h文件(該文件沒用,但是名稱和cubemx生成的spi初始化文件名相同會造成後面編譯失敗)。
②打開platform.h文件,再打開宏定義#define PLATFORM SX12xxEiger(默認這條宏定義是被註釋掉的,所以我們要打開它,這裏我用的是Source Insight4.0打開的platform.h文件,用其他軟件打開也可以,看個人習慣。更改後記得保存)
③打開sx12xxEiger.c文件,屏蔽或刪除掉該文件內所有函數。(我這裏就是用Keil5 MDK打開的sx12xxEiger.c文件,然後Ctrl+A全選,右鍵Advanced選擇Comment Selection註釋)
④打開sx12xxEiger.h文件,修改#include “stm32f10x.h” 爲 #include “stm32f0xx_hal.h”
⑤修改sx1276-Hal.h中#define GET_TICK_COUNT( ) HAL_GetTick()
⑥接下來的錯誤都集中在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 "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 )
{
}
⑦編譯,MDK的編譯會強制每個.c或.h文件最後都要空一行,根據提示把警告的文件後面回車多添加一行新行。
以上添加新行後編譯,如果還存在錯誤,就把上面七步再重新檢查一遍,看看有沒有文件漏添新行,或者更改宏定義或者其他代碼時是否有非法輸入字符。例如我上個截圖中除了需要添加新行外,就還有其他錯誤。經過逐步檢查發現在第⑤步修改sx1276-Hal.h中#define GET_TICK_COUNT( ) HAL_GetTick() 時有中文輸入法的字符出現,更改之後再保存,編譯,就沒事啦。
最終編譯成功如下:
到此,官方LORA驅動的移植就完成啦~
之後我們就可以基於lora的驅動編寫自己的應用代碼了。