/********************************************************* //file :hd_dev_gpio.c //author :boly //date :2021/10/21 //version :V1.0 //brief :GSP HARD层GPIO接口C文件 *********************************************************/ /* Includes-----------------------------------------------------------------------------------*/ #define APP_TERMINALSLAVE485_JT808_USE #define JT808_FRAM_HEAD_ID 0xA2 #ifdef APP_TERMINALSLAVE485_JT808_USE /* Includes-----------------------------------------------------------------------------------*/ #include "TerminalSlave485.h" #include "TerminalSlave485_jt808.h" #include "CollectMaster485.h" #include "ScreenMaster485.h" #include "KeySlave485.h" #include "Elec_Seal.h" #include "usart.h" #include "Data_deal.h" #include "Randomcode.h" #include "spi.h" #include "Dwin.h" #include "DS1302.h" #include "leaf_ota.h" #include "md5c.h" #include "cmsis_os.h" #include "func_ram_record.h" #include "func_queue_record.h" /* Private macro------------------------------------------------------------------------------*/ /* Private typedef----------------------------------------------------------------------------*/ #pragma pack(1) typedef struct SEND_DATA_UNIT_STC { uint32_t flowID; //发送数据ID uint32_t lenth; //发送数据长度 uint32_t send_cnt; //发送计数器 uint8_t buf[DATA_UNIT_SIZE - sizeof(uint32_t)*3]; //发送数据缓冲区 }SEND_DATA_UNIT_STC; typedef struct JT808_DATA_OBJ { uint32_t flowID; //Y为32Bit的流水号-高位在前,此流水号来源于控制板主动上报的传感器数据包内,如A1封装 uint32_t back_cnt; //接收超时计数 uint32_t link_cnt; //连接计数器 uint32_t link_ok; //连接标志位 SEND_DATA_UNIT_STC send_data; }JT808_DATA_OBJ; #pragma pack() /* Private define-----------------------------------------------------------------------------*/ /* Private variables--------------------------------------------------------------------------*/ Pass41SensorScanParam_TypeDef Pass41SensorScanParam; JT808_DATA_OBJ jt808_obj = { .flowID = 1, .back_cnt = 0, //接收超时计数 .link_cnt = 0, .link_ok = 0, .send_data.flowID = 0, .send_data.lenth = 0, .send_data.buf = {0}, }; extern uint8_t Cang_IO_tbak[4][64]; extern uint32_t overflow_cnt_bak; extern unsigned char overflow_flag_bak; extern uint8_t Cang01_IO[64]; extern uint8_t Cang02_IO[64]; extern uint8_t Cang03_IO[64]; extern uint8_t Cang04_IO[64]; extern uint8_t Cang05_IO[64]; extern uint8_t Cang06_IO[64]; extern uint8_t Cang07_IO[64]; extern uint8_t Cang08_IO[64]; extern uint32_t overflow_cnt; /* Private function prototypes----------------------------------------------------------------*/ int jt808_Build_0x02_TimeCmd(uint8_t *pBuf); int jt808_Build_0x01_flowID(uint8_t *pBuf, uint32_t flow_id); int jt808_Build_0x61_ManHole_Big_SW(uint8_t *pBuf); int jt808_Build_0x62_ManHole_Small_SW(uint8_t *pBuf); int jt808_Build_0x63_Dump_info(uint8_t *pBuf); int jt808_Build_0x64_HaiDiFa(uint8_t *pBuf); int jt808_Build_0x6d_Cang_info(uint8_t *pBuf); int jt808_Build_0x70_Sealing(uint8_t *pBuf); int jt808_Build_0x71_DumpBox_info(uint8_t *pBuf); int jt808_Build_0x72_ManHole_Box_info(uint8_t *pBuf); void jt808_update_0x40_data(void); int jt808_BuildSealTxCmd(uint8_t *pBuf, uint8_t *pEmergencyflag); // 40命令 void mem_swap(uint8_t *des,int len) { int i,tlen; uint8_t dat; tlen = (len>>1); len--; for(i=0;i0) { if(memcmp(Cang_IO_tbak[0],Cang01_IO,64)) { emergencyflag=0x80; } memcpy(Cang_IO_tbak[0],Cang01_IO,64); } if(StoreNumber>1) { if(memcmp(Cang_IO_tbak[1],Cang02_IO,64)) { emergencyflag=0x80; } memcpy(Cang_IO_tbak[1],Cang02_IO,64); } if(StoreNumber>2) { if(memcmp(Cang_IO_tbak[2],Cang03_IO,64)) { emergencyflag=0x80; } memcpy(Cang_IO_tbak[2],Cang03_IO,64); } if(StoreNumber>3) { if(memcmp(Cang_IO_tbak[3],Cang04_IO,64)) { emergencyflag=0x80; } memcpy(Cang_IO_tbak[3],Cang04_IO,64); } if(StoreNumber>4) { if(memcmp(Cang_IO_tbak[4],Cang05_IO,64)) { emergencyflag=0x80; } memcpy(Cang_IO_tbak[4],Cang05_IO,64); } if(StoreNumber > 5) { StoreNumber = 5; } if((overflow_cnt==0) && (overflow_cnt==overflow_cnt_bak)) { overflow_flag=0; } else { overflow_flag=1; } overflow_cnt_bak=overflow_cnt; if(overflow_flag_bak!=overflow_flag) { emergencyflag=0x80; } overflow_flag_bak=overflow_flag; pBuf[send_pos++] = emergencyflag; //紧急上报位 pBuf[send_pos++] = 0x00; //数据状态:00正常;01未收到数据;02乱码 pBuf[send_pos++] = StoreNumber; pBuf[send_pos++] = 0x22; pBuf[send_pos++] = overflow_flag; //61 人孔大盖 开关 send_pos += jt808_Build_0x61_ManHole_Big_SW((uint8_t *)pBuf+send_pos); //62 人孔小盖 开关 send_pos += jt808_Build_0x62_ManHole_Small_SW((uint8_t *)pBuf+send_pos); //63 卸油阀 开关 send_pos += jt808_Build_0x63_Dump_info((uint8_t *)pBuf+send_pos); //64 底阀 开关 send_pos += jt808_Build_0x64_HaiDiFa((uint8_t *)pBuf+send_pos); //6D 仓状态 send_pos += jt808_Build_0x6d_Cang_info((uint8_t *)pBuf+send_pos); //70 铅封状态 send_pos += jt808_Build_0x70_Sealing((uint8_t *)pBuf+send_pos); //71 卸油箱门 开关 send_pos += jt808_Build_0x71_DumpBox_info((uint8_t *)pBuf+send_pos); //72 人孔箱护罩 开关 send_pos += jt808_Build_0x72_ManHole_Box_info((uint8_t *)pBuf+send_pos); //01 流水号 4字节 整数 send_pos += jt808_Build_0x01_flowID((uint8_t *)pBuf+send_pos, flowID); //02 时间戳 6字节 字符串 BCD[6] YY-MM-DD-hh-mm-ss(GMT+8 时间,本标准中之后涉及的时间均采用此时区) send_pos += jt808_Build_0x02_TimeCmd((uint8_t *)pBuf+send_pos); //数据帧长度 pBuf[1] = send_pos-2; #if 0 while (send_pos<(120+2)) { pBuf[send_pos++] = 0; }; #endif if (pEmergencyflag) *pEmergencyflag = emergencyflag; return send_pos; } /** *************************************** * 更新老协议0x40系统状态 * 输入:void * 返回: void *************************************** */ uint8_t JT808_0x40_buf[256]={0};//大小+1 136 uint8_t JT808_0x40_len = 0; void jt808_update_0x40_data(void) { uint8_t JT808_emergencyflag = 0; JT808_0x40_len = jt808_BuildSealTxCmd(JT808_0x40_buf, &JT808_emergencyflag); return; } /** *************************************** * 构建6D 仓状态 * 输入:pBuf-构建数据的存放首地址 * 返回: 构建数据的字节总数 *************************************** */ int jt808_Build_0x6d_Cang_info(uint8_t *pBuf) { int idx=0; int i = 0; pBuf[idx++] = 0x6D; //类型 for (i = 0; i < StoreNumber; i++) { //pBuf[idx++] = 1; //每仓数量 //Sealing_Data.Sealing_state_oiltype[i] :仓状态与油品: //Sealing_Data.Sealing_state_oiltype[i] = (Byte_high<<4)|Byte_low; //高4位值1:装油,2:有油,3:卸油,4:空仓(无油),低4位代表油品,高四位非等于4(空仓)值默认1,否则为0; pBuf[idx++] = (Sealing_Data.Sealing_state_oiltype[i] &0xf0)>> 4; } return idx; } /** *************************************** * 构建61 人孔大盖 开关状态 * 输入:pBuf-构建数据的存放首地址 * 返回: 构建数据的字节总数 *************************************** */ int jt808_Build_0x61_ManHole_Big_SW(uint8_t *pBuf) { int idx=0; int i,j; if(((Config_info_all.ManHole_Big_info/StoreNumber) == 0) ||((Config_info_all.ManHole_Big_info&0x80)==0x80)) { return 0; } pBuf[idx++] = 0x61; for (i = 0; i < StoreNumber; i++) { pBuf[idx++] = Config_info_all.ManHole_Big_info/StoreNumber; for(j=0;j> 4; } return idx; } /** *************************************** * 构建01 流水号 4字节 整数 * 输入:pBuf-构建数据的存放首地址 * 返回: 构建数据的字节总数 *************************************** */ int jt808_Build_0x01_flowID(uint8_t *pBuf,uint32_t flow_id) { int idx=0; // 2022-8-25, 新增加的子命令 // 01, 流水号 // 02, 时间戳 do { pBuf[idx++] = 0x01; pBuf[idx++] = (flow_id>>24) & 0xff; pBuf[idx++] = (flow_id>>16) & 0xff; pBuf[idx++] = (flow_id>>8) & 0xff; pBuf[idx++] = (flow_id>>0) & 0xff; }while(0); return idx; } /** *************************************** * 构建20命令数据 时间戳 -- hex制式 * 输入:pBuf-构建数据的存放首地址 * 返回: 构建数据的字节总数 *************************************** */ extern SDateTime m_datetime; int jt808_Build_0x02_TimeCmd(uint8_t *pBuf) { int send_pos=0; //02 时间戳 6字节 字符串 BCD[6] YY-MM-DD-hh-mm-ss(GMT+8 时间,本标准中之后涉及的时间均采用此时区) pBuf[send_pos++] = 0x02; pBuf[send_pos++] = HEXtoBCD(m_datetime.year); pBuf[send_pos++] = HEXtoBCD(m_datetime.month); pBuf[send_pos++] = HEXtoBCD(m_datetime.day); pBuf[send_pos++] = HEXtoBCD(m_datetime.hour); pBuf[send_pos++] = HEXtoBCD(m_datetime.min); pBuf[send_pos++] = HEXtoBCD(m_datetime.sec); return send_pos; } /** *************************************** * 构建40命令数据 电子铅封 -- hex制式 * 输入:pBuf-构建数据的存放首地址 * 返回: 构建数据的字节总数 *************************************** */ int jt808_BuildSealTxCmd(uint8_t *pBuf, uint8_t *pEmergencyflag) // 40命令 { Return_data *ret; int n = 0; uint8_t emergencyflag = 0; *pBuf++ = 0x40; ret = Seal_Tx_Readvalue(0,0); *pBuf++ = ret->length/2; // 调用返回的数据是asii制式的,所以真实的hex数是其一半 for(n=0; n < ret->length/2 && n < 100; n++) { pBuf[n] = MODBUS_ASCII_AsciiToHex(ret->data + 2*n); } emergencyflag = pBuf[0]; if(pEmergencyflag) *pEmergencyflag = emergencyflag; return n+2; } /** *************************************** * 构建91命令数据 IO状态 -- hex制式 * 输入:pBuf-构建数据的存放首地址 * 返回: 构建数据的字节总数 *************************************** */ int jt808_Build91Cmd(uint8_t *pBuf, uint8_t *pEmergencyflag) { Return_data *ret; int n = 0; uint8_t emergencyflag = 0; *pBuf++ = 0x91; ret = IO_Tx_Readvalue(0,0); *pBuf++ = ret->length/2; // 调用返回的数据是asii制式的,所以真实的hex数是其一半 for(n=0; n < ret->length/2 && n < 100; n++) { pBuf[n] = MODBUS_ASCII_AsciiToHex(ret->data + 2*n); } emergencyflag = pBuf[0]; if(pEmergencyflag) *pEmergencyflag = emergencyflag; return n+2; } /** *************************************** * 检测当前连接状态 * 输入:无 * 返回: 无 *************************************** */ void jt808_link_check(void) { if(jt808_obj.back_cnt < (Pass41SensorScanParam.nstep*Pass41SensorScanParam.step)) { jt808_obj.link_cnt++; } else { jt808_obj.link_cnt = 0; } if(jt808_obj.link_cnt > 0) { jt808_obj.link_ok = true; } else { jt808_obj.link_ok = false; } return; } /** *************************************** * 将缓冲区数据帧内容,放入串口发送数据缓冲区 * 输入:无 * 返回: 无 *************************************** */ void jt808_send_buf_data(void) { if(jt808_obj.send_data.lenth == 0) { return; } //将缓冲区数据帧内容,放入串口发送数据缓冲区 memcpy(USART1_TX_BUF,jt808_obj.send_data.buf,jt808_obj.send_data.lenth); //发送次数进行累加 jt808_obj.send_data.send_cnt++; //打上补发标记 USART1_TX_BUF[3] |= 0x80; //通过串口将数据发送出去 TerminalSlave485_Send_Data(USART1_TX_BUF,jt808_obj.send_data.lenth); return; } /** *************************************** * 处理接收到的返回数据帧 * 输入:无 * 返回: 无 *************************************** */ JT808_DataBack_DATA jt808_data_back = {0}; void jt808_recv_func_DataBack(uint8_t * buf ,uint8_t len) { uint32_t read_len = 0; jt808_obj.back_cnt = 0; memcpy(&jt808_data_back, buf ,sizeof(jt808_data_back)); mem_swap((uint8_t *)&(jt808_data_back.flowID),sizeof(jt808_data_back.flowID)); if(jt808_data_back.flowID == jt808_obj.send_data.flowID) { //清除发送缓冲区数据 memset((void *)&(jt808_obj.send_data), 0x00, sizeof(jt808_obj.send_data)); #if USE_QUEUE_RECORD==1 if(func_record_queue_flash_get() == true) { read_len = func_record_queue_read((void *)&(jt808_obj.send_data), (uint32_t)DATA_UNIT_SIZE); } else #endif #if USE_RAM_RECORD==1 { //从内存数据栈中读取缓冲数据 read_len = func_ram_record_delete((void *)&(jt808_obj.send_data), DATA_UNIT_SIZE); } #else { ; } #endif if( read_len != DATA_UNIT_SIZE) { memset((void *)&(jt808_obj.send_data), 0x00, sizeof(jt808_obj.send_data)); } else if( jt808_obj.send_data.buf[0] != JT808_FRAM_HEAD_ID) { memset((void *)&(jt808_obj.send_data), 0x00, sizeof(jt808_obj.send_data)); } //如果本帧数据重发次数大于5,则清除本帧数据 if(jt808_obj.send_data.send_cnt > 5) { memset((void *)&(jt808_obj.send_data), 0x00, sizeof(jt808_obj.send_data)); } } return; } /** *************************************** * 将发送序列ID放入FRAM * 输入:当前发送序列号 * 返回: 无 *************************************** */ void jt808_save_Scan_flowID(uint32_t flowID) { FM25L16B_Write_N_Bytes(FRAM_ADDR_Scan_flowID, (uint8_t *)&flowID, sizeof(flowID)); return; } /** *************************************** * 初始化数据帧序列ID * 输入:发送序列号指针地址 * 返回: 无 *************************************** */ void jt808_read_Scan_flowID(uint32_t * flowID) { FM25L16B_Read_N_Bytes(FRAM_ADDR_Scan_flowID, (uint8_t *)flowID, sizeof(flowID)); return; } /** *************************************** * 将发送缓冲区中的数据,放入RAM,并将当前 * 产生的数据放入缓冲区 * 输入:无 * 返回: 无 *************************************** */ void jt808_save_send_data(uint8_t * buf ,uint16_t len) { if(jt808_obj.send_data.flowID != 0) { #if USE_QUEUE_RECORD==1 if(func_record_queue_flash_get() == true) { func_record_queue_write((uint8_t *)&(jt808_obj.send_data) , DATA_UNIT_SIZE); } else #endif #if USE_RAM_RECORD==1 { func_ram_record_write((uint8_t *)&(jt808_obj.send_data) , DATA_UNIT_SIZE); } #else { ; } #endif memset((void *)&(jt808_obj.send_data), 0x00, sizeof(jt808_obj.send_data)); } jt808_obj.send_data.flowID = jt808_obj.flowID; jt808_obj.send_data.lenth = len; if(len > sizeof(jt808_obj.send_data.buf)) { len = sizeof(jt808_obj.send_data.buf); } memset(jt808_obj.send_data.buf, 0x00, sizeof(jt808_obj.send_data.buf)); memcpy(jt808_obj.send_data.buf, buf, len); return; } /** *************************************** * xy,新透传,41串口透传,模拟F3轮询传感器 * 按照周期1构建数据,按照周期2发送数据 * 输入:无 * 返回: 无 * 发送区的格式为: * 数据负载类别,1Byte * 传感器命令数据包数,1Byte * 具体的各个命令数据包,NByte *************************************** */ void jt808_DoInternalSensorScanAndPost(void) { int xlen=0, ylen=0; uint8_t emergencyflag=0; uint8_t *pSendBuf = USART1_TX_BUF; static int step = 0; static int nstep = 0; if(++step % Pass41SensorScanParam.step == 0) { for(int n=0; n 1 && buf[1] > 0){ Pass41SensorScanParam.step = buf[0]; Pass41SensorScanParam.nstep = buf[1]; if(buf[2] > 0 && buf[2] <= 8){ Pass41SensorScanParam.cmd_num = buf[2]; for (int n = 0; n < Pass41SensorScanParam.cmd_num; n++){ Pass41SensorScanParam.cmd_arr[n] = buf[3+n]; } }else{ Pass41SensorScanParam.cmd_num = 2; Pass41SensorScanParam.cmd_arr[0] = 0x40; Pass41SensorScanParam.cmd_arr[1] = 0x91; } }else{ Pass41SensorScanParam.step = 5; Pass41SensorScanParam.nstep = 6; Pass41SensorScanParam.cmd_num = 2; Pass41SensorScanParam.cmd_arr[0] = 0x40; Pass41SensorScanParam.cmd_arr[1] = 0x91; } }else{ Pass41SensorScanParam.enable = 0; Pass41SensorScanParam.step = 5; Pass41SensorScanParam.nstep = 6; Pass41SensorScanParam.cmd_num = 1; Pass41SensorScanParam.cmd_arr[0] = JT808_FRAM_HEAD_ID; } //初始化发送序列ID jt808_read_Scan_flowID(&(jt808_obj.flowID)); } /** *************************************** * 初始化发送配置参数 * 输入:无 * 返回: 无 *************************************** */ uint8_t jt808_Build_Read_WorkSt(uint8_t * PayLoad) { uint8_t idx = 0; PayLoad[idx++] = func_record_queue_flash_get(); PayLoad[idx++] = jt808_obj.link_ok; uint32_t msg_num = 0; if(PayLoad[0] == true) { msg_num = func_record_queue_obj_cnt(); } else { msg_num = func_ram_obj_num(DATA_UNIT_SIZE); } PayLoad[idx++] = (msg_num>>24)&0xff; PayLoad[idx++] = (msg_num>>16)&0xff; PayLoad[idx++] = (msg_num>>8)&0xff; PayLoad[idx++] = (msg_num)&0xff; return idx; } #endif /*************APP_TERMINALSLAVE485_JT808_USE*******************/