你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

串口的校验位数据怎么算到的

[复制链接]
踮起脚摘苹果 提问时间:2020-7-30 10:30 /
/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位校验和是怎么算的吗?

收藏 评论5 发布时间:2020-7-30 10:30

举报

5个回答
陌路夕颜 回答时间:2020-8-3 18:02:49
你都有源码了直接在线仿真一下就明白了,先弄懂这个函数HexToAscill,然后再看199到208行的代码
mylovemcu 回答时间:2020-8-4 09:03:03
通常校验说的有两种  一种是串口本身的校验  属于硬件校验  就是奇偶校验  另一种就是你用的这种  协议中自定义的
奇偶校验是不需要考虑的  自定义的校验需要程序实现的  
具体实现的方式有很多  
你这种属于和校验  就是把所有的数据都加一起  得出一个16位数据  存在最后的字节中  但你这个每两个和加完以后又减去一个固定的值  这就是防止破解的  如果单纯的和校验是很容易破解的  但是减去一个固定值破解起来就困难了许多  减去的这个固定值是在接收两端都设计好  就能增加破解难度
其他的破解还有CRC  或者利用公式  等等  都是为了数据的安全和可靠性
踮起脚摘苹果 回答时间: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码参与校验
踮起脚摘苹果 回答时间:2020-8-4 10:42:34
mylovemcu 发表于 2020-8-4 09:03
通常校验说的有两种  一种是串口本身的校验  属于硬件校验  就是奇偶校验  另一种就是你用的这种  协议中自 ...

正解
butterflyspring 回答时间:2020-8-12 10:44:51
mylovemcu 发表于 2020-8-4 09:03
通常校验说的有两种  一种是串口本身的校验  属于硬件校验  就是奇偶校验  另一种就是你用的这种  协议中自 ...

全面,准确,正解

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版