基于MM32与M26物联网入门:远程呼叫及开锁

应用场景

适用于庭院大门,当有来客呼叫时,实现手动开锁、远程开锁的功能;

应用功能

通过MM32主控芯片与M26 2G通讯模块与远程服务器进行连接,当有访客按下CALL按键时,本地响应门铃(本应用暂未接门铃),同时进行远程呼叫;户主可以通过OPEN按键直接给访客开门,也可以通过服务器发送OPEN指令进行远程开门;

在没有访客呼叫时,MM32与服务器之间每间隔10秒钟进行一次心跳包传输,以保证与服务器之间SOCKET链路的连接;

在有访客呼叫时,若没有进行开锁动作,则每间隔3秒钟向服务器端发送一个呼叫指令;当接收到服务器端OPEN开锁命令时,执行开锁动作,开锁时间保持3秒钟,开销期间并向服务器反馈开锁是否成功的状态;

硬件模块

在网上淘到一块基于M26的2G通讯板,将主控MCU替换成MM32F0273D6P,这样省去了通讯板的设计及绘制,因为之前做过不少的工业远程控制项目,所以对通讯板的原理、控制都已经很熟悉了;通讯板如下图所示,带有5个接口及一个用户自己定义按键:1路光耦输出控制、2路带极性的光耦输入采集、1路无极性的光耦输入采集、以及1个UART程序烧录接口;

对硬件设计进行分析后,正好满足我们当前的硬件需求:1路光耦输出控制用于门锁的控制、2路带极性的光耦输入采集用于手动开锁按键和门外的呼叫按键、最后1路无极性的光耦输入采集则用于门锁的开关状态检测(我们选用的电磁锁是带有开关状态输出的);

为什么选用MM32F0273D6P这个芯片呢?基于通讯板,我们需要一个LQFP48封装的芯片,其次MM32F0273D6P是一个32位的Cortex-M0的控制芯片,最高工作主频可达到96MHz,运行速度够快;带有128KB FLASH程序存储空间,以及16KB SRAM的运行内存,能够满足在物联网工程项目功能上的应用;最后就是通讯板是通过UART下载程序的,MM32F0273D6P出厂自带了ISP功能,可以通过BOOT引脚来选择启动程序,配合上位机软件实现程序的烧录。

原理图设计

除了通讯板之外,我们还需要另外一块硬件单板配合演示/调试,功能如下:2个按键(1个手动开锁按键、1个门外呼叫按键)、1个门锁开关控制电路(继电器控制方式)、1个门锁开关状态检测电路(用于检测门锁的开关状态,以及确认门锁控制是否正常),最后就是开发板的供电(5V)以及门锁供电(12V);原理图如下所示:

PCB设计3D效果图

整机实物图

功能实现代码:按键检测及处理

/*******************************************************************************
 

[url=home.php?mod=space&uid=247401]@brief[/url]      
 

@param      
 

@retval      
 

[url=home.php?mod=space&uid=93590]@Attention[/url]   
 

*******************************************************************************/
 

void KEY_SubScan(uint8_*State, uint8_t *Count, uint8_t Value, char *Name)
 

{
 

    if(*State == 0)
 

    {
 

        if(Value == Bit_RESET) *Count += 1;
 

        else                   *Count  = 0;
 

        if(*Count > 5)
 

        {
 

            *Count = 0; *State = 1;
 

            {
 

                BSP_LOCK_Control(LOCK_MODE_MANUAL, ENABLE);

                if(RemoteState != 0)
 

                {
 

                    RemoteState = 0;

                }
 

            }
 

        }
 

    }
 

    else
 

    {

        if(Value != Bit_RESET) *Count += 1;

        else                   *Count  = 0;

        if(*Count > 5)

        {

            *Count = 0; *State = 0;

            {
 

                BSP_LOCK_Control(LOCK_MODE_MANUAL, DISABLE);
 

            }

            {
 

                if(RemoteState == 0)

                {
 

                    RemoteState = 1;

                }
 

            }
 

        }
 

    }
 

}

/*******************************************************************************
 

[url=home.php?mod=space&uid=247401]@brief[/url]      
 

@param      
 

@retval      
 

[url=home.php?mod=space&uid=93590]@Attention[/url]   
 

*******************************************************************************/
 

void KEY_Scan(void)

{

    static uint8_t KeyState[3] = {0, 0, 0};
 

    static uint8_t KeyCount[3] = {0, 0, 0};
 

功能实现代码:M26启动及配置

uint8_t  M26_Buffer[1000];
 

uint16_t M26_Length  =  0;

/*******************************************************************************
 

[url=home.php?mod=space&uid=247401]@brief[/url]      

@param     

@retval      

[url=home.php?mod=space&uid=93590]@Attention[/url]   

*******************************************************************************/

void M26_InitBuffer(void)

{

    M26_Length = 0;

    memset(M26_Buffer, 0, sizeof(M26_Buffer));

}

/*******************************************************************************

[url=home.php?mod=space&uid=247401]@brief[/url]      

@param      

@retval      

[url=home.php?mod=space&uid=93590]@Attention[/url]   

*******************************************************************************/

void M26_SendData(uint8_t Data)
 

{

    UART_SendData(UART2, Data);
 

    while(UART_GetFlagStatus(UART2, UART_IT_TXIEN) == RESET);
 

}

/*******************************************************************************
 

@brief      
 

@param      
 

@retval      
 

@attention   
 

*******************************************************************************/
 

void M26_SendString(char *str)
 

{

    while(*str)

    {

        M26_SendData(*str++);

    }

}

/*******************************************************************************

@brief      

@param      

@retval      

@attention   

*******************************************************************************/

uint32_t M26_AT_WaitForReply(char *Keyword, uint32_t Timeout)

{

    M26_InitBuffer();

    while(Timeout--)

    {

        if(QUEUE_EMPTY(QUEUE_M26_RX_IDX) == 0)

        {

            M26_Buffer[M26_Length++] = QUEUE_READ(QUEUE_M26_RX_IDX);

            if(strstr((char *)M26_Buffer, Keyword) != NULL)
 

            {

            }
 

        }

        SysTick_DelayMS(1);
 

    }

    return Timeout;
 

}

/*******************************************************************************
 

@brief      
 

@param      
 

@retval      
 

@attention   
 

*******************************************************************************/

uint32_t M26_AT_SendCommand(char *Command, char *Response, uint32_t Timeout)

{

    if(Command != NULL)

    {

        M26_SendString(Command);

    }

    if(Timeout != 0)
 

    {

        return (Timeout - M26_AT_WaitForReply(Response, Timeout));

    }
 

    else
 

    {

        return 1;

    }

}

/*******************************************************************************
 

@brief      
 

@param      
 

@retval      
 

@attention   
 

*******************************************************************************/
 

void M26_SendMessage(char *str)
 

{
 

    char Buffer[200];

    memset(Buffer, 0, sizeof(Buffer));
 

    M26_SendString(str);

_AT_SendCommand(NULL, "SEND OK", 1000));
 

}
 

/*******************************************************************************
 

@brief      
 

@param      
 

@retval      
 

@attention   
 

*******************************************************************************/
 

void M26_AT_Startup(void)
 

{
 

_AT_SendCommand(NULL, "RDY",          10000));
 

_AT_SendCommand(NULL, "+CFUN: 1",     10000));
 

_AT_SendCommand(NULL, "+CPIN: READY", 10000));
 

_AT_SendCommand(NULL, "Call Ready",   10000));
 

_AT_SendCommand(NULL, "SMS Ready",    10000));
 

_AT_SendCommand("AT", "OK",           10000));
 

    {

        {

           break;

        }

        SysTick_DelayMS(500);

    }
 

_AT_SendCommand(NULL, "CONNECT OK", 20000));

功能实现代码:呼叫及开锁控制

/*******************************************************************************
 

@brief      
 

@param      
 

@retval      
 

@attention   
 

*******************************************************************************/
 

void BSP_LOCK_Control(uint8_t Mode, uint8_t Enable)
 

{
 

    LockMode = Mode;

    if(Enable == 0)
 

    {
 

* 上锁 */
 

    }
 

    else
 

    {
 

* 开锁 */
 

    }
 

}
 

/*******************************************************************************
 

@brief      
 

@param      
 

@retval      
 

@attention   
 

*******************************************************************************/
 

void BSP_LOCK_Handler(void)
 

{
 

    static uint8_t LockTimeout = 0;

    if(LockMode == LOCK_MODE_REMOTE)

    {

        LockTimeout++;

        if(LockTimeout == 15)
 

        {
 

            if(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_5))
 

            {

            }
 

            else
 

            {

            }
 

        }

        if(LockTimeout >= 30)

        {

            RemoteState = 0;
 

            BSP_LOCK_Control(LOCK_MODE_MANUAL, DISABLE);
 

        }
 

    }
 

    else

    {

        LockTimeout = 0;

    }

}

/*******************************************************************************
 

@brief      
 

@param      
 

@retval      
 

@attention   
 

*******************************************************************************/
 

void REMOTE_Handler(void)

{
 

    if(RemoteState == 0)

    {
 

        if(RemoteHeartbeat++ >= 100)
 

        {
 

            RemoteHeartbeat = 0;
 


 

        }

    }

    if(RemoteState == 1)
 

    {
 

        RemoteCount++;
 


 

        if(RemoteCount >= 30)
 

        {
 

            RemoteCount = 0;
 


 

        }
 

    }
 

    else
 

    {
 

        RemoteCount = 0;
 

    }
 

}

/*******************************************************************************
 

@brief      
 

@param      
 

@retval      
 

@attention   
 

*******************************************************************************/
 

void MESSAGE_Handler(void)
 

{
 

    if(QUEUE_EMPTY(QUEUE_M26_RX_IDX) == 0)
 

    {
 

        MSG_Buffer[MSG_Length++] = QUEUE_READ(QUEUE_M26_RX_IDX);
 


 

* 返回开锁成功或失败 */

        {

            RemoteState = 2;
 


 

            BSP_LOCK_Control(LOCK_MODE_REMOTE, ENABLE);

            MSG_Length = 0;
 

            memset(MSG_Buffer, 0, sizeof(MSG_Buffer));
 

        }
 

    }

演示效果

服务器我们使用花生壳内网穿透映射的方式,将域名及端口号映射到本地内网的IP和端口,再使用网络调试助手软件建立一个TCP/IP服务器,来进行演示,如下图:

ISP下载程序

系统启动&M26初始化配置

呼叫后手动开锁

呼叫后远程开锁

---------------------

作者:xld0932
链接:https://bbs.21ic.com/icview-3205330-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值