既然前几篇介绍了外部中断、Timer中断与USART,那接下来就结合这三种中断来模拟红绿灯出来吧。
这一次会用到定时器(TIM2)、外部中断还有一个USART。
设计想法 :
Timer :红绿灯有一定的时序,可以利用Timer中断来控制。
EXTI : 某些路口有行人按钮,当按下时会从闪黄灯转为正常红绿灯。
USART : 用来模拟路旁的号誌控制箱
首先先整理一下程式设计的想法


实作
第一步先设定LED连接的GPIO脚位,这边我是连接PB13-15一样都设置GPIO_Output
先来看看优先权如何设定,以上方设计的来看优先权会是USART→EXTI→Timer,在.ioc档当中可以去做设置。在这边中断分组选择4也就是4个bit全用来作为Preemption priority分级。
宣告几个全域变数之后会需要用到~
float timesec; //用来计算秒数的int mode = 0; //模式 0:闪黄灯(EXTI) 1:红绿灯(Timer) 2:控制箱(USART)char Rxbuf[1];char Txbuf[30];
之后可以将各中断回调函数先写好
外部中断 : 由闪黄灯进入红绿灯时序void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){if(GPIO_Pin == GPIO_PIN_13){mode = 1;}}
定时中断 : 控制三种灯号的时间变化在这边首先选择TIM2,我设定为0.5s中断一次方便之后计算。

写入定时中断的函数,在这边因为定时器设定为0.5s,所以我对于秒数增加为0.5。
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim){ if (htim->Instance == htim2.Instance) {timesec+=0.5; }}
USART : 模拟控制箱控制灯号,判断接收到哪种指令亮起对应灯号void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){if(huart->Instance == huart2.Instance){mode = 2;HAL_UART_Receive_IT(huart, (uint8_t*)&Rxbuf, 1);sprintf(Txbuf, "控制箱模式 : %c\r\n", Rxbuf[0]);HAL_UART_Transmit_IT(&huart2, (uint8_t*)&Txbuf, sizeof(Txbuf));}}
Trafficmode: 用来根据mode变数来选择对应的亮灯方式mode 0 : 闪黄灯mode 1 : 红绿灯,藉由外部中断触发进入模式1后启用定时器。到达总时长5秒后会切换为闪黄灯模式。mode 2 : 控制箱,在接收到电脑所传送的指令(R/G/Y/E)后亮起对应灯号。void Trafficmode(int modex){switch(modex){case 0:HAL_GPIO_WritePin(GPIOB, GLED_Pin, RESET);HAL_GPIO_WritePin(GPIOB, RLED_Pin, RESET);HAL_GPIO_TogglePin(GPIOB, YLED_Pin);HAL_Delay(500);break;case 1:HAL_TIM_Base_Start_IT(&htim2); //Start Timer Interruptif(timesec>=0&×ec<=1.5){HAL_GPIO_WritePin(GPIOB, YLED_Pin, RESET);HAL_GPIO_WritePin(GPIOB, RLED_Pin, RESET);HAL_GPIO_WritePin(GPIOB, GLED_Pin, SET);}else if(timesec>1.5&×ec<=2.5){HAL_GPIO_WritePin(GPIOB, GLED_Pin, RESET);HAL_GPIO_WritePin(GPIOB, YLED_Pin, SET);}else if(timesec>2.5&×ec<=5){HAL_GPIO_WritePin(GPIOB, YLED_Pin, RESET);HAL_GPIO_WritePin(GPIOB, RLED_Pin, SET);}else{HAL_TIM_Base_Stop_IT(&htim2);timesec=0;mode=0;}break;case 2:if(Rxbuf[0] == 0x47) //G{HAL_GPIO_WritePin(GPIOB, YLED_Pin, RESET);HAL_GPIO_WritePin(GPIOB, RLED_Pin, RESET);HAL_GPIO_WritePin(GPIOB, GLED_Pin, SET);}else if(Rxbuf[0] == 0x59) //Y{HAL_GPIO_WritePin(GPIOB, YLED_Pin, SET);HAL_GPIO_WritePin(GPIOB, RLED_Pin, RESET);HAL_GPIO_WritePin(GPIOB, GLED_Pin, RESET);}else if(Rxbuf[0] == 0x52) //R{HAL_GPIO_WritePin(GPIOB, YLED_Pin, RESET);HAL_GPIO_WritePin(GPIOB, RLED_Pin, SET);HAL_GPIO_WritePin(GPIOB, GLED_Pin, RESET);}elsemode =0;}}