游戏百科

STM32新手必看!LoRa模块驱动最全教程

从零搭建基于STM32的M系列通信例程介绍本文适用于零基础,手把手搭建基于STM32单片机控制亿佰特公司E22-xxxM

从零搭建基于STM32的M系列通信例程

介绍

本文适用于零基础,手把手搭建基于STM32单片机控制亿佰特公司E22-xxxMxx的模块,旨在降低M系列模块开发难度,帮助大家更快上手M系列的模组。

二、CubeMX生成HEL库代码文件

本文使用的单片机型号为STM32F407VET6,打开STM32CubeMX软件,如果没有这个软件请到官网进行下载,官网连接https://www.st.com/stm32cubemx。新建代码工程如图2.1所示,进入CubeMX界面之后,点击“序号1”新建代码工程。

图2.1

选择对应的芯片创建工程。如图2.2所示,进入工程创建之后,在“序号1”的框框里面输入自己的STM单片机型号,我这里使用的是STM32F407VET6单片机,所以输入“STM32F407VET6”,然后选中“序号2”的内容,最后点击“序号3”,开始新工程的搭建。

图2.2

配置SWD烧录接口。如图2.3所示,进去芯片配置界面,点击“System Core”选项卡里面的“序号1”SYS,然后找到“序号2”的选择框,我们选择“Serial Wire”,这样程序烧录引脚就配置好了,以便后续程序的烧入和Debug调试。

图2.3

配置时钟输入源。如图2.4所示,还是在“System Core”选项卡里面找到“序号1”RCC,选择单片机的时钟源,点击“序号2”的下拉菜单,选择“Crystall/Ceramic Resonator”晶振,这里只配了高速时钟,如果需要低速时钟的话,可以自己配置下面的选项卡“Low Speed Clock(LSE)”配置即可。

图2.4

配置LED灯初始化。如图2.5所示,接下来配置LED,用于发送接收时候状态的指示,可以选择不配置。本文使用到的单片机控制LED 的GPIO口是PC13,这里选择你自己的单片机控制LED的IO口引脚就行,本文就以PC13口作为示例。首先找到并点击“序号1”的PC13芯片引脚,选择“GPIO_Output”,接下来点击“序号3”就会弹出下面的选择框,如“序号4”所示,可以参考“序号4”的配置,这样LED的GPIO口就配置好了。

图2.5

配置DIO1中断引脚。DIO1是亿佰特M系类模块特有的可配置通用 IO 口,不同单片机引脚些许不同,主要是看单片机这个引脚有无EXTI中断引脚,本文是以PA3作为示例,如图2.6所示,首先点击“序号1”,然后选择“GPIO_EXTI3”,继续点击“序号3”,然后按照“序号4”进行配置。

图2.6

配置NSS引脚。如图2.7所示,按照上文的方式配置SPI_CS片选引脚。

图2.7

配置RESET复位引脚。如图2.8所示,按照上文的方式配置RESET引脚。

图2.8

配置BUSY引脚。如图2.9所示,按照上文的方式配置BUSY引脚。

图2.9

配置TXEN发送使能引脚。如图2.10所示,按照上文的方式配置TXEN引脚。

图2.10

配置RXEN接收使能引脚。如图2.11所示,按照上文的方式配置RXEN引脚。

图2.11

配置NVIC中断。引脚已经配置完毕,如图2.12所示,在这个界面选择“序号1”NVIC,这里开启EXTI中断使能,勾选上“序号2”,使能EXTI中断。

图2.12

配置系统时钟树。如图2.13所示。点击序号1“Clock Configuration”,然后在“序号2”的框中改为8,我们选择的是8MHz的晶振,这里按照自己单片机的实际晶振可做修改,然后点击“序号3”,再点击“序号4”,最后把“序号5”的框中改为72,这里配置的系统时钟频率是72MHz,也可以自己选择配置成自己想要且合理的系统时钟频率。

图2.13

配置SPI通信。如图2.14所示,选择“序号1”的Connectivity,点击“序号2”的SPI1,然后点击“序号3”的菜单下拉框,选择“Full-Duplex Master”,继续点击“序号4”出现下面的选项框,找到“序号5”,把这个“Prescaler”改成16,注意不管怎么配置,一定要确保“序号5”下面一行的Baud Rate为4.5Mbits/s或者更高。

图2.14

配置USART串口。如图2.15所示,选择“序号1”,点击序号“2”,选择“USART1”,然后点击“序号3”的菜单下拉框,选择“Asynchronous”,然后点击“序号4”弹出选择框,找到“序号5”,把波特率改为“9600 Bit/s”,这样串口通信就配置好了。

图2.15

配置USART串口中断。如图2.16所示,选择“序号1”,在点击“序号2”的USART1,选择“序号3”的 “NVIC Settings”,然后勾选“序号4”,使能串口中断。

图2.16

项目管理工程配置。如图2.17所示,先点击“序号1”,然后在“序号2”的框中为自己的工程文件取名字,我这里取名为“STM_M”,再在“序号3”中选择自己工程文件的存储位置,最后在选择框“序号4”中选择“MDK-ARM”。

图2.17

项目管理代码生成器配置。如图2.18所示,选择“序号1”,然后点击“序号2”,这里选项的意思是该工程文件只生成必要的函数库文件,再勾选上“序号3”,最后选择点击“序号4”完成工程代码的生成。

图2.18

三、Keil文件配置及其代码编写

3.1 射频芯片底层驱动文件配置

本文使用E22系列模块,使用的射频芯片为sx126x,可以在Semtech官网进行下载sx126x驱动文件,下载地址如下

https://github.com/Lora-net/sx126x_driver/archive/refs/tags/v2.3.2.zip

把下载好的文件解压缩,得到“sx126x_driver-x.x.x”文件夹,把此文件夹移动到XX\STM32_M\Drivers项目的驱动文件夹下。打开keil工程“STM32_M.uvprojx”,按照如图3.1所示,添加sx126x驱动.c文件。

图3.1

再通过图3.2所示,添加sx126x驱动.h文件。注意“序号5”文件路径是XX\STM32_M\Drivers\sx126x_driver-2.3.2\src。

图3.2

3.2 编写射频模块硬件抽象层代码

e22_hal.c代码见附件1,e22_demo.c代码见附件2。

在XX\STM32_M\Core\Src文件下创建“e22_hal.c”文件,名字可以自己取。然后按照图3.3所示,添加e22_hal.c文件。

图3.3

然后在e22_hal.c文件中进行代码的编写,先引用sx126x、gpio和spi的头文件,如图3.4所示。

图3.4

编写射频模组复位函数和状态忙等待函数,如图3.5所示。

图3.5

编写射频模组唤醒函数,如图3.6所示。

图3.6

编写射频模组寄存器写入函数,如图3.7所示。

图3.7

编写射频模组寄存器读取函数,如图3.8所示。

图3.8

编写射频模组发送和接收切换函数,如图3.9所示。

图3.9

最后在e22_hal.h文件的最末尾加上如下代码,详细见图3.9(2)所示。

sx126x_hal_status_t sx126x_rf_switch_tx(void);

sx126x_hal_status_t sx126x_rf_switch_rx(void);

图3.9(2)

在XX\STM32_M\Core\Src文件下创建“e22_demo.c”文件和e22_demo.h,名字可以自己取。然后在Keil中像添加e22_hal.c文件一样添加e22_ demo.c文件。

然后在e22_demo.c文件中进行代码编写,如图3.10所示,引用头文件和书写相关结构体,注意配置默认参数时,要注意自己模块的初始频率,本文使用的170MHz的频率,因此选择frequency_mhz = 170。

图3.10

编写射频模组SPI读写测试和晶振启动测试函数,如图3.11所示。

图3.11

编写射频模组初始化函数,如图3.12所示,注意图中红色框框的内容,选择自己模块的对应频率,本文使用模块的频率为170Mhz。

图3.12

编写射频模组重新配置参数函数,如图3.13所示。

图3.13

编写射频模组的射频发射函数,如图3.14所示。

图3.14

编写射频模组的持续接收函数,如图3.15所示。

图3.15

编写射频模组查询是否有接收数据的函数,如图3.16所示。

图3.16

编写射频模组中断响应函数,如图3.17和图3.18所示。

图3.17

图3.18

3.3 其他细节代码

在main.h文件中,添加头文件引用,结构体和函数声明,代码如下,具体见图3.19和2.20所示。

#include <stdbool.h>

#include <stdio.h>

typedef struct

{

int lora_sf;

int lora_bw;

int lora_cr;

int frequency_mhz;

int tx_power;

int tx_count;

}menu_config_t;

extern menu_config_t user_config;

void e22_demo_init( void );

void e22_demo_menu_config( menu_config_t *config );

void e22_demo_transmit( uint8_t *buffer , uint8_t length );

void e22_demo_receive( void );

void e22_demo_dio1_interrupt_callback(void);

bool e22_demo_check_rx_done( uint8_t *buffer, uint8_t * length  , int8_t *rssi);

图3.19

图3.20

在stm32f4xx_it.c文件中(不同型号的单片机的文件名不一样),添加中断回调函数,最好在void EXTI3_IRQHandler(void)函数下方,添加如下函数,详细见图3.21所示。

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

{

if( GPIO_Pin == DIO1_Pin )

{

e22_demo_dio1_interrupt_callback();

}

}

图3.21

四、应用与实现

4.1 接收

在main.c文件中,while(1)前面和while(1)里面添加如下代码,详细见图4.1所示。

e22_demo_init();

e22_demo_menu_config( &user_config );

e22_demo_receive();

static uint8_t rx_mode_buffer[255];

static uint8_t rx_mode_length = 0;

int8_t rx_rssi = 0;

if( e22_demo_check_rx_done( rx_mode_buffer, &rx_mode_length, &rx_rssi) == true )

{

/* 如果接收到数据,灯进行闪烁 */

HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);

}

图4.1

软件配置好了,接线按照STM32CubeMX配置的进行连线,下图4.2是本文使用的单片机与模块的接线,最后下载程序到单片机,射频模块接上天线,最终完成接收的功能。注意,接收到信息并未处理,请自主实现,本教程模组接收到信息时,对应LED灯闪一下。

图4.2

4.2 发送

在main.c文件中,while(1)前面和while(1)里面添加如下代码,详细见图4.3所示。

e22_demo_init();

e22_demo_menu_config( &user_config );

e22_demo_receive();

uint8_t value[12] = {0x54,0x58,0x2E,0x30,0x31,0x30,0x2E,0x30,0x30,0x34,0x2E,0x00};

uint8_t tx_length = 0;

e22_demo_transmit( (uint8_t*)value , 12);

HAL_Delay(500);

HAL_GPIO_WritePin( LED_GPIO_Port,  LED_Pin, GPIO_PIN_SET);

HAL_Delay(500);

图4.3

软件配置好了,接线按照STM32CubeMX配置的进行连线,最后下载程序到单片机,射频模块接上天线,最终完成发送的功能,每隔0.5秒发送一包数据。