完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
概述
这篇文章是对刚刚学习单片机的小伙伴们,提的一些处理技巧思维。(我在项目上经常使用这样的处理思路) 现在举个栗子,应用场景是这样的,比如:在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(“关机唤醒中断rn”); 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好些。当然也不是说逻辑不好,各有利弊,看使用情况而定。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1855 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1647 浏览 1 评论
1124 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
748 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1706 浏览 2 评论
1959浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
770浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
599浏览 3评论
620浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
578浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-6 09:34 , Processed in 1.149668 second(s), Total 76, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号