1.概述:
智能家居物理网项目中,常见到各种传感器数据采集,这次我负责的设备终端node结点由一个磁性接近门开关和一个stm8L系列的单片机构成,采集的数据是门开关的状态,开or关。
2.传感器:
用到的传感器是磁性接近开关,这是接近开关的一种,磁性接近开关是传感器家族中众多种类中的一个,它是利用电磁工作原理,是一种位置传感器。它能通过传感器与物体之间的位置关系变化,将非电量或电磁量转化为所希望的电信号,从而达到控制或测量的目的。
3.采集流程:
模拟关门:从设备SWT(门开关传感器)的两块磁铁合上,会产生电平跳转,向主设备单片机stm8的gpio引脚发送跳变信号,stm8开始采集它发送过来的电平数据(0或1),这只是一个电平数据而已,之后我会根据我制定的类似于TLV协议的报文格式,封装成一条数据报文,报文里包含有很多条数据。
这是我定制的报文格式:
报文头 |
报文长度 |
网络号 |
源设备地址 |
电池电压 |
传感器类型 |
门传感器数据(01/00) |
CRC16校验 |
0x50 |
1 Byte |
2 Byte |
1 Byte |
1 byte |
1 Byte |
1~15 Byte |
2 Byte |
4.,通过AT命令配置相关信息填充报文,然后封装,写到STM8的eeprom里,再把完整报文通过AP模块的射频芯片发给网关。
1. 调用 sys_board_init()让板级初始化:
包括初始化系统时钟、初始化延时函数、初始化串口函数、初始化eeprom、打印开发板信息
1.void sys_board_init(void)
2.{
3. sys_clock_init();
4. msTimingDelay_Init();
5. dbg_uart_init(DEF_UBR_BAUDRATE);
6.
7. load_eeprom_conf();
8.
9. display_board_info( );
10.
11.#ifndef LORA_AP
12. g_rtc_timeout = g_sys_eep_conf.settings.report_time;
13. sys_wakeup_init();
14. get_battery_voltage(); /* 获取电池电压,将会设置全局变量 g_battery_voltage */
15.#endif
16.}
2.初始化完成后调用turn_led(LED_POWER, ON) 把power灯打开,
LED函数定义处: stm8_board.c(里面有stm8板子的相关函数)
1./*******************
2.* LED操作函数 *
3.******************/
4.void turn_led(uint8_t which, uint8_t cmd)
5.{
6.if(OFF == cmd)
7.{
8.if(which == LED_POWER)
9.GPIO_Init(SYSRUN_LED_PIN, GPIO_Mode_Out_PP_High_Slow);
10.else if(which == LED_STATUS)
11.GPIO_Init(LED_STATUS_PIN, GPIO_Mode_Out_PP_High_Slow);
12.}
13.else
14.{
15.if(which == LED_POWER)
16.GPIO_Init(SYSRUN_LED_PIN, GPIO_Mode_Out_PP_Low_Slow);
17.else if(which == LED_STATUS)
18.GPIO_Init(LED_STATUS_PIN, GPIO_Mode_Out_PP_Low_Slow);
19.}
20.}
3.检查AT指令
4.调用conf_eeprom.c中的 print_lora_settings()
打印lora配置信息,lora配置信息由AT命令修改,并写入eeprom中。
1.void print_lora_settings(void)
2.{
3.printf("Freq[%luMHz] BW[%sKHz] SF[%u] TXPWR[%d] CCR[%u] Address[%d:%d]\n",
4.LoRaSettings.RFFrequency/1000000, bw_list[LoRaSettings.SignalBw],
5.LoRaSettings.SpreadingFactor, LoRaSettings.Power, LoRaSettings.ErrorCoding,
6.g_sys_eep_conf.settings.netid, g_sys_eep_conf.settings.devid);
7.}
5.调用rtc_set_timeout(),设置RTC定时器上报时间
RTC超时函数定义处: stm8_board.c(里面有stm8板子的相关函数)
uint16_t g_rtc_timeout=5; /* RTC wakeup timeout */ 5s超时
/*初始化定时器定时中断唤醒函数 */
void rtc_set_timeout(void)
{
if( g_rtc_timeout > 0 )
{
RTC_WakeUpCmd(DISABLE); //禁用周期唤醒功能
RTC_SetWakeUpCounter(g_rtc_timeout); // 把计数器值传入[void RTC_SetWakeUpCounter(uint16_t RTC_WakeupCounter)
{
/* Disable the write protection for RTC registers */
RTC->WPR = 0xCA;
RTC->WPR = 0x53;
/* Configure the Wakeup Timer counter */
RTC->WUTRH = (uint8_t)(RTC_WakeupCounter >> 8);
RTC->WUTRL = (uint8_t)(RTC_WakeupCounter);
/* Enable the write protection for RTC registers */
RTC->WPR = 0xFF;
}
]
9.g_rtc_timeout = g_sys_eep_conf.settings.report_time; //从eeprom里读取设置计数值
10.RTC_WakeUpCmd(ENABLE);//按顺序写OXCA、0X53->寄存器RTC_[ErrorStatus RTC_WakeUpCmd(FunctionalState NewState)
{
ErrorStatus status = ERROR;
uint16_t wutwfcount = 0; //复位计数器
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState)); //检查输入参数
/* Disable the write protection for RTC registers */
RTC->WPR = 0xCA;
RTC->WPR = 0x53;//解除寄存器保护
if (NewState != DISABLE)
{
/* Enable the Wakeup Timer */
RTC->CR2 |= (uint8_t)RTC_CR2_WUTE;
status = SUCCESS;
}
else
{
/* Disable the Wakeup Timer */
RTC->CR2 &= (uint8_t)~RTC_CR2_WUTE;
/* Wait until WUTWF flag is set */
while (((RTC->ISR1 & RTC_ISR1_WUTWF) == RESET) && ( wutwfcount != WUTWF_TIMEOUT))
{
wutwfcount++;
}
/* Check WUTWF flag is set or not */
if ((RTC->ISR1 & RTC_ISR1_WUTWF) == RESET)
{
status = ERROR;
}
else
{
status = SUCCESS;
}
}
/* Enable the write protection for RTC registers */
RTC->WPR = 0xFF;
/* Return the status*/
return (ErrorStatus)status;
}]WPR解除寄存器保护,唤醒计时器
}
}
6.大体配置好板级、打开led、用AT命令把配置写入eeprom、让RTC使能后,
用While(1)进入死循环,让单片机一直跑。
7.当产生以下事件中的任一种中断事件,if(g_key_report|g_switch_report| g_rtc_report),任意项标志位为1,就开始采集工作:按下复位按键事件( g_key_report)、门开关变化事件(g_switch_report)RTC定时时间到要上报( g_rtc_report)
/*括号里为标志位,assert值为1或0*/
8.门开关传感器开始采集数据(采样)、判断、并通过LORA上报
入口函数:sensor_proc_sample()
函数定义处:sensor_proc.c(各种传感器的封包并通过LoRa发送的函数)