【STM32+CubeMX+HAL库】摩尔斯译码器开发

        虽然寄存器开发执行效率很高,但代码的移植性只能说一般,标准库导入文件,相对来说也比较麻烦,那么CubeMX和HAL库的出现,让广大开发者们多了一份选择。

        STM32CubeMX给了想上手开发STM32的同学一个非常便利的条件,希望越来越多的开发者们能轻松上手这款工具,我也在不断努力学习HAL库开发STM32,供广大爱好者们参考学习。

        同时这也是我发的第一篇博客,会有许多问题,希望大家能及时指出,我会感激不尽的,希望通过这个博客,能对大家在STM32的学习有所帮助。

我用的板子是正点原子探索者开发板,MCU型号为STM32F407ZGT6。

我喜欢稚辉君所称的优雅的开发方式,我选用JetBrians系的CLion作为我的IDE

具体配置方法参见稚辉君b站专栏配置CLion用于STM32开发【优雅の嵌入式开发】 - 哔哩哔哩 (bilibili.com)

STM32CubeMX版本6.5.0是最新版本

目录

一、要求

二、基本配置

1.配置时钟

 2.按键的设置:

3. 闪烁的LED设置:

4.改变亮度的LED的设置:

 5.计算按键无操作的时间的配置:

 6.串口的配置:

 7.总体的中断配置:

三、基本思路及代码设计

功能一

功能二

功能三


一、要求

        我们先看一下这个摩尔斯译码器的要求:

【STM32+CubeMX+HAL库】摩尔斯译码器开发_第1张图片

 【STM32+CubeMX+HAL库】摩尔斯译码器开发_第2张图片

【STM32+CubeMX+HAL库】摩尔斯译码器开发_第3张图片

20210811221614776.png

【STM32+CubeMX+HAL库】摩尔斯译码器开发_第4张图片

 

 我们可以分析一波摩尔斯译码器功能大致是这样的:

我们首先要明确,摩尔斯译码器的原理就是将符号转换成点和划的排列组合或将点和划的组合转换成字符。

那么,摩尔斯译码器可以分为输入功能和输出功能。

输出功能:长短按的按键结合,构成划和点的组合,再将这些组合,翻译成最终的字符并输出。

输入功能:输入字符,翻译成点和划,再将这些组合,反映在灯亮的时间长短上。

我们可以直接分析所需要用到的外设:

反映亮度的LED:定时器PWM功能;

闪烁的LED:通用输入输出端口GPIO;

按键:外部中断EXTI;

发送和接受字符:通用异步收发器UART,并开启DMA。

需要的外设就这么多,我们一个一个功能开始讲。

二、基本配置

首先我们在cubemx里配置一些基本的设置

1.配置时钟

开启外部高速时钟HSE,晶振设置为8MHz,主频168MHz。

选择HSE,PLLCLK通道。

 

【STM32+CubeMX+HAL库】摩尔斯译码器开发_第5张图片

 

 2.按键的设置:

PE2对应KEY2,开启外部中断EXTI2,下降沿触发,默认上拉。

【STM32+CubeMX+HAL库】摩尔斯译码器开发_第6张图片

 

【STM32+CubeMX+HAL库】摩尔斯译码器开发_第7张图片

 

3. 闪烁的LED设置:

GPIO输出模式(GPIO_Output),推挽输出(Output Push Pull),高速输出模式(Fast Mode)

【STM32+CubeMX+HAL库】摩尔斯译码器开发_第8张图片

 

 

4.改变亮度的LED的设置:

时钟源选择内部时钟,

PF9对应TIM14,CHANNEL_1通道,开启PWM模式,

预分频系数设置为83,则频率=84MHz/(83+1)=1MHz, 

重装载值设置为999,周期=1us×1000=1ms,

【STM32+CubeMX+HAL库】摩尔斯译码器开发_第9张图片

 

 

 5.计算按键无操作的时间的配置:

选择TIM2作为计算时间的定时器,并开启内部时钟,

预分频系数设置为8400-1,则频率=84MHz/8400=10000Hz,

重装载值设为10000-1,则周期=0.1ms×10000=1s

 

【STM32+CubeMX+HAL库】摩尔斯译码器开发_第10张图片

 6.串口的配置:

打开USART1串口,开启异步收发模式,波特率为115200,1停止位,无奇偶校验并打开DMA,将USART1_RX设置为循环接收模式。

【STM32+CubeMX+HAL库】摩尔斯译码器开发_第11张图片

 

【STM32+CubeMX+HAL库】摩尔斯译码器开发_第12张图片

 

 

 

 7.总体的中断配置:

这些中断优先级不要设为0,以防与系统中更重要的中断打架

以我的习惯设置抢占优先级为四位,那么子优先级为零位

 外部中断EXTI2:抢占优先级设置为5,子优先级为0;

定时器TIM2:抢占优先级为6,子优先级为0;

串口异步收发USART1:抢占优先级为7,子优先级为0;

 

【STM32+CubeMX+HAL库】摩尔斯译码器开发_第13张图片

 

最后将工程完善一下

工程名称什么的就不在这里多讲

注意要把各个外设的代码分成.c和.h文件,便于查找各个外设的代码。 

【STM32+CubeMX+HAL库】摩尔斯译码器开发_第14张图片

 

 【STM32+CubeMX+HAL库】摩尔斯译码器开发_第15张图片

 

三、基本思路及代码设计

功能一

        按键按下则开启外部中断,经过软件消抖后,计算按键按下的时间,记录进入中断的次数,在这里,我定义了一个数组sign[6](由0,1,9组成,0代表点,1代表划,9代表空),依据摩尔斯电码图,一个字符对应的点划数最多为六,那么一次翻译最多6个点划就够了,然后进入翻译,将点划组合数组翻译成字符,传送回上位机。我们在按键按完之后打开计数的定时器TIM2,每到1s进入一次中断,并把字符发回上位机。

主函数:

/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "Key.h"
#include "breath_led.h" 
#include "sign.h"
#include "input_content.h" 
#include "string.h"
/* USER CODE END Includes */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define UART_DMA_BUFF_LEN_MAX 255//接收字符的最大长度
#define SIGN_LENGTH_MAX 6//点划符号组的最大长度
#define LED_LONG_TIME 600//LED长亮时间
#define LED_SHORT_TIME 200//LED短亮时间
#define LED_REST_TIME 200//LED间隔时间
#define CHARACTER_REST_TIME 1000//每个字符之间LED的空闲时间
#define KEY_LONG_OR_SHORT 500//长按和短按的判定标识
/* USER CODE END PD */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
uint8_t UartRxBuff[UART_DMA_BUFF_LEN_MAX];//接收的字符
uint8_t UartTxBuff;//发送的字符
uint16_t UartRxBuffLen = 0;//已收到字符串长度
uint32_t exti_time = 0;//进入中断的次数-1
uint32_t key_down_time = 0;//按键按下的时间
uint32_t sign[SIGN_LENGTH_MAX] = {null,null,null,null,null,null};//默认电码组合为空
enum
{
	point = 0U,//点
	row = 1U,//划
	null = 9U//空
};

/* 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_TIM2_Init();
  MX_TIM14_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
	__HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	 HAL_UART_Receive_DMA(&huart1,UartRxBuff,UART_DMA_BUFF_LEN_MAX);
     for(int x = 0;UartRxBuff[x] != '\0';x++)
     {
         character_to_sign(UartRxBuff + x);
         led_control();
         HAL_Delay(CHARACTER_REST_TIME);
     }
     memset(UartRxBuff,0,sizeof UartRxBuff);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

中断回调函数

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if(GPIO_Pin == GPIO_PIN_2){
        /**关闭定时器*/
        HAL_TIM_Base_Stop_IT(&htim2);
        /**计数器值清0*/
        __HAL_TIM_SET_COUNTER(&htim2,0);
        /**检测按键按下的时间*/
        while(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin) == GPIO_PIN_RESET){
            delayMicroseconds(1000);
            key_down_time++;
        }
        sign[exti_time] = Key_Time_Judge(key_down_time);
        /**根据进入中断的次数将每次按下的时间翻译成代号*/
        exti_time = Key_Exti_Judge(exti_time);
        /**判断是否要发送*/
        DataTx_Judge();
        /**打开定时器*/
        HAL_TIM_Base_Start_IT(&htim2);
        /**按下时间清0*/
        key_down_time = 0;
    }
}

这里面有一个延时函数delayMicroseconds()

参见: STM32精确延时/计时方法(不用定时器) - 知乎 (zhihu.com)

static inline void delayMicroseconds(uint32_t us)
{
    __IO uint32_t currentTicks = SysTick->VAL;
    /* Number of ticks per millisecond */
    const uint32_t tickPerMs = SysTick->LOAD + 1;
    /* Number of ticks to count */
    const uint32_t nbTicks = ((us - ((us > 0) ? 1 : 0)) * tickPerMs) / 1000;
    /* Number of elapsed ticks */
    uint32_t elapsedTicks = 0;
    __IO uint32_t oldTicks = currentTicks;
    do {
        currentTicks = SysTick->VAL;
        elapsedTicks += (oldTicks < currentTicks) ? tickPerMs + oldTicks - currentTicks :
                        oldTicks - currentTicks;
        oldTicks = currentTicks;
    } while (nbTicks > elapsedTicks);
}

根据时间判定点和划

uint32_t Key_Time_Judge(uint32_t time)
{
	uint32_t x;
	/*500ms内判定为点*/
	if(time <= KEY_LONG_OR_SHORT)
		x = point;
	/*大于500ms判定为划*/
	else if(time > KEY_LONG_OR_SHORT)
		x = row;
	/*其他为null*/
	else
		x = null;
	return x;
}

判断点和划的代号数组是否已经全部赋值

uint32_t Key_Exti_Judge(uint32_t exti)
{
	switch(exti)
	{
		/*如果sign数组到第六个元素,进入中断次数清0*/
		case 5:
		{
			exti = 0;
			break;
		}
		/*没到则递增*/
		default:
		{
			exti++;
			break;
		}
	}
	return exti;
}

判断是否要发送

void DataTx_Judge(void)
{
	if(exti_time == 0)
	{
		/*将时间代号转换成字符*/
		UartTxBuff = sign_to_character(sign);
		/*发送*/
		HAL_UART_Transmit_DMA(&huart1,&UartTxBuff,1);
		/*将时间代号清0*/
		sign_clear();
	}
}

清空点划的组合

void sign_clear(void)
{
	int y;
	for(y = 0;y < SIGN_LENGTH_MAX;y++)
	{
		sign[y] = null;
	}
}

按键1s后无操作将信息发送出去

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim == &htim2)
	{
		/*关掉定时器*/
		HAL_TIM_Base_Stop_IT(&htim2);
		/*清空计数器值*/
		TIM2->CNT = 0;
		/*进入中断次数清0*/
		exti_time = 0;
		/*把得到的时间长短转译成的代号翻译成文字*/
		UartTxBuff = sign_to_character(sign);
		/*清空时间长短转译成的代号*/
		sign_clear();
		/*向上位机传输字符*/
		HAL_UART_Transmit_DMA(&huart1,&UartTxBuff,1);
		/*判断字符是否为数字,并控制灯的亮度*/
		LED_Brightness_Control(&UartTxBuff);
	}
}

将点和划翻译成字符

/*按键电平时间长短转换成字符*/
unsigned char sign_to_character(uint32_t * p)
{
	unsigned char character;
	     if(*p == point 	&& *(p+1) == row && *(p+2) == null &&*(p+3) == null &&*(p+4) == null && *(p+5) == null) character = 'A';
	else if(*p == row 	&&*(p+1) == point &&*(p+2) == point &&*(p+3) == point &&*(p+4) == null  &&*(p+5) == null)	 character = 'B';
	else if(*p == row 	&&*(p+1) == point &&*(p+2) == row 	&&*(p+3) == point &&*(p+4) == null	&&*(p+5) == null)	 character = 'C';
	else if(*p == row 	&&*(p+1) == point &&*(p+2) == point &&*(p+3) == null	&&*(p+4) == null	&&*(p+5) == null)	 character = 'D';
	else if(*p == point &&*(p+1) == null	&&*(p+2) == null	&&*(p+3) == null	&&*(p+4) == null	&&*(p+5) == null)	 character = 'E';
	else if(*p == point &&*(p+1) == point &&*(p+2) == row 	&&*(p+3) == point &&*(p+4) == null	&&*(p+5) == null)	 character = 'F';
	else if(*p == row 	&&*(p+1) == row 	&&*(p+2) == point &&*(p+3) == null	&&*(p+4) == null	&&*(p+5) == null)	 character = 'G';
	else if(*p == point &&*(p+1) == point &&*(p+2) == point &&*(p+3) == point &&*(p+4) == null	&&*(p+5) == null)	 character = 'H';
	else if(*p == point &&*(p+1) == point &&*(p+2) == null	&&*(p+3) == null	&&*(p+4) == null	&&*(p+5) == null)	 character = 'I';
	else if(*p == point &&*(p+1) == row 	&&*(p+2) == row		&&*(p+3) == row		&&*(p+4) == null	&&*(p+5) == null)	 character = 'J';
	else if(*p == row 	&&*(p+1) == point &&*(p+2) == row		&&*(p+3) == null	&&*(p+4) == null	&&*(p+5) == null)	 character = 'K';
	else if(*p == point &&*(p+1) == row 	&&*(p+2) == point &&*(p+3) == point &&*(p+4) == null	&&*(p+5) == null)	 character = 'L';
	else if(*p == row 	&&*(p+1) == row 	&&*(p+2) == null	&&*(p+3) == null	&&*(p+4) == null	&&*(p+5) == null)	 character = 'M';
	else if(*p == row 	&&*(p+1) == point &&*(p+2) == null	&&*(p+3) == null	&&*(p+4) == null	&&*(p+5) == null)	 character = 'N';
	else if(*p == row		&&*(p+1) == row 	&&*(p+2) == row		&&*(p+3) == null	&&*(p+4) == null	&&*(p+5) == null)	 character = 'O';
	else if(*p == point &&*(p+1) == row 	&&*(p+2) == row		&&*(p+3) == point &&*(p+4) == null	&&*(p+5) == null)	 character = 'P';
	else if(*p == row		&&*(p+1) == row		&&*(p+2) == point &&*(p+3) == row 	&&*(p+4) == null	&&*(p+5) == null)	 character = 'Q';
	else if(*p == point &&*(p+1) == row 	&&*(p+2) == point	&&*(p+3) == null	&&*(p+4) == null	&&*(p+5) == null)	 character = 'R';
	else if(*p == point &&*(p+1) == point &&*(p+2) == point &&*(p+3) == null	&&*(p+4) == null	&&*(p+5) == null)	 character = 'S';
	else if(*p == row		&&*(p+1) == null	&&*(p+2) == null	&&*(p+3) == null	&&*(p+4) == null	&&*(p+5) == null)	 character = 'T';
	else if(*p == point &&*(p+1) == point	&&*(p+2) == row 	&&*(p+3) == null	&&*(p+4) == null	&&*(p+5) == null)	 character = 'U';
	else if(*p == point &&*(p+1) == point	&&*(p+2) == point	&&*(p+3) == row 	&&*(p+4) == null	&&*(p+5) == null)	 character = 'V';
	else if(*p == point &&*(p+1) == row 	&&*(p+2) == row 	&&*(p+3) == null	&&*(p+4) == null	&&*(p+5) == null)	 character = 'W';
	else if(*p == row		&&*(p+1) == point &&*(p+2) == point &&*(p+3) == row 	&&*(p+4) == null	&&*(p+5) == null)	 character = 'X';
	else if(*p == row		&&*(p+1) == point &&*(p+2) == row 	&&*(p+3) == row		&&*(p+4) == null	&&*(p+5) == null)	 character = 'Y';
	else if(*p == row		&&*(p+1) == row		&&*(p+2) == point &&*(p+3) == point &&*(p+4) == null	&&*(p+5) == null)	 character = 'Z';
	else if(*p == row		&&*(p+1) == row		&&*(p+2) == row 	&&*(p+3) == row 	&&*(p+4) == row 	&&*(p+5) == null)	 character = '0';
	else if(*p == point &&*(p+1) == row 	&&*(p+2) == row 	&&*(p+3) == row 	&&*(p+4) == row 	&&*(p+5) == null)	 character = '1';
	else if(*p == point &&*(p+1) == point &&*(p+2) == row		&&*(p+3) == row 	&&*(p+4) == row 	&&*(p+5) == null)	 character = '2';
	else if(*p == point &&*(p+1) == point &&*(p+2) == point &&*(p+3) == row 	&&*(p+4) == row 	&&*(p+5) == null)	 character = '3';
	else if(*p == point &&*(p+1) == point &&*(p+2) == point &&*(p+3) == point &&*(p+4) == row 	&&*(p+5) == null)	 character = '4';
	else if(*p == point &&*(p+1) == point &&*(p+2) == point &&*(p+3) == point &&*(p+4) == point &&*(p+5) == null)	 character = '5';
	else if(*p == row		&&*(p+1) == point &&*(p+2) == point &&*(p+3) == point &&*(p+4) == point &&*(p+5) == null)	 character = '6';
	else if(*p == row		&&*(p+1) == row 	&&*(p+2) == point &&*(p+3) == point &&*(p+4) == point &&*(p+5) == null)	 character = '7';
	else if(*p == row		&&*(p+1) == row 	&&*(p+2) == row 	&&*(p+3) == point &&*(p+4) == point &&*(p+5) == null)	 character = '8';
	else if(*p == row		&&*(p+1) == row 	&&*(p+2) == row 	&&*(p+3) == row 	&&*(p+4) == point &&*(p+5) == null)	 character = '9';
	else if(*p == point &&*(p+1) == point &&*(p+2) == row 	&&*(p+3) == row 	&&*(p+4) == point &&*(p+5) == point) character = '?';
	else if(*p == row 	&&*(p+1) == point &&*(p+2) == point &&*(p+3) == row 	&&*(p+4) == point &&*(p+5) == null)  character = '/';
	else if(*p == row 	&&*(p+1) == point &&*(p+2) == row 	&&*(p+3) == row 	&&*(p+4) == point	&&*(p+5) == row) 	 character = '(';
	else if(*p == row 	&&*(p+1) == point &&*(p+2) == point &&*(p+3) == point &&*(p+4) == point &&*(p+5) == row)   character = '-';
	else if(*p == point &&*(p+1) == row 	&&*(p+2) == point &&*(p+3) == row  	&&*(p+4) == point &&*(p+5) == row)   character = '.';
		else character = '\0';
		return character;
}

发送完成回调函数

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
	/*是否发送完成*/
	if(!__HAL_UART_GET_FLAG(&huart1,UART_IT_TC))
	{
		return;
	}
	/*清空发送完成标志位*/
	__HAL_UART_CLEAR_FLAG(&huart1,UART_IT_TC);
	/*把时间代号复位*/
	sign_clear();
}

功能二

如果发送的字符为'0'~'9',控制灯的亮度

void LED_Brightness_Control(uint8_t * number)
{
	uint32_t LED_brightness;
    /*判断是否为'0'~'9'*/
	if((* number >= '0')&&(* number <= '9'))
	{
		/*由于计数周期设置为999,则‘1’对应的比较值为100,以此类推*/
		LED_brightness = (* number - '0') * K;
		/*开启灯所在定时器PWM功能*/
		HAL_TIM_PWM_Start(&htim14,TIM_CHANNEL_1);
		/*设置占空比*/
		__HAL_TIM_SET_COMPARE(&htim14,TIM_CHANNEL_1,LED_brightness);
	}
	else ;
}

 

功能三

先输入一个字符,将其解析成点和划的组合,点亮200ms,划亮600ms,间隔为200ms,字符和字符之间间隔为1s。

不定长接收,采用空闲中断IDLE的方法,将接收到的字符,挨个解析并挨个亮灯。

中断服务函数

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
	
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */
	UART_Rx_Callback(&huart1);
  /* USER CODE END USART1_IRQn 1 */
}

接收的回调函数

void UART_Rx_Callback(UART_HandleTypeDef * huart)
{
	/*判断是否发生了帧结束*/
	if(!__HAL_UART_GET_FLAG(huart,UART_FLAG_IDLE))
	{
		return;
	}
	/*清楚标志位*/
	__HAL_UART_CLEAR_IDLEFLAG(huart);
	/*判断串口端口*/
	if(huart == &huart1)
	{
		/*进入帧中断回调函数*/
		UART_Rx_IDLE_Callback(&huart1);
	}
}

如果是一帧接收完成则进入帧完成回调函数

void UART_Rx_IDLE_Callback(UART_HandleTypeDef * huart)
{
	if(huart == &huart1)
	{
		/*停止DMA接收*/
		HAL_UART_DMAStop(&huart1);
	}
}

字符解析成点划


void character_to_sign(uint8_t * character)
{
		switch(*character)
		{
			case 'A': {sign[0] = point; sign[1] = row; 	 sign[2] = null;  sign[3] = null;  sign[4] = null;  sign[5] = null;  break; }
			case 'B': {sign[0] = row; 	sign[1] = point; sign[2] = point; sign[3] = point; sign[4] = null;  sign[5] = null;  break; }
			case 'C': {sign[0] = row; 	sign[1] = point; sign[2] = row; 	sign[3] = point; sign[4] = null;  sign[5] = null;  break; }
			case 'D': {sign[0] = row; 	sign[1] = point; sign[2] = point; sign[3] = null;  sign[4] = null;  sign[5] = null;  break; }
			case 'E': {sign[0] = point; sign[1] = row; 	 sign[2] = null;  sign[3] = null;  sign[4] = null;  sign[5] = null;  break; }
			case 'F': {sign[0] = point; sign[1] = point; sign[2] = row; 	sign[3] = point; sign[4] = null;  sign[5] = null;  break; }
			case 'G': {sign[0] = row; 	sign[1] = row; 	 sign[2] = point; sign[3] = null;  sign[4] = null;  sign[5] = null;  break; }
			case 'H': {sign[0] = point; sign[1] = point; sign[2] = point; sign[3] = point; sign[4] = null;  sign[5] = null;  break; }
			case 'I': {sign[0] = point; sign[1] = point; sign[2] = null;  sign[3] = null;  sign[4] = null;  sign[5] = null;  break; }
			case 'J': {sign[0] = point; sign[1] = row; 	 sign[2] = row; 	sign[3] = row;   sign[4] = null;  sign[5] = null;  break; }
			case 'K': {sign[0] = row; 	sign[1] = point; sign[2] = row; 	sign[3] = null;  sign[4] = null;  sign[5] = null;  break; }
			case 'L': {sign[0] = point; sign[1] = row; 	 sign[2] = point; sign[3] = point; sign[4] = null;  sign[5] = null;  break; }
			case 'M': {sign[0] = row; 	sign[1] = row;   sign[2] = null;  sign[3] = null;  sign[4] = null;  sign[5] = null;  break; }
			case 'N': {sign[0] = row; 	sign[1] = point; sign[2] = null;  sign[3] = null;  sign[4] = null;  sign[5] = null;  break; }
			case 'O': {sign[0] = row; 	sign[1] = row; 	 sign[2] = row; 	sign[3] = null;  sign[4] = null;  sign[5] = null;  break; }
			case 'P': {sign[0] = point; sign[1] = row;	 sign[2] = row; 	sign[3] = point; sign[4] = null;  sign[5] = null;  break; }
			case 'Q': {sign[0] = row; 	sign[1] = row;	 sign[2] = point; sign[3] = row;   sign[4] = null;  sign[5] = null;  break; }
			case 'R': {sign[0] = point; sign[1] = row;	 sign[2] = point; sign[3] = null;  sign[4] = null;  sign[5] = null;  break; }
			case 'S': {sign[0] = point; sign[1] = point; sign[2] = point; sign[3] = null;  sign[4] = null;  sign[5] = null;  break; }
			case 'T': {sign[0] = row; 	sign[1] = null;  sign[2] = null;  sign[3] = null;  sign[4] = null;  sign[5] = null;  break; }
			case 'U': {sign[0] = point; sign[1] = point; sign[2] = row; 	sign[3] = null;  sign[4] = null;  sign[5] = null;  break; }
			case 'V': {sign[0] = point; sign[1] = point; sign[2] = point; sign[3] = row;   sign[4] = null;  sign[5] = null;  break; }
			case 'W': {sign[0] = point; sign[1] = row;	 sign[2] = row; 	sign[3] = null;  sign[4] = null;  sign[5] = null;  break; }
			case 'X': {sign[0] = row; 	sign[1] = point; sign[2] = point; sign[3] = row;   sign[4] = null;  sign[5] = null;  break; }
			case 'Y': {sign[0] = row; 	sign[1] = point; sign[2] = row; 	sign[3] = row;   sign[4] = null;  sign[5] = null;  break; }
			case 'Z': {sign[0] = row; 	sign[1] = row;	 sign[2] = point; sign[3] = point; sign[4] = null;  sign[5] = null;  break; }
			case '0': {sign[0] = row; 	sign[1] = row;	 sign[2] = row; 	sign[3] = row;   sign[4] = row; 	sign[5] = null;  break; }
			case '1': {sign[0] = point; sign[1] = row;	 sign[2] = row; 	sign[3] = row;   sign[4] = row; 	sign[5] = null;  break; }
			case '2': {sign[0] = point; sign[1] = point; sign[2] = row; 	sign[3] = row;   sign[4] = row;		sign[5] = null;  break; }
			case '3': {sign[0] = point; sign[1] = point; sign[2] = point; sign[3] = row;   sign[4] = row; 	sign[5] = null;  break; }
			case '4': {sign[0] = point; sign[1] = point; sign[2] = point; sign[3] = point; sign[4] = row; 	sign[5] = null;  break; }
			case '5': {sign[0] = point; sign[1] = point; sign[2] = point; sign[3] = point; sign[4] = point; sign[5] = null;  break; }
			case '6': {sign[0] = row; 	sign[1] = point; sign[2] = point; sign[3] = point; sign[4] = point; sign[5] = null;  break; }
			case '7': {sign[0] = row; 	sign[1] = row;	 sign[2] = row; 	sign[3] = point; sign[4] = point; sign[5] = null;  break; }
			case '8': {sign[0] = row; 	sign[1] = row;	 sign[2] = row; 	sign[3] = row;   sign[4] = point; sign[5] = null;  break; }
			case '9': {sign[0] = row; 	sign[1] = row;	 sign[2] = row; 	sign[3] = row;   sign[4] = row; 	sign[5] = null;  break; }
			case '?': {sign[0] = point; sign[1] = point; sign[2] = row; 	sign[3] = row;   sign[4] = point; sign[5] = point; break; }
			case '/': {sign[0] = row; 	sign[1] = point; sign[2] = point; sign[3] = row;   sign[4] = point; sign[5] = null;  break; }
			case '(': {sign[0] = row; 	sign[1] = point; sign[2] = row; 	sign[3] = row;   sign[4] = point; sign[5] = row; 	 break; }
			case '-': {sign[0] = row; 	sign[1] = point; sign[2] = point; sign[3] = point; sign[4] = point; sign[5] = row;   break; }
			case '.': {sign[0] = point; sign[1] = row;	 sign[2] = point; sign[3] = row;   sign[4] = point; sign[5] = row;   break; }
			default:break;
	}
}

通过点划控制灯亮时间长短

/*根据发送过来的字符解析成电平时间长短通过GPIO的方式输出为灯亮的时间*/
void led_control(void)
{
	int i = 0;
	for(i = 0;i < SIGN_LENGTH_MAX;i++)
	{
		switch(sign[i])
		{
			case 0:
			{
				HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);
				HAL_Delay(LED_SHORT_TIME);
				HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);
				HAL_Delay(LED_REST_TIME);
				break;
			}
			case 1:
			{
				HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);
				HAL_Delay(LED_LONG_TIME);
				HAL_GPIO_TogglePin(GPIOF,GPIO_PIN_10);
				HAL_Delay(LED_REST_TIME);
				break;
			} 
			default:break;
		}
	}	
	/*每执行一次后,把解析的标志初始化*/
	sign_clear();
}

以上则是摩尔斯译码器的全部代码,希望这篇文章对您以后的学习有帮助,如果有问题,可以在评论区提出来,欢迎大家在评论区交流。

 

你可能感兴趣的:(stm32)