本文参考《新大陆传感网1+X培训中级教材》
1.任务要求:
本任务要求设计一个 LED 流水灯系统,该系统与上位机之间通过串行通信接口相连。上位 机可发送命令对 LED 流水灯系统进行控制,具体要求如下:
系统中有 8 个 LED 灯,分别是 LED1~LED8。系统上电时,8 个 LED 灯默认为熄灭状态。系统运行时,8 个 LED 灯依次点亮。
LED 流水灯的工作模式有两种:
模式一:8 个 LED 灯依次点亮,每个 LED 灯点亮 1 秒后熄灭,然后切换为另一个,点亮顺序为 LED0、LED1、……、LED7,并以此循环往复;
模式二:8 个 LED 灯依次点亮,每个 LED 灯点亮 1 秒后熄灭,然后切换为另一个,点亮顺序为 LED7、LED6、……、LED0,并以此循环往复。
上位机以串行通信的方式发送命令至该系统进行 LED 流水灯工作模式的切换 “mode_1#”和“mode_2#”分别对应模式一和模式二的控制,命令“stop#”控制 LED 流水灯停止运行并全灭;
2.任务实施
2.1. 建立 STM32CubeMX 工程并生成初始 C 代码
(1). 建立 STM32CubeMX 工程并生成初始 C 代码在“STM32_WorkSpace”文件夹下新建文件夹“task4_USART_WaterFlow_LED”用于保 存本任务工程。
(2).在“STM32_WorkSpace”文件夹下新建文件夹“task4_USART_WaterFlow_LED”用于保
存本任务工程。
(3)选择 MCU 型号
(4)配置调试端口
(5)配置 MCU 时钟树
(6)配置 LED 灯的 GPIO 功能
LED0~LED7 共 8 个 LED 灯的 GPIO 引脚功能的配置可参考 按键+点灯的任务;
(7)配置 USART 外设的工作参数
展开“Pinout & Configuration”标签页左侧的“Connectivity”选项(图 2-46 的 标号①处),选择“USART1”选项(图 2-46 的标号②处)。
对图 1中的其他配置过程说明如下:
标号③:将 USART1 的模式配置为“Asynchronous(异步)”。
标号④:点击“Parameter Settings(参数配置)”标签。
标号⑤:配置 USART1 的“Baud Rate(波特率)”为 115200 Bits/s。
标号⑥:配置“Data Direction(数据方向)”为“Receive and Transmit(接收与发送)”。
标号⑦:已配置好功能的引脚显示。
USART1 的 NVIC 配置步骤如图 2-所示:
点击“NVIC Settings”标签(图 2 的标号①处),勾选“Enabled”复选框(图 2 的标号②处)使能 USART1 的“global interrupt(全局中断)”。其中断优先级保留默认配置:抢占优先级“0”,子优先级“0”。
(8)保存 STM32CubeMX 工程
点击“File(文件)”菜单,选择“Save Project(保存工程)”选项。然后定位到文件
夹“D:\STM32_WorkSpace\task4_USART_WaterFlow_LED”,点击“确定”保存 STM32CubeM 工程
(9)生成初始 C 代码工程
参考 相关内容进行“C 代码生成”与“工程保存”的配置,最后点击“GENERATE CODE(生成代码)”按钮,生成串行通信控制 LED 灯系统的初始 C 代码工程。
2.2 完善代码
(1)在usart.h 或main.c中补充头文件:
#include <stdio.h>
在usart.c或 main.c补充代码:
int fputc(int ch,FILE *f)
{
HAL_UART_Transmit(&huart1,(uint8_t *)&ch,1,0xffff);
return ch;
}
(1)修改中断服务程序
将 “ stm32f1xx_it.c ” 文 件 中 的 中 断 服 务 程 序 USART1_IRQHandler()“HAL_UART_IRQHandler(&huart1)”修改为“USER_UART_IRQHandler(&huart1)”。修改
后的代码如下:
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
USER_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
}
(2)编写用户自定义的 USART 接收中断服务函数
在“main.h”中输入以下代码:
/* USER CODE BEGIN EFP */
void USER_UART_IRQHandler(UART_HandleTypeDef *huart);
/* USER CODE END EFP */
在“main.c”中输入以下代码:
/* USER CODE BEGIN PV */
uint8_t dataBuf[128] = {0};
const char stringMode1[8] = "mode_1#";
const char stringMode2[8] = "mode_2#";
const char stringStop[8] = "stop#";
int8_t ledMode = -1;
uint16_t LED_value = 0;
uint8_t uart1RxState = 0;
uint8_t uart1RxCounter = 0;
uint8_t uart1RxBuff[128] = {0};
/* USER CODE END PV */
在 main.c 中编写 USER_UART_IRQHandler 的业务逻辑代码:
/* USER CODE BEGIN 4 */
void USER_UART_IRQHandler(UART_HandleTypeDef *huart)
{
if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE) != RESET))
{
__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
uart1RxBuff[uart1RxCounter] = (uint8_t)(huart1.Instance->DR & (uint8_t)0x00ff);
uart1RxCounter++;
__HAL_UART_GET_FLAG(&huart1,UART_FLAG_RXNE);
}
if((__HAL_UART_GET_FLAG(&huart1,UART_FLAG_IDLE) != RESET))
{
__HAL_UART_DISABLE_IT(&huart1,UART_IT_IDLE);
uart1RxState = 1;
}
}
/* USER CODE END 4 */
(3)编写 LED 流水灯显示程序
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_USART1_UART_Init();
/* USER CODE BEGIN 2 */
__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);
printf("hello word\r\n");
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
if(uart1RxState == 1)
{
if(strstr((const char *)uart1RxBuff,stringMode1)!=NULL)
{
printf("I'm in mode_1!\r\n");
ledMode = 1;
LED_value = 0x80;
}
else if(strstr((const char *)uart1RxBuff,stringMode2)!=NULL)
{
printf("I'm in mode_2!\r\n");
ledMode = 2;
LED_value = 0x01;
}
else if(strstr((const char *)uart1RxBuff,stringStop)!=NULL)
{
printf("I'm stop!\r\n");
ledMode = 0;
LED_value = 0;
}
uart1RxState = 0;
uart1RxCounter = 0;
memset(uart1RxBuff,0,128);
}
HAL_GPIO_WritePin(GPIOE,0xff,GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOE,LED_value,GPIO_PIN_RESET);
HAL_Delay(1000);
switch(ledMode)
{
case 1:
LED_value = LED_value>>1;
if(LED_value==0)
LED_value = 0x80;
break;
case 2:
LED_value = LED_value<<1;
if(LED_value==0x100)
LED_value=0x01;
break;
case 0:
LED_value = 0;
break;
}
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
代码编写好后,编译程序,下载程序到 STM32 开发板后 MCU 会自动重启并运行, 一开始 8 个 LED 灯默认为熄灭状态。系统运行时,8 个 LED 灯依次点亮。打开串口助手,输入命令“mode_1#”,可以看到 8 个 LED 灯依次点亮,每个 LED 灯点亮 1 秒后熄灭,然后切换为另一个,点亮顺序为 LED1、LED1、……、LED8,并以此循环往复。
输入“mode_2#”,8 个 LED 灯依次点亮,每个 LED 灯点亮 1 秒后熄灭,然后切换为另一个,
点亮顺序为 LED8、LED6、……、LED1,并以此循环往复。输入“stop#”控制 LED 流水灯停止运行并全灭。