1+X 传感网中级备考微实例:串行通信控制 LED 灯应用开发

本文参考《新大陆传感网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 的标号②处)。

图:USART1 的参数配置

对图 1中的其他配置过程说明如下:
标号③:将 USART1 的模式配置为“Asynchronous(异步)”。
标号④:点击“Parameter Settings(参数配置)”标签。
标号⑤:配置 USART1 的“Baud Rate(波特率)”为 115200 Bits/s。
标号⑥:配置“Data Direction(数据方向)”为“Receive and Transmit(接收与发送)”。
标号⑦:已配置好功能的引脚显示。
USART1 的 NVIC 配置步骤如图 2-所示:
图2:USART1 的 NVIC 配置

点击“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 流水灯停止运行并全灭。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,841评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,415评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,904评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,051评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,055评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,255评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,729评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,377评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,517评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,420评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,467评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,144评论 3 317
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,735评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,812评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,029评论 1 256
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,528评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,126评论 2 341