STM32单片机裸机程序-高级实现实时性处理方法
概述
这篇文章是对刚刚学习单片机的小伙伴们,提的一些处理技巧思维。(我在项目上经常使用这样的处理思路)
现在举个栗子,应用场景是这样的,比如:在while(1)中在处理一些裸机,然后碰巧又在延时时候,当你又有其他事件(这个事件是外部触发而来的)比较紧急要处理这个事件时,这时候,CUP肯定是处理不来,需要等待while(1)处理完延时之后,才能处理这个比较紧急的事件,这时候,可能有人会说,你干嘛不在外部中断去处理这个事件呢,但是如果这个事件刚好也要延时呢?怎么办,一般好的程序不会在中断函数里面使用过多的延时,还有很多逻辑的事件,这时候就要换一种处理思维了。哈哈,想必大家也会想到它,那就是定时器,如果这时候使用定时器的话,问题肯定能处理的比在while(1)的大循环干等待延时要强的多,完美的组合就是,要中断与定时器搭配来使用才行,这样的处理事件就不会因为延时逻辑过长导致其它事件处理不及时的问题。(废话有点多,请谅解)
1、打个比方:我的项目上有关机功能
2、首先配置一个单独的定时器(我这里配置的是 基本定时器6,注意:如果Tim不够用的话,可以使用SysTick_Handler/滴答定时器代替,使用方法同理。)
3、该定时专门处理这个关机逻辑的,这时根据自己的需求修改定时器的频率
tim.c 文件
/* USER CODE BEGIN 0 */
#include "adc.h"
extern void Power_OFF(void);
/* USER CODE END 0 */
.
.
.
/* USER CODE BEGIN 1 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2)
{
#ifdef TIMER_SAMPLING_MODE
get_ADC_Channel_Val();
#endif
}
else if(htim->Instance == TIM6)
{
//编写回调逻辑,即定时器6定时1000us后的逻辑 1ms=1次
Power_OFF();
}
}
/* USER CODE END 1 */
Power_OFF()函数:
void Power_ON(void)
{
uint32_t tickstart = HAL_GetTick();
while(1)
{
//读Power_on是否是高电平
if(HAL_GPIO_ReadPin(POWER_OFF_GPIO_Port,POWER_OFF_Pin)==GPIO_PIN_SET)
{
if((HAL_GetTick() - tickstart) >= 3000) //如果大于3s
{
g_powerON_flag = 1;
HAL_GPIO_WritePin(POWER_ON_GPIO_Port,POWER_ON_Pin,GPIO_PIN_SET); //开机
HAL_GPIO_WritePin(MOT_EN_GPIO_Port,MOT_EN_Pin,GPIO_PIN_SET); //MOT_ON
HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET); //LED_ON
HAL_Delay(500);
HAL_GPIO_WritePin(MOT_EN_GPIO_Port,MOT_EN_Pin,GPIO_PIN_RESET); //MOT_OFF
HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET); //LED_OFF
HAL_Delay(500);
HAL_GPIO_WritePin(MOT_EN_GPIO_Port,MOT_EN_Pin,GPIO_PIN_SET); //MOT_ON
HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_SET); //LED_ON
HAL_Delay(500);
HAL_GPIO_WritePin(MOT_EN_GPIO_Port,MOT_EN_Pin,GPIO_PIN_RESET); //MOT_OFF
HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET); //LED_OFF
break;
}
}
else
{
HAL_GPIO_WritePin(POWER_ON_GPIO_Port,POWER_ON_Pin,GPIO_PIN_RESET); //不开机
HAL_GPIO_WritePin(MOT_EN_GPIO_Port,MOT_EN_Pin,GPIO_PIN_RESET); //MOT_OFF
HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,GPIO_PIN_RESET); //LED_OFF
}
}
}
外部中断脚代码处理逻辑
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == POWER_OFF_Pin)
{
/* Clear Wake Up Flag */
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
if(HAL_GPIO_ReadPin(POWER_OFF_GPIO_Port,POWER_OFF_Pin)==SET)
{
//printf("关机唤醒中断\r\n");
g_powerOffWakeUp_flag=1;
HAL_TIM_Base_Start_IT(&htim6); //开启定时器
}
}
}
main.c 文件
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_LPUART1_UART_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
//事件1
HAL_Delay(1000);
//事件2
HAL_Delay(3000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
总结一下:其实这样处理思想,可以应用在很多地方,可达到实时性。不需要管while(1)中大循环的逻辑。有点像多线程处理一样。
这里的main.c代码,在实际开发中也不太允许这样处理,这样实时性太差了,也是很多小白刚学单片机犯最多的错误。这样写一看就知道是菜鸟。当然,我那样写不是很高大尚,其实想处理多线程的思路,还是引入RTOS好些。当然也不是说逻辑不好,各有利弊,看使用情况而定。
相关文章
- 解决“只能通过Chrome网上应用商店安装该程序”的方法
- 让C程序更高效的10种方法
- sql语法:inner join on, left join on, right join on详细使用方法
- 微信小程序 iphone6 和 iphone6plus 如何设置rpx单位,通俗易懂的方法
- C#程序不包含适合于入口点的静态“Main”方法怎么办
- golang 值方法和指针方法
- Python实现计算圆周率π的值到任意位的方法示例
- 在Python中操作文件之truncate()方法的使用教程
- C# Winform WCF 调试服务端的程序(三种方法)
- JavaScript 实现网页截屏五种方法
- 微信小程序开发系列教程三:微信小程序的调试方法
- Atitit 数据建模的技术总结 目录 1. 数据建模1 2. 常见建模技术2 2.1. 电子表格程序 计算机辅助设计 (CAD) 2 2.2. Er图2 3. 建模方法2 3.1. .
- 【nodejs】使用 npm安装模块方法
- Ipython:Ipython中Magic Functions魔法函数的简介、使用方法(单百分号%如%matplotlib inline、双百分号%%如%%!)之详细攻略
- Python:python语言中与时间有关的库函数简介、安装、使用方法(获取当前时间/计算程序块前后运行时间/模型训练时间或耗费时间)之详细攻略
- 练习 1-13 编写一个程序,打印输入中单词长度的直方图(水平)(方法2)
- 万能删除文件及文件目录的方法,包括所有的流氓软件及顽固程序(还未测试)
- 小程序渲染html的两种方法
- Hadoop集群最迅速的配置免密码登陆方法
- Win11管理和优先处理通知的方法
- 类方法中的一类特殊方法:构造方法
- 出错的方法有可能是JDK,也可能是程序员写的程序,无论谁写的,抛出一定用throw