NSString+WithCRCModbus.m 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. //
  2. // NSString+WithCRCModbus.m
  3. // iOS-CRC
  4. //
  5. // Created by leon on 2017/3/7.
  6. //
  7. //
  8. /**
  9. * CRC在线检验网址:https://www.lammertbies.nl/comm/info/crc-calculation.html
  10. * http://stackoverflow.com/questions/33794878/when-converting-nsdata-to-unsigned-char-i-get-the-wrong-result
  11. * http://stackoverflow.com/questions/10214990/how-to-convert-nsdata-to-char-array-containing-hexa-values
  12. * http://stackoverflow.com/questions/12971117/how-to-convert-nsdata-to-char
  13. */
  14. #import "NSString+WithCRCModbus.h"
  15. @implementation NSString (WithCRCModbus)
  16. - (NSString*)withCrc16CCITT{
  17. if(self.length%2!=0){
  18. return nil;
  19. }
  20. return [self stringByAppendingString:[self getCrcString2]];
  21. }
  22. uint16_t xmodem_crc16_ccitt_2(const uint8_t *pbBuf, uint32_t dwLen)
  23. {
  24. uint16_t wCRC = 0;
  25. uint16_t bCycle;
  26. while (dwLen-- > 0)
  27. {
  28. wCRC ^= (unsigned short) *pbBuf++ << 8;
  29. for (bCycle = 0; bCycle < 8; bCycle++)
  30. {
  31. if (wCRC & 0x8000)
  32. {
  33. wCRC = wCRC << 1 ^ 0x1021;
  34. }
  35. else
  36. {
  37. wCRC <<= 1;
  38. }
  39. }
  40. }
  41. return wCRC;
  42. }
  43. - (NSString*)getCrcString2{
  44. NSData *nsdataString = [self toNSData];
  45. unsigned char *chars = (unsigned char *)[nsdataString bytes];
  46. // unsigned short result = [self CRC16:chars length:nsdataString.length];
  47. unsigned short result = xmodem_crc16_ccitt_2(chars, nsdataString.length);
  48. //下面这种方式方可,直接用dataWithBytes传short的地址可能导致字节反序
  49. // 参考:http://www.jianshu.com/p/0d8cf741584a
  50. Byte b1=result & 0xff;
  51. Byte b2=(result>>8) & 0xff;
  52. Byte byte[] = {b1, b2};
  53. NSData *data = [NSData dataWithBytes:byte length:sizeof(byte)];
  54. return [self toNSString:data];
  55. }
  56. - (NSString*)withCrc16Modbus{
  57. if(self.length%2!=0){
  58. return nil;
  59. }
  60. return [self stringByAppendingString:[self getCrcString]];
  61. }
  62. - (NSString*)getCrcString{
  63. NSData *nsdataString = [self toNSData];
  64. unsigned char *chars = (unsigned char *)[nsdataString bytes];
  65. unsigned short result = [self CRC16:chars length:nsdataString.length];
  66. //下面这种方式方可,直接用dataWithBytes传short的地址可能导致字节反序
  67. // 参考:http://www.jianshu.com/p/0d8cf741584a
  68. Byte b1=result & 0xff;
  69. Byte b2=(result>>8) & 0xff;
  70. Byte byte[] = {b1, b2};
  71. NSData *data = [NSData dataWithBytes:byte length:sizeof(byte)];
  72. return [self toNSString:data];
  73. }
  74. // http://liumh.com/2015/06/06/convert-between-nsdata-and-hexstr/
  75. - (NSData *)toNSData{
  76. if (!self || [self length] == 0) {
  77. return nil;
  78. }
  79. NSMutableData *hexData = [[NSMutableData alloc] initWithCapacity:8];
  80. NSRange range;
  81. if ([self length] % 2 == 0) {
  82. range = NSMakeRange(0, 2);
  83. } else {
  84. range = NSMakeRange(0, 1);
  85. }
  86. for (NSInteger i = range.location; i < [self length]; i += 2) {
  87. unsigned int anInt;
  88. NSString *hexCharStr = [self substringWithRange:range];
  89. NSScanner *scanner = [[NSScanner alloc] initWithString:hexCharStr];
  90. [scanner scanHexInt:&anInt];
  91. NSData *entity = [[NSData alloc] initWithBytes:&anInt length:1];
  92. [hexData appendData:entity];
  93. range.location += range.length;
  94. range.length = 2;
  95. }
  96. return hexData;
  97. }
  98. // http://liumh.com/2015/06/06/convert-between-nsdata-and-hexstr/
  99. - (NSString *)toNSString:(NSData*)data{
  100. if (!self || [self length] == 0) {
  101. return @"";
  102. }
  103. NSMutableString *string = [[NSMutableString alloc] initWithCapacity:[self length]];
  104. [data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) {
  105. unsigned char *dataBytes = (unsigned char*)bytes;
  106. for (NSInteger i = 0; i < byteRange.length; i++) {
  107. NSString *hexStr = [NSString stringWithFormat:@"%x", (dataBytes[i]) & 0xff];
  108. if ([hexStr length] == 2) {
  109. [string appendString:hexStr];
  110. } else {
  111. [string appendFormat:@"0%@", hexStr];
  112. }
  113. }
  114. }];
  115. return string;
  116. }
  117. const char chCRCHTalbe[]={
  118. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  119. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  120. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  121. 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  122. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  123. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  124. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  125. 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  126. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  127. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  128. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  129. 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  130. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  131. 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  132. 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  133. 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  134. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  135. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  136. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  137. 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  138. 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  139. 0x00, 0xC1, 0x81, 0x40
  140. };
  141. const char chCRCLTalbe[] =
  142. {
  143. 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
  144. 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
  145. 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
  146. 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
  147. 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
  148. 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
  149. 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
  150. 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
  151. 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
  152. 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
  153. 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
  154. 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
  155. 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,
  156. 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
  157. 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
  158. 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
  159. 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
  160. 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
  161. 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
  162. 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
  163. 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
  164. 0x41, 0x81, 0x80, 0x40
  165. };
  166. /*
  167. *decription: 计算CRC校验码
  168. *input: 无符号进制字符串数组
  169. *output: CRC检验码
  170. */
  171. -(unsigned short)CRC16:(unsigned char *)puchMsg length:(unsigned int) usDataLen
  172. {
  173. unsigned char chCRCHi = 0xFF; // 高CRC字节初始化
  174. unsigned char chCRCLo = 0xFF; // 低CRC字节初始化
  175. unsigned short wIndex;
  176. while(usDataLen--)
  177. {
  178. wIndex = chCRCLo ^ *puchMsg++ ;
  179. chCRCLo = chCRCHi ^ chCRCHTalbe[wIndex];
  180. chCRCHi = chCRCLTalbe[wIndex] ;
  181. }
  182. return ((chCRCHi << 8) | chCRCLo) ;
  183. }
  184. @end