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

【经验分享】STM32 CRC32 ( Delphi )

[复制链接]
STMCU小助手 发布时间:2022-1-23 16:06
  1. /*

  2. The CRC calculation unit mainly consists of a single 32-bit data register, which:
  3. is used as an input register to enter new data in the CRC calculator
  4. (when writing into the register) holds the result of the previous CRC calculation
  5. (when reading the register)

  6. Each write operation into the data register creates a combination of
  7. the previous CRC value and the new one
  8. (CRC computation is done on the whole 32-bit data word, and not byte per byte).

  9. The CPU is stalled during the computation, thus allowing back-to-back write accesses or
  10. consecutive write and read accesses, without having to insert software wait cycles.
  11. The CRC calculator can be reset to FFFF FFFFh with the RESET control bit in the CRC_CR register.
  12. This operation does not affect the contents of the CRC_IDR register
  13. POLY_USED_IN_STM32     0x04C11DB7
  14. #define CRC_INITIALVALUE     0xFFFFFFFF
  15. 1. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_CRC, ENABLE); /* Enable CRC clock */
  16. 2.
  17. // 00 01 02 03          --> 0x03020100
  18. // 00 01 02 03 04       --> 0x03020100, 0x04000000
  19. // 00 01 02 03 04 05    --> 0x03020100, 0x05040000
  20. // 00 01 02 03 04 05 06 --> 0x03020100, 0x06050400
  21. //
  22. uint32_t stm32_hw_crc32(uint32_t crc32, uint8_t pBuffer[], uint32_t NumOfByte)
  23. {
  24.   uint32_t last_data;
  25.   uint32_t NumOfDWord = NumOfByte>>2;
  26.   uint32_t NumOfTailByte =  NumOfByte & 3 ;

  27.   CRC_ResetDR();
  28.   crc32 = CRC_CalcBlockCRC( (uint32_t  *)pBuffer, NumOfDWord );

  29.   switch ( NumOfTailByte )
  30.   {
  31.     case 0:
  32.       return crc32;
  33.     case 1:
  34.       last_data = pBuffer[NumOfByte-1] << 24;
  35.       break;
  36.     case 2:
  37.       last_data = *( (uint16_t *)(&pBuffer[NumOfByte-2]) );
  38.       last_data <<= 16;
  39.       break;
  40.     case 3:
  41.       last_data = *( (uint16_t *)(&pBuffer[NumOfByte-3]) );
  42.       last_data <<= 8;
  43.       last_data += pBuffer[NumOfByte-1]<<24;
  44.       break;
  45.   }
  46.   return CRC_CalcCRC( last_data );
  47. }



  48. uint32_t stm32_sw_crc32_by_bit(uint32_t crc32, uint8_t pBuffer[], uint32_t NumOfByte)
  49. {
  50.   uint32_t last_data;
  51.   uint32_t NumOfDWord = NumOfByte>>2;
  52.   uint32_t NumOfTailByte =  NumOfByte & 3 ;
  53.   
  54.   while(NumOfDWord--)
  55.   {
  56.     crc32 = crc32 ^ *((unsigned long *)pBuffer);
  57.     pBuffer += 4;

  58.     for(int i=0; i<32; i++)
  59.     {
  60.       if (crc32 & 0x80000000)
  61.         crc32 = (crc32 << 1) ^ POLY_USED_IN_STM32;
  62.       else
  63.         crc32 = (crc32 << 1);
  64.     }
  65.   }
  66.   
  67.   switch ( NumOfTailByte )
  68.   {
  69.     case 0:
  70.       return crc32;     
  71.     case 1:
  72.       last_data = pBuffer[0] << 24;
  73.       break;
  74.     case 2:
  75.       last_data = *( (uint16_t *)(&pBuffer[0]) );
  76.       last_data <<= 16;
  77.       
  78.       break;
  79.     case 3:
  80.       last_data = *( (uint16_t *)(&pBuffer[0]) );
  81.       last_data <<= 8;
  82.       last_data += pBuffer[2]<<24;
  83.       break;
  84.   }
  85.   crc32 = stm32_sw_crc32_by_bit( crc32, (uint8_t *)&last_data, 4);
  86.   return crc32;
  87. }


  88. // Nibble lookup table for 0x04C11DB7 polynomial
  89. const unsigned long sw_crc32_by_nibble_table[16] = {
  90.   0x00000000,0x04C11DB7,0x09823B6E,0x0D4326D9,
  91.   0x130476DC,0x17C56B6B,0x1A864DB2,0x1E475005,
  92.   0x2608EDB8,0x22C9F00F,0x2F8AD6D6,0x2B4BCB61,
  93.   0x350C9B64,0x31CD86D3,0x3C8EA00A,0x384FBDBD
  94. };

  95. uint32_t stm32_sw_crc32_by_nibble(uint32_t crc32, uint8_t pBuffer[], uint32_t NumOfByte)  
  96. {
  97.   uint32_t last_data;
  98.   uint32_t NumOfDWord = NumOfByte>>2;
  99.   uint32_t NumOfTailByte =  NumOfByte & 3 ;
  100.   
  101.   while(NumOfDWord--)
  102.   {
  103.     crc32 = crc32 ^ *((unsigned long *)pBuffer);
  104.     pBuffer += 4;
  105.     crc32 = (crc32 << 4) ^ sw_crc32_by_nibble_table[crc32 >> 28];
  106.     crc32 = (crc32 << 4) ^ sw_crc32_by_nibble_table[crc32 >> 28];
  107.     crc32 = (crc32 << 4) ^ sw_crc32_by_nibble_table[crc32 >> 28];
  108.     crc32 = (crc32 << 4) ^ sw_crc32_by_nibble_table[crc32 >> 28];
  109.     crc32 = (crc32 << 4) ^ sw_crc32_by_nibble_table[crc32 >> 28];
  110.     crc32 = (crc32 << 4) ^ sw_crc32_by_nibble_table[crc32 >> 28];
  111.     crc32 = (crc32 << 4) ^ sw_crc32_by_nibble_table[crc32 >> 28];
  112.     crc32 = (crc32 << 4) ^ sw_crc32_by_nibble_table[crc32 >> 28];
  113.   }
  114.   
  115.   switch ( NumOfTailByte )
  116.   {
  117.     case 0:
  118.       return crc32;     
  119.     case 1:
  120.       last_data = pBuffer[0] << 24;
  121.       break;
  122.     case 2:
  123.       last_data = *( (uint16_t *)(&pBuffer[0]) );
  124.       last_data <<= 16;
  125.       
  126.       break;
  127.     case 3:
  128.       last_data = *( (uint16_t *)(&pBuffer[0]) );
  129.       last_data <<= 8;
  130.       last_data += pBuffer[2]<<24;
  131.       break;
  132.   }
  133.   crc32 = stm32_sw_crc32_by_nibble( crc32, (uint8_t *)&last_data, 4);
  134.   return crc32;
  135. }

  136. unsigned long sw_crc32_by_byte_table[256] =
  137. {
  138.   0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, // 0..3
  139.   0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, // 4..7
  140.   0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, // 8..B
  141.   0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, // C..F
  142.   
  143.   0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
  144.   0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
  145.   0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
  146.   0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
  147.   0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
  148.   0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
  149.   0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
  150.   0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
  151.   0xd4326d90, 0xd0f37027, 0**b056fe, 0xd9714b49,
  152.   0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
  153.   0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
  154.   0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
  155.   0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
  156.   0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
  157.   0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
  158.   0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
  159.   0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
  160.   0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
  161.   0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
  162.   0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
  163.   0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
  164.   0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
  165.   0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
  166.   0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
  167.   0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
  168.   0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
  169.   0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
  170.   0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
  171.   0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
  172.   0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
  173.   0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
  174.   0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
  175.   0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
  176.   0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
  177.   0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
  178.   0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
  179.   0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
  180.   0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
  181.   0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
  182.   0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
  183.   0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
  184.   0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
  185.   0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
  186.   0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
  187.   0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
  188.   0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
  189.   0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
  190.   0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
  191.   0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
  192.   0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
  193.   0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
  194.   0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
  195.   0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
  196.   0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
  197.   0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
  198.   0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
  199.   0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
  200.   0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
  201.   0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
  202.   0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
  203. };
  204. uint32_t stm32_sw_crc32_by_byte(uint32_t crc32, uint8_t pBuffer[], uint32_t NumOfByte)  
  205. {
  206.   uint32_t last_data;
  207.   uint32_t NumOfDWord = NumOfByte>>2;
  208.   uint32_t NumOfTailByte =  NumOfByte & 3 ;
  209.   
  210.   while(NumOfDWord--)
  211.   {
  212.     crc32 = crc32 ^ *((unsigned long *)pBuffer);
  213.     pBuffer += 4;
  214.     crc32 = (crc32 << 8) ^ sw_crc32_by_byte_table[crc32 >> 24];
  215.     crc32 = (crc32 << 8) ^ sw_crc32_by_byte_table[crc32 >> 24];
  216.     crc32 = (crc32 << 8) ^ sw_crc32_by_byte_table[crc32 >> 24];
  217.     crc32 = (crc32 << 8) ^ sw_crc32_by_byte_table[crc32 >> 24];
  218.   }
  219.   
  220.   switch ( NumOfTailByte )
  221.   {
  222.     case 0:
  223.       return crc32;     
  224.     case 1:
  225.       last_data = pBuffer[0] << 24;
  226.       break;
  227.     case 2:
  228.       last_data = *( (uint16_t *)(&pBuffer[0]) );
  229.       last_data <<= 16;
  230.       
  231.       break;
  232.     case 3:
  233.       last_data = *( (uint16_t *)(&pBuffer[0]) );
  234.       last_data <<= 8;
  235.       last_data += pBuffer[2]<<24;
  236.       break;
  237.   }
  238.   crc32 = stm32_sw_crc32_by_byte( crc32, (uint8_t *)&last_data, 4);
  239.   return crc32;
  240. }
复制代码
  1. unit uCRC32;
  2. interface
  3. uses
  4.   Windows;
  5.   function stm32_sw_crc32_by_byte(crc32 : DWORD;
  6.     pBuffer : pbyte; NumOfByte : DWORD) : DWORD;
  7.   function uCrc32_Demo : DWORD;
  8. implementation
  9. const
  10.   sw_crc32_by_byte_table : array[0..255] of DWORD =
  11.   (
  12.   $00000000, $04c11db7, $09823b6e, $0d4326d9,    // 0..3
  13.   $130476dc, $17c56b6b, $1a864db2, $1e475005,    // 4..7
  14.   $2608edb8, $22c9f00f, $2f8ad6d6, $2b4bcb61,    // 8..B
  15.   $350c9b64, $31cd86d3, $3c8ea00a, $384fbdbd,    // C..F
  16.   $4c11db70, $48d0c6c7, $4593e01e, $4152fda9,
  17.   $5f15adac, $5bd4b01b, $569796c2, $52568b75,
  18.   $6a1936c8, $6ed82b7f, $639b0da6, $675a1011,
  19.   $791d4014, $7ddc5da3, $709f7b7a, $745e66cd,
  20.   $9823b6e0, $9ce2ab57, $91a18d8e, $95609039,
  21.   $8b27c03c, $8fe6dd8b, $82a5fb52, $8664e6e5,
  22.   $be2b5b58, $baea46ef, $b7a96036, $b3687d81,
  23.   $ad2f2d84, $a9ee3033, $a4ad16ea, $a06c0b5d,
  24.   $d4326d90, $d0f37027, $ddb056fe, $d9714b49,
  25.   $c7361b4c, $c3f706fb, $ceb42022, $ca753d95,
  26.   $f23a8028, $f6fb9d9f, $fbb8bb46, $ff79a6f1,
  27.   $e13ef6f4, $e5ffeb43, $e8bccd9a, $ec7dd02d,
  28.   $34867077, $30476dc0, $3d044b19, $39c556ae,
  29.   $278206ab, $23431b1c, $2e003dc5, $2ac12072,
  30.   $128e9dcf, $164f8078, $1b0ca6a1, $1fcdbb16,
  31.   $018aeb13, $054bf6a4, $0808d07d, $0cc9cdca,
  32.   $7897ab07, $7c56b6b0, $71159069, $75d48dde,
  33.   $6b93dddb, $6f52c06c, $6211e6b5, $66d0fb02,
  34.   $5e9f46bf, $5a5e5b08, $571d7dd1, $53dc6066,
  35.   $4d9b3063, $495a2dd4, $44190b0d, $40d816ba,
  36.   $aca5c697, $a864db20, $a527fdf9, $a1e6e04e,
  37.   $bfa1b04b, $bb60adfc, $b6238b25, $b2e29692,
  38.   $8aad2b2f, $8e6c3698, $832f1041, $87ee0df6,
  39.   $99a95df3, $9d684044, $902b669d, $94ea7b2a,
  40.   $e0b41de7, $e4750050, $e9362689, $edf73b3e,
  41.   $f3b06b3b, $f771768c, $fa325055, $fef34de2,
  42.   $c6bcf05f, $c27dede8, $cf3ecb31, $cbffd686,
  43.   $d5b88683, $d1799b34, $dc3abded, $d8fba05a,
  44.   $690ce0ee, $6dcdfd59, $608edb80, $644fc637,
  45.   $7a089632, $7ec98b85, $738aad5c, $774bb0eb,
  46.   $4f040d56, $4bc510e1, $46863638, $42472b8f,
  47.   $5c007b8a, $58c1663d, $558240e4, $51435d53,
  48.   $251d3b9e, $21dc2629, $2c9f00f0, $285e1d47,
  49.   $36194d42, $32d850f5, $3f9b762c, $3b5a6b9b,
  50.   $0315d626, $07d4cb91, $0a97ed48, $0e56f0ff,
  51.   $1011a0fa, $14d0bd4d, $19939b94, $1d528623,
  52.   $f12f560e, $f5ee4bb9, $f8ad6d60, $fc6c70d7,
  53.   $e22b20d2, $e6ea3d65, $eba91bbc, $ef68060b,
  54.   $d727bbb6, $d3e6a601, $dea580d8, $da649d6f,
  55.   $c423cd6a, $c0e2d0dd, $cda1f604, $c960ebb3,
  56.   $bd3e8d7e, $b9ff90c9, $b4bcb610, $b07daba7,
  57.   $ae3afba2, $aafbe615, $a7b8c0cc, $a379dd7b,
  58.   $9b3660c6, $9ff77d71, $92b45ba8, $9675461f,
  59.   $8832161a, $8cf30bad, $81b02d74, $857130c3,
  60.   $5d8a9099, $594b8d2e, $5408abf7, $50c9b640,
  61.   $4e8ee645, $4a4ffbf2, $470cdd2b, $43cdc09c,
  62.   $7b827d21, $7f436096, $7200464f, $76c15bf8,
  63.   $68860bfd, $6c47164a, $61043093, $65c52d24,
  64.   $119b4be9, $155a565e, $18197087, $1cd86d30,
  65.   $029f3d35, $065e2082, $0b1d065b, $0fdc1bec,
  66.   $3793a651, $3352bbe6, $3e119d3f, $3ad08088,
  67.   $2497d08d, $2056cd3a, $2d15ebe3, $29d4f654,
  68.   $c5a92679, $c1683bce, $cc2b1d17, $c8ea00a0,
  69.   $d6ad50a5, $d26c4d12, $df2f6bcb, $dbee767c,
  70.   $e3a1cbc1, $e760d676, $ea23f0af, $eee2ed18,
  71.   $f0a5bd1d, $f464a0aa, $f9278673, $fde69bc4,
  72.   $89b8fd09, $8d79e0be, $803ac667, $84fbdbd0,
  73.   $9abc8bd5, $9e7d9662, $933eb0bb, $97ffad0c,
  74.   $afb010b1, $ab710d06, $a6322bdf, $a2f33668,
  75.   $bcb4666d, $b8757bda, $b5365d03, $b1f740b4
  76. );
  77. // 00 01 02 03          --> 0x03020100
  78. // 00 01 02 03 04       --> 0x03020100, 0x04000000
  79. // 00 01 02 03 04 05    --> 0x03020100, 0x05040000
  80. // 00 01 02 03 04 05 06 --> 0x03020100, 0x06050400
  81. //
  82. function stm32_sw_crc32_by_byte(crc32 : DWORD;
  83.   pBuffer : pbyte; NumOfByte : DWORD) : DWORD;
  84. var
  85.   i : DWORD;
  86. last_data : array[0..3] of byte;
  87.   NumOfDWord : DWORD;
  88.   NumOfTailByte : DWORD;
  89. begin
  90. NumOfDWord := NumOfByte shr 2;
  91. NumOfTailByte :=  NumOfByte and 3 ;
  92.   for i := 0 to  NumOfDWord-1 do
  93.   begin
  94.     crc32 := crc32 xor ( PDWORD( pbuffer ) )^;
  95.     Inc( pbuffer, 4);
  96.     crc32 := (crc32 shl 8) xor sw_crc32_by_byte_table[crc32 shr 24];
  97.     crc32 := (crc32 shl 8) xor sw_crc32_by_byte_table[crc32 shr 24];
  98.     crc32 := (crc32 shl 8) xor sw_crc32_by_byte_table[crc32 shr 24];
  99.     crc32 := (crc32 shl 8) xor sw_crc32_by_byte_table[crc32 shr 24];
  100.   end;
  101.   if NumOfTailByte <> 0 then
  102.   begin
  103.     for i := 0 to 3 do
  104.       last_data[i] := 0;
  105.     if NumOfTailByte = 1 then
  106.     begin
  107.       last_data[3] := pBuffer^;
  108.     end
  109.     else if NumOfTailByte = 2 then
  110.     begin
  111.       last_data[2] := pBuffer^;
  112.       Inc( pBuffer );
  113.       last_data[3] := pBuffer^;
  114.     end
  115.     else
  116.     begin
  117.       last_data[1] := pBuffer^;
  118.       Inc( pBuffer );
  119.       last_data[2] := pBuffer^;
  120.       Inc( pBuffer );
  121.       last_data[3] := pBuffer^;
  122.     end;
  123.     crc32 :=  stm32_sw_crc32_by_byte( crc32, @last_data, 4 );
  124.   end;
  125. result := crc32;
  126. end;
  127. function uCrc32_Demo : DWORD;
  128. var
  129.   crc32 : DWORD;
  130.   buffer : array[0..3] of DWORD;
  131. begin
  132.   buffer[0] := $12345678;
  133.   buffer[1] := $00000000;
  134.   buffer[2] := $12345678;
  135.   crc32 := stm32_sw_crc32_by_byte( $FFFFFFFF, @buffer, 12 );
  136.   buffer[3] := crc32;
  137.   crc32 := stm32_sw_crc32_by_byte( $FFFFFFFF, @buffer, 16 );
  138.   result := crc32;
  139. end;
复制代码


收藏 评论0 发布时间:2022-1-23 16:06

举报

0个回答

所属标签

相似技术帖

官网相关资源

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