iT邦幫忙

0

STM32-7 結合中斷來做個紅綠燈吧!

  • 分享至 

  • xImage
  •  

既然前幾篇介紹了外部中斷、Timer中斷與USART,那接下來就結合這三種中斷來模擬紅綠燈出來吧。
這一次會用到定時器(TIM2)、外部中斷還有一個USART。
設計想法 :
Timer :紅綠燈有一定的時序,可以利用Timer中斷來控制。
EXTI : 某些路口有行人按鈕,當按下時會從閃黃燈轉為正常紅綠燈。
USART : 用來模擬路旁的號誌控制箱
首先先整理一下程式設計的想法

  1. 利用Timer中斷來完成時序的控制
  2. 當UART與EXTI同時觸發,UART先行執行直到收到退出指令
  3. EXTI觸發後回到預設紅綠燈時序,經過n秒後回到閃黃燈
    https://ithelp.ithome.com.tw/upload/images/20220313/20146325teah6FoNqJ.png
    https://ithelp.ithome.com.tw/upload/images/20220313/20146325VLqrO5pY5J.png

實作

第一步先設定LED連接的GPIO腳位,這邊我是連接PB13-15一樣都設置GPIO_Output
https://ithelp.ithome.com.tw/upload/images/20220313/20146325jYojvLhLOx.png
先來看看優先權如何設定,以上方設計的來看優先權會是USART→EXTI→Timer,在.ioc檔當中可以去做設置。在這邊中斷分組選擇4也就是4個bit全用來作為Preemption priority分級。
https://ithelp.ithome.com.tw/upload/images/20220313/201463254FAffVj1TR.png
宣告幾個全域變數之後會需要用到~

float timesec; //用來計算秒數的
int mode = 0; //模式  0:閃黃燈(EXTI) 1:紅綠燈(Timer) 2:控制箱(USART)
char Rxbuf[1];
char Txbuf[30];

之後可以將各中斷回調函數先寫好

  1. 外部中斷 : 由閃黃燈進入紅綠燈時序
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
	if(GPIO_Pin == GPIO_PIN_13)
	{
		mode = 1;
	}
}
  1. 定時中斷 : 控制三種燈號的時間變化
    在這邊首先選擇TIM2,我設定為0.5s中斷一次方便之後計算。
    https://ithelp.ithome.com.tw/upload/images/20220313/20146325ypZ8EY6Dxm.png
    寫入定時中斷的函數,在這邊因為定時器設定為0.5s,所以我對於秒數增加為0.5。
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	 if (htim->Instance == htim2.Instance)
	 {
			timesec+=0.5;
	 }
}
  1. 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));
	}
}
  1. 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 Interrupt
					if(timesec>=0&&timesec<=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&&timesec<=2.5)
					{
						HAL_GPIO_WritePin(GPIOB, GLED_Pin, RESET);
						HAL_GPIO_WritePin(GPIOB, YLED_Pin, SET);
					}
					else if(timesec>2.5&&timesec<=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;
			}
}

圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言