电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
lora开发之 lora驱动移植详解基于 SX1278 & STM32F051K8U6
分 享
扫描二维码分享
lora开发之 lora驱动移植详解基于 SX1278 & STM32F051K8U6
lora
STM32
物联网
Hello Pointer!!!
关注
发布时间: 2019-12-24
丨
阅读: 5086
#### 1 硬件品台 安信可 lora模块 SX1278 扩频模块 通讯距离可以达到10公里 SPI接口驱动 300kbp SPI通讯速率 通讯频谱 410-525 MHz ,常用的是 470MHz 最大发射功率可以达到 18+-1dbm 单片机 STM32F051k 32位低功耗 48mhz 48pin IO ram 64k 传感器: 温湿度传感器 风扇 三轴传感器 cubemx IAR #### 2 节点入网 LoRa 网络运行参数 PAID: 0X1010 (网络ID号) 相当于TCP IP的端口号 只有在同一个PAID里面节点才可以和网关通讯,每一个节点或者是协调器 都有一个地址,地址可以自己随意定义 协调器地址(网关): 0xFFFF 体征数据采集节点 0x1201 饲养环境控制节点 0x1202 饲养环境采集节点 0x1203 实时命令下发 (利用串口) #### 6 lora开发环境以及驱动移植 cubemx 环境搭建 HAL库 (硬件抽象库)与 STD库(标准库 寄存器操作)对比 STD标准库 寄存器操作,将一些基本的寄存器操作封装成函数 HAL库-硬件抽象库 将硬件变为抽象层,从使用上与硬件无关 HAL库优势 HAL方便移植 HAL库是ST官方主推库 2015年后的新出芯片都不支持STD库 F7 L0等已经不支持标准库 HAL库 硬件抽象层不用动 下面这个就是ST官网的cubemx下载链接,我们可以从这里获取它的软件和外设文档等信息。 [STM32CubeMX下载地址](http://www.st.com/content/st_com/en/products/development-tools/software-development-tools/stm32-software-development-tools/stm32-configurators-and-code-generators/stm32cubemx.html#get-software "STM32CubeMX下载地址") STM32CubeMX 安装步骤 1 安装JAVA运行环境,JavaScript8u151.exe(自行百度下载) 2 安装 SetupSTM32CubeMX-4.22.0.exe 最好不要带中文路径 3 加载 “stm32cube_fw_f0_v180.zip” HAL库到 STM32CubeMX中 安装完JAVA运行环境后,双击 SetupSTM32CubeMX-4.22.0.exe ,以管理员身份运行,最好 不要选择有中文路径的目录,然后一路下一步就可以了。下图就是软件运行起来的样子 ![CubeMX界面](https://cf04.ickimg.com/bbsimages/201911/b221a4e7c248a0a83fc826834f98350d.png "CubeMX界面") 4加载 HAL库 点击 help -> install New libraries ![库文件安装](https://cf04.ickimg.com/bbsimages/201911/8e285189bf338471a172ea37327b1132.png "库文件安装") 点击from Local 选择我们事先下载好的固件包路径即可,对应固件包前面变为绿色,说明已经安装成功 ![HAL固件包](https://cf04.ickimg.com/bbsimages/201911/8a8110c03d236afaf1c96d5175c5481d.png "HAL固件包") 5开始使用 CubeMX 新建工程 New Projecr -> 选择对应芯片型号 ![新建工程](https://cf04.ickimg.com/bbsimages/201911/b8b8896e59dc76dfb8cba636d3779dfc.png "新建工程") Project 里面有一个setting project name 工程名字 路径 IDE(MDK IAR) 注意在代码生成(Code Gemerator)勾选下列选项,这样的话它生成的外设文件会自动生成 .c 和 .h 的文件。 ![勾选相应选项](https://cf04.ickimg.com/bbsimages/201911/3e4f714bea0e9e814531d6435e7da70f.png "勾选相应选项") 尝试配置GPIO口为输出模式 ,为之后移植做准备 ![端口模式设置](https://cf04.ickimg.com/bbsimages/201911/a70ffe080f68a3b0c1d95fd5168f8bca.png "端口模式设置") 下载IAR(自行百度) MO工程建立 1. IO口配置如下图 ![端口配置](https://cf04.ickimg.com/bbsimages/201911/b6017eb9e8d93d954c5dd1d76dc0c13c.png "端口配置") 2 时钟配置 2.1选择时钟源 2.2设置倍频 2.3 选择锁相环 2.4 使系统时钟工作在 48MHz的频率下 如下图 选择外部时钟 HSE 6倍频 时钟源PLLCLK 时钟为48Mhz ![时钟配置](https://cf04.ickimg.com/bbsimages/201911/3319698a845ad98fe31ec3cda4d10042.png "时钟配置") 3 外设配置 3.1 USART 配置 配置为异步通讯模式 无硬件流控 设置波特率 115200 接收设为DMA ![串口配置](https://cf04.ickimg.com/bbsimages/201911/5113ee5ddfb99b54a20dc63bc6a9bcf6.png "串口配置") 3.2 SPI配置 选择全双工主机模式 硬件片选不使能 设置波特率为 1.5MBit/s 时钟极性为低电平驱动 时钟相位为第一边沿 ![SPI配置](https://cf04.ickimg.com/bbsimages/201911/1d7c1aa824de070147efabd20991e9be.png "SPI配置") 之后点击如下图所示 GENERATE CODE 生成代码 ![生成工程文件](https://cf04.ickimg.com/bbsimages/201911/349b181ac5575371331608162254bd94.png "生成工程文件") 4 printf函数重定向,在主函数当中插入printf重定向 ```c main.c /@@* USER CODE BEGIN Header */ /@@** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * *
© Copyright (c) 2019 STMicroelectronics. * All rights reserved.
* * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * ****************************************************************************** */ /@@* USER CODE END Header */ /@@* Includes ------------------------------------------------------------------*/ #include "main.h" #include "adc.h" #include "dma.h" #include "spi.h" #include "usart.h" #include "gpio.h" #include
/@@* Private includes ----------------------------------------------------------*/ /@@* USER CODE BEGIN Includes */ /@@* USER CODE END Includes */ /@@* Private typedef -----------------------------------------------------------*/ /@@* USER CODE BEGIN PTD */ /@@* USER CODE END PTD */ /@@* Private define ------------------------------------------------------------*/ /@@* USER CODE BEGIN PD */ /@@* USER CODE END PD */ /@@* Private macro -------------------------------------------------------------*/ /@@* USER CODE BEGIN PM */ /@@* USER CODE END PM */ /@@* Private variables ---------------------------------------------------------*/ /@@* USER CODE BEGIN PV */ int fputc(int ch, FILE *f); /@@* USER CODE END PV */ /@@* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /@@* USER CODE BEGIN PFP */ /@@* USER CODE END PFP */ /@@* Private user code ---------------------------------------------------------*/ /@@* USER CODE BEGIN 0 */ /@@* USER CODE END 0 */ /@@** * @brief The application entry point. * @retval int */ 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_DMA_Init(); MX_ADC_Init(); MX_USART1_UART_Init(); MX_SPI1_Init(); /@@* USER CODE BEGIN 2 */ printf("systerm init ok!"); /@@* USER CODE END 2 */ /@@* Infinite loop */ /@@* USER CODE BEGIN WHILE */ while (1) { /@@* USER CODE END WHILE */ /@@* USER CODE BEGIN 3 */ } /@@* USER CODE END 3 */ } /@@** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; /@@** Initializes the CPU, AHB and APB busses clocks */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI14|RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSI14State = RCC_HSI14_ON; RCC_OscInitStruct.HSI14CalibrationValue = 16; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL6; RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /@@** Initializes the CPU, AHB and APB busses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) { Error_Handler(); } PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1; PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK1; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); } } /@@* USER CODE BEGIN 4 */ /@@* USER CODE END 4 */ /@@** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /@@* USER CODE BEGIN Error_Handler_Debug */ /@@* User can add his own implementation to report the HAL error return state */ /@@* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /@@** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(char *file, uint32_t line) { /@@* USER CODE BEGIN 6 */ /@@* User can add his own implementation to report the file name and line number, tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /@@* USER CODE END 6 */ } #endif /@@* USE_FULL_ASSERT */ int fputc(int ch, FILE *f) { while((USART1->ISR& 0X40)==0) USART1-> TDR =(uint8_t) ch; return ch; } /@@************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ ``` 之后编译看看有没有错然后下载程序看看串口是否打印 systerm init ok! 这条信息,如果成功打印说明程序烧写成功。 7 lora驱动移植 7.1驱动源码文件说明 7.2 Source Insight 安装说明 7.3 硬件抽象层 我们打开官方固件库: 链接:https://pan.baidu.com/s/1eX2DKYVTfJHsRzxCQ9h8Xw 提取码:82qf 我们可以看到其中包含有4个文件夹 doc 官方说明文档 lst obj 是工程编译时候的零时文件 src 包含有 Lora 模块的所有驱动源码, ![lora官方驱动](https://cf04.ickimg.com/bbsimages/201911/e3355445fab6da484130958ff0197bea.png "lora官方驱动") 我们打开 src文件 可以看到如下图所示 ![src文件夹](https://cf04.ickimg.com/bbsimages/201911/6432c19221b60ff64f862f39dc649b92.png "src文件夹") main.c 是官方提供的示例代码 platform: 硬件平台驱动源码(官方提供了不同的MCU驱动源码 M3 M4) radio: 是我们操作Lora模块的无线驱动源码,以及无线驱动的一个简易框架 我们打开 platform 这个文件夹,可以看到很多硬件平台的相关文件,在这个文件夹下 只需要看 sx12xxEiger这个文件夹就可以了, ![platform文件夹](https://cf04.ickimg.com/bbsimages/201911/67095c00c0a6dfaac501142d372ce7f5.png "platform文件夹") 打开之后可以看到很多 .c 和 .h 文件,这个只需要看 fifo.c led.c sx1276-Hal.c sx12xxEiger ![.c .h 文件](https://cf04.ickimg.com/bbsimages/201911/fdf56d3cd42cae0be9d1be8843e8ad17.png ".c .h 文件") 我们打开 radio 这个文件夹,看到了很多文件,我们只需要去关心 1276这款芯片的驱动源码即可 ![radio文件](https://cf04.ickimg.com/bbsimages/201911/643b77385f5158aeb807b8e92c0da751.png "radio文件") 我们打开官方提供的数据手册,这个手册可以同时适用 SX1276 1278 1277 ,他们的数据规格操作和原理都是一样的 ,国内主要使用 1278这款芯片,它的工作频段主要是 137-525MHz lora数据手册链接:https://pan.baidu.com/s/1-xrj3ngvW17UZJ3OJl3atA 提取码:1ky1 ![lora数据手册](https://cf04.ickimg.com/bbsimages/201911/933923ad95e388f141d14348b0433777.png "lora数据手册") #### 驱动框架 ![驱动框架](https://cf04.ickimg.com/bbsimages/201911/8e94c4ddb65f68468fc0bdec977e886a.png "驱动框架") 应用层: 板级初始化射频的初始化 以及收发任务 无线驱动层: 射频的收发参数设置,以及应用层有关的抽象层设计 硬件抽象层: 主要用于MCU与Lora模块的驱动开发 我们主要移植硬件抽象层和无线驱动层 #### Source Insigned (自行安装) 安装完之后打开lora源码如图所示 ![lora源码](https://cf04.ickimg.com/bbsimages/201911/5d3a00fa9b81fe10038246e820ca3c96.png "lora源码") #### 硬件抽象层分析 数字 IO SPI串行总线 硬件复位 ![硬件接口图](https://cf04.ickimg.com/bbsimages/201911/118dafc342adc546df10452cb2352622.png "硬件接口图") lora模块原理图 这里只连接了 DIO0-DIO3 以及片选脚时钟脚和收发脚 ![lora模块原理图](https://cf04.ickimg.com/bbsimages/201911/09f73311a0c4c23aea1d9adbb62413c0.png "lora模块原理图") 接下来我们看源码对驱动的设计 ![SPI接口函数](https://cf04.ickimg.com/bbsimages/201911/911c35d733b97d07b85d71416db80de8.png "SPI接口函数") 以上函数 具有读取 接收 单个字节或者多字节数据的作用 ![DIO接口函数](https://cf04.ickimg.com/bbsimages/201911/724fe3009571f9e41f1ad108b7b3d8f5.png "DIO接口函数") DIO接口函数 读取0-5接口的数据。 接下来我们来看SPI的接口源码 用 Source Insigned 打开sx1276-hal.c文件 ,这样我们就看到了 Lora的读写函数 ![lora读写函数](https://cf04.ickimg.com/bbsimages/201911/b0c8242c6f4499452a3b1c9427ae8d8f.png "lora读写函数") 硬件接口函数 IO端口驱动 SX1276initio——————>输入输出初始化 SX1276SetReset——————>硬件复位 队列接口驱动 SX1276Writefifo——————>队列写数据 SX1276Readfifo——————>队列读数据 无线工作模式驱动 SX1276WriteRxTx——————>修改LoRa无线工作模式 void SX1276InitIo( void )函数根据不同的硬件平台完成IO口的初始化,在硬件接口的驱动中我们只需要看SPI总线以及我们数字IO口的驱动即可。 将如图所示的两个文件一直到我们之前建好的工程当中去 ![lora驱动移植1](https://cf04.ickimg.com/bbsimages/201911/61fd1992282a0752073d0ce8411a6ba8.png "lora驱动移植1") 添加驱动文件 ![添加驱动](https://cf04.ickimg.com/bbsimages/201911/d1d4e7ed383f6710d88b231ef87e5cd0.png "添加驱动") #### 驱动源码修改驱动源码修改 sX1276官方固件库是不支持 M0的,不支持HAL库的,所有的IO口也不对应。 所以我们要进行驱动源码的修改 一 修改为支持的硬件平台 打开platform.h修改如下代码 ![代码修改1](https://cf04.ickimg.com/bbsimages/201911/4467e4b408bc954e8e42960b887517de.png "代码修改1") 在其他的.h里面也将它修改掉 二 修改工程路径, 添加 platform 和radio 的工程路径 需要修改工程的包含路径 ![工程路径](https://cf04.ickimg.com/bbsimages/201911/2de1cdbbab384abd646c1649e45259e0.png "工程路径") 三 修改 sx12xxEiger.c 然后将sx12xxEiger.c 里面没有用到的部分也都注释掉 ![注释无用函数](https://cf04.ickimg.com/bbsimages/201911/2c46959bd71b0777e0b18f33853cacfc.png "注释无用函数") ```c //#if( defined( STM32F4XX ) || defined( STM32F2XX ) || defined( STM32F429_439xx ) ) // //#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED // #if defined ( __ICCARM__ ) /@@*!< IAR Compiler */ // #pragma data_alignment=4 // #endif //#endif /@@* USB_OTG_HS_INTERNAL_DMA_ENABLED */ // //__ALIGN_BEGIN USB_OTG_CORE_HANDLE USB_OTG_dev __ALIGN_END ; // //#else //#endif ``` 只要是关于初始化的也都注释掉,应为cubemx已经做好了 ```c //void BoardInit( void ) //{ // uint8_t i; // // /@@* Setup SysTick Timer for 1 us interrupts ( not too often to save power ) */ // if( SysTick_Config( SystemCoreClock / 1000 ) ) // { // /@@* Capture error */ // while (1); // } // // // Initialize SPI // SpiInit( ); // // // Initialize I2C // I2cInit( ); // // // Initialize IO expander // IoeInit( ); // // // Initialize LED // for( i = 0; i < LED_NB; i++ ) // { // LedInit( ( tLed )i ); // } // IoePinOn( LED_1_PIN ); // IoePinOn( LED_2_PIN ); // IoePinOn( LED_3_PIN ); // //#if( defined( STM32F4XX ) || defined( STM32F2XX ) || defined( STM32F429_439xx ) ) // // USBD_Init( &USB_OTG_dev, //#ifdef USE_USB_OTG_HS // USB_OTG_HS_CORE_ID, //#else // USB_OTG_FS_CORE_ID, //#endif // &USR_desc, // &USBD_CDC_cb, // &USR_cb ); //#else // /@@* Configure the used GPIOs*/ // GPIO_Configuration( ); // /@@* Additional EXTI configuration (configure both edges) */ // EXTI_Configuration( ); // // USB_Interrupts_Config( ); // Set_USBClock( ); // USB_Init( ); //#endif //} ``` 四 修改 LED.c 打开LED.h ```c typedef enum { LED_GREEN = 0, LED_RX = 1, LED_TX = 2, LED_NT = 3, #if defined( STM32F4XX ) || defined( STM32F2XX ) || defined( STM32F429_439xx ) LED_DBG3 = 4, #endif } tLed; //注释有关时钟的部分 // RED #define LED1_PIN GPIO_Pin_2 #define LED1_GPIO_PORT GPIOB //#define LED1_GPIO_CLK RCC_AHB1Periph_GPIOE // GREEN #define LED2_PIN GPIO_Pin_1 #define LED2_GPIO_PORT GPIOB //#define LED2_GPIO_CLK RCC_AHB1Periph_GPIOE // DBG1 #define LED3_PIN GPIO_Pin_0 #define LED3_GPIO_PORT GPIOB //#define LED3_GPIO_CLK RCC_AHB1Periph_GPIOE 在LED.c里面 注释掉有关于端口配置的部分 //GPIO_TypeDef* LedPort[LED_NB] = { // LED1_GPIO_PORT, // LED2_GPIO_PORT, // LED3_GPIO_PORT, // LED4_GPIO_PORT, //#if defined( STM32F4XX ) || defined( STM32F2XX ) || defined( STM32F429_439xx ) // LED5_GPIO_PORT, //#endif // }; //const uint16_t LedPin[LED_NB] = { // LED1_PIN, // LED2_PIN, // LED3_PIN, // LED4_PIN, //#if defined( STM32F4XX ) || defined( STM32F2XX ) || defined( STM32F429_439xx ) // LED5_PIN //#endif // }; //const uint32_t LedClk[LED_NB] = { // LED1_GPIO_CLK, // LED2_GPIO_CLK, // LED3_GPIO_CLK, // LED4_GPIO_CLK, //#if defined( STM32F4XX ) || defined( STM32F2XX ) || defined( STM32F429_439xx ) // LED5_GPIO_CLK //#endif // }; 同时,LED初始化也注释掉 //void LedInit( tLed led ) //{ // GPIO_InitTypeDef GPIO_InitStructure; // //#if defined( STM32F2XX ) || defined( STM32F4XX ) || defined( STM32F429_439xx ) // // RCC_AHB1PeriphClockCmd( LedClk[led], ENABLE ); // // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; // GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //#else // // RCC_APB2PeriphClockCmd( LedClk[led], ENABLE ); // // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //#endif // // GPIO_InitStructure.GPIO_Pin = LedPin[led]; // GPIO_Init( LedPort[led], &GPIO_InitStructure ); // GPIO_WriteBit( LedPort[led], LedPin[led], LED_OFF ); //} void LedOn( tLed led ) { HAL_GPIO_WritePin( LedPort[led], LedPin[led], LED_ON ); } void LedOff( tLed led ) { HAL_GPIO_WritePin( LedPort[led], LedPin[led], LED_OFF ); } void LedToggle( tLed led ) { // LedPort[led]->ODR ^= LedPin[led]; } ``` 五 修改 sx1276-Hal.c ```c //修改 sx1276-Hal.c //#if defined( STM32F4XX ) || defined( STM32F2XX ) //#define RESET_IOPORT GPIOG //#define RESET_PIN GPIO_Pin_12 //#elif defined( STM32F429_439xx ) //#define RESET_IOPORT GPIOG //#define RESET_PIN GPIO_Pin_12 //#else //#define RESET_IOPORT GPIOA //#define RESET_PIN GPIO_Pin_1 //#endif /@@*! * SX1276 DIO pins I/O definitions */ #if defined( STM32F4XX ) || defined( STM32F2XX ) #define DIO0_IOPORT GPIOG #define DIO0_PIN GPIO_Pin_13 #elif defined( STM32F429_439xx ) #define DIO0_IOPORT GPIOG #define DIO0_PIN GPIO_Pin_13 #else #define DIO0_IOPORT GPIOA #define DIO0_PIN GPIO_Pin_11 #endif #if defined( STM32F4XX ) || defined( STM32F2XX ) #define DIO1_IOPORT GPIOB #define DIO1_PIN GPIO_Pin_8 #elif defined( STM32F429_439xx ) #define DIO1_IOPORT GPIOB #define DIO1_PIN GPIO_Pin_7 #else #define DIO1_IOPORT GPIOB #define DIO1_PIN GPIO_Pin_12 #endif #if defined( STM32F4XX ) || defined( STM32F2XX ) #define DIO2_IOPORT GPIOA #define DIO2_PIN GPIO_Pin_2 #elif defined( STM32F429_439xx ) #define DIO2_IOPORT GPIOA #define DIO2_PIN GPIO_Pin_2 #else #define DIO2_IOPORT GPIOC #define DIO2_PIN GPIO_Pin_3 #endif //#if defined( STM32F4XX ) || defined( STM32F2XX ) || defined( STM32F429_439xx ) //#define DIO3_IOPORT //#define DIO3_PIN RF_DIO3_PIN //#else //#define DIO3_IOPORT //#define DIO3_PIN RF_DIO3_PIN //#endif // //#if defined( STM32F4XX ) || defined( STM32F2XX ) || defined( STM32F429_439xx ) //#define DIO4_IOPORT //#define DIO4_PIN RF_DIO4_PIN //#else //#define DIO4_IOPORT //#define DIO4_PIN RF_DIO4_PIN //#endif // //#if defined( STM32F4XX ) || defined( STM32F2XX ) || defined( STM32F429_439xx ) //#define DIO5_IOPORT //#define DIO5_PIN RF_DIO5_PIN //#else //#define DIO5_IOPORT //#define DIO5_PIN RF_DIO5_PIN //#endif // //#if defined( STM32F4XX ) || defined( STM32F2XX ) || defined( STM32F429_439xx ) //#define RXTX_IOPORT //#define RXTX_PIN FEM_CTX_PIN //#else //#define RXTX_IOPORT //#define RXTX_PIN FEM_CTX_PIN //#endif void SX1276InitIo( void ) { // 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 } ``` #### LoRa 模块上电自检 上电去读取芯片的ID如果读取成功说明驱动移植成功。 ![lora模块上电自检](https://cf04.ickimg.com/bbsimages/201911/76decb9ef2998501ff03dc1033ec8bf5.png "lora模块上电自检") 我们需要复制一下函数到 mian 函数当中去,并包含相应的头文件 ```c //sx1278以下为sx1276相关的头文件 #include "platform.h" #include "sx1276-Hal.h" #include "sx12xxEiger.h" #include "sx1276-LoRa.h" #include "sx1276-LoRaMisc.h" //打印 sx1276相关的 ID,如果能打印成功,说明我们 1276的驱动已经移植成功了 uint_8 RegVersion =0; // SX1276Read( REG_LR_VERSION, &SX1276LR->RegVersion ); SX1276Read( REG_LR_VERSION,&RegVersion ); if(RegVersion!=0x12) { printf("lora read Error!") } else { printf("lora read ok!") } ) ``` #### LoRa Pingpong系统设计 01 深入了解 LoRa 技术原理 1 lora 扩频通讯技术原理 lora扩频通讯技术能有效地解决无线通信中的多路径衰退、以及噪声干扰的问题,是由好莱坞女星 HedyLamart 发明的。 C:信号质量 W:信号带宽 S:信号功率 N:噪声功率 在信噪比(S/N)相同的情况下,我们如果去提高信号带宽,那么我们的信号质量也会同比增高。LoRa就是通过提高我们的信号带宽来提高信号质量,也就是将用户数据与扩频数据进行异或,从而得到我们的发送数据,发送数据增加了带宽,但是同时提高了发射增益(也就是提高了信号的增益(信号质量)) C/W = 1.44(S/N)(这里是约等于) 2 lora关键技术参数 信号带宽(BW): 增加BW可以提高有效数据速率以缩短时间,但是以牺牲部分接收灵敏度为代价,对于LoRa芯片SX127x,Lora带宽为双边带宽(全信道带宽),而FSK调制方式的BW是指单边带宽 ![lora带宽](https://cf04.ickimg.com/bbsimages/201911/ac45072e5d073072919f3763e0742407.png "lora带宽") 不同的带宽通讯速率是不一样的,带宽越高通讯速率就越快。通讯质量就越好 扩频因子:(Fs) 是将本来用一位表示的信息变成多位,从而提高信号的通讯质量 ,扩频因子越大信号质量越好,扩频因子越大,对应的信噪比越小。 ![](https://cf04.ickimg.com/bbsimages/201911/2c391a66fef8d7ff048279d77efc520e.png) ![](https://cf04.ickimg.com/bbsimages/201911/d76f8cf56b845cf7908cbb4853221e6f.png) 编码率:(CR):提高信号数据的冗余,在有用信号里面加一些冗余数,我们可以从这些冗余数据里面来提高数据可靠性。 Lora 符号速率 Rs计算: Rs = BW/(2^SF) Lora 数据速率DR计算: DR= SF*(BW/2^SF)*CR 这里主要看数据速率,我们通过调节我们的 带宽 扩频因子 以及 编码率,可以去设置我们的通讯速率,以及通讯距离同样也可以设置电池寿命(链路运算 传输时间 电池寿命 以及距离) 3 lora数据收发任务 接收分为 连续接收和单次接收 在源码里面 sx1276-LoRa.c void SX1276LoRaInit( void )这个函数用于设置工作模式,以及接收缓存区 频率,最后设置为 标准工作模式 LoRaSettings 这个结构体含有频率 功率 带宽 扩频因子 编码率 等参数。我们只需要在这个结构体里面设置LoRa参数就可以进行初始化 uint32_t SX1272LoRaProcess( void ) 有一个switch,里面有多种工作模式: 接收 发送 信道检测,不同的工作模式有不同的处理。 在做lora开发时,都需要进行参数设置 02 lorapingpong系统设计 Pingpong系统设计需求 将终端定义为 Master 和 Slave Master 主动发送 ping数据 接收pong数据 Slave 如果接收到ping数据,回应pang数据 ,读取事件任务表里面的状态字,来判断接收发送的状态 ![](https://cf04.ickimg.com/bbsimages/201911/95f1621aff8f99ad574ebd8a33d7e537.png) 在 sx1276-LoRa.c下 void SX1272LoRaGetRxPacket( void *buffer, uint16_t *size ) 数据包获取 void SX1272LoRaSetTxPacket( const void *buffer, uint16_t size ) 数据包发送 我们利用上述函数就能实现数据的发送,同时要设置无线的任务转态为发送,这样就可以开启发送 整个无线工作的状态就是通过下列几个机制实现的 ,我们只需要监听以及设置这些工作状态,那么我们就可以实现数据的收发 ```c typedef enum { RFLR_STATE_IDLE,// 空闲 RFLR_STATE_RX_INIT,//接收初始化 RFLR_STATE_RX_RUNNING,//接收进行 RFLR_STATE_RX_DONE, //接收完成 RFLR_STATE_RX_TIMEOUT,//接收超时 RFLR_STATE_TX_INIT,//发送初始化 RFLR_STATE_TX_RUNNING,//发送进行 RFLR_STATE_TX_DONE,//发送完成 RFLR_STATE_TX_TIMEOUT,//发送超时 RFLR_STATE_CAD_INIT,//信道活动监听 RFLR_STATE_CAD_RUNNING, }tRFLRStates; ``` #### pingpong系统义务流程分析 初始化 ->判断设备类型->如果是主机则开启发送ping,是从机,则开启接收ping 设置中心频率为 470MHz 设置信号带宽为 500khz 设置扩频因子为 7 开启CRC校验 设置为隐式包头() 数据格式: 前导码+头数据+实际发送的负载数据+负载校验。 前导码: 在我们发送数据之前要设置一个同步码,只有相同的同步码才可以进行交互 头数据:(可包含 可不包含)0不包含 1包含,包含头数据通讯可靠性会更好 设置为连续接收模式 不使用跳频 发射接收的超时时间设置为1s 负载长度设置为4 #### 03 lorapingpong系统功能开发 1 IAR工程配置 选择 project-> Edit Configurations ![](https://cf04.ickimg.com/bbsimages/201911/48ff1f27a8ffdf82d3d58590bf4f229f.png) 然后设置宏定义 ![](https://cf04.ickimg.com/bbsimages/201911/49b737be85a6faba15b56d9525942e52.png) 2 搭建框架 3 编码 04 lorapingpong系统功能调试
烧写程序
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
1
)
Hello Pointer!!!
关注
评论
(4)
登录后可评论,请
登录
或
注册
秋风2015
121
天前...
文章不能收藏呀
0
回复
发布
Hello Pointer!!!
回复
秋风2015
120
天前...
你好有问题可以加Q 860099671
0
回复
发布
秋风2015
121
天前...
不错哟
0
回复
发布
dwwzl
120
天前...
很详细的啊
1
回复
发布
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交