一、項(xiàng)目背景
隨著城市規(guī)模的不斷擴(kuò)大和交通運(yùn)輸方式的日益發(fā)展,鐵路與公路的交叉口已經(jīng)成為常見的場景。然而,這些交叉口往往存在一定的安全隱患,因?yàn)橛袝r(shí)不易發(fā)現(xiàn)列車行進(jìn)的情況,導(dǎo)致公路上的車輛或行人可能會無意中闖入鐵路區(qū)域,從而引發(fā)重大交通事故。
為了解決這個(gè)問題,當(dāng)前開發(fā)了一款基于STM32的鐵路自動(dòng)圍欄系統(tǒng)。該系統(tǒng)采用了STM32F103RCT6作為主控芯片,并使用步進(jìn)電機(jī)來控制鐵路圍欄的開啟和閉合。同時(shí),系統(tǒng)還配備了紅外感應(yīng)器,以便能夠及時(shí)監(jiān)測到列車的通過情況。
當(dāng)系統(tǒng)監(jiān)測到有列車即將通過鐵路交叉口時(shí),公路信號燈會立刻變?yōu)榧t燈,蜂鳴器也會發(fā)出警報(bào)聲音,以提醒行人和車輛注意安全。同時(shí),鐵路兩側(cè)的圍欄也會自動(dòng)關(guān)閉,在列車通過后再次打開。這樣,就能有效地防止公路車輛和行人誤闖鐵路區(qū)域,保障了路人的安全。
二、系統(tǒng)設(shè)計(jì)
2.1 硬件部分
STM32F103RCT6主鐵路自動(dòng)圍欄系統(tǒng)的硬件部分主要包括:STM32F103RCT6主控芯片、步進(jìn)電機(jī)、紅外感應(yīng)器、信號燈、蜂鳴器。 【1】STM32F103RCT6主控芯片是整個(gè)系統(tǒng)的核心,負(fù)責(zé)控制圍欄的開啟和閉合、監(jiān)測紅外感應(yīng)器的狀態(tài)、控制信號燈的變化以及控制蜂鳴器的報(bào)警聲音。
【2】步進(jìn)電機(jī)是用來控制鐵路圍欄的開啟和閉合的設(shè)備,其動(dòng)力來源為驅(qū)動(dòng)芯片ULN2003。
【3】紅外感應(yīng)器是用來監(jiān)測列車的通過情況,當(dāng)感應(yīng)到列車時(shí)輸出高電平信號,否則輸出低電平信號。
【4】信號燈則用來提示道路行人和車輛當(dāng)前狀態(tài),紅燈表示停止,綠燈表示通行。
【5】蜂鳴器則是用來發(fā)出報(bào)警聲音,提醒行人和車輛注意安全。
2.2 軟件部分
程序主要分為四部分:系統(tǒng)初始化、紅外感應(yīng)器檢測、鐵路圍欄控制和信號燈控制。
【1】系統(tǒng)初始化主要是對硬件進(jìn)行初始化,包括設(shè)置STM32的時(shí)鐘、GPIO口的初始化等。
【2】紅外感應(yīng)器檢測部分則是對紅外感應(yīng)器進(jìn)行監(jiān)測,當(dāng)感應(yīng)到列車時(shí)輸出高電平信號,程序通過讀取該信號實(shí)現(xiàn)對鐵路圍欄的控制和信號燈的變化。
【3】鐵路圍欄控制部分主要是通過對步進(jìn)電機(jī)的控制來實(shí)現(xiàn)圍欄的開啟和閉合。
【4】信號燈控制部分則是通過對GPIO口的控制來實(shí)現(xiàn)信號燈的變化,當(dāng)感應(yīng)到列車時(shí),將信號燈變?yōu)榧t色,否則為綠色。
三、核心代碼實(shí)現(xiàn)
3.1 28BYJ48步進(jìn)電機(jī)代碼
以下是使用STM32F103RCT6驅(qū)動(dòng)28BYJ-48步進(jìn)電機(jī)實(shí)現(xiàn)正反轉(zhuǎn)控制并封裝成子函數(shù)調(diào)用的完整代碼實(shí)現(xiàn)過程。
首先,需要定義相關(guān)引腳和變量:
#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);
}
接著,編寫正轉(zhuǎn)和反轉(zhuǎn)函數(shù)的代碼:
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;
}
}
最后,可以封裝正轉(zhuǎn)和反轉(zhuǎn)函數(shù)成子函數(shù):
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);
?}
最后,可以在主函數(shù)中使用這些封裝好的子函數(shù):
int main(void)
{
init_GPIO();
?
// 正轉(zhuǎn)200步
rotate_motor(200, 0);
?
// 反轉(zhuǎn)100步
rotate_motor(100, 1);
?
// 停止電機(jī)
motor_stop();
?
while (1);
}
3.2 蜂鳴器報(bào)警代碼
#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 紅外感應(yīng)器代碼
#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; // 對應(yīng)中斷線 EXTI1
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; // 上升沿和下降沿觸發(fā)
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
?
NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn; // 中斷向量
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02; // 搶占優(yōu)先級2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x03; // 響應(yīng)優(yōu)先級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
}
四、總結(jié)
當(dāng)前設(shè)計(jì)的這種基于STM32的鐵路自動(dòng)圍欄系統(tǒng),通過對鐵路交叉口進(jìn)行有效的監(jiān)測和控制,實(shí)現(xiàn)了對過往車輛和行人的有效防護(hù)。該系統(tǒng)采用STM32F103RCT6作為主控芯片,使用步進(jìn)電機(jī)控制鐵路圍欄的開啟和閉合,使用紅外感應(yīng)器來監(jiān)測列車的通過情況。在公路與鐵路的交叉路口,若在遠(yuǎn)處感應(yīng)到有列車即將通過,則公路信號燈變?yōu)榧t燈,蜂鳴器報(bào)警,鐵路兩側(cè)圍欄自動(dòng)閉合;直至感應(yīng)到列車徹底離開,公路信號燈變?yōu)榫G燈,蜂鳴器關(guān)閉,圍欄打開。系統(tǒng)具有結(jié)構(gòu)簡單、性能可靠等優(yōu)點(diǎn),在實(shí)際應(yīng)用中取得了良好的效果。
審核編輯:湯梓紅
-
芯片
+關(guān)注
關(guān)注
456文章
50908瀏覽量
424485 -
STM32
+關(guān)注
關(guān)注
2270文章
10906瀏覽量
356479 -
步進(jìn)電機(jī)
+關(guān)注
關(guān)注
150文章
3113瀏覽量
147574 -
鐵路
+關(guān)注
關(guān)注
1文章
67瀏覽量
17897 -
單片機(jī)
+關(guān)注
關(guān)注
0文章
216瀏覽量
16658
發(fā)布評論請先 登錄
相關(guān)推薦
評論