新聞中心

EEPW首頁 > 設(shè)計(jì)應(yīng)用 > 基于MSPM0G3507的非接觸門禁控制系統(tǒng)

基于MSPM0G3507的非接觸門禁控制系統(tǒng)

作者:lulugl 時(shí)間:2025-01-20 來源:EEPW 收藏

1   項(xiàng)目簡介

本文引用地址:http://2s4d.com/article/202501/466478.htm

在一些特殊的場(chǎng)所,比如傳染病病房、手術(shù)室等需要嚴(yán)格區(qū)分污染區(qū)與非污染區(qū)的場(chǎng)景,對(duì)于非接觸來替換一些按鍵等,就非常有意義。本項(xiàng)目是通過手勢(shì)傳感器來控制隔離門禁的案例。

控制端在正常接收到門禁端的狀態(tài)信息后,獲門禁位置信息,同步顯示到OLED 屏上。當(dāng)手勢(shì)傳感器捕捉到指定動(dòng)作后,通過CAN 總線發(fā)送手勢(shì)指令。

門禁端在啟動(dòng)后執(zhí)行自檢,將起點(diǎn)到終點(diǎn)的位置檢測(cè)好,并把運(yùn)行一次的時(shí)間打包通過CAN 總結(jié)發(fā)送出來。門禁端在接收到指令后,與本身的位置相結(jié)合,執(zhí)行相應(yīng)的指令。通過PWM 來產(chǎn)生指定頻率的脈沖驅(qū)動(dòng)步進(jìn)電機(jī),通過DIR 高低電平設(shè)置來改變電機(jī)運(yùn)行方向,通過滑臺(tái)來實(shí)現(xiàn)門禁的打開與關(guān)閉功能。

實(shí)現(xiàn)功能,手勢(shì)向上,關(guān)閉門禁,手勢(shì)向下,打開門禁,手勢(shì)下壓,急停。

2   硬件結(jié)構(gòu)圖

1737348244363568.png

1.1 Bom表(寫明器件型號(hào));


序號(hào)
名稱
型號(hào)
數(shù)量
備注
1開發(fā)板
LP-MSPM0G3507
3
【1】
2CAN_TTL
未知
3
【2】
3OLED
SSD1306
2【3】
4手勢(shì)傳感器
PAJ7620
2【4】
5霍爾傳感器
3144
2【5】
652步進(jìn)電機(jī)
——
1【6】
7步進(jìn)電機(jī)驅(qū)動(dòng)器
——
1【7】
8滑臺(tái)
——
1無圖片
9直流電源

image.png

【1】

image.png

【2】

image.png

【3】

image.png

【4】

image.png

【5】

image.png

【6】

image.png

【7】

1.2 軟件開發(fā):

【開發(fā)平臺(tái)】

Code Composer Studio Version: 12.7.0.00007

【外設(shè)的配置】

本項(xiàng)目主要的外設(shè)由IIC、PWM、CAN 來驅(qū)動(dòng)。

1.1.1 IIC 的配置

配置為1M 的速率,同時(shí)開啟收接中斷,配置發(fā)送與接收的緩沖區(qū)。

1737349319860761.png

1.1.2 PWM的配置

選擇pwm0,以及通道0 為輸出,配置輸出1KHz的輸出波形,占空比50%。

1737349375789283.png

配置輸出的IO為PB0

1737349419733440.png

1.1.3 CAN的配置

配置仲裁速率為250K,數(shù)據(jù)傳輸速率為2M。

1737349454208931.png

選擇RX為PA13,TX為PA12

1737349495484449.png

保存后生成工程。

【公共代碼】

CAN 發(fā)送與接收代碼

1. CAN 接收中斷函數(shù)的實(shí)現(xiàn):

void MCAN0_INST_IRQHandler(void)

{

switch ( DL_MCAN_getPendingInterrupt(MCAN0_INST)) {case DL_MCAN_IIDX_LINE1:

/ * Check MCAN interrupts fired during TX/RX of CAN package */gInterruptLine1Status |= DL_MCAN_getIntrStatus(MCAN0_INST);

DL_MCAN_clearIntrStatus(MCAN0_INST,

gInterruptLine1Status,

DL_MCAN_INTR_SRC_MCAN_LINE_1);

gServiceInt = true;

break;

default:

break;

}

}

代碼中如果有CAN 的數(shù)據(jù)接收,則更新接收標(biāo)志

gServiceInt。

在主循環(huán)中判斷接收接收標(biāo)志位,如果為真則調(diào)用數(shù)據(jù)處理函數(shù)

if(true == gServiceInt)

{

gServiceInt = false;

rxFS.fillLvl = 0;

if ((gInterruptLine1Status & MCAN_IR_RF0N_MASK) == MCAN_IR_RF0N_MASK) {rxFS.num = DL_MCAN_RX_FIFO_NUM_0;

while ((rxFS.fillLvl) == 0) {

DL_MCAN_getRxFIFOStatus(MCAN0_INST, &rxFS);

}

DL_MCAN_readMsgRam(MCAN0_INST, DL_MCAN_MEM_TYPE_FIFO, 0U, rxFS.num, &rxMsg);

DL_MCAN_writeRxFIFOAck(MCAN0_INST, rxFS.num, rxFS.getIdx);

processRxMsg(&rxMsg);

gInterruptLine1Status &= ~(MCAN_IR_RF0N_MASK);

/* Add request for transmission. */

}

}

在數(shù)據(jù)處理函數(shù)中,如果是門禁端,則判斷是否為命令的ID,如果是則根據(jù)命令設(shè)置電機(jī)運(yùn)行方向:

void processRxMsg(DL_MCAN_RxBufElement

*rxMsg)

{

uint32_t idMode;

uint32_t id;

idMode = rxMsg->xtd;

if (ID_MODE_EXTENDED == idMode) {id = rxMsg->id;

} else {

/ * Assuming package is using 11-bit standardID.

* When package uses standard id, ID is stored inID[28:18]*/

id = ((rxMsg->id & (uint32_t) 0x1FFC0000) >>(uint32_t) 18);

}

switch (id) {

case 0x3:

mydoor_t.run_dir = rxMsg->data[1];

set_dir();

break;

default:

/* Don’t do anything */break;

}

}

在控制端則對(duì)接收的ID 進(jìn)行判斷,并進(jìn)行數(shù)據(jù)解析:

void processRxMsg(DL_MCAN_RxBufElement*rxMsg)

{

uint32_t idMode;

uint32_t id;

idMode = rxMsg->xtd;

if (ID_MODE_EXTENDED == idMode) {id = rxMsg->id;

} else {

/ * Assuming package is using 11-bit standardID.

* When package uses standard id, ID is stored inID[28:18]*/

id = ((rxMsg->id & (uint32_t) 0x1FFC0000) >>(uint32_t) 18);

}

switch (id) {case 0x4:

mydoor_recv.run_state = rxMsg->data[0] ;

mydoor_recv.run_dir = rxMsg->data[1] ;

mydoor_recv.start_flage = rxMsg->data[2] ;

mydoor_recv.stop_flage = rxMsg->data[3] ;

mydoor_recv.run_one_time = rxMsg->data[4]+ (rxMsg->data[5]<<8);

mydoor_recv.run_this_time = rxMsg->data[6]

+ (rxMsg->data[7]<<8);

mydoor_recv.sta_link = 1 ;

break;

default:

/* Don’t do anything */

break;

}

}

CAN 發(fā)送:

在進(jìn)入主循環(huán)中,先對(duì)CAN 的數(shù)據(jù)進(jìn)行初始化:

txMsg0.id = ((uint32_t)(0x4)) << 18U;

/* Transmit data frame. */

txMsg0.rtr = 0U;

/* 11-bit standard identifier. */

txMsg0.xtd = 0U;

/* ESI bit in CAN FD format depends only on

error passive flag. */

txMsg0.esi = 0U;

/* Transmitting 4 bytes. */

txMsg0.dlc = 8U;

/ * CAN FD frames transmitted with bit rate

switching. */

txMsg0.brs = 1U;

/* Frame transmitted in CAN FD format. */

txMsg0.fdf = 1U;

/* Store Tx events. */

txMsg0.efc = 1U;

/* Message Marker. */

txMsg0.mm = 0xAAU;

/* Data bytes. */

txMsg0.data[0] = LED0_STATUS_ON;

txMsg0.data[1] = 0x00;

并根據(jù)對(duì)應(yīng)的功能進(jìn)行數(shù)據(jù)封門,并執(zhí)行數(shù)據(jù)發(fā)送功能:

if(1==mydoor_t.start_flage)

{

DL_TimerG_stopCounter(PWM_0_

INST);

mydoor_t.run_one_time = Tick -

mydoor_t.run_this_time;

mydoor_t.run_this_time = 0;

door_flag = 2;

// 記錄總時(shí)間

txMsg0.data[4] = (uint8_t)mydoor_

t.run_one_time;

txMsg0.data[5] = (uint8_t)(mydoor_

t.run_one_time>>8);

// 記錄起始時(shí)間

/ * Write Tx Message to the Message

RAM. */

DL_MCAN_writeMsgRam(MCAN0_

INST, DL_MCAN_MEM_TYPE_BUF, 0, &txMsg0);

/* Add request for transmission. */

DL_MCAN_TXBufAddReq(MCAN0_

INST, 0);

}

【PWM】

在pwm 代碼方面只需要啟動(dòng)或者關(guān)閉定時(shí)器就行了

void run_motor(void)

{

switch (mydoor_t.run_dir)

{

case 0x01:

if(mydoor_t.stop_flage == 0) // 如果沒有達(dá)到終點(diǎn)

{

DL_TimerG_startCounter(PWM_0_INST);

}

else{

DL_TimerG_stopCounter(PWM_0_INST);

}

break;

case 0x02:

if(mydoor_t.start_flage == 0)

{

DL_TimerG_startCounter(PWM_0_INST);

}

else

{

DL_TimerG_stopCounter(PWM_0_INST);

mydoor_t.run_state = 0;

}

break;

default:

DL_TimerG_stopCounter(PWM_0_INST);

mydoor_t.run_state = 0;

break;

}

}

【IIC 驅(qū)動(dòng)】

在工程中添加i2c 的驅(qū)動(dòng)封裝i2c_app.c/h

image.png

這個(gè)驅(qū)動(dòng)封裝了讀寫兩個(gè)驅(qū)動(dòng),可實(shí)現(xiàn)與硬件低層的解耦。具體代碼見附件。

1737349838768886.png

【OLED】

使用公有的OLED 驅(qū)動(dòng)庫,只需要封裝OLED_WR_Byte 即可實(shí)現(xiàn)驅(qū)動(dòng)的移植。

void OLED_WR_Byte(uint8_t dat, uint8_t mode)

{

if (mode)

{

i2c_app_write(I2C_OLED_INST, 0x3C, data,&dat, 1);

}

else

{

i2c_app_write(I2C_OLED_INST, 0x3C, cmd,&dat, 1);

}

}

手勢(shì)傳感器有現(xiàn)成的驅(qū)動(dòng)庫,我這里只需要添加iic的讀寫驅(qū)動(dòng)即可。

【PAJ7620 手勢(shì)傳感器】

PAJ7620 移植驅(qū)動(dòng),與OLED 一樣也只需要重寫讀寫函數(shù)即可以完成驅(qū)動(dòng)的移植

static void DEV_I2C_WriteByte(I2C_Regs *PAJ7620U2_I2C,uint8_t add_, uint8_t data_)

{

uint8_t Buf[1] = {0};

Buf[0] = data_;

i2c_app_write(I2C1, 0x73, add_,Buf, 2);

}

static void DEV_I2C_WriteWord(I2C_Regs *PAJ7620U2_I2C,uint8_t add_, uint16_t data_)

{

uint8_t Buf[2] = {0};

Buf[0] = data_ >> 8;

Buf[1] = data_;

i2c_app_write(I2C1, 0x73, add_,Buf, 2);

}

static uint8_t DEV_I2C_ReadByte(I2C_Regs *

PAJ7620U2_I2C,uint8_t add_)

{

uint8_t state;

uint8_t Buf[1];

Buf[0] = add_;

state = i2c_app_read(I2C1, 0x73, add_,Buf, 1);

if(state == 0)

{

return Buf[0];

}

else

return state;

}

以上是主要代碼的介紹。

【程序流程圖】

門禁端

image.png

image.png

3   項(xiàng)目總結(jié)

本項(xiàng)目主要是在利用Ti 的MSPM0G3507 這顆優(yōu)秀的MCU 來實(shí)現(xiàn)特殊環(huán)境下的無接觸的門禁控制,可以實(shí)現(xiàn)多點(diǎn)對(duì)一點(diǎn)控制,一對(duì)多的數(shù)據(jù)交互。

整個(gè)項(xiàng)目的亮點(diǎn)就是MSPM0G3507 擁有80M 主頻, 搭載了FDCAN 高速總線, 可以輕松實(shí)現(xiàn)多個(gè)MCU 的組網(wǎng),相比傳感的485 的總線組網(wǎng)有質(zhì)的提升,F(xiàn)DCAN 總線可以實(shí)現(xiàn)多對(duì)多的組網(wǎng)。同時(shí)這個(gè)MCU還有高速的IIC 總線,可以實(shí)現(xiàn)一路IIC 驅(qū)動(dòng)多個(gè)如OLED、PAJ7620 的外設(shè)。

同時(shí)使用了MSPM0G3507 的PWM 外設(shè),可以精準(zhǔn)的驅(qū)動(dòng)步進(jìn)電機(jī)。實(shí)現(xiàn)如門禁等電機(jī)控制場(chǎng)景。

(本文來源于《EEPW》



關(guān)鍵詞: 202501

評(píng)論


技術(shù)專區(qū)

關(guān)閉