基于MSPM0G3507的非接觸門禁控制系統(tǒng)
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)圖
1.1 Bom表(寫明器件型號(hào));
序號(hào) | 名稱 | 型號(hào) | 數(shù)量 | 備注 |
1 | 開發(fā)板 | LP-MSPM0G3507 | 3 | 【1】 |
2 | CAN_TTL | 未知 | 3 | 【2】 |
3 | OLED | SSD1306 | 2 | 【3】 |
4 | 手勢(shì)傳感器 | PAJ7620 | 2 | 【4】 |
5 | 霍爾傳感器 | 3144 | 2 | 【5】 |
6 | 52步進(jìn)電機(jī) | —— | 1 | 【6】 |
7 | 步進(jìn)電機(jī)驅(qū)動(dòng)器 | —— | 1 | 【7】 |
8 | 滑臺(tái) | —— | 1 | 無圖片 |
9 | 直流電源 |
【1】
【2】
【3】
【4】
【5】
【6】
【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ū)。
1.1.2 PWM的配置
選擇pwm0,以及通道0 為輸出,配置輸出1KHz的輸出波形,占空比50%。
配置輸出的IO為PB0
1.1.3 CAN的配置
配置仲裁速率為250K,數(shù)據(jù)傳輸速率為2M。
選擇RX為PA13,TX為PA12
保存后生成工程。
【公共代碼】
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
這個(gè)驅(qū)動(dòng)封裝了讀寫兩個(gè)驅(qū)動(dòng),可實(shí)現(xiàn)與硬件低層的解耦。具體代碼見附件。
【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;
}
以上是主要代碼的介紹。
【程序流程圖】
門禁端
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》202501)
評(píng)論