【总结(三)】单片机重点知识总结记录(串口重定向+按键消抖+延时)

embedded/2024/12/24 9:43:51/

一.串口重定向

串口重定向代码如下

注意:

  • 要添加头文件include "stdio.h"
  • 要勾选微库,即Use MicroLIB
/**********重定向************/
//串口1
int fputc(int ch, FILE *f)
{HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);return ch;
}int fgetc(FILE * f)
{uint8_t ch = 0;HAL_UART_Receive(&huart1,&ch, 1, 0xffff);return ch;
}
/**********************************/

二.按键消抖算法

延时消抖

uint8_t Key_GetValue(void)
{uint8_t value = 0;if(HAL_GPIO_ReadPin(GPIOA,KEY_A_Pin) == GPIO_PIN_SET)value = 1;if(HAL_GPIO_ReadPin(GPIOA,KEY_B_Pin) == GPIO_PIN_SET)value = 2;if(HAL_GPIO_ReadPin(GPIOA,KEY_C_Pin) == GPIO_PIN_SET)value = 3;if(HAL_GPIO_ReadPin(GPIOA,KEY_D_Pin) == GPIO_PIN_SET)value = 4;return value;
}uint8_t Key_Scan(void)
{uint8_t key_number = 0;key_number = Key_GetValue();if(key_number != 0){mdelay(20);while( Key_GetValue() != 0);mdelay(20);return key_number;}return 0;
}

三行消抖

主要消抖算法如下:

void Key_RemoveShake(void)
{Key_Value = Key_GetValue();//获取按下键值Key_Down = Key_Value & (Key_Value ^ Key_Last);//获取下降沿Key_Up = ~Key_Value & (Key_Value ^ Key_Last);//获取上升沿Key_Last = Key_Value;//键值覆盖
}

若按键共阴(公共端为地),则按下时为下降沿,只需判断下降沿是否存在即可判断是否有按键按下:

uint8_t Key_Press(void)
{return Key_Down ? Key_Value : 0;
}

完整代码如下:

//              KEY1   PD8
//              KEY2   PD9
//              KEY3   PD10
//              KEY4   PD11
//              KEY5   PD12
//              KEY6   PD13#include "Key.h"uint8_t Key_Value,Key_Down,Key_Up,Key_Last;uint8_t Key_GetValue(void)
{if(HAL_GPIO_ReadPin(GPIOD,KEY1_Pin) == 0)return 1;if(HAL_GPIO_ReadPin(GPIOD,KEY2_Pin) == 0)return 2;if(HAL_GPIO_ReadPin(GPIOD,KEY3_Pin) == 0)return 3;if(HAL_GPIO_ReadPin(GPIOD,KEY4_Pin) == 0)return 4;if(HAL_GPIO_ReadPin(GPIOD,KEY5_Pin) == 0)return 5;if(HAL_GPIO_ReadPin(GPIOD,KEY6_Pin) == 0)return 6;return 0;
}//以下函数需要在中断中使用,推荐10ms定时器中断
void Key_RemoveShake(void)
{Key_Value = Key_GetValue();//获取按下键值Key_Down = Key_Value & (Key_Value ^ Key_Last);//获取下降沿Key_Up = ~Key_Value & (Key_Value ^ Key_Last);//获取上升沿Key_Last = Key_Value;//键值覆盖
}uint8_t Key_Press(void)
{return Key_Down ? Key_Value : 0;
}

三.非阻塞延时

阻塞式延时

直接循环解决 

void delay(u16 num)
{u16 i,j;for(i=0;i<num;i++)for(j=0;j<10000;j++);
}

定时器中断实现 

void udelay(int us)
{extern TIM_HandleTypeDef        htim1;TIM_HandleTypeDef *hHalTim = &htim1;uint32_t ticks;uint32_t told, tnow, tcnt = 0;uint32_t reload = __HAL_TIM_GET_AUTORELOAD(hHalTim);ticks = us * reload / (1000);  /* 假设reload对应1ms */told = __HAL_TIM_GET_COUNTER(hHalTim);while (1){tnow = __HAL_TIM_GET_COUNTER(hHalTim);if (tnow != told){if (tnow > told){tcnt += tnow - told;}else{tcnt += reload - told + tnow;}told = tnow;if (tcnt >= ticks){break;}}}}

特别注意:HAL_Delay()也算是阻塞式延时,虽然它使用的是滴答定时器中断来进行读数,但是其延时过程仍为忙等待过程,因此仍是阻塞式延时。

非阻塞延时

         实际上裸机应该是不能实现真正意义上的非阻塞延时的,即处理器在延时过程中去完成别的任务,但是一般来说换个名字我们可能更熟悉——时间片轮询。

        当我们配置一个毫秒级的定时器中断时,在其中定义一个时间标志,进行自增或自减后判断是否到达对应时间然后在函数外执行相应功能。

uint16_t Timer_1000ms = 0,Timer_1000ms_Flag = 0;void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{if (htim == (&htim2)){++Timer_1000ms;if(Timer_1000ms >= 1000){Timer_1000ms_Flag = 1;Timer_1000ms = 0;}}
}void Task1()
{//...
}int main(void)
{while(1){if(Timer_1000ms_Flag == 1){Task1();Timer_1000ms_Flag = 0;}}
}

http://www.ppmy.cn/embedded/148301.html

相关文章

【JUC编程】JUC 多线程基础全面解析(待更新版)

文章目录 JUC 多线程基础全面解析一、线程与并发基础1. 什么是线程&#xff1f;2. 并发与并行的区别3. Java 线程的基本创建方式 二、JUC 核心组件1. 线程池2. 锁机制3. 并发集合 三、线程间通信工具1. CountDownLatch2. CyclicBarrier3. Semaphore 四、原子操作类五、并发工具…

dcdc buck闭环数控型稳压电源仿真+单片机程序及实验报告

资料下载地址&#xff1a;dcdc buck闭环数控型稳压电源仿真单片机程序及实验报告 一、实验目的 设计并制作一台数控型DCDC稳压电源。 二、实验要求 1、输出电压范围 &#xff1a;0.5v~4.5v。可以通过按键实现电压调整 2、必须使用PID闭环控制算法 3、发挥部分&#xff1a; PID…

刷题 两数之和

https://leetcode.cn/problems/two-sum/submissions/588870256/?envTypestudy-plan-v2&envIdtop-100-liked 参考快排算法 https://blog.csdn.net/oSKyTonight/article/details/129813861 /** Note: The returned array must be malloced, assume caller calls free(). */…

MapReduce的shuffle过程详解

文章目录 MapReduce的shuffle过程详解一、引言二、Shuffle过程详解1、Map端Shuffle1.1、分区&#xff08;Partition&#xff09;1.2、排序&#xff08;Sort&#xff09;1.3、分割&#xff08;Spill&#xff09; 2、Reduce端Shuffle 三、使用示例四、总结 MapReduce的shuffle过程…

stm32中有哪些库?其中标准库和HAL库有什么区别?

stm32中有哪些库&#xff1f; 1. STM32标准外设库&#xff08;Standard Peripheral Library&#xff09; 介绍&#xff1a;STM32 标准外设库是 STM32 官方提供的一个硬件抽象库&#xff0c;旨在简化对 STM32 各类外设&#xff08;如 GPIO、UART、SPI、I2C、ADC、PWM 等&#x…

(补)算法刷题Day24: BM61 矩阵最长递增路径

题目链接 思路 方法一&#xff1a;dfs暴力回溯 使用原始used数组4个方向遍历框架 &#xff0c; 全局添加一个最大值判断最大的路径长度。 方法二&#xff1a;加上dp数组记忆的优雅回溯 抛弃掉used数组&#xff0c;使用dp数组来记忆遍历过的节点的最长递增路径长度。每遍历到已…

LeetCode 209. 长度最小的子数组 (C++实现)

1. 题目描述 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 子数组 [numsl, numsl1, …, numsr-1, numsr] &#xff0c;并返回其长度。如果不存在符合条件的子数组&#xff0c;返回 0 。 示例 1&#xff1a; 输…

32岁前端干了8年,是继续做前端开发,还是转其它工作

前端发展有瓶颈&#xff0c;变来变去都是那一套&#xff0c;只是换了框架换了环境。换了框架后又得去学习&#xff0c;虽然很快上手&#xff0c;但是那些刚毕业的也很快上手了&#xff0c;入门门槛越来越低&#xff0c;想转行或继续卷&#xff0c;该如何破圈 这是一位网友的自述…