既然前幾篇介紹了外部中斷、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;
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if (htim->Instance == htim2.Instance)
{
timesec+=0.5;
}
}
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));
}
}
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 Interrupt
if(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);
}
else
mode =0;
}
}