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

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

[复制链接]
踮起脚摘苹果 提问时间: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管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版