搜索
查看: 1166|回复: 5

[已解决] 串口的校验位数据怎么算到的

[复制链接]

该用户从未签到

14

主题

76

帖子

9

蝴蝶豆

金牌会员

最后登录
2023-12-5
发表于 2020-7-30 10:30:00 | 显示全部楼层 |阅读模式
/S00/1/ 0044 000000000000 0000 40 003C 3D 5C 21 1B 0100001F FFFF15 00000000 002D 0000 00 2C 2048
/S00/1/ 0044 000000000000 0000 40 003C 3D 5C 21 1B 0100001F FFFF14 00000000 002D 0000 00 2C 1F48

/S00/1/ 0044 000000000000 0000 40 003C 3C 5C 21 1B 0100011F FFFF13 000002F8 0001 0000 00 2C 155C
以上面数据为例,算一下末尾的 2048 1F48  155C 为校验位,均为十六进制表示
在u8 USART1_Tranfer(void)中的checksum表示的是校验

  1. /*十六进制转成ASCII码*/
  2. u8 HexToAscill(u16 *hex, u8 *ascillbuf, u8 buflenth)
  3. {
  4.         u16 phex=*hex;
  5.         u8 i=1;
  6.         for(i=0;i<buflenth;i++)
  7.         {
  8.                  ascillbuf[i] = 0;
  9.         }
  10.         i = 1;
  11.         if(&ascillbuf[buflenth-1]==NULL||phex==NULL)
  12.         {
  13.                 for(i=0;i<buflenth;i++)
  14.                 {
  15.                         if(ascillbuf[i]==0)
  16.                         {
  17.                                 ascillbuf[i] = 0 + '0';
  18.                         }
  19.                 }
  20.                 return 0;
  21.         }

  22.         while(phex!=0)
  23.         {
  24.                 if((phex)%16<=9)
  25.                 {
  26.                         ascillbuf[buflenth-i] = (phex)%16 + '0';
  27.                 }
  28.                 else
  29.                 {
  30.                         ascillbuf[buflenth-i] = (phex)%16 + '7';//将10进制的phex转换成16进制取其个位+'7'ASSCII
  31.                 }
  32.                
  33.                 phex = (phex)/16;
  34.                
  35.                 i++;
  36.                
  37.                 if(buflenth<i)
  38.                 {
  39.                         break;
  40.                 }
  41.         }
  42.         for(i=0;i<buflenth;i++)
  43.         {
  44.                 if(ascillbuf[i]==0)
  45.                 {
  46.                         ascillbuf[i] = 0 + '0';
  47.                 }
  48.         }
  49.         return 1;
  50. }



  51. typedef union{
  52.         u8 usart1_data[75];
  53.         struct{
  54.                 u8  head[7];// /S00/1/
  55.                 u8  data_lentgh[4];/*from time data to checksum data*/
  56.                 u8  datetime[12];
  57.                 u8  random_number[4];
  58.                 u8  fault_code[2];
  59.                 u8  tds1_value[4];/*原水*/
  60.                 u8  tds2_value[2];/*净水*/
  61.                 u8  ntc0_temperature[2];/*不加热*/
  62.                 u8  ntc1_temperature[2];/*热水*/
  63.                 u8  ntc2_temperature[2];/*保温*/
  64.                 u8  fixed_state[8];//固定状态
  65.                 u8  percentage_of_filter_core[6];/*1 2 3*/
  66.                 u8  total_running_time_of_water_pump[8];/*单位:秒*/               
  67. ///                u8  PressurePumpCurrent[4];//增压泵电流,单位:mA               
  68.                 u8  real_time_water_output[4];/*单位:毫升*/
  69.                 u8  the_rest_of_the_day_bucket[4];
  70.                 u8  fixtype[2];        
  71.                 u8  end0[2];
  72.         }s;
  73. }__attribute__ ((aligned (1)))USART1_TRANSFER0_DATA_UNION;
  74. extern volatile  USART1_TRANSFER0_DATA_UNION     Usart1_transf_data;

  75. typedef union{
  76.         u8 all[4];
  77.         struct{
  78.                 u8 checksum[4];
  79.                 u8 end[2];/*\r\n*/
  80.         }s;
  81. }__attribute__ ((aligned (1)))USART1_DATA_END;
  82. extern volatile  USART1_DATA_END                 Usart1_data_end;

  83. u8 USART1_Tranfer(void)
  84. {
  85.         char i=0,j=0,z=0;
  86.     u8 datanum = 0;
  87.     u8 head3 = 0;
  88.     u8 head4 = 0;
  89.     u16 checksum = 0;
  90.         u16 *p=NULL;
  91.         u8 req_dat_num=0,req_dat[30];
  92.         u8 transdata[164]={0};
  93.         static u16 ticker=0;

  94.    
  95.         
  96.         if(Transf_fifo[BEGIN]!=0)
  97.         {
  98.                

  99.                 System_Data.usart1_tran_data_len = sizeof(USART1_TRANSFER0_DATA_UNION)+req_dat_num-7;
  100.                 //System_Data.usart1_tran_data_len = 77;//对应协议下发数据的指令字符串长度,除去Check Sum
  101.                 Usart1_transf_data.s.head[0] = '/';
  102.                 Usart1_transf_data.s.head[1] = 'S';
  103.                 Usart1_transf_data.s.head[2] = head3;
  104.                 Usart1_transf_data.s.head[3] = head4;
  105.                 Usart1_transf_data.s.head[4] = '/';
  106.                 Usart1_transf_data.s.head[5] = '1';
  107.                 Usart1_transf_data.s.head[6] = '/';
  108.                 Usart1_transf_data.s.end0[0] = '2';
  109.                 Usart1_transf_data.s.end0[1] = 'C';

  110.                 Usart1_transf_data.s.ntc0_temperature[0] = '2';
  111.                 Usart1_transf_data.s.ntc0_temperature[1] = '2';

  112.                

  113.                 for(i=0;i<sizeof(Usart1_transf_data.s.datetime);i++)
  114.                 {
  115.                         if(Usart1_transf_data.s.datetime[i]==0)
  116.                         {
  117.                                 Usart1_transf_data.s.datetime[i] += '0';//时间码
  118.                         }
  119.                 }
  120.                 for(i=0;i<sizeof(Usart1_transf_data.s.random_number);i++)//回应随机数
  121.                 {
  122.                         if(Usart1_transf_data.s.random_number[i]==0)
  123.                         {
  124.                                 Usart1_transf_data.s.random_number[i] += '0';
  125.                         }
  126.                 }               
  127.                 for(i=0;i<sizeof(Usart1_transf_data.s.fixed_state);i++)//固定状态
  128.                 {
  129.                         Usart1_transf_data.s.fixed_state[i] = System_Data.fixed_state[i];//固定状态的首字符为0
  130.                 }
  131.                 for(i=0;i<sizeof(Usart1_transf_data.s.fixed_state);i++)//fixed_state[0] 为预留
  132.                 {
  133.                         if(Usart1_transf_data.s.fixed_state[i]==0)
  134.                         {
  135.                                 Usart1_transf_data.s.fixed_state[i] += '0';
  136.                         }
  137.                 }
  138.                 for(i=0;i<sizeof(Usart1_transf_data.s.percentage_of_filter_core);i++)
  139.                 {
  140.                         Usart1_transf_data.s.percentage_of_filter_core[i] = 'F';//表示滤芯的首位值
  141.                 }
  142.                 if(Save_Data.s.machine_type==0||Save_Data.s.machine_type>9)
  143.                 {
  144.                          Usart1_transf_data.s.percentage_of_filter_core[4] = '0';//表示的是滤芯的第5位,为什么不是'1'呢?
  145.                 }
  146.                 else
  147.                 {
  148.                         Usart1_transf_data.s.percentage_of_filter_core[4] = Save_Data.s.machine_type + '0'; //不太明白
  149.                 }
  150.                
  151.                 if(MachineWorkStatus==10)
  152.                 {
  153.                           Usart1_transf_data.s.percentage_of_filter_core[5] = 'A';//代表第六个元素的ASCII值
  154.                 }
  155.                 else
  156.                 {
  157.                          Usart1_transf_data.s.percentage_of_filter_core[5] = MachineWorkStatus + '0';//
  158.                 }
  159.                
  160.                 HexToAscill((u16*)&(System_Data.pressure_pump_all_run_time), (u8*)Usart1_transf_data.s.total_running_time_of_water_pump, \
  161.                                  sizeof(Usart1_transf_data.s.total_running_time_of_water_pump));
  162.                
  163.                 //增加串口协议,用4位十六进制数表示增压泵电流,单位:mA
  164. ///                HexToAscill((u16*)&(System_Data.press_pump_current), (u8*)Usart1_transf_data.s.PressurePumpCurrent, \
  165. ///                                 sizeof(Usart1_transf_data.s.PressurePumpCurrent));
  166.                
  167.         
  168.                 HexToAscill((u16*)&(System_Data.real_time_water_output), (u8*)Usart1_transf_data.s.real_time_water_output, \
  169.                                  sizeof(Usart1_transf_data.s.real_time_water_output));

  170.                 HexToAscill((u16*)&(System_Data.the_rest_of_the_day_bucket), (u8*)Usart1_transf_data.s.the_rest_of_the_day_bucket, \
  171.                                  sizeof(Usart1_transf_data.s.the_rest_of_the_day_bucket));

  172.                 HexToAscill((u16*)&(System_Data.fixtype), (u8*)Usart1_transf_data.s.fixtype, \
  173.                                  sizeof(Usart1_transf_data.s.fixtype));
  174.                
  175.                 /*头部*/
  176.                 for(i=0;i<sizeof(USART1_TRANSFER0_DATA_UNION);i++)
  177.                 {
  178.                         transdata[i] = Usart1_transf_data.usart1_data[i];
  179.                 }
  180.                 /*中部 添加请求上位机的信息数据*/
  181.                 for(i=sizeof(USART1_TRANSFER0_DATA_UNION);i<sizeof(USART1_TRANSFER0_DATA_UNION)+req_dat_num;i++)
  182.                 {
  183.                         transdata[i] = req_dat[i-sizeof(USART1_TRANSFER0_DATA_UNION)];
  184.                 }
  185.                 p = (u16*)&transdata[7];
  186.                 for(i=0;i<(req_dat_num+sizeof(USART1_TRANSFER0_DATA_UNION)-7)/2;i++)
  187.                 {
  188.                         checksum += p[i];
  189.             // if(p[i]>64) checksum -= 55;
  190.             // else
  191.             checksum -= 48;
  192.             //if(i == 10) temp = checksum;
  193.                 }
  194.         temp = p[12]-48;//
  195.                 HexToAscill((u16*)&(checksum), (u8*)Usart1_data_end.s.checksum, \
  196.                                  sizeof(Usart1_data_end.s.checksum));
  197.                
  198.                 Usart1_data_end.s.end[0] = '\r';
  199.                 Usart1_data_end.s.end[1] = '\n';
  200.                  /*尾部*/
  201.                 for(i=sizeof(USART1_TRANSFER0_DATA_UNION)+req_dat_num;i<req_dat_num+sizeof(USART1_TRANSFER0_DATA_UNION)+sizeof(USART1_DATA_END);i++)
  202.                 {
  203.                         transdata[i] = Usart1_data_end.all[i-sizeof(USART1_TRANSFER0_DATA_UNION)-req_dat_num];
  204.                 }
  205.                
  206.                 datanum = sizeof(USART1_TRANSFER0_DATA_UNION)+sizeof(USART1_DATA_END)+req_dat_num;
  207.                 for(i=0;i<datanum;i++)
  208.                 {
  209.                         USART_SendData(USART1,transdata[i]);
  210.                         
  211.                         while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET){}
  212.                 }
  213.                 for(i=0;i<FIFO_LENGTH-1;i++)
  214.                 {
  215.                         Transf_fifo[i] = Transf_fifo[i+1];
  216.                 }
  217.                 Transf_fifo[FIFO_LENGTH-1] = 0;
  218.         }


  219.         return 0;
  220. }
复制代码
有知道最上面的那3行最末尾的4位校验和是怎么算的吗?

回复

使用道具 举报

该用户从未签到

0

主题

587

帖子

82

蝴蝶豆

金牌会员

最后登录
2024-1-2
发表于 2020-8-3 18:02:49 | 显示全部楼层
你都有源码了直接在线仿真一下就明白了,先弄懂这个函数HexToAscill,然后再看199到208行的代码
回复 支持 反对

使用道具 举报

该用户从未签到

14

主题

736

帖子

256

蝴蝶豆

论坛元老

最后登录
2021-4-20
发表于 2020-8-4 09:03:03 | 显示全部楼层
通常校验说的有两种  一种是串口本身的校验  属于硬件校验  就是奇偶校验  另一种就是你用的这种  协议中自定义的
奇偶校验是不需要考虑的  自定义的校验需要程序实现的  
具体实现的方式有很多  
你这种属于和校验  就是把所有的数据都加一起  得出一个16位数据  存在最后的字节中  但你这个每两个和加完以后又减去一个固定的值  这就是防止破解的  如果单纯的和校验是很容易破解的  但是减去一个固定值破解起来就困难了许多  减去的这个固定值是在接收两端都设计好  就能增加破解难度
其他的破解还有CRC  或者利用公式  等等  都是为了数据的安全和可靠性
回复 支持 反对

使用道具 举报

该用户从未签到

14

主题

76

帖子

9

蝴蝶豆

金牌会员

最后登录
2023-12-5
 楼主| 发表于 2020-8-4 09:51:35 | 显示全部楼层
陌路夕颜 发表于 2020-8-3 18:02
你都有源码了直接在线仿真一下就明白了,先弄懂这个函数HexToAscill,然后再看199到208行的代码 ...

是的,已经算到了
  1. p = (u16*)&transdata[7];
  2.                 for(i=0;i<(req_dat_num+sizeof(USART1_TRANSFER0_DATA_UNION)-7)/2;i++)//字符和十六进制是2:1的关系,一个字符/一个ASCII 1个字节,可表示2位十六进制数
  3.                 {
  4.                         checksum += p[i];
  5.             // if(p[i]>64) checksum -= 55;
  6.             // else
  7.             checksum -= 48;
  8.             //if(i == 10) temp = checksum;
  9.                 }
复制代码


u8类型用(u16*)的指针,一次性取16bit   00 46 00 ...  然后HexToAscii是先转后一个字节的ASCII,再转前一个字节的ASCII (0x3030-30H)+(0x3634-30H)+...+[0x(n+(n-1))-30H] (n=48)  总共是48个ASCII码参与校验
回复 支持 反对

使用道具 举报

该用户从未签到

14

主题

76

帖子

9

蝴蝶豆

金牌会员

最后登录
2023-12-5
 楼主| 发表于 2020-8-4 10:42:34 | 显示全部楼层
mylovemcu 发表于 2020-8-4 09:03
通常校验说的有两种  一种是串口本身的校验  属于硬件校验  就是奇偶校验  另一种就是你用的这种  协议中自 ...

正解
回复 支持 反对

使用道具 举报

该用户从未签到

3

主题

1306

帖子

929

蝴蝶豆

版主

最后登录
2021-3-31
发表于 2020-8-12 10:44:51 | 显示全部楼层
mylovemcu 发表于 2020-8-4 09:03
通常校验说的有两种  一种是串口本身的校验  属于硬件校验  就是奇偶校验  另一种就是你用的这种  协议中自 ...

全面,准确,正解
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条

Archiver|手机版|小黑屋|论坛-意法半导体STM32/STM8技术社区

GMT+8, 2024-4-30 00:11 , Processed in 1.167997 second(s), 34 queries .

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.

快速回复 返回顶部 返回列表