整个项目基于RT-thread系统搭建,类似于共享单车的模式,是为共享锁,由微信小程序扫码然后远程开锁,并对锁的控制,需要有低功耗。
小程序界面
板子照片
MCU为STM32L431CCT6 ,NBIOT采用有人NB73,板子集成了电机驱动芯片(用来控制门锁驱动电机)蜂鸣器驱动,以及一个超低静态电流的LDO,以及低功耗的电压检测电路。
最终整个板子的功耗为30uA,MCU+NBIOT+LDO+电压检测电路。
整个系统最重要的就是低功耗的实现,在这里除了特别选用了STM32L4的MCU,以及电路上其他器件的选型也特别重要,特别是稳压芯片的的静态电路不容忽视。
除此之外,也还要有软件上的控制,这里我使用的RT-thread的PM组件,进入了待机模式,并设置了两个唤醒按键以及RTC定时唤醒。
设置唤醒按键的HAL库函数如下
HAL_PWR_EnableWakeUpPin(PWR_WAKEUP_PIN1_HIGH|PWR_WAKEUP_PIN2_HIGH);
设置PIN1高电平唤醒以及PIN2高电平唤醒,在此之前,由于系统进入待机模式后,所有IO都处于复位状态,为了避免误动作,需要使用如下函数,来设置待机模式的引脚状态。
HAL_PWREx_EnableGPIOPullDown(PWR_GPIO_A, PWR_GPIO_BIT_0); HAL_PWREx_EnablePullUpPullDownConfig();
这是是设置了A0。
然后就可以愉快的进入待机模式了,当然进入之前,需要将唤醒标志位清0.
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
其中PWR_FLAG_WU可以有多个参数选择,WUF1、WUF2等等,看看库函数的注释就可以了。
然后就可以调用RTT的PM组件进入待机模式了。
rt_pm_request(PM_SLEEP_MODE_STANDBY);
当然,唤醒后,是出于复位装状态,会重新执行初始化,这里最好判断一下是否是被唤醒以及被什么方式唤醒。可以使用如下函数:
__HAL_PWR_GET_FLAG(PWR_FLAG_WUF1)
这里WUF1指的是WKUP_PIN1的事件。
我这里使用的是闹钟中断作为唤醒,你只需要初始化RTC在设置闹钟中断就可以,但是唤醒后复位并不会进入闹钟中断,他只是唤醒。
我本打算在RTT中直接添加RTC组件,但我发现他并没有使用硬件的闹钟中断,所以我在他的drv_rtc中自行实现了闹钟中断的初始化及设置函数。如下
rt_err_t rtc_set_alarmA(rt_uint8_t week, rt_uint8_t hour, rt_uint8_t min, rt_uint8_t sec,rt_uint32_t alarm_mask)
{
RTC_AlarmTypeDef RTC_AlarmSturuct;
RTC_AlarmSturuct.AlarmTime.Hours = hour; //小时
RTC_AlarmSturuct.AlarmTime.Minutes = min; //分钟
RTC_AlarmSturuct.AlarmTime.Seconds = sec; //秒
RTC_AlarmSturuct.AlarmTime.SubSeconds = 0;
RTC_AlarmSturuct.AlarmTime.TimeFormat = RTC_HOURFORMAT12_AM;
RTC_AlarmSturuct.AlarmMask = alarm_mask;
RTC_AlarmSturuct.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_NONE;
RTC_AlarmSturuct.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_WEEKDAY; //按星期
RTC_AlarmSturuct.AlarmDateWeekDay = week; //星期
RTC_AlarmSturuct.Alarm = RTC_ALARM_A; //闹钟A
if(HAL_RTC_SetAlarm_IT(&RTC_Handler, &RTC_AlarmSturuct, RTC_FORMAT_BIN)!=HAL_OK)
{
return -RT_ERROR;
}
HAL_NVIC_SetPriority(RTC_Alarm_IRQn, 0x01, 0x02); //抢占优先级1,子优先级2
HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
return RT_EOK;
}
只要正常使用RTT系统的settime函数设置RTC时间,在调用rtc_set_alarmA函数即可添加闹钟。闹钟中断函数只需要在某处定义即可。