2024-12-01 13:49:43 +08:00
|
|
|
|
/*
|
|
|
|
|
* @Author : stark1898y 1658608470@qq.com
|
|
|
|
|
* @Date : 2024-09-04 17:33:57
|
|
|
|
|
* @LastEditors: mbw && 1600520629@qq.com
|
|
|
|
|
* @LastEditTime: 2024-11-30 16:32:01
|
|
|
|
|
* @FilePath: \ble_bjq_ch303rct6_ml307\bsp\src\bsp_hr.c
|
|
|
|
|
* @Description :
|
|
|
|
|
*
|
|
|
|
|
* Copyright (c) 2024 by yzy, All Rights Reserved.
|
|
|
|
|
*/
|
|
|
|
|
#include "bsp_hr.h"
|
|
|
|
|
#include "lwrb.h"
|
|
|
|
|
#include "bsp_flash.h"
|
|
|
|
|
#include "bsp_rtc.h"
|
2024-12-03 10:24:55 +08:00
|
|
|
|
#include "at_device_ml307.h"
|
2024-12-01 13:49:43 +08:00
|
|
|
|
#include "user_sys.h"
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define LOG_TAG "bsp_hr"
|
|
|
|
|
#define LOG_LVL LOG_LVL_DBG
|
|
|
|
|
#include <ulog.h>
|
|
|
|
|
|
|
|
|
|
ALIGN(RT_ALIGN_SIZE)
|
|
|
|
|
static char hr_thread_stack[HR_THREAD_STACK_SIZE];
|
|
|
|
|
static struct rt_thread hr_thread;
|
|
|
|
|
|
|
|
|
|
#define HR_RX_RB_LENGTH (64U)
|
|
|
|
|
#define HR_TX_RB_LENGTH (256U)
|
|
|
|
|
|
|
|
|
|
static lwrb_t hr_rx_rb;
|
|
|
|
|
static rt_uint8_t hr_rx_rb_data[HR_RX_RB_LENGTH];
|
|
|
|
|
|
|
|
|
|
static lwrb_t hr_tx_rb;
|
|
|
|
|
static rt_uint8_t hr_tx_rb_data[HR_TX_RB_LENGTH];
|
|
|
|
|
|
|
|
|
|
static rt_sem_t hr_rx_ok_sem;
|
|
|
|
|
static rt_sem_t hr_rx_parity_err_sem;
|
|
|
|
|
|
|
|
|
|
static rt_timer_t hr_timer;
|
|
|
|
|
uint8_t hr_rx_count = 0; // 接收缓冲区中,已经收到的数据包数量
|
|
|
|
|
void hr_timeout(void *parameter)
|
|
|
|
|
{
|
|
|
|
|
rt_sem_release(hr_rx_ok_sem);
|
|
|
|
|
rt_timer_stop(hr_timer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void USARTx_SendByte(USART_TypeDef *pUSARTx, uint8_t data)
|
|
|
|
|
{
|
|
|
|
|
USART_SendData(pUSARTx, data);
|
|
|
|
|
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void USARTx_SendStr(USART_TypeDef *pUSARTx, char *str)
|
|
|
|
|
{
|
|
|
|
|
uint8_t i = 0;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
USARTx_SendByte(pUSARTx, *(str + i));
|
|
|
|
|
i++;
|
|
|
|
|
} while (*(str + i) != '\0');
|
|
|
|
|
while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TC) == RESET);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 串口发送数据
|
|
|
|
|
unsigned int BSP_Hr_Send_Data(const void *buf, unsigned int len)
|
|
|
|
|
{
|
|
|
|
|
unsigned int ret;
|
|
|
|
|
|
|
|
|
|
ret = lwrb_write(&hr_tx_rb, buf, len);
|
|
|
|
|
USART_ITConfig(HR_UART, USART_IT_TXE, ENABLE);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* @description: 从帧起始符开始到校验码之前所有字节的和的模256,即各字节不计超过255的溢出值的二进制算术和。
|
|
|
|
|
* @param {uint8_t} *data
|
|
|
|
|
* @param {uint16_t} len
|
|
|
|
|
* @return {*}
|
|
|
|
|
*/
|
|
|
|
|
static rt_uint8_t HR_CheckSum(const rt_uint8_t *data, rt_size_t len)
|
|
|
|
|
{
|
|
|
|
|
rt_uint8_t sum = 0;
|
|
|
|
|
|
|
|
|
|
for (rt_size_t i = 0; i < len; i++)
|
|
|
|
|
{
|
|
|
|
|
sum += data[i];
|
|
|
|
|
}
|
|
|
|
|
return sum;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @description: 从接收缓冲区中获取一帧有效数据
|
|
|
|
|
* @param {TsFrameData} *pFrameData 主机帧
|
|
|
|
|
* @param {uint8_t} *p_src 接收缓冲区
|
|
|
|
|
* @param {uint16_t} src_len 接收缓冲区长度
|
|
|
|
|
* @return {*}
|
|
|
|
|
*/
|
|
|
|
|
TsFrameData *HR_GetFrameData(const rt_uint8_t *p_src, const rt_uint8_t src_len)
|
|
|
|
|
{
|
|
|
|
|
rt_uint8_t data_field_len = 0;
|
|
|
|
|
rt_uint8_t check_sum = 0;
|
|
|
|
|
|
|
|
|
|
TsFrameData *get_buffer = RT_NULL;
|
|
|
|
|
|
|
|
|
|
for (rt_size_t i = 0; i < src_len; i++)
|
|
|
|
|
{
|
|
|
|
|
if (p_src[i] == FRAME_HEADER)
|
|
|
|
|
{
|
|
|
|
|
data_field_len = p_src[i + 3];
|
|
|
|
|
|
|
|
|
|
if (p_src[i + 3 + data_field_len + 2] == FRAME_TAIL)
|
|
|
|
|
{
|
|
|
|
|
check_sum = HR_CheckSum(&p_src[i], (4 + data_field_len));
|
|
|
|
|
|
|
|
|
|
if (p_src[i + 3 + data_field_len + 1] == check_sum)
|
|
|
|
|
{
|
|
|
|
|
get_buffer = (TsFrameData *)rt_malloc(sizeof(TsFrameData) + sizeof(rt_uint8_t) * data_field_len);
|
|
|
|
|
if (get_buffer == RT_NULL)
|
|
|
|
|
{
|
|
|
|
|
LOG_E("get space fail\r\n");
|
|
|
|
|
|
|
|
|
|
return RT_NULL;
|
|
|
|
|
}
|
|
|
|
|
get_buffer->c1 = p_src[i + 1];
|
|
|
|
|
get_buffer->c2 = p_src[i + 2];
|
|
|
|
|
get_buffer->len = data_field_len;
|
|
|
|
|
|
|
|
|
|
if (data_field_len > 0)
|
|
|
|
|
{
|
|
|
|
|
rt_memmove(get_buffer->data, &p_src[i + 4], data_field_len);
|
|
|
|
|
}
|
|
|
|
|
LOG_D("HR_GetDataFrame Success!");
|
|
|
|
|
|
|
|
|
|
return get_buffer;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
LOG_E("HR_GetDataFrame Fail!");
|
|
|
|
|
|
|
|
|
|
return get_buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rt_uint8_t HR_GenerateRawFrame(TsRawFrameData *pRawData, rt_uint8_t c1, TeFrameC2 c2, const rt_uint8_t *p_src, rt_uint8_t src_len)
|
|
|
|
|
{
|
|
|
|
|
pRawData->len = src_len + 6;
|
|
|
|
|
|
|
|
|
|
rt_memset(pRawData->buf, 0, sizeof(pRawData->buf));
|
|
|
|
|
|
|
|
|
|
pRawData->buf[0] = FRAME_HEADER;
|
|
|
|
|
pRawData->buf[1] = c1;
|
|
|
|
|
pRawData->buf[2] = c2;
|
|
|
|
|
pRawData->buf[3] = src_len;
|
|
|
|
|
|
|
|
|
|
rt_memmove(&pRawData->buf[4], p_src, src_len);
|
|
|
|
|
|
|
|
|
|
// 从帧起始符开始到校验码之前所有字节的和的模256
|
|
|
|
|
// ,即各字节不计超过255的溢出值的二进制算术和。
|
|
|
|
|
pRawData->buf[pRawData->len - 2] = HR_CheckSum(&pRawData->buf[0], pRawData->len - 2);
|
|
|
|
|
pRawData->buf[pRawData->len - 1] = FRAME_TAIL;
|
|
|
|
|
|
|
|
|
|
// LOG_HEX("HrRawData", 16, &pRawData->buf[0], pRawData->len);
|
|
|
|
|
|
|
|
|
|
return RT_EOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rt_uint8_t HR_ProcessData(const TsFrameData *pHostFrameData)
|
|
|
|
|
{
|
|
|
|
|
TuFlashProductTimeLimitFrame ReadLimitTime = {0};
|
|
|
|
|
TsRawFrameData RawData;
|
|
|
|
|
rt_uint8_t data_field[64] = {0};
|
|
|
|
|
rt_uint8_t c1, c2, data_len = 0;
|
|
|
|
|
|
|
|
|
|
c1 = pHostFrameData->c1;
|
|
|
|
|
c2 = pHostFrameData->c2;
|
|
|
|
|
|
|
|
|
|
switch (c2)
|
|
|
|
|
{
|
|
|
|
|
case kNumOfRecords: // 查询各类记录的总数 AA 00 00 00 AA 55
|
|
|
|
|
{
|
|
|
|
|
LOG_D("kNumOfRecords");
|
|
|
|
|
c1 = 0;
|
|
|
|
|
data_len = sizeof(TsTotalRecords);
|
|
|
|
|
if (Flash_GetTotalRecord((TsTotalRecords *)&data_field[0]) != RESET)
|
|
|
|
|
{
|
|
|
|
|
goto send;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case kAlarmRecord: // 查询第n条探测器报警记录AA 01 01 00 AC 55
|
|
|
|
|
{
|
|
|
|
|
LOG_D("kAlarmRecord(%d)", c1);
|
|
|
|
|
data_len = 7;
|
|
|
|
|
data_field[0] = c1;
|
|
|
|
|
if (Flash_GetRecord(kAlarmRecord, c1, (TsRecordsTime *)(&data_field[1])) != RESET)
|
|
|
|
|
{
|
|
|
|
|
if (data_field[0] == 0)
|
|
|
|
|
{
|
|
|
|
|
rt_memset(data_field, 0, data_len);
|
|
|
|
|
}
|
|
|
|
|
goto send;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case kAlarmRcyRecord: // 查询第n条探测器报警恢复记录 AA 01 02 00 AD 55
|
|
|
|
|
{
|
|
|
|
|
LOG_D("kAlarmRcyRecord(%d)", c1);
|
|
|
|
|
data_len = 7;
|
|
|
|
|
data_field[0] = c1;
|
|
|
|
|
if (Flash_GetRecord(kAlarmRcyRecord, c1, (TsRecordsTime *)(&data_field[1])) != RESET)
|
|
|
|
|
{
|
|
|
|
|
goto send;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case kFaultRecord: // 查询第n条探测器故障记录 AA 01 03 00 AE 55
|
|
|
|
|
{
|
|
|
|
|
LOG_D("kFaultRecord(%d)", c1);
|
|
|
|
|
data_len = 7;
|
|
|
|
|
data_field[0] = c1;
|
|
|
|
|
if (Flash_GetRecord(kFaultRecord, c1, (TsRecordsTime *)(&data_field[1])) != RESET)
|
|
|
|
|
{
|
|
|
|
|
goto send;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case kFaultRcyRecord: // 查询第n条探测器故障恢复记录 AA 01 04 00 AF 55 AA 66 04 00 14 55
|
|
|
|
|
{
|
|
|
|
|
LOG_D("kFaultRcyRecord(%d)", c1);
|
|
|
|
|
data_len = 7;
|
|
|
|
|
data_field[0] = c1;
|
|
|
|
|
if (Flash_GetRecord(kFaultRcyRecord, c1, (TsRecordsTime *)(&data_field[1])) != RESET)
|
|
|
|
|
{
|
|
|
|
|
goto send;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case kPowerFailureRecord: // 查询第n条探测器掉电记录 AA 01 05 00 B0 55
|
|
|
|
|
{
|
|
|
|
|
LOG_D("kPowerFailureRecord(%d)", c1);
|
|
|
|
|
data_len = 7;
|
|
|
|
|
data_field[0] = c1;
|
|
|
|
|
if (Flash_GetRecord(kPowerFailureRecord, c1, (TsRecordsTime *)(&data_field[1])) != RESET)
|
|
|
|
|
{
|
|
|
|
|
goto send;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case kPowerOnRecord: // 查询第n条探测器上电记录 AA 01 06 00 B1 55
|
|
|
|
|
{
|
|
|
|
|
LOG_D("kPowerOnRecord(%d)", c1);
|
|
|
|
|
data_len = 7;
|
|
|
|
|
data_field[0] = c1;
|
|
|
|
|
if (Flash_GetRecord(kPowerOnRecord, c1, (TsRecordsTime *)(&data_field[1])) == READY)
|
|
|
|
|
{
|
|
|
|
|
goto send;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case kSensorFailureRecord: // 查询气体传感器失效记录 AA 00 07 00 B1 55
|
|
|
|
|
{
|
|
|
|
|
LOG_D("kSensorFailureRecord(%d)", c1);
|
|
|
|
|
|
|
|
|
|
data_len = 7;
|
|
|
|
|
if (Flash_GetRecord(kSensorFailureRecord, 1, (TsRecordsTime *)&data_field[1]) != RESET)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (c1 != 0) // 接收到的数据不对,直接返回0
|
|
|
|
|
{
|
|
|
|
|
rt_memset(data_field, 0, data_len);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (data_field[1] == 0) // 未失效
|
|
|
|
|
{
|
|
|
|
|
rt_memset(data_field, 0, data_len);
|
|
|
|
|
}
|
|
|
|
|
else // 失效
|
|
|
|
|
{
|
|
|
|
|
data_field[0] = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
goto send;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case kGetCurrentTime: // AA 00 08 00 B2 55
|
|
|
|
|
{
|
|
|
|
|
LOG_D("kGetCurrentTime");
|
|
|
|
|
|
|
|
|
|
data_len = sizeof(TsRecordsTime);
|
|
|
|
|
RTC_GetTime();
|
|
|
|
|
|
|
|
|
|
data_field[0] = (uint8_t)((RtcDateTime.year >> 8) & (0XFF));
|
|
|
|
|
data_field[1] = (uint8_t)((RtcDateTime.year) & (0xFF));
|
|
|
|
|
data_field[2] = RtcDateTime.month;
|
|
|
|
|
data_field[3] = RtcDateTime.day;
|
|
|
|
|
data_field[4] = RtcDateTime.hour;
|
|
|
|
|
data_field[5] = RtcDateTime.minute;
|
|
|
|
|
|
|
|
|
|
goto send;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/*扩展命令*/
|
|
|
|
|
case kGetCurrentTimeSecond: // AA 00 09 00 B3 55
|
|
|
|
|
{
|
|
|
|
|
LOG_D("kGetCurrentTimeSecond");
|
|
|
|
|
|
|
|
|
|
data_len = 7;
|
|
|
|
|
RTC_GetTime();
|
|
|
|
|
|
|
|
|
|
data_field[0] = (uint8_t)((RtcDateTime.year >> 8) & (0XFF));
|
|
|
|
|
data_field[1] = (uint8_t)((RtcDateTime.year) & (0xFF));
|
|
|
|
|
data_field[2] = RtcDateTime.month;
|
|
|
|
|
data_field[3] = RtcDateTime.day;
|
|
|
|
|
data_field[4] = RtcDateTime.hour;
|
|
|
|
|
data_field[5] = RtcDateTime.minute;
|
|
|
|
|
data_field[6] = RtcDateTime.second;
|
|
|
|
|
|
|
|
|
|
goto send;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case kSetCurrentTime: /*2024-03-25 17:34:56 AA 00 0A 07 07 E8 03 19 11 22 38 31 55*/
|
|
|
|
|
{
|
|
|
|
|
LOG_D("kSetCurrentTime");
|
|
|
|
|
|
|
|
|
|
data_len = 7;
|
|
|
|
|
|
|
|
|
|
RtcDateTime.hour = pHostFrameData->data[4];
|
|
|
|
|
RtcDateTime.minute = pHostFrameData->data[5];
|
|
|
|
|
RtcDateTime.second = pHostFrameData->data[6];
|
|
|
|
|
RtcDateTime.day = pHostFrameData->data[3];
|
|
|
|
|
RtcDateTime.month = pHostFrameData->data[2];
|
|
|
|
|
RtcDateTime.year = (rt_uint16_t)(pHostFrameData->data[0] << 8 | pHostFrameData->data[1]);
|
|
|
|
|
|
|
|
|
|
RTC_SetTime(RtcDateTime.year, RtcDateTime.month, RtcDateTime.day,
|
|
|
|
|
RtcDateTime.hour, RtcDateTime.minute, RtcDateTime.second);
|
|
|
|
|
|
|
|
|
|
RTC_GetTime();
|
|
|
|
|
data_field[0] = (uint8_t)((RtcDateTime.year >> 8) & (0XFF));
|
|
|
|
|
data_field[1] = (uint8_t)((RtcDateTime.year) & (0xFF));
|
|
|
|
|
data_field[2] = RtcDateTime.month;
|
|
|
|
|
data_field[3] = RtcDateTime.day;
|
|
|
|
|
data_field[4] = RtcDateTime.hour;
|
|
|
|
|
data_field[5] = RtcDateTime.minute;
|
|
|
|
|
data_field[6] = RtcDateTime.second;
|
|
|
|
|
|
|
|
|
|
goto send;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case kSetFactoryTime: /*2024-03-26 9:30:00 AA 00 0B 07 07 E8 03 1A 09 1E 00 EF 55*/
|
|
|
|
|
{
|
|
|
|
|
LOG_D("kSetFactoryTime\r\n");
|
|
|
|
|
data_len = 7;
|
|
|
|
|
Flash_SetProductTimeLimit((rt_uint16_t)(pHostFrameData->data[0] << 8 | pHostFrameData->data[1]), pHostFrameData->data[2],
|
|
|
|
|
pHostFrameData->data[3], pHostFrameData->data[4], pHostFrameData->data[5], pHostFrameData->data[6], kFactoryTimeId);
|
|
|
|
|
Flash_GetProductTimeLimit(&ReadLimitTime, kFactoryTimeId);
|
|
|
|
|
|
|
|
|
|
data_field[0] = (uint8_t)(ReadLimitTime.Struct.year >> 8);
|
|
|
|
|
data_field[1] = (uint8_t)(ReadLimitTime.Struct.year);
|
|
|
|
|
data_field[2] = ReadLimitTime.Struct.month;
|
|
|
|
|
data_field[3] = ReadLimitTime.Struct.day;
|
|
|
|
|
data_field[4] = ReadLimitTime.Struct.hour;
|
|
|
|
|
data_field[5] = ReadLimitTime.Struct.minute;
|
|
|
|
|
data_field[6] = ReadLimitTime.Struct.second;
|
|
|
|
|
|
|
|
|
|
goto send;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case kSetExpirationTime: /*2028-3-26 9:30:00 AA 00 0C 07 07 EC 03 1A 09 1E 00 F4 55*/
|
|
|
|
|
{
|
|
|
|
|
LOG_D("kSetExpirationTime");
|
|
|
|
|
|
|
|
|
|
data_len = 7;
|
|
|
|
|
|
|
|
|
|
Flash_SetProductTimeLimit((uint16_t)(pHostFrameData->data[0] << 8 | pHostFrameData->data[1]), pHostFrameData->data[2], pHostFrameData->data[3], pHostFrameData->data[4], pHostFrameData->data[5], pHostFrameData->data[6], kExpirationTimeId);
|
|
|
|
|
Flash_GetProductTimeLimit(&ReadLimitTime, kExpirationTimeId);
|
|
|
|
|
|
|
|
|
|
data_field[0] = (uint8_t)(ReadLimitTime.Struct.year >> 8);
|
|
|
|
|
data_field[1] = (uint8_t)(ReadLimitTime.Struct.year);
|
|
|
|
|
data_field[2] = ReadLimitTime.Struct.month;
|
|
|
|
|
data_field[3] = ReadLimitTime.Struct.day;
|
|
|
|
|
data_field[4] = ReadLimitTime.Struct.hour;
|
|
|
|
|
data_field[5] = ReadLimitTime.Struct.minute;
|
|
|
|
|
data_field[6] = ReadLimitTime.Struct.second;
|
|
|
|
|
|
|
|
|
|
goto send;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
send:
|
|
|
|
|
{
|
|
|
|
|
if ((c1 == 0) && ((0 < c2) & (c2 < kSensorFailureRecord)))
|
|
|
|
|
{
|
|
|
|
|
rt_memset(data_field, 0, data_len);
|
|
|
|
|
}
|
|
|
|
|
HR_GenerateRawFrame(&RawData, c1, (TeFrameC2)c2, data_field, data_len);
|
|
|
|
|
|
|
|
|
|
BSP_Hr_Send_Data(&RawData.buf[0], RawData.len);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return RT_EOK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// int usr_sprintf(char *buf, const char *format, ...)
|
|
|
|
|
// {
|
|
|
|
|
// int n;
|
|
|
|
|
// va_list arg_ptr;
|
|
|
|
|
// if (rt_thread_self() != RT_NULL)
|
|
|
|
|
// rt_enter_critical();
|
|
|
|
|
// va_start(arg_ptr, format);
|
|
|
|
|
// n = vsprintf(buf, format, arg_ptr);
|
|
|
|
|
// va_end(arg_ptr);
|
|
|
|
|
// if (rt_thread_self() != RT_NULL)
|
|
|
|
|
// rt_exit_critical();
|
|
|
|
|
// return n;
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// 查找 [] 并判断字符串
|
|
|
|
|
int Process_Factor_Cmd(const char *rx_buff, size_t length)
|
|
|
|
|
{
|
|
|
|
|
TuFlashProductTimeLimitFrame ReadLimitTime;
|
|
|
|
|
|
|
|
|
|
char buf[512] = {0};
|
|
|
|
|
char imei[16] = {0};
|
|
|
|
|
char imsi[16] = {0};
|
|
|
|
|
char iccid[21] = {0};
|
|
|
|
|
// 工厂命令
|
|
|
|
|
const char factory_cmd1[] = "[getParameter]"; // 工厂命令1
|
|
|
|
|
// const char factory_cmd2[] = "[getCH4]"; // 工厂命令2
|
|
|
|
|
|
|
|
|
|
// 查找 []
|
|
|
|
|
const char *start_bracket = memchr(rx_buff, '[', length);
|
|
|
|
|
const char *end_bracket = memchr(start_bracket, ']', length - (start_bracket - rx_buff));
|
|
|
|
|
|
|
|
|
|
if (start_bracket && end_bracket)
|
|
|
|
|
{
|
|
|
|
|
// 计算 [] 之间的字符串长度
|
|
|
|
|
size_t cmd_length = end_bracket - start_bracket + 1;
|
|
|
|
|
char cmd[cmd_length + 1];
|
|
|
|
|
rt_strncpy(cmd, start_bracket, cmd_length);
|
|
|
|
|
cmd[cmd_length] = '\0';
|
|
|
|
|
if (rt_strcmp(cmd, factory_cmd1) == 0) // 比较接收到的字符串与 factory_cmd1
|
|
|
|
|
{
|
|
|
|
|
rt_uint8_t time_buf[8] = {0};
|
|
|
|
|
|
|
|
|
|
if ((*(rt_uint8_t *)FLASH_FACTOR_TIME_NUM_ADDR != 0xE3)&&(*(rt_uint8_t *)FLASH_FACTOR_TIME_NUM_ADDR != 0x39))
|
|
|
|
|
{
|
|
|
|
|
for (rt_uint8_t i = 0; i < 6; i++)
|
|
|
|
|
{
|
|
|
|
|
time_buf[i] = *(rt_uint8_t *)( FLASH_FACTOR_TIME_NUM_ADDR + i);
|
|
|
|
|
LOG_D("%02x", time_buf[i]);
|
|
|
|
|
}
|
|
|
|
|
rt_uint32_t cnt = (rt_uint32_t)((time_buf[2]<<16)| (time_buf[1] << 8)|time_buf[0]);
|
|
|
|
|
LOG_D("time_buf[2] = %02x time_buf[1] = %02x time_buf[0] = %02x cnt = %04d", time_buf[2], time_buf[1], time_buf[0], cnt);
|
2024-12-03 10:24:55 +08:00
|
|
|
|
Get_Iot_Imei(imei, FLASH_NB_IMEI_LEN);
|
|
|
|
|
Get_Iot_Imsi(imsi, FLASH_NB_IMSI_LEN);
|
|
|
|
|
Get_Iot_Iccid(iccid, FLASH_NB_ICCID_LEN);
|
2024-12-01 13:49:43 +08:00
|
|
|
|
rt_sprintf(buf,
|
|
|
|
|
"\r\n[ID :YD4N02/%02d%02d%02d%04d]\r\n"
|
|
|
|
|
"[IMEI:%s]\r\n"
|
|
|
|
|
"[IMSI:%s]\r\n"
|
|
|
|
|
"[CCID:%s]\r\nOK\r\n",
|
|
|
|
|
time_buf[5], time_buf[4], time_buf[3], cnt, imei, imsi, iccid);
|
|
|
|
|
|
|
|
|
|
BSP_Hr_Send_Data(buf, rt_strlen(buf));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Flash_GetProductTimeLimit(&ReadLimitTime, kFactoryTimeId);
|
|
|
|
|
if ((ReadLimitTime.Struct.year != 2000 + time_buf[5])&&
|
|
|
|
|
(ReadLimitTime.Struct.month != time_buf[4])&&
|
|
|
|
|
(ReadLimitTime.Struct.day != time_buf[3]))//只写入一次
|
|
|
|
|
{
|
|
|
|
|
RTC_GetTime();
|
|
|
|
|
Flash_SetProductTimeLimit(2000 + time_buf[5], time_buf[4], time_buf[3], RtcDateTime.hour, RtcDateTime.minute, RtcDateTime.second, kFactoryTimeId);
|
|
|
|
|
Flash_SetProductTimeLimit(2000 + time_buf[5] + 8, time_buf[4], time_buf[3], RtcDateTime.hour, RtcDateTime.minute, RtcDateTime.second, kExpirationTimeId);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
LOG_E("[%s] is not set\r\n", "factory time");
|
|
|
|
|
BSP_Hr_Send_Data("factory time is not set\r\n", rt_strlen("factory time is not set\r\n"));
|
|
|
|
|
}
|
|
|
|
|
return RT_EOK;
|
|
|
|
|
}
|
|
|
|
|
// else if (rt_strcmp(cmd, factory_cmd2) == 0) // 比较接收到的字符串与 factory_cmd2
|
|
|
|
|
// {
|
|
|
|
|
// rt_sprintf(buf,
|
|
|
|
|
// "\r\n[STATUS :0x%X]\r\n"
|
|
|
|
|
// "[VALUE :%.2f]\r\n"
|
|
|
|
|
// "[LIGHT :%.2f]\r\n"
|
|
|
|
|
// "[PD :%.2f]\r\n"
|
|
|
|
|
// "[TEMPERTURE :%.2f]\r\n"
|
|
|
|
|
// "[TEC-TEMPERTURE:%.2f]\r\n"
|
|
|
|
|
// "[WORKTIME :%d]\r\nOK\r\n",
|
|
|
|
|
// H308.Data.fault_code, H308.Data.lel, H308.Data.signal_strength, H308.Data.gain, H308.Data.temp, (H308.Data.laser_temp / 10), work_duration);
|
|
|
|
|
// LOG_D("buf:%s", buf);
|
|
|
|
|
// BSP_Hr_Send_Data(buf, rt_strlen(buf));
|
|
|
|
|
//
|
|
|
|
|
// return RT_EOK;
|
|
|
|
|
// }
|
|
|
|
|
}
|
|
|
|
|
return RT_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void hr_thread_entry(void *param)
|
|
|
|
|
{
|
|
|
|
|
LOG_D("hr_thread_entry");
|
|
|
|
|
uint8_t rx_buff[32] = {0};
|
|
|
|
|
// LOG_D("factor_time addr = %x", FLASH_FACTOR_TIME_NUM_ADDR);
|
|
|
|
|
while (1)
|
|
|
|
|
{
|
|
|
|
|
rt_sem_take(hr_rx_ok_sem, RT_WAITING_FOREVER);
|
|
|
|
|
if (rt_sem_trytake(hr_rx_parity_err_sem) == 0)
|
|
|
|
|
{
|
|
|
|
|
LOG_D("hr_rx_parity_err_sem");
|
|
|
|
|
lwrb_free(&hr_rx_rb);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
uint8_t len = lwrb_get_full(&hr_rx_rb);
|
|
|
|
|
lwrb_read(&hr_rx_rb, rx_buff, len);
|
|
|
|
|
LOG_HEX("hr_rx_data:", 16, &rx_buff[0], len);
|
|
|
|
|
if (SysControl.status <= kPreheatingEvent)//等待预热完成和激光器自检
|
|
|
|
|
{
|
|
|
|
|
char buf[128] = "[CH4-Module power-on self-check,please wait]";
|
|
|
|
|
|
|
|
|
|
BSP_Hr_Send_Data(buf, rt_strlen(buf));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (Process_Factor_Cmd(rx_buff, len) == RT_EOK)
|
|
|
|
|
{
|
|
|
|
|
LOG_D("工厂命令处理"); // 工厂命令处理
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (len >= HOST_FRAME_MIN_LEN)
|
|
|
|
|
{
|
|
|
|
|
TsFrameData *HostFrameData = HR_GetFrameData(rx_buff, len);
|
|
|
|
|
if (HostFrameData != RT_NULL)
|
|
|
|
|
{
|
|
|
|
|
LOG_HEX("HostFrameData", 16, &HostFrameData->data[0], HostFrameData->len); // 数据段
|
|
|
|
|
HR_ProcessData(HostFrameData);
|
|
|
|
|
}
|
|
|
|
|
rt_free(HostFrameData);
|
|
|
|
|
HostFrameData = RT_NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rt_memset(rx_buff, 0, len);
|
|
|
|
|
rt_thread_mdelay(10);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Hr_Init(void)
|
|
|
|
|
{
|
|
|
|
|
GPIO_InitTypeDef GPIO_InitStructure = {0};
|
|
|
|
|
USART_InitTypeDef USART_InitStructure = {0};
|
|
|
|
|
NVIC_InitTypeDef NVIC_InitStructure = {0};
|
|
|
|
|
|
|
|
|
|
lwrb_init(&hr_rx_rb, hr_rx_rb_data, sizeof(hr_rx_rb_data));
|
|
|
|
|
lwrb_init(&hr_tx_rb, hr_tx_rb_data, sizeof(hr_tx_rb_data));
|
|
|
|
|
|
|
|
|
|
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
|
|
|
|
|
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
|
|
|
|
|
|
|
|
|
|
GPIO_InitStructure.GPIO_Pin = HR_TX_GPIO_PIN;
|
|
|
|
|
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
|
|
|
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
|
|
|
GPIO_Init(HR_TX_GPIO_PORT, &GPIO_InitStructure);
|
|
|
|
|
|
|
|
|
|
GPIO_InitStructure.GPIO_Pin = HR_RX_GPIO_PIN;
|
|
|
|
|
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
|
|
|
|
|
GPIO_Init(HR_RX_GPIO_PORT, &GPIO_InitStructure);
|
|
|
|
|
|
|
|
|
|
USART_DeInit(HR_UART); // 寄存器恢复默认值
|
|
|
|
|
USART_InitStructure.USART_BaudRate = HR_BAUDRATE;
|
|
|
|
|
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
|
|
|
|
|
USART_InitStructure.USART_StopBits = USART_StopBits_1;
|
|
|
|
|
USART_InitStructure.USART_Parity = USART_Parity_Even;
|
|
|
|
|
|
|
|
|
|
USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
|
|
|
|
|
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
|
|
|
|
|
USART_Init(HR_UART, &USART_InitStructure);
|
|
|
|
|
|
|
|
|
|
USART_ITConfig(HR_UART, USART_IT_RXNE, ENABLE);
|
|
|
|
|
USART_ITConfig(HR_UART, USART_IT_PE, ENABLE);
|
|
|
|
|
USART_ITConfig(HR_UART, USART_IT_TXE, DISABLE);
|
|
|
|
|
|
|
|
|
|
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
|
|
|
|
|
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
|
|
|
|
|
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
|
|
|
|
|
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
|
|
|
|
NVIC_Init(&NVIC_InitStructure);
|
|
|
|
|
|
|
|
|
|
USART_Cmd(HR_UART, ENABLE);
|
|
|
|
|
LOG_I("hr Init");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int BSP_HR_Init(void)
|
|
|
|
|
{
|
|
|
|
|
Hr_Init();
|
|
|
|
|
|
|
|
|
|
hr_rx_ok_sem = rt_sem_create("hr_rx_ok_sem", 0, RT_IPC_FLAG_FIFO);
|
|
|
|
|
if (hr_rx_ok_sem == RT_NULL)
|
|
|
|
|
{
|
|
|
|
|
LOG_E("hr_rx_ok_sem create failed");
|
|
|
|
|
}
|
|
|
|
|
hr_rx_parity_err_sem = rt_sem_create("hr_rx_pe", 0, RT_IPC_FLAG_FIFO);
|
|
|
|
|
if (hr_rx_parity_err_sem == RT_NULL)
|
|
|
|
|
{
|
|
|
|
|
LOG_E("hr_rx_parity_err_sem create failed");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hr_timer = rt_timer_create("hr_timeout", hr_timeout, RT_NULL, 100, RT_TIMER_FLAG_PERIODIC);
|
|
|
|
|
if (hr_timer == RT_NULL)
|
|
|
|
|
{
|
|
|
|
|
LOG_E("hr_timer create failed");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rt_err_t ret = rt_thread_init(&hr_thread,
|
|
|
|
|
"hr_thread",
|
|
|
|
|
hr_thread_entry,
|
|
|
|
|
RT_NULL,
|
|
|
|
|
&hr_thread_stack[0],
|
|
|
|
|
sizeof(hr_thread_stack),
|
|
|
|
|
HR_THREAD_PRIORITY, HR_THREAD_TIMESLICE);
|
|
|
|
|
|
|
|
|
|
if (ret == RT_EOK)
|
|
|
|
|
{
|
|
|
|
|
rt_thread_startup(&hr_thread);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
LOG_E("rt_thread_init hr_thread Failed");
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
INIT_PREV_EXPORT(BSP_HR_Init);
|
|
|
|
|
|
|
|
|
|
void USART2_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
|
|
|
|
|
void USART2_IRQHandler(void)
|
|
|
|
|
{
|
|
|
|
|
GET_INT_SP();
|
|
|
|
|
rt_interrupt_enter();
|
|
|
|
|
unsigned char data;
|
|
|
|
|
if (USART_GetITStatus(HR_UART, USART_IT_PE) != RESET)
|
|
|
|
|
{
|
|
|
|
|
rt_sem_release(hr_rx_parity_err_sem);
|
|
|
|
|
}
|
|
|
|
|
if (USART_GetITStatus(HR_UART, USART_IT_RXNE) != RESET)
|
|
|
|
|
{
|
|
|
|
|
data = USART_ReceiveData(HR_UART);
|
|
|
|
|
lwrb_write(&hr_rx_rb, &data, 1);
|
|
|
|
|
rt_timer_start(hr_timer);
|
|
|
|
|
}
|
|
|
|
|
if (USART_GetITStatus(HR_UART, USART_IT_TXE) != RESET)
|
|
|
|
|
{
|
|
|
|
|
if (lwrb_read(&hr_tx_rb, &data, 1))
|
|
|
|
|
USART_SendData(HR_UART, data);
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
USART_ITConfig(HR_UART, USART_IT_TXE, DISABLE);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
rt_interrupt_leave();
|
|
|
|
|
FREE_INT_SP();
|
|
|
|
|
}
|