一、項目背景
隨著城市規模的不斷擴大和交通運輸方式的日益發展,鐵路與公路的交叉口已經成為常見的場景。然而,這些交叉口往往存在一定的安全隱患,因為有時不易發現列車行進的情況,導致公路上的車輛或行人可能會無意中闖入鐵路區域,從而引發重大交通事故。
為了解決這個問題,當前開發了一款基于STM32的鐵路自動圍欄系統。該系統采用了STM32F103RCT6作為主控芯片,并使用步進電機來控制鐵路圍欄的開啟和閉合。同時,系統還配備了紅外感應器,以便能夠及時監測到列車的通過情況。
當系統監測到有列車即將通過鐵路交叉口時,公路信號燈會立刻變為紅燈,蜂鳴器也會發出警報聲音,以提醒行人和車輛注意安全。同時,鐵路兩側的圍欄也會自動關閉,在列車通過后再次打開。這樣,就能有效地防止公路車輛和行人誤闖鐵路區域,保障了路人的安全。
二、系統設計
2.1 硬件部分
STM32F103RCT6主鐵路自動圍欄系統的硬件部分主要包括:STM32F103RCT6主控芯片、步進電機、紅外感應器、信號燈、蜂鳴器。 【1】STM32F103RCT6主控芯片是整個系統的核心,負責控制圍欄的開啟和閉合、監測紅外感應器的狀態、控制信號燈的變化以及控制蜂鳴器的報警聲音。
【2】步進電機是用來控制鐵路圍欄的開啟和閉合的設備,其動力來源為驅動芯片ULN2003。
【3】紅外感應器是用來監測列車的通過情況,當感應到列車時輸出高電平信號,否則輸出低電平信號。
【4】信號燈則用來提示道路行人和車輛當前狀態,紅燈表示停止,綠燈表示通行。
【5】蜂鳴器則是用來發出報警聲音,提醒行人和車輛注意安全。
2.2 軟件部分
程序主要分為四部分:系統初始化、紅外感應器檢測、鐵路圍欄控制和信號燈控制。
【1】系統初始化主要是對硬件進行初始化,包括設置STM32的時鐘、GPIO口的初始化等。
【2】紅外感應器檢測部分則是對紅外感應器進行監測,當感應到列車時輸出高電平信號,程序通過讀取該信號實現對鐵路圍欄的控制和信號燈的變化。
【3】鐵路圍欄控制部分主要是通過對步進電機的控制來實現圍欄的開啟和閉合。
【4】信號燈控制部分則是通過對GPIO口的控制來實現信號燈的變化,當感應到列車時,將信號燈變為紅色,否則為綠色。
三、核心代碼實現
3.1 28BYJ48步進電機代碼
以下是使用STM32F103RCT6驅動28BYJ-48步進電機實現正反轉控制并封裝成子函數調用的完整代碼實現過程。
首先,需要定義相關引腳和變量:
#include "stm32f10x.h"
?
#define IN1_PIN GPIO_Pin_0
#define IN2_PIN GPIO_Pin_1
#define IN3_PIN GPIO_Pin_2
#define IN4_PIN GPIO_Pin_3
?
GPIO_InitTypeDef GPIO_InitStructure;
?
uint8_t step = 0;
然后,編寫初始化GPIO的代碼:
void init_GPIO(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
?
GPIO_InitStructure.GPIO_Pin = IN1_PIN | IN2_PIN | IN3_PIN | IN4_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
接著,編寫正轉和反轉函數的代碼:
void forward(void)
{
switch(step)
{
case 0:
GPIO_SetBits(GPIOA, IN1_PIN);
GPIO_ResetBits(GPIOA, IN2_PIN | IN3_PIN | IN4_PIN);
break;
case 1:
GPIO_SetBits(GPIOA, IN1_PIN | IN2_PIN);
GPIO_ResetBits(GPIOA, IN3_PIN | IN4_PIN);
break;
case 2:
GPIO_SetBits(GPIOA, IN2_PIN);
GPIO_ResetBits(GPIOA, IN1_PIN | IN3_PIN | IN4_PIN);
break;
case 3:
GPIO_SetBits(GPIOA, IN3_PIN | IN2_PIN);
GPIO_ResetBits(GPIOA, IN1_PIN | IN4_PIN);
break;
case 4:
GPIO_SetBits(GPIOA, IN3_PIN);
GPIO_ResetBits(GPIOA, IN1_PIN | IN2_PIN | IN4_PIN);
break;
case 5:
GPIO_SetBits(GPIOA, IN4_PIN | IN3_PIN);
GPIO_ResetBits(GPIOA, IN1_PIN | IN2_PIN);
break;
case 6:
GPIO_SetBits(GPIOA, IN4_PIN);
GPIO_ResetBits(GPIOA, IN1_PIN | IN2_PIN | IN3_PIN);
break;
case 7:
GPIO_SetBits(GPIOA, IN1_PIN | IN4_PIN);
GPIO_ResetBits(GPIOA, IN2_PIN | IN3_PIN);
break;
}
step++;
if(step == 8)
{
step = 0;
}
}
?
void backward(void)
{
switch(step)
{
case 0:
GPIO_SetBits(GPIOA, IN1_PIN | IN4_PIN);
GPIO_ResetBits(GPIOA, IN2_PIN | IN3_PIN);
break;
case 1:
GPIO_SetBits(GPIOA, IN4_PIN);
GPIO_ResetBits(GPIOA, IN1_PIN | IN2_PIN | IN3_PIN);
break;
case 2:
GPIO_SetBits(GPIOA, IN3_PIN | IN4_PIN);
GPIO_ResetBits(GPIOA, IN1_PIN | IN2_PIN);
break;
case 3:
GPIO_SetBits(GPIOA, IN3_PIN);
GPIO_ResetBits(GPIOA, IN1_PIN | IN2_PIN | IN4_PIN);
break;
case 4:
GPIO_SetBits(GPIOA, IN2_PIN | IN3_PIN);
GPIO_ResetBits(GPIOA, IN1_PIN | IN4_PIN);
break;
case 5:
GPIO_SetBits(GPIOA, IN2_PIN);
GPIO_ResetBits(GPIOA, IN1_PIN | IN3_PIN | IN4_PIN);
break;
case 6:
GPIO_SetBits(GPIOA, IN1_PIN | IN2_PIN);
GPIO_ResetBits(GPIOA, IN3_PIN | IN4_PIN);
break;
case 7:
GPIO_SetBits(GPIOA, IN1_PIN);
GPIO_ResetBits(GPIOA, IN2_PIN | IN3_PIN | IN4_PIN);
break;
}
step--;
if(step == -1)
{
step = 7;
}
}
最后,可以封裝正轉和反轉函數成子函數:
void rotate_motor(int steps, int direction)
{
int i = 0;
for(i = 0; i < steps; i++)
? ? {
? ? ? ? ?if(direction == 0)
? ? ? ? {
? ? ? ? ? ? ?forward();
? ? ? ? }
? ? ? ? ?else if(direction == 1)
? ? {
? ? ? ? ?backward();
? ? }
?}
??
?void motor_stop(void)
?{
? GPIO_ResetBits(GPIOA, IN1_PIN | IN2_PIN | IN3_PIN | IN4_PIN);
?}
最后,可以在主函數中使用這些封裝好的子函數:
int main(void)
{
init_GPIO();
?
// 正轉200步
rotate_motor(200, 0);
?
// 反轉100步
rotate_motor(100, 1);
?
// 停止電機
motor_stop();
?
while (1);
}
3.2 蜂鳴器報警代碼
#include "stm32f10x.h"
#define BUZZER_GPIO_PIN GPIO_Pin_7
#define BUZZER_GPIO_PORT GPIOC
?
void buzzer_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
?
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = BUZZER_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽輸出模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(BUZZER_GPIO_PORT, &GPIO_InitStructure);
}
?
void buzzer_on(void)
{
GPIO_SetBits(BUZZER_GPIO_PORT, BUZZER_GPIO_PIN); // Buzzer on
}
?
void buzzer_off(void)
{
GPIO_ResetBits(BUZZER_GPIO_PORT, BUZZER_GPIO_PIN); // Buzzer off
}
3.3 紅外感應器代碼
#include "stm32f10x.h"
#define IR_GPIO_PIN GPIO_Pin_1
#define IR_GPIO_PORT GPIOA
?
void ir_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
?
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = IR_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; // 下拉輸入模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(IR_GPIO_PORT, &GPIO_InitStructure);
?
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource1);
?
EXTI_InitStructure.EXTI_Line = EXTI_Line1; // 對應中斷線 EXTI1
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; // 上升沿和下降沿觸發
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
?
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; // 中斷向量
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; // 搶占優先級2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03; // 響應優先級3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
?
void EXTI1_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line1) != RESET)
{
// Do something when IR sensor detects the train
EXTI_ClearITPendingBit(EXTI_Line1);
}
}
3.4 信號燈控制代碼
#include "stm32f10x.h"
#define LED_GREEN_GPIO_PIN GPIO_Pin_6
#define LED_GREEN_GPIO_PORT GPIOB
#define LED_RED_GPIO_PIN GPIO_Pin_7
#define LED_RED_GPIO_PORT GPIOB
?
void led_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
?
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = LED_GREEN_GPIO_PIN | LED_RED_GPIO_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽輸出模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
?
void led_green_on(void)
{
GPIO_SetBits(LED_GREEN_GPIO_PORT, LED_GREEN_GPIO_PIN); // Green LED on
}
?
void led_green_off(void)
{
GPIO_ResetBits(LED_GREEN_GPIO_PORT, LED_GREEN_GPIO_PIN); // Green LED off
}
?
void led_red_on(void)
{
GPIO_SetBits(LED_RED_GPIO_PORT, LED_RED_GPIO_PIN); // Red LED on
}
?
void led_red_off(void)
{
GPIO_ResetBits(LED_RED_GPIO_PORT, LED_RED_GPIO_PIN); // Red LED off
}
四、總結
當前設計的這種基于STM32的鐵路自動圍欄系統,通過對鐵路交叉口進行有效的監測和控制,實現了對過往車輛和行人的有效防護。該系統采用STM32F103RCT6作為主控芯片,使用步進電機控制鐵路圍欄的開啟和閉合,使用紅外感應器來監測列車的通過情況。在公路與鐵路的交叉路口,若在遠處感應到有列車即將通過,則公路信號燈變為紅燈,蜂鳴器報警,鐵路兩側圍欄自動閉合;直至感應到列車徹底離開,公路信號燈變為綠燈,蜂鳴器關閉,圍欄打開。系統具有結構簡單、性能可靠等優點,在實際應用中取得了良好的效果。
審核編輯:湯梓紅
-
芯片
+關注
關注
455文章
50714瀏覽量
423142 -
STM32
+關注
關注
2270文章
10895瀏覽量
355740 -
步進電機
+關注
關注
150文章
3109瀏覽量
147443 -
鐵路
+關注
關注
1文章
67瀏覽量
17887 -
單片機
+關注
關注
0文章
214瀏覽量
16658
發布評論請先 登錄
相關推薦
評論