param.c 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660
  1. #include <string.h>
  2. #include "eeprom.h"
  3. #include "prj_com.h"
  4. #include "bill.h"
  5. #include "tdc_tof.h"
  6. #include "param.h"
  7. #include "app_nb.h"
  8. #include "alarm.h"
  9. Param_t Paramx;
  10. uint8_t rewrite_para_flag = 0;
  11. // DIAMETER_AND_TEMP_COMPENSATION_DEF Temp_compensation;//其中的diameter保存的校验值
  12. const char SOFT_VER[5] = {
  13. 'V', VER_TYPE, VER_OPERATOR, VER_MODULE, VER_FIRMWARE};
  14. // EEPROM_MAX_WRITE_SIZE 125
  15. // EEPROM_PAGE_SIZE 256
  16. /****************************************************************/
  17. ////由于_read_eeprom write_eeprom是针对存bill记录的,最后一个字节
  18. /// 自动校验,写参数不能用,这里需另外增加/////////
  19. /*********************批量写入数据********************************/
  20. // 参数1:dat 指向要写入的数据指针
  21. // 参数2:addr写入到M24M01存储器的地址
  22. // 参数3:len写入数据的长度(字节单位)
  23. // 返回:1:成功
  24. ////////////////////////////////////////////////////////////////
  25. uint8_t eeprom_MassWrite(uint8_t *dat, uint32_t addr, uint16_t len) //
  26. {
  27. if (addr > EEPROM_MAX_SIZE - 1 || addr + len > EEPROM_MAX_SIZE)
  28. return 1;
  29. // 已经跨页
  30. // uint8_t num=(uint8_t)(EEPROM_PAGE_SIZE/EEPROM_MAX_WRITE_SIZE+1);//每页需写入的次数
  31. // LOG("len= %d",len);
  32. uint32_t add_end = addr + len; // 地址末尾
  33. uint16_t w_size; // 写入数据大小
  34. uint8_t ret = 0;
  35. while (addr < add_end)
  36. {
  37. if (addr / EEPROM_PAGE_SIZE == (addr + EEPROM_MAX_WRITE_SIZE - 1) / EEPROM_PAGE_SIZE)
  38. { // 还在本页内
  39. w_size = EEPROM_MAX_WRITE_SIZE; // 取写入长度为最大长度
  40. }
  41. else
  42. { // 最大写入长度已经超过本页
  43. w_size = EEPROM_PAGE_SIZE - (addr % EEPROM_PAGE_SIZE); // 取写入长度刚好到页边界
  44. }
  45. if (addr + w_size > add_end)
  46. { // 写入长度已超出实际写入边界
  47. w_size = add_end - addr; // 取实际写入长度
  48. }
  49. ret |= write_eeprom_para(addr, dat, w_size); // 这里要改,write_eeprom是专门为写记录准备的,最后一个字节是校验位
  50. addr += w_size; // 地址增加
  51. dat += w_size; // 写数据指针增加
  52. // LOG("addr= %d,size= %d\r\n",addr,w_size);
  53. }
  54. //}
  55. return ret;
  56. }
  57. /*******************批量读取数据********************************/
  58. // 参数1 dat:读取数据保存指针
  59. // 参数2 addr 读取数据eeprom起始地址
  60. // 参数3 len:读取长度
  61. // 返回:1:成功
  62. /***************************************************************/
  63. uint8_t eeprom_MassRead(uint8_t *dat, uint32_t addr, uint16_t len)
  64. {
  65. memset(dat, 0, len);
  66. uint16_t i;
  67. uint8_t ret = 0;
  68. if (addr > EEPROM_MAX_SIZE - 1 || addr + len > EEPROM_MAX_SIZE)
  69. { // 写入空间超过了最大地址范围
  70. return 1;
  71. }
  72. if (len > EEPROM_MAX_READ_SIZE)
  73. { // 超过最大写读取长度
  74. for (i = 0; i < len / EEPROM_MAX_READ_SIZE; i++)
  75. { // 每次读取最大长度
  76. ret |= read_eeprom_para(addr + i * EEPROM_MAX_READ_SIZE, dat + i * EEPROM_MAX_READ_SIZE, EEPROM_MAX_READ_SIZE); // 要改
  77. }
  78. if ((len % EEPROM_MAX_READ_SIZE) != 0)
  79. { // 整长度读完后,读取可能剩余的部分
  80. ret |= read_eeprom_para(addr + i * EEPROM_MAX_READ_SIZE, dat + i * EEPROM_MAX_READ_SIZE, len % EEPROM_MAX_READ_SIZE);
  81. }
  82. }
  83. else
  84. { // 未超过最大长度
  85. ret |= read_eeprom_para(addr, dat, len);
  86. }
  87. return ret;
  88. }
  89. #define DEFAULT_PATH_SKEW 0 // 超声波通道偏差修正系数
  90. #if VER_MODULE == 3
  91. #define DEFAULT_PIPE_COE 2.288299 // COE系数
  92. #else
  93. #define DEFAULT_PIPE_COE 0.1168745 // COE系数
  94. #endif
  95. #define DEFAULT_IMEI "000000000000000" // 默认IMEI
  96. #define DEFAULT_CCID "00000000000000000000" // 默认IMEI
  97. // 01234567890123456789
  98. #define DEFAULT_MUX_CH_NO1 0
  99. #define DEFAULT_MUX_CH_NO2 1
  100. #define DEFAULT_MUX_CH_NO3 2
  101. #define DEFAULT_MUX_CH_NO4 3
  102. void LoadDefaultParam(void) // 加载默认参数值
  103. {
  104. // memset((uint8_t *)&Paramx, 0, sizeof(Param_t));
  105. eeprom_MassRead((unsigned char *)&Paramx, PARAMX_START_ADDR, sizeof(Param_t)); // 读取参数
  106. Paramx.path_skew[0] = DEFAULT_PATH_SKEW;
  107. Paramx.path_skew[1] = DEFAULT_PATH_SKEW;
  108. Paramx.path_skew[2] = DEFAULT_PATH_SKEW;
  109. Paramx.path_skew[3] = DEFAULT_PATH_SKEW; // 通道修正系数
  110. Paramx.pipe_coe = DEFAULT_PIPE_COE; // coe系数
  111. // strcpy(Paramx.imei, DEFAULT_IMEI); // imei号
  112. // Paramx.imei[sizeof(DEFAULT_IMEI) - 1] = 0;
  113. // strcpy(Paramx.ccid, DEFAULT_CCID); // CCID号
  114. // Paramx.ccid[sizeof(DEFAULT_CCID) - 1] = 0;
  115. Paramx.mux_ch_no[0] = DEFAULT_MUX_CH_NO1;
  116. Paramx.mux_ch_no[1] = DEFAULT_MUX_CH_NO2;
  117. Paramx.mux_ch_no[2] = DEFAULT_MUX_CH_NO3;
  118. Paramx.mux_ch_no[3] = DEFAULT_MUX_CH_NO4; // 多路开关地址
  119. // Paramx.dev_id[0] = 0x00; //a6
  120. Paramx.dev_id[0] = 0x80; // bcd //a5
  121. Paramx.dev_id[1] = 0x55; // bcd
  122. Paramx.dev_id[2] = 0x60; // bcd
  123. Paramx.dev_id[3] = 0x10; // bcd
  124. Paramx.dev_id[4] = 0x00; // bcd
  125. Paramx.dev_id[5] = 0x03; // bcd//设备地址 A0
  126. #if VER_MODULE == 3
  127. Paramx.chan_num = 2; // 超声波通道数量
  128. Paramx.diameter = 100; // 直径
  129. #else
  130. Paramx.chan_num = 1; // 超声波通道数量
  131. Paramx.diameter = 25; // 直径
  132. #endif
  133. Paramx.pressure_sensor = 2; // without pressure sensor 是否带压力传感器,默认不带
  134. Paramx.settlement_day = 0; // 结算日,默认 每月最后一天
  135. Paramx.report_base_hour = 0;
  136. Paramx.report_base_min = 0;
  137. Paramx.report_base_sec = 0; // 上报时间点
  138. Paramx.report_interval = 24 * 60; // 上报间隔 1天
  139. Paramx.high_temp_alarm_thres = 32767; // 高温报警阈值
  140. Paramx.low_temp_alarm_thres = -32768; // 低温报警阈值
  141. Paramx.large_flow_alarm_thres = 0; // 大流量报警阈值
  142. Paramx.large_flow_cnti_moni_time = 0; // 大流量持续时间
  143. Paramx.cnti_flow_cnti_moni_time = 0; // 持续流量报警时间
  144. Paramx.leak_flow_alarm_thres = 0; // 渗漏报警阈值
  145. Paramx.leak_flow_cnti_moni_time = 0; // 渗漏报警持续时间
  146. Paramx.high_press_alarm_thres = 0; // 高压力报警阈值
  147. Paramx.low_press_alarm_thres = 0; // 低压力报警阈值
  148. Paramx.main_server_ip[0] = 221;
  149. Paramx.main_server_ip[1] = 236;
  150. Paramx.main_server_ip[2] = 31;
  151. Paramx.main_server_ip[3] = 231; // 主服务器ip地址
  152. Paramx.main_server_port = 12001; // 主服务器端口号
  153. Paramx.sub_server_ip[0] = 221; // 备用服务器ip地址
  154. Paramx.sub_server_ip[1] = 236;
  155. Paramx.sub_server_ip[2] = 31;
  156. Paramx.sub_server_ip[3] = 231;
  157. Paramx.sub_server_port = 12001; // 备用服务器端口号
  158. Paramx.dma_report_start[0] = 0;
  159. Paramx.dma_report_start[1] = 0;
  160. Paramx.dma_report_start[2] = 0; // dma上报起始时间 时分秒
  161. Paramx.dma_report_end[0] = 0;
  162. Paramx.dma_report_end[1] = 0;
  163. Paramx.dma_report_end[2] = 0; // dma上报结束时间 时分秒
  164. Paramx.dma_interval = 0; // dma上报间隔 分钟单位
  165. Paramx.total_positive_water[0] = 0;
  166. Paramx.total_positive_water[1] = 0;
  167. Paramx.total_positive_water[2] = 0;
  168. Paramx.total_positive_water[3] = 0; // 表底读数
  169. uint16_t i, j;
  170. for (i = 0; i < CHECK_TEMP_POINT; i++)
  171. { // 8个流量等级 ,3个温度等级下的修正流速,用于查找当前流速落入哪个区间
  172. Paramx.check_spdLvl_c[i].spd_lvl[0] = GetSpdLvl(Q1);
  173. Paramx.check_spdLvl_c[i].spd_lvl[1] = GetSpdLvl(1.6 * Q1);
  174. Paramx.check_spdLvl_c[i].spd_lvl[2] = GetSpdLvl(3.2 * Q1);
  175. Paramx.check_spdLvl_c[i].spd_lvl[3] = GetSpdLvl(8 * Q1);
  176. Paramx.check_spdLvl_c[i].spd_lvl[4] = GetSpdLvl(0.1 * Q3);
  177. Paramx.check_spdLvl_c[i].spd_lvl[5] = GetSpdLvl(0.2 * Q3);
  178. Paramx.check_spdLvl_c[i].spd_lvl[6] = GetSpdLvl(0.35 * (1.6 * Q1 + Q3));
  179. Paramx.check_spdLvl_c[i].spd_lvl[7] = GetSpdLvl(Q3);
  180. // init c value is 1340
  181. for (j = 0; j < CHECK_POINT_NUM; j++)
  182. { // 8个流量等级 ,3个温度等级下的基础声速,修正声速
  183. Paramx.check_spdLvl_c[i].base_c[j] = CHECK_C_VALUE;
  184. Paramx.check_spdLvl_c[i].cur_c[j] = CHECK_C_VALUE;
  185. }
  186. }
  187. // float *fp = (float *)Quad_Cell_Ary;
  188. // for (i = 0; i < Quad_Cell_NUM * 5; i++)
  189. // {
  190. // *fp = 1;
  191. // fp++;
  192. // }
  193. Paramx.b = 63;
  194. Paramx.n = 45;
  195. Paramx.q = 32;
  196. Paramx.r = 500;
  197. Paramx.q_value = CHECK_Q_VALUE; // 默认Q值,影响check脉冲计算
  198. Paramx.para_len = sizeof(Paramx) - 8;
  199. Paramx.para_crc32 = com_crc32L_next(0xFFFFFFFFu, (uint8_t *)(&Paramx) + 8, sizeof(Param_t) - 8, 0xEDB88320); // 计算crc校验值
  200. // eeprom_MassWrite((uint8_t *)&Paramx,PARAMX_START_ADDR,sizeof(Param_t));
  201. // eeprom_MassRead((uint8_t *)&Paramx,PARAMX_START_ADDR,sizeof(Param_t));
  202. rewrite_para_flag |= 0x1;
  203. Paramx.nb_band_flag = 0;
  204. }
  205. void get_para_to_tdcitf(void) // 获取参数给tdcItf
  206. {
  207. uint8_t i;
  208. for (i = 0; i < MUX_CH_NUM; i++)
  209. TdcItf.path_skew[i] = Paramx.path_skew[i];
  210. TdcItf.pipe_coe = Paramx.pipe_coe;
  211. TdcItf.ch_num = Paramx.chan_num;
  212. if (TdcItf.ch_num == 1)
  213. {
  214. TdcItf.ch_bit_map = 1;
  215. }
  216. else if (TdcItf.ch_num == 2)
  217. {
  218. TdcItf.ch_bit_map = 3;
  219. }
  220. else if (TdcItf.ch_num == 4)
  221. {
  222. TdcItf.ch_bit_map = 0x0F;
  223. }
  224. for (i = 0; i < MUX_CH_NUM; i++)
  225. TdcItf.mux_ch_no[i] = Paramx.mux_ch_no[i];
  226. }
  227. void ParamInit(void) // 上电初始化
  228. {
  229. uint8_t i;
  230. if (init_eeprom_mutx_flag == 0)
  231. {
  232. eeprom_mutx_init(); // 创建eeprom操作的互斥信号量,未进入调度前,不能用
  233. }
  234. eeprom_MassRead((unsigned char *)&Paramx, PARAMX_START_ADDR, sizeof(Param_t)); // 读取参数
  235. uint32_t crc = com_crc32L_next(0xFFFFFFFFu, (uint8_t *)(&Paramx) + 8, sizeof(Param_t) - 8, 0xEDB88320);
  236. if (crc != Paramx.para_crc32) // wxl2026-5-8 校验错误时记录日志
  237. rewrite_para_flag |= 4;
  238. if (Paramx.para_len != sizeof(Paramx) - 8)
  239. {
  240. LoadDefaultParam(); // 加载默认参数
  241. rewrite_para_flag |= 4;
  242. }
  243. // Nb_Run_t *nb_run;
  244. // GetNbRun(&nb_run);
  245. // Paramx.imei[15] = 0; // 限制长度,防止溢出
  246. // strcpy(nb_run->imei, Paramx.imei);
  247. // Paramx.ccid[31] = 0; // 限制长度,防止溢出
  248. // strcpy(nb_run->ccid, Paramx.ccid);
  249. // Paramx.ver_type = VER_TYPE; // type, 1: ultrasound flow meter;
  250. // Paramx.ver_operator = VER_OPERATOR; // operator, 1: China Telecom;
  251. // Paramx.ver_module = VER_MODULE; // module, 1: HC32_BC28;
  252. // Paramx.ver_firmware = VER_FIRMWARE; // firmware version;//设备版本信息
  253. #if VER_MODULE == 4
  254. if (Paramx.chan_num != 1)
  255. {
  256. Paramx.chan_num = 1;
  257. rewrite_para_flag |= 1;
  258. }
  259. #endif
  260. get_para_to_tdcitf(); // 获取参数到tdcitf结构体
  261. memset((uint8_t *)&PatchInfo, 0, sizeof(PATCH_INFO_DEF));
  262. if (Check_quad_cell_data_valid(QUAD_CELL_START_ADDR) == 0)
  263. { // wxl2026-4-16
  264. get_quad_cell_data(Quad_Cell_Ary); // wxl2026-4-14
  265. }
  266. else
  267. {
  268. rewrite_para_flag |= 0x2;
  269. }
  270. alarm_init();
  271. bill_init();
  272. init_eeprom_mutx_flag = 1;
  273. }
  274. ////////////检查参数时,发现参数不合法,加载默认参数后重新eeprom/////////////////
  275. void check_rewrite_para(void)
  276. {
  277. if (StartUp != 2) // 在第二秒开始判断参数正确性
  278. return;
  279. if (rewrite_para_flag & 0x1)
  280. {
  281. // 保存主参数
  282. eeprom_MassWrite((uint8_t *)&Paramx, PARAMX_START_ADDR, sizeof(Param_t));
  283. rewrite_para_flag |= 0x4;
  284. }
  285. if (rewrite_para_flag & 0x2)
  286. {
  287. // 保存主参数
  288. set_diameter_and_quad_cell_data(0, &Quad_Cell_Ary);
  289. }
  290. // crc校验错误写日志
  291. if (rewrite_para_flag & 0x4) // wxl2026-5-8
  292. {
  293. write_alarm(LOG_PARA_CRC_ERROR, 1, 5555);
  294. set_crc_check_para();
  295. }
  296. rewrite_para_flag = 0;
  297. }
  298. uint16_t GetSpdLvl(double flow_rate)
  299. { // 获取当前流速,用于查表
  300. return (uint16_t)(flow_rate * 1000000 / 3600 / TdcItf.pipe_coe);
  301. }
  302. // modified by yuewei 20260316 only use check_spdLvl_c[0] start
  303. // check temperature interval: 0~10/10~40/40 and above
  304. /*
  305. uint16_t CheckTempRangeIndex(float temp) {//获取温度等级索引号
  306. if (temp >= 40.0) {
  307. return 2;
  308. } if (temp >= 10.0) {
  309. return 1;
  310. }
  311. return 0;
  312. }
  313. */
  314. // 获取温度等级索引号,only use 0
  315. uint16_t CheckTempRangeIndex(float temp)
  316. {
  317. return 0;
  318. }
  319. // modified by yuewei 20260316 only use check_spdLvl_c[0] end
  320. /**************************************************/
  321. // 获取流速等级索引号,用于获取校正系数
  322. /***************************************************/
  323. #if 0
  324. uint8_t CheckCValueIndex(uint16_t temp_idx, uint16_t spdLvl) {
  325. uint8_t i;
  326. uint16_t mid;
  327. CheckSpdLvlC_t *p = &Paramx.check_spdLvl_c[temp_idx];
  328. if (spdLvl <= p->spd_lvl[0]) {
  329. return 0;
  330. }
  331. for (i = 0; i < CHECK_POINT_NUM - 1; i++) {
  332. mid = (p->spd_lvl[i + 1] + p->spd_lvl[i]) / 2;
  333. if (spdLvl >= p->spd_lvl[i] && spdLvl < mid) {
  334. return i;
  335. } else if (spdLvl >= mid && spdLvl < p->spd_lvl[i + 1]) {
  336. return i + 1;
  337. }
  338. }
  339. return CHECK_POINT_NUM - 1;
  340. }
  341. #endif
  342. #if 0
  343. // modified by yuewei 20260429 start
  344. uint8_t CheckCValueIndex(uint16_t temp_idx, uint16_t spdLvl)
  345. {
  346. // 1. Boundary safety limit, only 3 temperature intervals, actually use index 0 only
  347. if (temp_idx >= 3)
  348. {
  349. return 0;
  350. }
  351. CheckSpdLvlC_t *p = &Paramx.check_spdLvl_c[temp_idx];
  352. uint8_t i;
  353. // 2. Less than minimum speed level -> fixed return 0
  354. if (spdLvl <= p->spd_lvl[0])
  355. {
  356. return 0;
  357. }
  358. // 3. Direct interval judgment (hysteresis canceled)
  359. for (i = 0; i < CHECK_POINT_NUM - 1; i++)
  360. {
  361. // Directly match speed level interval
  362. #if VER_MODULE == 3
  363. if (spdLvl + 3 <= p->spd_lvl[i + 1])
  364. #else
  365. if (spdLvl <= p->spd_lvl[i + 1])
  366. #endif
  367. {
  368. return i;
  369. }
  370. }
  371. // 4. Greater than maximum speed level -> return last index
  372. return CHECK_POINT_NUM - 1;
  373. }
  374. // modified by yuewei 20260429 end
  375. #endif
  376. // add by yuewei 20260731,输入的流速等级spd_lvl减5,吸附到接近的流速等级
  377. uint8_t CheckCValueIndex(uint16_t temp_idx, uint16_t spdLvl)
  378. {
  379. // 1. 温度区间安全限界,仅0/1/2有效
  380. if (temp_idx >= 3)
  381. {
  382. return 0;
  383. }
  384. CheckSpdLvlC_t *p = &Paramx.check_spdLvl_c[temp_idx];
  385. uint8_t i;
  386. uint8_t best_idx = 0;
  387. uint16_t min_diff;
  388. uint16_t curr_diff;
  389. spdLvl = spdLvl - 5; // add by yuewei 20260629
  390. // 初始化最小差值为第一个点差值
  391. if (spdLvl >= p->spd_lvl[0])
  392. min_diff = spdLvl - p->spd_lvl[0];
  393. else
  394. min_diff = p->spd_lvl[0] - spdLvl;
  395. // 遍历所有速度点,寻找差值最小的下标
  396. for (i = 1; i < CHECK_POINT_NUM; i++)
  397. {
  398. if (spdLvl >= p->spd_lvl[i])
  399. curr_diff = spdLvl - p->spd_lvl[i];
  400. else
  401. curr_diff = p->spd_lvl[i] - spdLvl;
  402. // 更新最小差值与最优索引
  403. if (curr_diff < min_diff)
  404. {
  405. min_diff = curr_diff;
  406. best_idx = i;
  407. }
  408. }
  409. return best_idx;
  410. }
  411. // 获取在不同温度和流速等级下的,声速修正系数
  412. float CheckFlowCorrectFactor(float temp, uint16_t spdLvl)
  413. {
  414. uint16_t temp_idx = CheckTempRangeIndex(temp);
  415. uint8_t c_idx = CheckCValueIndex(temp_idx, spdLvl);
  416. CheckSpdLvlC_t *p = &Paramx.check_spdLvl_c[temp_idx];
  417. uint16_t curr_c = p->cur_c[c_idx];
  418. uint16_t base_c = p->base_c[c_idx];
  419. LOG("spdLvl=%d,curr_c = %d,c_idx=%d\n", spdLvl, curr_c, c_idx);
  420. return ((float)curr_c * 1.0f) / (float)base_c;
  421. }
  422. uint32_t BillTime(uint8_t year, uint8_t month) // 确定结算日的上报时间(取)
  423. {
  424. uint8_t last_day = last_day_of_month(year, month);
  425. uint8_t day;
  426. if (Paramx.settlement_day == 0)
  427. {
  428. return 0;
  429. }
  430. if (Paramx.settlement_day > 0 && Paramx.settlement_day <= last_day)
  431. {
  432. day = Paramx.settlement_day;
  433. }
  434. else
  435. {
  436. day = last_day;
  437. }
  438. return ((day << 24) | (Paramx.report_base_hour << 16) |
  439. (Paramx.report_base_min << 8) | Paramx.report_base_sec); // 上报时分秒
  440. }
  441. /////////////////获取参数结构体指针//////////////////////
  442. // 输入参数:指向结构体指针的指针
  443. // 返回参数:无
  444. //////////////////////////////////////
  445. void GetParam(Param_t **para)
  446. {
  447. *para = &Paramx;
  448. }
  449. ///////////////////////保存所有参数//////////////////
  450. // 输入参数:无
  451. // 返回参数:无
  452. //////将内存中的param参数全部写入到eeprom中//////////
  453. void SaveParam(void)
  454. {
  455. uint32_t param_len = 0;
  456. uint32_t param_crc;
  457. uint8_t *data;
  458. uint8_t i;
  459. Nb_Run_t *nb_run;
  460. GetNbRun(&nb_run);
  461. Paramx.path_skew[0] = TdcItf.path_skew[0];
  462. Paramx.path_skew[1] = TdcItf.path_skew[1];
  463. Paramx.path_skew[2] = TdcItf.path_skew[2];
  464. Paramx.path_skew[3] = TdcItf.path_skew[3];
  465. Paramx.pipe_coe = TdcItf.pipe_coe;
  466. // memcpy(Paramx.imei, nb_run->imei, 16); // imei号保存
  467. // memcpy(Paramx.ccid, nb_run->ccid, 32); // ccid号保存
  468. memcpy(Paramx.mux_ch_no, TdcItf.mux_ch_no, sizeof(TdcItf.mux_ch_no)); // 多路开关地址
  469. Paramx.para_crc32 = com_crc32L_next(0xFFFFFFFFu, (uint8_t *)(&Paramx) + 8, sizeof(Param_t) - 8, 0xEDB88320);
  470. Paramx.para_len = sizeof(Paramx) - 8;
  471. eeprom_MassWrite((uint8_t *)&Paramx, PARAMX_START_ADDR, sizeof(Paramx));
  472. }
  473. /////////////////设置版本号 保存到eeprom中///////////////////////
  474. // 参数:版本号uchar
  475. // 返回:无
  476. ///////////////////////////////
  477. // void set_param_firmware_ver(uint8_t ver)
  478. //{ // 设置版本号
  479. // Paramx.ver_firmware = ver;
  480. // uint32_t addr = offsetof(Param_t, ver_firmware) + PARAMX_START_ADDR;
  481. // write_eeprom_para(addr, (uint8_t *)&ver, sizeof(ver));
  482. // set_crc_check_para();
  483. // }
  484. ////////////获取版本号//////////////
  485. // 参数:无
  486. // 返回:版本号数值uchar
  487. ////////////////////////
  488. uint8_t get_param_firmware_ver(void)
  489. { // 读取版本号
  490. return VER_FIRMWARE;
  491. }
  492. /////////////////获取超声波通道数/////////////////////
  493. /// 参数:无
  494. // 返回:超声波通道数
  495. /////////////////////////////////////
  496. uint8_t GetChNum(void)
  497. {
  498. uint8_t numb;
  499. get_channel_numb(&numb);
  500. return numb;
  501. }
  502. int8_t get_channel_numb(uint8_t *numb)
  503. { // 获取通道数
  504. *numb = Paramx.chan_num;
  505. return 0;
  506. }
  507. /////////////////////////////与红外通讯相关的设置和读取///////////////////////////////////////////
  508. //////////////////////////////////对paramx参数进行crc校验,并保存crc校验值////////////////////////////////////////////////////////////////
  509. // 参数:无
  510. // 返回0:正常 1:异常
  511. uint8_t set_crc_check_para(void)
  512. {
  513. Paramx.para_crc32 = com_crc32L_next(0xFFFFFFFFu, (uint8_t *)(&Paramx) + 8, sizeof(Param_t) - 8, 0xEDB88320);
  514. return write_eeprom_para(PARAMX_START_ADDR + offsetof(Param_t, para_crc32), (uint8_t *)&Paramx.para_crc32, sizeof(Paramx.para_crc32)); // 校验值长度
  515. return 0;
  516. }
  517. /////////////////////////检查新参数是否改变,如果改变则保存/////////////////////////////////////////////////
  518. // 参数1: new_para新参数值
  519. // 参数2: old_para原参数值
  520. // 参数3: len参数长度
  521. // 参数5:flag保存是否修改的标志1:修改了,0,未修改
  522. // 返回:0:保存成功 1:失败
  523. /////////////////////////////////////////////////////////////////////////////
  524. uint8_t set_para_if_nessary(void *new_para, void *old_para, uint8_t len, uint8_t *flag)
  525. {
  526. uint8_t *dat1 = new_para; // 转换为char型指针
  527. uint8_t *dat2 = old_para; // 转换为char型指针
  528. // if(memcmp(dat1,dat2,len)==0){//检查新数据和老数据是否一致
  529. // return 0;
  530. // }
  531. memcpy(dat2, dat1, len); // 更新参数值,在paramx中
  532. *flag = 1; // 参数更改标志,用于crc校验参考
  533. uint32_t addr = PARAMX_START_ADDR + (uint32_t)old_para - (uint32_t)&Paramx; // 取改参数在eeprom中的地址
  534. uint8_t ret;
  535. ret = write_eeprom_para(addr, dat1, len); // 返回写入是否成功标志 0:成功,1失败
  536. ret |= read_eeprom_para(addr, old_para, len); // 写入后读回来
  537. get_para_to_tdcitf();
  538. return 0;
  539. }
  540. //////////////////设置硬件参数参数////////////////////////////
  541. /// 参数:HardWarePara 包含 是否带压力传感器指示 pressure_sensor //
  542. // 关断参数:pipe_coe
  543. // 返回: 成功返回1, 失败返回2
  544. ///////////////////////////////////
  545. int8_t set_hardware_para(HardWareParaDef *HardWarePara)
  546. {
  547. uint8_t flag = 0, ret = 0;
  548. if (HardWarePara->pipe_coe <= 0)
  549. return 2; // 数据不合法
  550. if (HardWarePara->pressure_sensor != 1 && HardWarePara->pressure_sensor != 2)
  551. return 2;
  552. ret |= set_para_if_nessary(&HardWarePara->pipe_coe, &Paramx.pipe_coe, sizeof(Paramx.pipe_coe), &flag);
  553. ret |= set_para_if_nessary(&HardWarePara->pressure_sensor, &Paramx.pressure_sensor, sizeof(Paramx.pressure_sensor), &flag);
  554. if (flag == 1)
  555. { // 保存crc校验
  556. ret |= set_crc_check_para();
  557. }
  558. return (ret == 0 ? 0 : -1); // write_eeprom_para在成功写入后返回0,否则返回非零值
  559. }
  560. ////////////////////////读取硬件参数///////////////////////////////////
  561. // 参数:硬件参数指针HardWareParaDef
  562. // 返回:0:读取不成功, 1:读取成功
  563. ///////////////////////////////////////////////////////////////////////
  564. int8_t get_hardware_para(HardWareParaDef *HardWarePara)
  565. {
  566. HardWarePara->pipe_coe = Paramx.pipe_coe;
  567. HardWarePara->pressure_sensor = Paramx.pressure_sensor;
  568. return 0;
  569. }
  570. PATCH_INFO_DEF PatchInfo;
  571. ///////////////////设置表端开始升级信息//////////////////////////////////////////
  572. // 参数patch_info:表端升级相关信息指针
  573. // 返回:1:设置成功 2:版本号不匹配 3:升级包长度值超过允许长度
  574. /////////////////////////////////////////////////////////
  575. int8_t set_patch_info(PATCH_INFO_DEF *patch_info)
  576. {
  577. memset((uint8_t *)&PatchInfo, 0, sizeof(PATCH_INFO_DEF));
  578. if (patch_info->new_ver[4] <= patch_info->cur_ver[4] || patch_info->new_ver[0] != patch_info->cur_ver[0] || patch_info->new_ver[1] != patch_info->cur_ver[1] || patch_info->new_ver[2] != patch_info->cur_ver[2] || patch_info->new_ver[3] != patch_info->cur_ver[3])
  579. { // 新版本信息不合法
  580. return 2;
  581. }
  582. if (patch_info->cur_ver[0] != 'V')
  583. return 2;
  584. if (patch_info->cur_ver[1] != VER_TYPE)
  585. return 2;
  586. if (patch_info->cur_ver[2] != VER_OPERATOR)
  587. return 2;
  588. if (patch_info->cur_ver[3] != VER_MODULE)
  589. return 2;
  590. if (patch_info->cur_ver[4] != VER_FIRMWARE)
  591. return 2; // 差分包当前版本和正在运行的版本不一致
  592. if (patch_info->patch_len > DIFF_PATCH_PACKET_SIZE)
  593. return 3; // 长度超过写入最大长度
  594. memcpy(PatchInfo.cur_ver, patch_info->cur_ver, sizeof(patch_info->cur_ver)); // 保存当前版本号
  595. memcpy(PatchInfo.new_ver, patch_info->new_ver, sizeof(patch_info->new_ver)); // 保存新版本号
  596. PatchInfo.packet_crc = patch_info->packet_crc; // 数据的总校验值
  597. PatchInfo.patch_len = patch_info->patch_len; // 数据总长度
  598. PatchInfo.per_packet_len = patch_info->per_packet_len; // 固定512字节
  599. // PatchInfo.per_packet_len=patch_info->per_packet_len;//每包数据长度
  600. PatchInfo.update_status = 0x1; // 开始升级标志
  601. PatchInfo.cur_num = 1; // 当前升级包序号,初始0,第一包值=1
  602. PatchInfo.res_crc16 = 0; // 累计crc,没来一包数据校验一次,最后检查和中校验值是否相等
  603. PatchInfo.flash_addr_ptr = 0; // 当前flash写入地址
  604. LOG("packet num =%d,total size = %d\r\n",
  605. (patch_info->patch_len + PatchInfo.per_packet_len - 1) / PatchInfo.per_packet_len,
  606. patch_info->patch_len);
  607. return 1;
  608. }
  609. ////////////////////////////向flash写入差分包/////////////////////////////////////////
  610. ////DIFF_PACKET_DEF参数1 numb:包序号,从1开始
  611. // DIFF_PACKET_DEF参数2: len:差分包长度,目前默认是512byte
  612. // DIFF_PACKET_DEF参数3:data指针 指向要写入的差分包数据
  613. // 返回:1:成功写入 2:crc失败 6:未收到开始包 7:数据包序号不对
  614. //////////////////////////////////////////////////////////////////////////////
  615. // const uint8_t app_addr=0;
  616. uint8_t write_diff_patch_to_flash(DIFF_PACKET_DEF *Packet)
  617. {
  618. McuFlash_WP_t WP;
  619. uint8_t last_dat = 0;
  620. uint16_t write_len;
  621. if (PatchInfo.update_status != 1)
  622. return 0x6;
  623. if (Packet->packet_numb != PatchInfo.cur_num)
  624. return 6; // 不是下一个包
  625. //////////////////确定最后一帧及写入长度///////////////////
  626. Packet->packet_size = Packet->packet_size; // DIFF_PER_PACKET_SIZE;//固定
  627. if (Packet->packet_numb * PatchInfo.per_packet_len >= PatchInfo.patch_len)
  628. {
  629. last_dat = 1;
  630. write_len = (uint16_t)(PatchInfo.patch_len % PatchInfo.per_packet_len);
  631. }
  632. else
  633. {
  634. last_dat = 0; // 中间帧数据
  635. write_len = Packet->packet_size;
  636. }
  637. // write_len = Packet->packet_size;
  638. PatchInfo.res_crc16 = pack_crc_check(PatchInfo.res_crc16, Packet->data, write_len);
  639. if (Packet->packet_numb == 1)
  640. { // 第一包数据,先擦除
  641. #ifndef DEBUG_PATCH
  642. rt_enter_critical();
  643. // McuFlash_Unlock();
  644. McuFlash_EraseSegment(DIFF_PATCH_PACKET_START, DIFF_PATCH_PACKET_SIZE);
  645. // McuFlash_Lock();
  646. rt_exit_critical();
  647. #endif
  648. // erase_flash_memory(DIFF_PATCH_PACKET_START, DIFF_PATCH_PACKET_SIZE);
  649. }
  650. #ifndef DEBUG_PATCH
  651. write_flash_memory(Packet->data, DIFF_PATCH_PACKET_START + PatchInfo.flash_addr_ptr, write_len);
  652. #endif
  653. #ifdef APP_DEBUG_PRINT
  654. LOG("write patch num= %d\r\n", PatchInfo.cur_num);
  655. #endif
  656. PatchInfo.cur_num++;
  657. PatchInfo.flash_addr_ptr += write_len;
  658. if (last_dat == 1)
  659. { // 最后一包
  660. if (PatchInfo.res_crc16 != PatchInfo.packet_crc)
  661. {
  662. LOG("update data crc err pack:%d\r\n", Packet->packet_numb);
  663. return 2;
  664. }
  665. else
  666. {
  667. PatchInfo.update_status = 2; // 升级包写入结束,bootloader用该位判断是否需要升级,升级完成后将该位清零
  668. // 未升级的情况下,bootloader根据代码的完整程度和版本的新旧情况运行app
  669. // 写差分升级包升级的信息,供bootloader使用
  670. PatchInfo.run_app_ver_addr = (uint32_t)SOFT_VER;
  671. #ifndef DEBUG_PATCH
  672. erase_flash_memory(DIFF_UPDATE_INFO_START, DIFF_UPDATE_INFO_SIZE); // 写flash
  673. write_flash_memory((uint8_t *)&PatchInfo, DIFF_UPDATE_INFO_START, sizeof(PATCH_INFO_DEF));
  674. #endif
  675. LOG("last packet ok\r\n");
  676. NbRun.reset_mcu_cnt = 5;
  677. return 1; // 最后一包
  678. }
  679. }
  680. return 1; // 0x10;//中间包
  681. }
  682. //************设置主服务器和从服务器的ip地址和端口号******************************/
  683. // 参数dat:指向SERVER_IP_PORT_DEF结构体
  684. // 返回:成功返回1,失败返回2
  685. /////////////////////////////////////////////////////////////////////////////////
  686. int8_t set_server_ip_port_para(SERVER_IP_PORT_DEF *server_ip_para)
  687. {
  688. uint8_t flag = 0, ret = 0;
  689. // uint32_t addr;
  690. ret |= set_para_if_nessary(server_ip_para->main_server_ip, Paramx.main_server_ip, sizeof(Paramx.main_server_ip), &flag);
  691. ret |= set_para_if_nessary(&server_ip_para->main_server_port, &Paramx.main_server_port, sizeof(Paramx.main_server_port), &flag);
  692. ret |= set_para_if_nessary(server_ip_para->sub_server_ip, Paramx.sub_server_ip, sizeof(Paramx.sub_server_ip), &flag);
  693. ret |= set_para_if_nessary(&server_ip_para->sub_server_port, &Paramx.sub_server_port, sizeof(Paramx.sub_server_port), &flag);
  694. if (flag == 1)
  695. { // 保存crc校验
  696. // Paramx.para_crc32 = com_crc32L_next(0xFFFFFFFFu, (uint8_t *)(&Paramx+8), sizeof(Param_t)-8, 0xEDB88320);
  697. // ret|=write_eeprom_para(PARAMX_START_ADDR+offsetof(Param_t,para_crc32),(uint8_t *)&Paramx.para_crc32,sizeof(Paramx.para_crc32));//校验值长度
  698. ret |= set_crc_check_para();
  699. }
  700. return (ret == 0 ? 0 : -1); // write_eeprom_para在成功写入后返回0,否则返回非零值
  701. }
  702. ////////////////////////////读取主服务器和备用服务器ip地址和端口号/////////////////////////////
  703. // 参数server_ip_dat :SERVER_IP_PORT_DEF类型指针,用于保存主服务器和备用服务器的端口和ip地址信息
  704. //////////////////////////////////////////////////////////
  705. int8_t get_server_ip_port_para(SERVER_IP_PORT_DEF *server_ip_para)
  706. {
  707. memcpy(server_ip_para->main_server_ip, Paramx.main_server_ip, sizeof(Paramx.main_server_ip));
  708. server_ip_para->main_server_port = Paramx.main_server_port;
  709. memcpy(server_ip_para->sub_server_ip, Paramx.sub_server_ip, sizeof(Paramx.sub_server_ip));
  710. server_ip_para->sub_server_port = Paramx.sub_server_port;
  711. return 0;
  712. }
  713. ////////////////////////////设置定时上报周期和时间间隔/////////////////////////////////////////////////////
  714. // 参数:regular_report_para定时上报数据结构体,包含起始基准时间,间隔时间u\
  715. //返回:1:成功2:失败
  716. /////////////////////////////////////////////////////////////////////////////////////////////////////////
  717. int8_t set_regular_report_para(REGULAR_REPORT_DEF *regular_report_para)
  718. {
  719. uint8_t flag = 0, ret = 0;
  720. if (regular_report_para->report_base_hour > 23 || regular_report_para->report_base_min > 59 || regular_report_para->report_base_sec > 59)
  721. return 2;
  722. ret |= set_para_if_nessary(&regular_report_para->report_base_hour, &Paramx.report_base_hour, 3, &flag); // 年月日参数
  723. ret |= set_para_if_nessary(&regular_report_para->report_interval, &Paramx.report_interval, sizeof(Paramx.report_interval), &flag); // 时间间隔
  724. if (flag == 1)
  725. { // 保存crc校验
  726. ret |= set_crc_check_para();
  727. }
  728. return (ret == 0 ? 0 : -1);
  729. }
  730. /////////////////////////////读取定时上报周期和时间间隔信息//////////////////////////////////////////////
  731. // 参数regular_report_para保存定时上报数据结构体
  732. // 返回:1成功读取
  733. ////////////////////////////////////////////
  734. int8_t get_regular_report_para(REGULAR_REPORT_DEF *regular_report_para)
  735. {
  736. regular_report_para->report_base_hour = Paramx.report_base_hour;
  737. regular_report_para->report_base_min = Paramx.report_base_min;
  738. regular_report_para->report_base_sec = Paramx.report_base_sec;
  739. regular_report_para->report_interval = Paramx.report_interval;
  740. return 0;
  741. }
  742. ///////////////////////////////////设置DMA定时上报周期参数////////////////////////////////////////////////
  743. // 参数:dma_report_para dma参数结构体,包含dma起始时间结束时间和时间间隔参数
  744. // 返回:1:成功 2:失败
  745. ////////////////////////////////////////////////////////////////////////////////////
  746. int8_t set_dma_regular_report_para(DMA_REGULAR_REPORT_DEF *dma_report_para)
  747. {
  748. uint8_t flag = 0, ret = 0;
  749. // 判断数据是否在正常范围内
  750. if (dma_report_para->dma_report_start_hour > 23 || dma_report_para->dma_report_start_min > 59 || dma_report_para->dma_report_start_sec > 59)
  751. return 2;
  752. if (dma_report_para->dma_report_end_hour > 23 || dma_report_para->dma_report_end_min > 59 || dma_report_para->dma_report_end_sec > 59)
  753. return 2;
  754. ret |= set_para_if_nessary(dma_report_para, Paramx.dma_report_start, 8, &flag); // 参数整体保存
  755. if (flag == 1)
  756. { // 保存crc校验
  757. ret |= set_crc_check_para();
  758. }
  759. return (ret == 0 ? 0 : -1);
  760. }
  761. //////////////////////////////读取DMA定时上报参数///////////////////////////////////////////////////////
  762. // 参数: dma_report_para 参数保存结构体
  763. // 返回1:获取成功2:失败
  764. ////////////////////////////////////////////////////////////////////////////////////////
  765. int8_t get_dma_regular_report_para(DMA_REGULAR_REPORT_DEF *dma_report_para)
  766. {
  767. dma_report_para->dma_report_start_hour = Paramx.dma_report_start[0];
  768. dma_report_para->dma_report_start_min = Paramx.dma_report_start[1];
  769. dma_report_para->dma_report_start_sec = Paramx.dma_report_start[2];
  770. dma_report_para->dma_report_end_hour = Paramx.dma_report_end[0];
  771. dma_report_para->dma_report_end_min = Paramx.dma_report_end[1];
  772. dma_report_para->dma_report_end_sec = Paramx.dma_report_end[2];
  773. dma_report_para->dma_interval = Paramx.dma_interval;
  774. return 0;
  775. }
  776. ////////////////////////设置流量告警参数//////////////////////////////////////
  777. // 参数:flow_alarm_para流量告警参数结构体
  778. // 返回:1:设置成功 2:失败
  779. int8_t set_flow_alarm_para(FLOW_ALARM_PARA_DEF *flow_alarm_para)
  780. {
  781. uint8_t flag = 0, ret = 0;
  782. // 判断数据是否在正常范围内
  783. ret = set_para_if_nessary(flow_alarm_para, &Paramx.large_flow_alarm_thres, 14, &flag); // 参数整体保存
  784. if (flag == 1)
  785. { // 保存crc校验
  786. ret |= set_crc_check_para();
  787. }
  788. return (ret == 0 ?: -1);
  789. }
  790. ////////////////////////////设置nb已选择频段标志/////////////////////////////////
  791. int8_t set_nb_band(uint8_t band)
  792. {
  793. uint8_t flag = 0, ret = 0;
  794. uint8_t dat = 0;
  795. // 判断数据是否在正常范围内
  796. Paramx.nb_band_flag = band;
  797. ret = set_para_if_nessary(&dat, &Paramx.nb_band_flag, 1, &flag); // 参数整体保存
  798. if (flag == 1)
  799. { // 保存crc校验
  800. ret |= set_crc_check_para();
  801. }
  802. return (ret == 0 ?: -1);
  803. }
  804. ////////////////////////获取流量告警参数值/////////////////////////////////////////
  805. // 参数flow_alarm_para 保存流量参数
  806. // 返回:1:成功 2:失败
  807. //////////////////////////////////////////////////////
  808. int8_t get_flow_alarm_para(FLOW_ALARM_PARA_DEF *flow_alarm_para)
  809. {
  810. flow_alarm_para->large_flow_alarm_thres = Paramx.large_flow_alarm_thres;
  811. flow_alarm_para->large_flow_cnti_moni_time = Paramx.large_flow_cnti_moni_time;
  812. flow_alarm_para->cnti_flow_cnti_moni_time = Paramx.cnti_flow_cnti_moni_time;
  813. flow_alarm_para->leak_flow_alarm_thres = Paramx.leak_flow_alarm_thres;
  814. flow_alarm_para->leak_flow_cnti_moni_time = Paramx.leak_flow_cnti_moni_time;
  815. return 0;
  816. }
  817. /////////////////////设置压力表告警参数///////////////////////////////////////////////////
  818. // 参数:press_alarm_para 要设置的压力表报警参数数据指针
  819. // 返回:1:成功,2:失败
  820. ///////////////////////////////////////////////////////////////////////////////
  821. int8_t set_press_alarm_para(PRESS_ALARM_PARA_DEF *press_alarm_para)
  822. {
  823. uint8_t flag = 0, ret = 0;
  824. uint8_t dat[4];
  825. memset(dat, 0, 4);
  826. dat[0] = press_alarm_para->high_press_alarm_thres;
  827. dat[2] = press_alarm_para->low_press_alarm_thres;
  828. if (dat[0] < dat[2])
  829. return 3;
  830. // 判断数据是否在正常范围内
  831. ret = set_para_if_nessary(dat, &Paramx.high_press_alarm_thres, 4, &flag); // 参数整体保存
  832. if (flag == 1)
  833. { // 保存crc校验
  834. ret |= set_crc_check_para();
  835. }
  836. return (ret == 0 ? 0 : -1);
  837. }
  838. ////////////////////////获取压力报警参数//////////////////////////////////////////////////
  839. ////参数 press_alarm_para 存储压力报警参数值,包括高压力和低压力报警阈值
  840. // 返回 1:读取成功
  841. ////////////////////////////////////////////////////////////////////////////////////////////
  842. int8_t get_press_alarm_para(PRESS_ALARM_PARA_DEF *press_alarm_para)
  843. {
  844. press_alarm_para->high_press_alarm_thres = Paramx.high_press_alarm_thres;
  845. press_alarm_para->low_press_alarm_thres = Paramx.low_press_alarm_thres;
  846. return 0;
  847. }
  848. /////////////////////////设置温度告警参数//////////////////////////////////////
  849. /////参数: temp_alarm_para 指针包含要存储的温度报警参数 包括高温和低温报警阈值
  850. // 返回 1:成功 2:失败
  851. ////////////////////////////////////////////////////////////////////////////
  852. int8_t set_temp_alarm_para(TEMP_ALARM_PARA_DEF *temp_alarm_para)
  853. {
  854. uint8_t flag = 0, ret = 0;
  855. if (temp_alarm_para->high_temp_alarm_thres < temp_alarm_para->low_temp_alarm_thres)
  856. return 2;
  857. ret = set_para_if_nessary(temp_alarm_para, &Paramx.high_temp_alarm_thres, 4, &flag); // 参数整体保存
  858. if (flag == 1)
  859. { // 保存crc校验
  860. ret |= set_crc_check_para();
  861. }
  862. return (ret == 0 ? 0 : -1);
  863. }
  864. /////////////////////////获取温度告警参数//////////////////////////////////////
  865. /////参数: temp_alarm_para 指针,保存读出的参数
  866. // 返回 1:成功 2:失败
  867. ////////////////////////////////////////////////////////////////////////////
  868. int8_t get_temp_alarm_para(TEMP_ALARM_PARA_DEF *temp_alarm_para)
  869. {
  870. temp_alarm_para->high_temp_alarm_thres = Paramx.high_temp_alarm_thres;
  871. temp_alarm_para->low_temp_alarm_thres = Paramx.low_temp_alarm_thres;
  872. return 0;
  873. }
  874. ////////////////////////////设置表端结算日参数/////////////////////////////////////
  875. // 参数:要写入的表端结算日数据
  876. // 返回 1:成功 2:失败
  877. ////////////////////////////////////////////////////////////////////////////////////
  878. int8_t set_settlement_day_para(SETTLEMENT_DAY_DEF *settlement_day_para)
  879. {
  880. uint8_t flag = 0, ret = 0;
  881. if (settlement_day_para->settlement_day > 31)
  882. return 2;
  883. ret = set_para_if_nessary(settlement_day_para, &Paramx.settlement_day, 1, &flag); // 参数整体保存
  884. if (flag == 1)
  885. { // 保存crc校验
  886. ret |= set_crc_check_para();
  887. }
  888. return (ret == 0 ? 0 : -1);
  889. }
  890. ////////////////////////////读取表端结算日参数/////////////////////////////////////
  891. // 参数:要写入的表端结算日数据
  892. // 返回 1:成功 2:失败
  893. ////////////////////////////////////////////////////////////////////////////////////
  894. int8_t get_settlement_day_para(SETTLEMENT_DAY_DEF *settlement_day_para)
  895. {
  896. settlement_day_para->settlement_day = Paramx.settlement_day;
  897. return 0;
  898. }
  899. ///////////////////////////////设置表端底读///////////////////////////////////////////////////
  900. // 参数:指向表端底读数据指针
  901. // 返回:1:成功 2:失败
  902. //////////////////////////////////////////////////////////////////////////////////////////////int8_t set_meter_bottom_data(METER_BOTTOM_DEF *bottom_data)
  903. int8_t set_meter_bottom_data(METER_BOTTOM_DEF *bottom_data)
  904. {
  905. uint8_t flag = 0, ret = 0;
  906. double base_read = (double)(uint32_t)((bottom_data->fw[3] << 24) |
  907. (bottom_data->fw[2] << 16) |
  908. (bottom_data->fw[1] << 8) |
  909. bottom_data->fw[0]);
  910. base_read *= 10000; // 0.01->0.000001//转换为0.000001单位
  911. if (base_read < FwCumFlow)
  912. flag = 1;
  913. FwCumFlow = base_read; // 更新当前流量和正向流量
  914. base_read = (double)(uint32_t)((bottom_data->bw[3] << 24) |
  915. (bottom_data->bw[2] << 16) |
  916. (bottom_data->bw[1] << 8) |
  917. bottom_data->bw[0]);
  918. base_read *= 10000; // 0.01->0.000001//转换为0.000001单位
  919. if (base_read < BwCumFlow)
  920. flag = 1;
  921. BwCumFlow = base_read;
  922. CumFlow = FwCumFlow - BwCumFlow;
  923. if (flag == 1)
  924. global_settle_flag = 1; // 设置总结算标志
  925. // SetBillCumFlow(CumFlow, FwCumFlow, BwCumFlow); // 设置当前流量数据
  926. save_cur_flow_flag = 1; // 保存到当前值,循环存储
  927. return 0;
  928. }
  929. ////////////////////////读取前18个月月结数据//////////////////////////////////////////
  930. // 参数:月结数据指针,空间大小18*11
  931. // 成功返回1,失败返回2
  932. /////////////////////////////////////////////////////////////////////////////////////
  933. int8_t get_18month_record_data(uint8_t *data)
  934. {
  935. uint8_t i, ret = 0;
  936. bill_t bill;
  937. rtc_run_t *rr;
  938. get_rtc_run(&rr); // 当前时间
  939. uint8_t flag, j;
  940. uint32_t date = ((rr->year << 16) | (rr->month << 8));
  941. for (i = 0; i < 18; i++)
  942. {
  943. date = prev_month(date);
  944. flag = get_month_used_bill((uint8_t)(date >> 16), (uint8_t)(date >> 8), &bill);
  945. ret |= flag;
  946. if (flag != 0)
  947. {
  948. for (j = 0; j < 11; j++)
  949. data[i * 11 + j] = 0;
  950. continue;
  951. }
  952. data[i * 11] = 0x14;
  953. data[i * 11 + 1] = bill.date[0];
  954. data[i * 11 + 2] = bill.date[1]; //
  955. data[i * 11 + 3] = (unsigned char)(bill.fw_used);
  956. data[i * 11 + 4] = (unsigned char)(bill.fw_used >> 8);
  957. data[i * 11 + 5] = (unsigned char)(bill.fw_used >> 16);
  958. data[i * 11 + 6] = (unsigned char)(bill.fw_used >> 24); // 正向流量
  959. data[i * 11 + 7] = (unsigned char)(bill.bw_used);
  960. data[i * 11 + 8] = (unsigned char)(bill.bw_used >> 8);
  961. data[i * 11 + 9] = (unsigned char)(bill.bw_used >> 16);
  962. data[i * 11 + 10] = (unsigned char)(bill.bw_used >> 24); // 反向流量
  963. }
  964. if (ret != 0)
  965. return -1;
  966. else
  967. return 0;
  968. }
  969. ////////////////////////读取前30日日结数据//////////////////////////////////////////
  970. // 参数:日结数据指针,空间大小30*12
  971. // 成功返回1,失败返回2
  972. /////////////////////////////////////////////////////////////////////////////////////
  973. int8_t get_30day_record_data(uint8_t *data)
  974. {
  975. uint8_t i, ret = 0;
  976. bill_t bill;
  977. rtc_run_t *rr;
  978. get_rtc_run(&rr); // 当前时间
  979. uint32_t date = ((rr->year << 16) | (rr->month << 8) | rr->day);
  980. uint8_t flag, j;
  981. for (i = 0; i < 30; i++)
  982. {
  983. date = prev_day(date);
  984. flag = get_day_used_bill((uint8_t)(date >> 16), (uint8_t)(date >> 8), (uint8_t)date, &bill);
  985. ret |= flag;
  986. if (flag != 0)
  987. {
  988. ret |= 1;
  989. for (j = 0; j < 12; j++)
  990. data[i * 12 + j] = 0;
  991. continue;
  992. }
  993. data[i * 12] = 0x14; // 20
  994. data[i * 12 + 1] = bill.date[0]; // 年
  995. data[i * 12 + 2] = bill.date[1]; // 月
  996. data[i * 12 + 3] = bill.date[2]; // 日
  997. data[i * 12 + 4] = (unsigned char)(bill.fw_used);
  998. data[i * 12 + 5] = (unsigned char)(bill.fw_used >> 8);
  999. data[i * 12 + 6] = (unsigned char)(bill.fw_used >> 16);
  1000. data[i * 12 + 7] = (unsigned char)(bill.fw_used >> 24);
  1001. data[i * 12 + 8] = (unsigned char)(bill.bw_used);
  1002. data[i * 12 + 9] = (unsigned char)(bill.bw_used >> 8);
  1003. data[i * 12 + 10] = (unsigned char)(bill.bw_used >> 16);
  1004. data[i * 12 + 11] = (unsigned char)(bill.bw_used >> 24);
  1005. }
  1006. if (ret != 0)
  1007. return -1;
  1008. else
  1009. return 0;
  1010. }
  1011. ////////////////////////读取结数据//////////////////////////////////////////
  1012. // 参数1:读取的年月日
  1013. /////////////////////////////////////////////////////////////////////////////////////
  1014. int8_t get_hour_record_data(uint8_t year, uint8_t month, uint8_t day, uint8_t *data)
  1015. {
  1016. uint8_t i;
  1017. hour_bill_t bill;
  1018. int32_t days;
  1019. // 1. 默认填零
  1020. memset(data, 0, 244);
  1021. // 2. 检查时间有效性
  1022. // days = get_days_between_now(year, month, day);
  1023. // 假设:有效范围为过去30天内(含今天,即0~30天)
  1024. // 如果 get_days_between_now 返回负数表示未来,正数表示过去
  1025. // if (days < 0 || days > 30)
  1026. //{
  1027. // return 0; // 不在30天内,返回全零(已memset)
  1028. //}
  1029. // 3. 读取数据
  1030. // 注意:请确认 get_hour_used_bill 的正确用法。
  1031. // 如果原代码 (uint8_t)date 是bug,这里应该传入正确的参数。
  1032. // 假设 get_hour_used_bill 需要 year, month, day, hour
  1033. // 由于我不知道 get_hour_used_bill 的确切签名,以下代码假设它需要修正以支持年月日
  1034. // 如果原系统确实只传 day 就能工作(例如底层驱动自动处理环形缓冲或当前月),则保留原调用方式但需注意局限性。
  1035. for (i = 0; i < 24; i++)
  1036. {
  1037. // 【重要】原代码这里强转 uint8_t 丢失了年月信息,极大概率是Bug。
  1038. // 如果 get_hour_used_bill 只能接受 uint8_t day,请确认它是否能正确读取指定年月的数据。
  1039. // 如果不能,你需要修改 get_hour_used_bill 或在此处提供完整日期上下文。
  1040. // 暂时沿用原调用方式,但加上注释警示
  1041. if (get_hour_used_bill(year, month, day, i, &bill) == 0)
  1042. {
  1043. // if (bill.date[0] != year || bill.date[1] != month || bill.date[2] != day || bill.date[3] != i) // if rec time is not valid drop it
  1044. // continue;
  1045. data[0] = 0x14; // 标记有效? 原代码在循环外设置 data[0]=0x14, 这里如果部分失败怎么处理?
  1046. // 原代码逻辑:只要进入else,data[0]就被设为0x14。
  1047. // 如果某个小时失败,bill是全零,拷贝进去也是零。
  1048. memcpy(&data[4 + i * 3], bill.fw_used, 3);
  1049. memcpy(&data[4 + 72 + i * 3], bill.bw_used, 3);
  1050. data[4 + 144 + i] = bill.pressure;
  1051. memcpy(&data[4 + 168 + i * 3], bill.flow_rate, 3);
  1052. }
  1053. // 如果读取失败,data对应位置保持为0(因为开头memset了)
  1054. }
  1055. // 设置头部信息,表示这是一条有效的记录结构(即使内容为0)
  1056. data[0] = 0x14;
  1057. data[1] = year;
  1058. data[2] = month;
  1059. data[3] = day;
  1060. return 0;
  1061. }
  1062. ////////////////////////////////比较两个时间的大小///////////////////////////////////////////
  1063. // 参数1,2,用于比较的两个时间结构体
  1064. // 返回:date1>date2时返回1,相等时返回0,date1<date2时返回-1
  1065. ///////////////////////////////////////////////////////////////////////////////////////////
  1066. int8_t datecmp(tm_t date1, tm_t date2)
  1067. {
  1068. if (date1.year > date2.year)
  1069. return 1;
  1070. else if (date1.year < date2.year)
  1071. return -1;
  1072. if (date1.month > date2.month)
  1073. return 1;
  1074. else if (date1.month < date2.month)
  1075. return -1;
  1076. if (date1.day > date2.day)
  1077. return 1;
  1078. else if (date1.day < date2.day)
  1079. return -1;
  1080. if (date1.hour > date2.hour)
  1081. return 1;
  1082. else if (date1.hour < date2.hour)
  1083. return -1;
  1084. if (date1.min > date2.min)
  1085. return 1;
  1086. else if (date1.min < date2.min)
  1087. return -1;
  1088. if (date1.sec > date2.sec)
  1089. return 1;
  1090. else if (date1.sec < date2.sec)
  1091. return -1;
  1092. return 0;
  1093. }
  1094. //////////////////////////////////获取5分钟密集数据///////////////////////////////////////////////////////////
  1095. // 参数get_5min_record_data:保存读取的起始时间和终止时间,
  1096. // 参数numb:读取的序号,0表示读取第一组数据,
  1097. // 返回1:表示读取成功 2:表示读取失败,3:读取成功,最后一帧数据
  1098. int8_t get_5min_record_data(GET_5MIN_REOCORD_DEF *get_5min_record_info, uint16_t numb, uint8_t *data)
  1099. {
  1100. uint8_t ret = 0;
  1101. uint8_t i;
  1102. hour_bill_t bill;
  1103. tm_t query_time; // 用户逻辑上的查询时间点(例如 10:00)
  1104. tm_t index_time; // 底层存储使用的索引时间点(例如 10:05)
  1105. tm_t start_time;
  1106. // 1. 初始化输出缓冲区
  1107. memset(data, 0, 24 * 16);
  1108. // 2. 解析起始时间 (用户传入的 start_time)
  1109. start_time.year = get_5min_record_info->start_time[0];
  1110. start_time.month = get_5min_record_info->start_time[1];
  1111. start_time.day = get_5min_record_info->start_time[2];
  1112. start_time.hour = get_5min_record_info->start_time[3];
  1113. start_time.min = get_5min_record_info->start_time[4];
  1114. start_time.min = (start_time.min / 5) * 5;
  1115. start_time.sec = 0;
  1116. // 3. 计算当前页的起始查询时间
  1117. // 每页 24 个点 * 5 分钟 = 120 分钟 = 7200 秒
  1118. uint32_t offset_seconds = (uint32_t)numb * 24 * 5 * 60;
  1119. memcpy(&query_time, &start_time, sizeof(tm_t));
  1120. if (offset_seconds > 0)
  1121. {
  1122. time_add_secs(&query_time, &query_time, offset_seconds);
  1123. }
  1124. // 4. 循环读取 24 个点
  1125. for (i = 0; i < 24; i++)
  1126. {
  1127. // 【关键修正】:因为底层存储使用“区间末尾时间”作为标记
  1128. memcpy(&index_time, &query_time, sizeof(tm_t));
  1129. // time_add_secs(&index_time, &index_time, 5 * 60);
  1130. // 5. 调用底层读取函数
  1131. // 使用 index_time (末尾时间) 进行查询
  1132. // 【严重警告】:请确认 get_5min_used_bill 能正确处理 index_time 的年月!
  1133. // 如果它只能处理当前月,查询历史数据必错。
  1134. uint8_t flag = get_5min_used_bill(index_time.year, index_time.month, index_time.day, index_time.hour, index_time.min, &bill);
  1135. if (flag != 0)
  1136. {
  1137. // 读取失败,该点数据保持为 0
  1138. ret |= 1;
  1139. }
  1140. else
  1141. {
  1142. // 填充数据
  1143. data[i * 16] = 0x14; // 标记有效
  1144. data[1 + i * 16] = bill.date[0];
  1145. data[2 + i * 16] = bill.date[1];
  1146. data[3 + i * 16] = bill.date[2];
  1147. data[4 + i * 16] = bill.date[3];
  1148. // 注意:这里返回给上层的分钟数,应该填 query_time.min (用户请求的逻辑时间)
  1149. // 还是 index_time.min (底层存储的物理时间)?
  1150. // 通常协议要求返回“数据所属的时间点”。如果用户查 10:00,期望看到 10:00 或 10:05?
  1151. // 根据原代码 logic: data[5 + i * 16] = (uint8_t)dest.min; (原代码用的是查询时间)
  1152. // 建议保持一致性,如果上层知道这是5分钟数据,通常展示开始时间或结束时间需统一。
  1153. // 这里暂且填入 index_time.min (10:05),因为这是数据的真实标记。
  1154. data[5 + i * 16] = index_time.min;
  1155. memcpy(&data[6 + i * 16], bill.fw_used, 10);
  1156. }
  1157. // 6. 移动到下一个查询点 (逻辑时间 + 5分钟)
  1158. time_add_secs(&query_time, &query_time, 5 * 60);
  1159. }
  1160. return ret ? -2 : 0;
  1161. }
  1162. //////////////////////////////读取日志信息///////////////////////////////////////////
  1163. // 参数:日志信息存储指针data, 一个30*13个字节
  1164. // 返回1:成功, 0:失败
  1165. /////////////////////////////////////////////////////////////////////////
  1166. int8_t get_log_record(uint8_t start, uint8_t num, uint8_t *data)
  1167. {
  1168. alarm_t alarm;
  1169. uint8_t i;
  1170. if (num > 30)
  1171. num = 30;
  1172. memset(data, 0, 30 * 13); // 先清零存储器
  1173. for (i = 0; i < num; i++)
  1174. {
  1175. if (read_alarm(start + i, &alarm) == 1)
  1176. { // 读取成功
  1177. memcpy(data, alarm.time, 7);
  1178. data[7] = alarm.err_no;
  1179. data[8] = alarm.type;
  1180. memcpy(&data[9], alarm.arg, 4);
  1181. }
  1182. data += 13;
  1183. }
  1184. return 0;
  1185. }
  1186. /////////////////////////////设置声道数/////////////////////////////////////////////
  1187. int8_t set_channel_numb(uint8_t *numb)
  1188. {
  1189. if (*numb == 0 || *numb > 4)
  1190. return -2;
  1191. uint8_t flag = 0, ret = 0;
  1192. // 判断数据是否在正常范围内
  1193. // add clear blank flag wxl 2026-5-21
  1194. TdcItf.blank_flag = 0;
  1195. set_mux_ch(0);
  1196. ret = set_para_if_nessary(numb, &Paramx.chan_num, 1, &flag); // 参数整体保存
  1197. if (flag == 1)
  1198. { // 保存crc校验
  1199. ret |= set_crc_check_para();
  1200. }
  1201. return (ret == 0 ? 0 : -1);
  1202. }
  1203. ////////////////////////////////读表地址/////////////////////////////////////////////////
  1204. int8_t get_device_addr(uint8_t *data)
  1205. {
  1206. memcpy(data, Paramx.dev_id, sizeof(Paramx.dev_id));
  1207. return 0;
  1208. }
  1209. ////////////////////////////////设置表地址////////////////////////////////////////////////
  1210. int8_t set_device_addr(uint8_t *data)
  1211. {
  1212. uint8_t flag = 0, ret = 0;
  1213. // 判断数据是否在正常范围内
  1214. ret = set_para_if_nessary(data, &Paramx.dev_id, 6, &flag); // 参数整体保存
  1215. if (flag == 1)
  1216. { // 保存crc校验
  1217. ret |= set_crc_check_para();
  1218. }
  1219. return (ret == 0 ? 0 : -1);
  1220. }
  1221. ////////////////////////////////设置流量参数////////////////////////////////////////////
  1222. // 参数flow_para指针保存8个流量数据,其中index成员是温度等级范围0~2
  1223. ////////////////////////////////////////////////////////////////////////////////////////
  1224. int8_t set_flow_para(FLOW_PARA_DEF *flow_para)
  1225. {
  1226. uint8_t flag = 0, ret = 0;
  1227. // 判断数据是否在正常范围内
  1228. uint8_t ser = CheckTempRangeIndex((float)flow_para->temp);
  1229. if (ser > 2)
  1230. return 2; // 温度等级确定的序号,一共3个温度等级
  1231. ret = set_para_if_nessary(flow_para->cur_c, Paramx.check_spdLvl_c[ser].cur_c, 16, &flag); // 参数整体保存
  1232. if (flag == 1)
  1233. { // 保存crc校验
  1234. ret |= set_crc_check_para();
  1235. }
  1236. return (ret == 0 ? 0 : -1);
  1237. }
  1238. /////////////////////////////读取流量参数///////////////////////////////////////////
  1239. // 参数flow_para指针保存流量信息,读取前应设置成员index值,范围0~2表示温度等级
  1240. ////////////////////////////////////////////////////////////////////////////////////
  1241. int8_t get_flow_para(FLOW_PARA_DEF *flow_para)
  1242. {
  1243. uint8_t i;
  1244. uint8_t ser = CheckTempRangeIndex((float)flow_para->temp);
  1245. for (i = 0; i < 8; i++)
  1246. {
  1247. flow_para->cur_c[i] = Paramx.check_spdLvl_c[ser].cur_c[i];
  1248. }
  1249. return 0;
  1250. }
  1251. /////////////////////////////////设置deltaTC流量参数/////////////////////////////////////////////////////////////
  1252. // 参数deltaTC_para保存相关参数,temp是温度值,整型
  1253. /////////////////////////////////////////////////////////////////////////////////
  1254. int8_t set_deltaTC_flow_para(DELTA_TC_FLOW_PARA_DEF *deltaTC_para)
  1255. {
  1256. uint8_t flag = 0, ret = 0;
  1257. const uint16_t base_data[8] = {1340, 1340, 1340, 1340, 1340, 1340, 1340, 1340};
  1258. // 判断数据是否在正常范围内
  1259. uint8_t ser = CheckTempRangeIndex((float)deltaTC_para->temp);
  1260. if (ser > 2)
  1261. return 2; // 温度等级确定的序号,一共3个温度等级
  1262. ret = set_para_if_nessary(deltaTC_para->cur_c, Paramx.check_spdLvl_c[ser].cur_c, 16, &flag); // 参数整体保存
  1263. ret |= set_para_if_nessary(deltaTC_para->spd_lvl, Paramx.check_spdLvl_c[ser].spd_lvl, 16, &flag); // 参数整体保存
  1264. ret |= set_para_if_nessary((uint16_t *)base_data, Paramx.check_spdLvl_c[ser].base_c, 16, &flag); // 参数整体保存
  1265. if (flag == 1)
  1266. { // 保存crc校验
  1267. ret |= set_crc_check_para();
  1268. }
  1269. return (ret == 0 ? 0 : -1);
  1270. }
  1271. /////////////////////读取参数deltaTC_para参数///////////////////////////////////
  1272. ///////////////参数中temp是温度值,
  1273. // 返回1:成功 2:失败
  1274. //////////////////////////////////////////////////////////////////////////
  1275. int8_t get_deltaTC_flow_para(DELTA_TC_FLOW_PARA_DEF *deltaTC_para)
  1276. {
  1277. uint8_t ser = CheckTempRangeIndex((float)deltaTC_para->temp);
  1278. if (ser > 2)
  1279. return 2; // 超出范围
  1280. uint8_t i;
  1281. for (i = 0; i < 8; i++)
  1282. {
  1283. deltaTC_para->cur_c[i] = Paramx.check_spdLvl_c[ser].cur_c[i];
  1284. deltaTC_para->spd_lvl[i] = Paramx.check_spdLvl_c[ser].spd_lvl[i];
  1285. }
  1286. return 0;
  1287. }
  1288. ////////////////////////设置口径和温度补偿值////////////////////////////////////////////////////////
  1289. // 返回1:成功,2失败
  1290. /////////////////////////////////////////////////////////////////////////////////////////////////////
  1291. int8_t set_diameter_and_quad_cell_data(uint16_t diameter, void *quad_cell_data)
  1292. {
  1293. uint8_t flag = 0, ret = 0;
  1294. if (diameter != 0)
  1295. { // 添加不为零判断
  1296. ret = set_para_if_nessary(&diameter, &Paramx.diameter, sizeof(Paramx.diameter), &flag); // 保存直径数据
  1297. if (flag == 1)
  1298. { // 保存crc校验
  1299. ret |= set_crc_check_para();
  1300. }
  1301. }
  1302. ret |= eeprom_MassWrite(quad_cell_data, QUAD_CELL_START_ADDR, sizeof(Quad_Cell_t) * Quad_Cell_NUM);
  1303. get_quad_cell_data(Quad_Cell_Ary);
  1304. return (ret == 0 ? 0 : -1);
  1305. }
  1306. ////////////////////////读取温度补偿值 在初始化时调用////////////////////////////////////////////////////////
  1307. // 参数data指向要存储的参数 其中包括125个温度补偿数据和一个直径数据
  1308. // 返回1:成功,2失败
  1309. /////////////////////////////////////////////////////////////////////////////////////////////////////
  1310. int8_t get_quad_cell_data(void *quad_cell_data)
  1311. {
  1312. uint8_t ret = 0;
  1313. ret = eeprom_MassRead(quad_cell_data, QUAD_CELL_START_ADDR, sizeof(Quad_Cell_t) * Quad_Cell_NUM);
  1314. return ret;
  1315. }
  1316. ////////////////////// 判断温度补偿数据是否合法////////////////////////////////
  1317. // 合法返回 0, 不合法返回-1
  1318. //////////////////////////////////////////////////////
  1319. #if VER_MODULE == 3
  1320. int8_t Check_quad_cell_data_valid(uint32_t quad_cell_addr)
  1321. {
  1322. // float temp[4];
  1323. Quad_Cell_t temp;
  1324. uint8_t i;
  1325. for (i = 0; i < Quad_Cell_NUM; i++)
  1326. {
  1327. eeprom_MassRead((uint8_t *)&temp, (uint32_t)quad_cell_addr + i * sizeof(Quad_Cell_t), sizeof(Quad_Cell_t));
  1328. if (temp.value < -100 || temp.value > 500000 ||
  1329. temp.coe.m < -100 || temp.coe.m > 500000 ||
  1330. temp.coe.k < -100 || temp.coe.k > 500000)
  1331. return -1;
  1332. }
  1333. return 0;
  1334. }
  1335. #else
  1336. int8_t Check_quad_cell_data_valid(uint32_t quad_cell_addr)
  1337. {
  1338. float temp[4];
  1339. uint8_t i;
  1340. for (i = 0; i < (Quad_Cell_NUM * 5) / 4; i++)
  1341. {
  1342. eeprom_MassRead((uint8_t *)temp, (uint32_t)quad_cell_addr + i * sizeof(float) * 4, sizeof(float) * 4);
  1343. if (temp[0] < -100 || temp[0] > 50000 ||
  1344. temp[1] < -100 || temp[1] > 50000 ||
  1345. temp[2] < -100 || temp[2] > 50000 ||
  1346. temp[3] < -100 || temp[3] > 50000)
  1347. return -1;
  1348. }
  1349. return 0;
  1350. }
  1351. #endif
  1352. ///////////////////////设置自动匹配电平参数///////////////////////////////////////////////
  1353. // 参数指针data 包含比较器和比较器门槛和门槛宽度
  1354. /////////////////////////////////////////////////////////////////////////////////////
  1355. int8_t set_auto_match_level_para(AUTO_MATCH_LEVEL_PARA_DEF *data)
  1356. {
  1357. uint8_t flag = 0, ret = 0;
  1358. ret = set_para_if_nessary(data, &Paramx.cmp_thers, 30, &flag); // 保存直径数据
  1359. if (flag == 1)
  1360. { // 保存crc校验
  1361. ret |= set_crc_check_para();
  1362. }
  1363. return (ret == 0 ? 0 : -1);
  1364. }
  1365. /////////////保存skew参数/////////////////////
  1366. /////////////////////////////////
  1367. int8_t set_skew_para(SKEW_PARA_DEF *skew_para)
  1368. {
  1369. uint8_t flag = 0, ret = 0;
  1370. ret = set_para_if_nessary(skew_para, &Paramx.path_skew, 16, &flag); // 保存直径数据
  1371. if (flag == 1)
  1372. { // 保存crc校验
  1373. ret |= set_crc_check_para();
  1374. }
  1375. return (ret == 0 ? 0 : -1);
  1376. }
  1377. ////////////////////////////读取自动匹配电平参数/////////////////////////////////////////////
  1378. // 参数指针保存比较器和比较器门槛宽度数据
  1379. // 返回1读取成功
  1380. ////////////////////////////////////////////////////////////////////
  1381. int8_t get_auto_match_level_para(AUTO_MATCH_LEVEL_PARA_DEF *data)
  1382. {
  1383. memcpy((uint8_t *)data, Paramx.cmp_thers, sizeof(AUTO_MATCH_LEVEL_PARA_DEF));
  1384. return 0;
  1385. }
  1386. int8_t set_nbqr_para(NBQR_PARA_DEF *nbqr_para)
  1387. {
  1388. uint8_t flag = 0, ret = 0;
  1389. ret = set_para_if_nessary(nbqr_para, &Paramx.n, sizeof(NBQR_PARA_DEF), &flag); // 保存直径数据
  1390. if (flag == 1)
  1391. { // 保存crc校验
  1392. ret |= set_crc_check_para();
  1393. }
  1394. return (ret == 0 ? 0 : -1);
  1395. }
  1396. int8_t get_bnqr_para(NBQR_PARA_DEF *nbqr_para)
  1397. {
  1398. nbqr_para->n = Paramx.n;
  1399. nbqr_para->b = Paramx.b;
  1400. nbqr_para->q = Paramx.q;
  1401. nbqr_para->r = Paramx.r;
  1402. return 0;
  1403. }
  1404. uint16_t pack_crc_check(uint16_t prev_data, uint8_t *data, uint16_t len)
  1405. {
  1406. uint16_t i, crc;
  1407. uint8_t index;
  1408. for (i = 0; i < len; i++)
  1409. {
  1410. index = (uint8_t)(data[i] ^ (prev_data >> 8));
  1411. crc = (uint16_t)(ccitt_table[index] ^ (prev_data << 8));
  1412. prev_data = crc;
  1413. }
  1414. return crc;
  1415. }
  1416. ///////////////////1秒一次运行的一些零星任务//////////////////////
  1417. uint8_t rtc_1s_flag;
  1418. void run_clk_task_handler(void)
  1419. {
  1420. #ifdef LED_DEF
  1421. rtc_run_t *rr;
  1422. get_rtc_run(&rr); // 获取当前时间
  1423. SetLed(LED1, rr->second % 2); // 1秒闪烁
  1424. #endif
  1425. check_rewrite_para(); // 相关参数判断,不合法的重写eeprom
  1426. rtc_1s_flag = 1;
  1427. }
  1428. //////////////////////////////////////
  1429. ///////////检查是否是新app第一次运行,如果是,则更新flash中的运行信息//////////////////
  1430. // 参数:无
  1431. // 返回:无
  1432. ////////////////////////////////////////////////////////////////////////////////////
  1433. void update_run_app_info(void)
  1434. {
  1435. if (StartUp != 5)
  1436. return;
  1437. PatchInfo = *(PATCH_INFO_DEF *)DIFF_UPDATE_INFO_START; // 整个结构体一起拷贝
  1438. #ifdef APP_DEBUG_PRINT
  1439. if (PatchInfo.update_status == 3)
  1440. {
  1441. LOG("new app first run\r\n");
  1442. }
  1443. else
  1444. {
  1445. LOG("old app run run\r\n");
  1446. }
  1447. LOG("cur ver = V%d.%d.%d.%d\r\n", VER_TYPE, VER_OPERATOR, VER_MODULE, VER_FIRMWARE);
  1448. #endif
  1449. if (PatchInfo.update_status != 0)
  1450. {
  1451. memset(&PatchInfo, 0, sizeof(PATCH_INFO_DEF));
  1452. write_flash_memory((uint8_t *)&PatchInfo, DIFF_UPDATE_INFO_START, sizeof(PATCH_INFO_DEF));
  1453. }
  1454. #ifndef DEBUG_RESET_LOG_NOT_SEND
  1455. write_alarm(LOG_MCU_RESET, 1, 5555); // wxl2026-5-8 非调试状态写入单片机复位事件日志
  1456. #endif
  1457. }
  1458. void write_flash_memory(uint8_t *data, uint32_t addr, uint32_t len)
  1459. {
  1460. McuFlash_WP_t WP;
  1461. feed_dog();
  1462. rt_enter_critical();
  1463. McuFlash_Unlock();
  1464. McuFlash_OpenWP(addr, &WP);
  1465. McuFlash_Buf2WP(data, len, &WP);
  1466. McuFlash_CloseWP(&WP);
  1467. McuFlash_Lock();
  1468. rt_exit_critical();
  1469. }
  1470. void erase_flash_memory(uint32_t addr, uint32_t size)
  1471. {
  1472. feed_dog();
  1473. rt_enter_critical();
  1474. McuFlash_Unlock();
  1475. McuFlash_EraseSegment(addr, size);
  1476. McuFlash_Lock();
  1477. rt_exit_critical();
  1478. }
  1479. const uint16_t ccitt_table[256] = {
  1480. 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
  1481. 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
  1482. 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
  1483. 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
  1484. 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
  1485. 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
  1486. 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
  1487. 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
  1488. 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
  1489. 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
  1490. 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
  1491. 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
  1492. 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
  1493. 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
  1494. 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
  1495. 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
  1496. 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
  1497. 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
  1498. 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
  1499. 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
  1500. 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
  1501. 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
  1502. 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
  1503. 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
  1504. 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
  1505. 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
  1506. 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
  1507. 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
  1508. 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
  1509. 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
  1510. 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
  1511. 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0};