实验简介
基于STM32F103C8T6的E01系列(nRF24L01P)和E01C系列(SI24R1)的EBYTE官网例程移植。EBYTE官网例程是基于STM8L151编写,本次实验的目的是将该例程移植到常见的MCU型号STM32F103C8T6,实现基本的无线通信。电脑端的串口调试助手操作和显示数据收发。(可以稍加修改,适用于其他STM32系列的MCU)
硬件环境
• 2个E01系列的相同型号的模块(或者2个E01C系列的相同型号的模块)
• 2个USB转TTL模块(CH340版本)
• 2个STM32F103C8T6最小系统板
• 1个STM32烧录器(DAP-LINK或者ST-LINK等等)
• 1台电脑
• 杜邦线若干
软件环境
• STM32的开发软件(MDK_ARM,IAR或者STM32CubeIDE等等)
• STM32CubeMX
• XCOM V2.6 串口调试助手
• CH340驱动
模块简介
视选择型号,参考厂家提供的模块手册。因为E01和E01C分别使用的nRF24L01P和SI24R1射频方案,但是寄存器基本一致,操作方式也大致相同,所以驱动程序可以通用。
本次实验使用E01-ML01D,基于nRF24L01P方案,3.3V供电,最大发射功率0dBm,参考通信距离100m。模块的寄存器和详细操作可以直接参考nRF24L01P的芯片手册。E01-ML01D模块示意及引脚定义如下图。
实验步骤
本次实验使用的STM32开发环境是MDK_ARM和STM32CubeMX,烧录器使用的是ST-LINK。涉及到的软件获取和安装方法这里不做介绍,建议参考网上的教程。注意,如果使用的大功率E01或者E01C模块,例如发射功率大于等于20dBm,需要考虑供电是否达到要求,本次使用的是E01-ML01D的发射电流在13mA,一般的STM32F103C8T6核心板都可以满足要求。
1.准备EBYTE官网例程
在亿佰特官网搜索E01-ML01D,在【相关下载】一栏,找到通信例程并下载解压。
2.新建STM32工程
①打开STM32CubeMX,新建STM32F103C8T6工程,进入MCU配置。
②配置System Core选项中的SYS和RCC
在Pinout & Configuration 一栏下展开System Core,分别配置SYS和RCC。
③Clock Configuration时钟树配置
时钟配置完成后,回到Pinout & Configuration一栏配置其他MCU外设。
④MCU的串口配置
选择USART1,配置USART1参数。
开启USART1全局中断。
⑤配置MCU的SPI
选择SPI1,配置为全双工主机模式,射频芯片的SPI速率最大支持10M,所以MCU的SPI的速率要小于等于10M,CPOL选择Low,CPHA选择1Edge,NSS引脚控制选择Software。不启用SPI1的全局中断,所以NVIC Setting不设置。
⑥GPIO配置
直接点击MCU对应引脚,将其配置。将PA4作为SPI1的片选引脚,PB0作为E01-ML01D模块的CE引脚,PB1作为E01-ML01D模块的IRQ引脚。所以需要把PA4和 PB0 配置为GPIO_Output,PB1配置为GPIO_Input。配置引脚后,在GPIO选项中,会显示配置的这三个引脚配置详情。然后在GPIO选项中,需要配置GPIO的其他参数。
这一步完成后,我们要使用的MCU外设已经基本完成配置,接下来是工程的设置和保存。
⑦设置工程以及保存路径
配置工程及代码生成配置,最后点击GENERATE CODE,等待进度条完成后会出现一个弹窗,选择Open Project 直接打开工程。接下来就是在MDK_ARM中的操作。
3.代码移植
①完成上面的步骤后,已经打开了创建的工程,先进行首次编译,查看是否有编译错误。
正常的编译结果应该是0 Error(s),0 Warning(s)。
②实现串口重定向,修改usart.c和usart.h文件
usart.c中修改两个位置。
一个是在/* USER CODE BEGIN 0 */和/* USER CODE END 0 */之间新添加如下代码:
/* USER CODE BEGIN 0 */
uint8_t uart_rx_data = 0;//串口中断接收的数据存储
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
/* USER CODE END 0 */
另一个是修改void MX_USART1_UART_Init(void)函数,在该函数中的
/* USER CODE BEGIN USART1_Init 2 */和 /* USER CODE END USART1_Init 2 */之间加入代码:
void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
HAL_UART_Receive_IT(&huart1,&uart_rx_data,1);//开启接收中断
/* USER CODE END USART1_Init 2 */
}
Usart.h中,需要包含stdio.h,在/* USER CODE BEGIN Includes */和/* USER CODE END Includes */之间加入代码:
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */
Usart.h中,在/* USER CODE BEGIN Private defines */和/* USER CODE END Private defines */之间加入代码:
/* USER CODE BEGIN Private defines */
extern uint8_t uart_rx_data;
/* USER CODE END Private defines */
启用MicroLIB
③在创建的工程路径下,新建一个名为MyFiles的文件夹,并将例程中的如下文件均复制到MyFiles文件夹中。
④添加MyFiles的文件夹路径到工程。
⑤在工程中新建文件夹,并将复制的文件添加到工程之中
⑥修改添加到MyFiles文件夹下的所有.c和.h文件
由于涉及到的修改较多,不做一一介绍,直接给出修改后的该文件夹下的所有文件附件。(可联系获取)
⑦修改main.c文件
在/* USER CODE BEGIN Includes */和/* USER CODE END Includes */之间添加为app.h 和bsp.h的包含:
/* USER CODE BEGIN Includes */
#include "bsp.h"
#include "app.h"
/* USER CODE END Includes */
修改int main(void)函数:
/**
* @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_SPI1_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
BSP_MCU_Initial();
BSP_RF_Initial();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
APP_Process();
}
/* USER CODE END 3 */
}
添加USART1的接收和发送中断回调函数,
在/* USER CODE BEGIN 4 */和/* USER CODE END 4 */加入代码:
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart == &huart1)
{
Uart_Rx_interrupt_Cb();
}
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if(huart == &huart1)
{
Uart_Tx_interrupt_Cb();
}
}
/* USER CODE END 4 */
⑧修改stm32f1xx_it.c文件
添加对app.h的包含,在/* USER CODE BEGIN Includes */和/* USER CODE END Includes */之间加入代码:
/* USER CODE BEGIN Includes */
#include "app.h"
/* USER CODE END Includes */
修改void SysTick_Handler(void)函数,
在 /* USER CODE BEGIN SysTick_IRQn 1 */和/* USER CODE END SysTick_IRQn 1 */之间加入:
/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
Uart_1ms_Interrupt_Cb();
/* USER CODE END SysTick_IRQn 1 */
}
至此,程序移植已经全部完成,再次重新编译。如果出现warning: #1-D: last line of file ends without a newline这个警告,请在该文件最后一行添加新行。
通信验证
①程序下载
将ST-LINK的下载接口与STM32核心板的下载接口连接,对应接线如下:
Debug配置:
配置完成后,点击LOAD进行下载。
下载成功后,会出现如下提示:
②硬件连接
建议在接线过程中断电操作。STM32核心板的供电使用自带的USB接口供电。
STM32核心板与E01-ML01D连接
STM32核心板与USB转TTL工具连接
③通信测试
将核心板通过USB接口供电,USB转TTL工具连接上电脑上的串口调试助手。串口调试助手配置如下:
将STM32核心板复位,它首先会检查与E01-ML01D的连接。如果连接成功,则会打印Link successful。如果链接失败,则会打印Link Fail Please check and reset module。最大连接次数为6次,每次连接会打印当前连接次数。
数据发送和接收,例程使用了nRF24L01P的ACK功能,所以在发送成功则会打印Send TX_DS,发送失败会打印Send MAX_RT。
总结
以上实验中,实现了基于STM32F103C8T6核心板的E01-ML01D的驱动移植以及通信验证,其中的E01-ML01D可以替换为任意型号的nRF24L01P或者Si24R1的模块。也可以稍加修改,适用于其他STM32系列的MCU。