原创 crc 个人总结

2020-8-9 11:57 742 15 6 分类: 汽车电子 文集: 杂项
一、介绍
CRC即循环冗余校验码(Cyclic Redundancy Check):是一种根据网络数据包或计算机文件等数据产生简短固定位数校验码的一种信道编码技术,主要用来检测或校验数据传输或者保存后可能出现的错误。数据通信领域中最常用的一种差错校验码,其信息字段和校验字段长度可以任意指定,但要求通信双方定义的CRC标准一致。
二、原理
基础原理来源于模2运算,通过除多项式取余数的方法得到CRC校验码。
多项式写法  例如  crc 16 ibm 多项式为:x16 + x15 + x2 + 1  16进制形式为 0x18005 其简记形式为0x8005, 我们大部分看到的是0x8005。
因为多项式的首尾必定为1。 1 xor 1 结果必定是0.
        输入值反转的意思是在计算之前先将二项式反转,然后再用得到的新值和数据进行计算。
        输入输出 初始值需异或。即先将要计算的数据与初始值的最低字节进行异或,然后再与多项式进行计算。
三、在线计算工具
CRC(循环冗余校验)在线计算_ip33.com 
网址:http://www.ip33.com/crc.html
特点:只有 crc 校验不过有个好处可以自定义crc 格式。
        CRC校验工具-在线工具 
        网址:http://www.metools.info/code/c15.html
特点:不仅有crc 校验工具还有其他计算工具,不足是crc 只能选着标准格式,不能自定义格式。
总结:两个工具使用都很不错,支持16进制和ascii 对复制过来的文件也很友好。
四、编程实现
实现方式主要分为两种
  1. 查表法。优点速度快,缺点占用一定的内存空间。
  2. 直接计算法。 优点占用内存空间小,缺点需要一定的计算量。
      源码实现(来源于网络没有找到原作者):
  1. uint8_t crc4_itu(uint8_t *data, uint_len length);
  2. uint8_t crc5_epc(uint8_t *data, uint_len length);
  3. uint8_t crc5_itu(uint8_t *data, uint_len length);
  4. uint8_t crc5_usb(uint8_t *data, uint_len length);
  5. uint8_t crc6_itu(uint8_t *data, uint_len length);
  6. uint8_t crc7_mmc(uint8_t *data, uint_len length);
  7. uint8_t crc8(uint8_t *data, uint_len length);
  8. uint8_t crc8_itu(uint8_t *data, uint_len length);
  9. uint8_t crc8_rohc(uint8_t *data, uint_len length);
  10. uint8_t crc8_maxim(uint8_t *data, uint_len length);//DS18B20
  11. uint16_t crc16_ibm(uint8_t *data, uint_len length);
  12. uint16_t crc16_maxim(uint8_t *data, uint_len length);
  13. uint16_t crc16_usb(uint8_t *data, uint_len length);
  14. uint16_t crc16_modbus(uint8_t *data, uint_len length);
  15. uint16_t crc16_ccitt(uint8_t *data, uint_len length);
  16. uint16_t crc16_ccitt_false(uint8_t *data, uint_len length);
  17. uint16_t crc16_x25(uint8_t *data, uint_len length);
  18. uint16_t crc16_xmodem(uint8_t *data, uint_len length);
  19. uint16_t crc16_dnp(uint8_t *data, uint_len length);
  20. uint32_t crc32(uint8_t *data, uint_len length);
  21. uint32_t crc32_mpeg_2(uint8_t *data, uint_len length);
  22. /******************************************************************************
  23. * Name: CRC-4/ITU x4+x+1
  24. * Poly: 0x03
  25. * Init: 0x00
  26. * Refin: True
  27. * Refout: True
  28. * Xorout: 0x00
  29. * Note:
  30. *****************************************************************************/
  31. uint8_t crc4_itu(uint8_t *data, uint_len length)
  32. {
  33. uint8_t i;
  34. uint8_t crc = 0; // Initial value
  35. while(length--)
  36. {
  37. crc ^= *data++; // crc ^= *data; data++;
  38. for (i = 0; i < 8; ++i)
  39. {
  40. if (crc & 1)
  41. crc = (crc >> 1) ^ 0x0C;// 0x0C = (reverse 0x03)>>(8-4)
  42. else
  43. crc = (crc >> 1);
  44. }
  45. }
  46. return crc;
  47. }
  48. /******************************************************************************
  49. * Name: CRC-5/EPC x5+x3+1
  50. * Poly: 0x09
  51. * Init: 0x09
  52. * Refin: False
  53. * Refout: False
  54. * Xorout: 0x00
  55. * Note:
  56. *****************************************************************************/
  57. uint8_t crc5_epc(uint8_t *data, uint_len length)
  58. {
  59. uint8_t i;
  60. uint8_t crc = 0x48; // Initial value: 0x48 = 0x09<<(8-5)
  61. while(length--)
  62. {
  63. crc ^= *data++; // crc ^= *data; data++;
  64. for ( i = 0; i < 8; i++ )
  65. {
  66. if ( crc & 0x80 )
  67. crc = (crc << 1) ^ 0x48; // 0x48 = 0x09<<(8-5)
  68. else
  69. crc <<= 1;
  70. }
  71. }
  72. return crc >> 3;
  73. }
  74. /******************************************************************************
  75. * Name: CRC-5/ITU x5+x4+x2+1
  76. * Poly: 0x15
  77. * Init: 0x00
  78. * Refin: True
  79. * Refout: True
  80. * Xorout: 0x00
  81. * Note:
  82. *****************************************************************************/
  83. uint8_t crc5_itu(uint8_t *data, uint_len length)
  84. {
  85. uint8_t i;
  86. uint8_t crc = 0; // Initial value
  87. while(length--)
  88. {
  89. crc ^= *data++; // crc ^= *data; data++;
  90. for (i = 0; i < 8; ++i)
  91. {
  92. if (crc & 1)
  93. crc = (crc >> 1) ^ 0x15;// 0x15 = (reverse 0x15)>>(8-5)
  94. else
  95. crc = (crc >> 1);
  96. }
  97. }
  98. return crc;
  99. }
  100. /******************************************************************************
  101. * Name: CRC-5/USB x5+x2+1
  102. * Poly: 0x05
  103. * Init: 0x1F
  104. * Refin: True
  105. * Refout: True
  106. * Xorout: 0x1F
  107. * Note:
  108. *****************************************************************************/
  109. uint8_t crc5_usb(uint8_t *data, uint_len length)
  110. {
  111. uint8_t i;
  112. uint8_t crc = 0x1F; // Initial value
  113. while(length--)
  114. {
  115. crc ^= *data++; // crc ^= *data; data++;
  116. for (i = 0; i < 8; ++i)
  117. {
  118. if (crc & 1)
  119. crc = (crc >> 1) ^ 0x14;// 0x14 = (reverse 0x05)>>(8-5)
  120. else
  121. crc = (crc >> 1);
  122. }
  123. }
  124. return crc ^ 0x1F;
  125. }
  126. /******************************************************************************
  127. * Name: CRC-6/ITU x6+x+1
  128. * Poly: 0x03
  129. * Init: 0x00
  130. * Refin: True
  131. * Refout: True
  132. * Xorout: 0x00
  133. * Note:
  134. *****************************************************************************/
  135. uint8_t crc6_itu(uint8_t *data, uint_len length)
  136. {
  137. uint8_t i;
  138. uint8_t crc = 0; // Initial value
  139. while(length--)
  140. {
  141. crc ^= *data++; // crc ^= *data; data++;
  142. for (i = 0; i < 8; ++i)
  143. {
  144. if (crc & 1)
  145. crc = (crc >> 1) ^ 0x30;// 0x30 = (reverse 0x03)>>(8-6)
  146. else
  147. crc = (crc >> 1);
  148. }
  149. }
  150. return crc;
  151. }
  152. /******************************************************************************
  153. * Name: CRC-7/MMC x7+x3+1
  154. * Poly: 0x09
  155. * Init: 0x00
  156. * Refin: False
  157. * Refout: False
  158. * Xorout: 0x00
  159. * Use: MultiMediaCard,SD,ect.
  160. *****************************************************************************/
  161. uint8_t crc7_mmc(uint8_t *data, uint_len length)
  162. {
  163. uint8_t i;
  164. uint8_t crc = 0; // Initial value
  165. while(length--)
  166. {
  167. crc ^= *data++; // crc ^= *data; data++;
  168. for ( i = 0; i < 8; i++ )
  169. {
  170. if ( crc & 0x80 )
  171. crc = (crc << 1) ^ 0x12; // 0x12 = 0x09<<(8-7)
  172. else
  173. crc <<= 1;
  174. }
  175. }
  176. return crc >> 1;
  177. }
  178. /******************************************************************************
  179. * Name: CRC-8 x8+x2+x+1
  180. * Poly: 0x07
  181. * Init: 0x00
  182. * Refin: False
  183. * Refout: False
  184. * Xorout: 0x00
  185. * Note:
  186. *****************************************************************************/
  187. uint8_t crc8(uint8_t *data, uint_len length)
  188. {
  189. uint8_t i;
  190. uint8_t crc = 0; // Initial value
  191. while(length--)
  192. {
  193. crc ^= *data++; // crc ^= *data; data++;
  194. for ( i = 0; i < 8; i++ )
  195. {
  196. if ( crc & 0x80 )
  197. crc = (crc << 1) ^ 0x07;
  198. else
  199. crc <<= 1;
  200. }
  201. }
  202. return crc;
  203. }
  204. /******************************************************************************
  205. * Name: CRC-8/ITU x8+x2+x+1
  206. * Poly: 0x07
  207. * Init: 0x00
  208. * Refin: False
  209. * Refout: False
  210. * Xorout: 0x55
  211. * Alias: CRC-8/ATM
  212. *****************************************************************************/
  213. uint8_t crc8_itu(uint8_t *data, uint_len length)
  214. {
  215. uint8_t i;
  216. uint8_t crc = 0; // Initial value
  217. while(length--)
  218. {
  219. crc ^= *data++; // crc ^= *data; data++;
  220. for ( i = 0; i < 8; i++ )
  221. {
  222. if ( crc & 0x80 )
  223. crc = (crc << 1) ^ 0x07;
  224. else
  225. crc <<= 1;
  226. }
  227. }
  228. return crc ^ 0x55;
  229. }
  230. /******************************************************************************
  231. * Name: CRC-8/ROHC x8+x2+x+1
  232. * Poly: 0x07
  233. * Init: 0xFF
  234. * Refin: True
  235. * Refout: True
  236. * Xorout: 0x00
  237. * Note:
  238. *****************************************************************************/
  239. uint8_t crc8_rohc(uint8_t *data, uint_len length)
  240. {
  241. uint8_t i;
  242. uint8_t crc = 0xFF; // Initial value
  243. while(length--)
  244. {
  245. crc ^= *data++; // crc ^= *data; data++;
  246. for (i = 0; i < 8; ++i)
  247. {
  248. if (crc & 1)
  249. crc = (crc >> 1) ^ 0xE0; // 0xE0 = reverse 0x07
  250. else
  251. crc = (crc >> 1);
  252. }
  253. }
  254. return crc;
  255. }
  256. /******************************************************************************
  257. * Name: CRC-8/MAXIM x8+x5+x4+1
  258. * Poly: 0x31
  259. * Init: 0x00
  260. * Refin: True
  261. * Refout: True
  262. * Xorout: 0x00
  263. * Alias: DOW-CRC,CRC-8/IBUTTON
  264. * Use: Maxim(Dallas)'s some devices,e.g. DS18B20
  265. *****************************************************************************/
  266. uint8_t crc8_maxim(uint8_t *data, uint_len length)
  267. {
  268. uint8_t i;
  269. uint8_t crc = 0; // Initial value
  270. while(length--)
  271. {
  272. crc ^= *data++; // crc ^= *data; data++;
  273. for (i = 0; i < 8; i++)
  274. {
  275. if (crc & 1)
  276. crc = (crc >> 1) ^ 0x8C; // 0x8C = reverse 0x31
  277. else
  278. crc >>= 1;
  279. }
  280. }
  281. return crc;
  282. }
  283. /******************************************************************************
  284. * Name: CRC-16/IBM x16+x15+x2+1
  285. * Poly: 0x8005
  286. * Init: 0x0000
  287. * Refin: True
  288. * Refout: True
  289. * Xorout: 0x0000
  290. * Alias: CRC-16,CRC-16/ARC,CRC-16/LHA
  291. *****************************************************************************/
  292. uint16_t crc16_ibm(uint8_t *data, uint_len length)
  293. {
  294. uint8_t i;
  295. uint16_t crc = 0; // Initial value
  296. while(length--)
  297. {
  298. crc ^= *data++; // crc ^= *data; data++;
  299. for (i = 0; i < 8; ++i)
  300. {
  301. if (crc & 1)
  302. crc = (crc >> 1) ^ 0xA001; // 0xA001 = reverse 0x8005
  303. else
  304. crc = (crc >> 1);
  305. }
  306. }
  307. return crc;
  308. }
  309. /******************************************************************************
  310. * Name: CRC-16/MAXIM x16+x15+x2+1
  311. * Poly: 0x8005
  312. * Init: 0x0000
  313. * Refin: True
  314. * Refout: True
  315. * Xorout: 0xFFFF
  316. * Note:
  317. *****************************************************************************/
  318. uint16_t crc16_maxim(uint8_t *data, uint_len length)
  319. {
  320. uint8_t i;
  321. uint16_t crc = 0; // Initial value
  322. while(length--)
  323. {
  324. crc ^= *data++; // crc ^= *data; data++;
  325. for (i = 0; i < 8; ++i)
  326. {
  327. if (crc & 1)
  328. crc = (crc >> 1) ^ 0xA001; // 0xA001 = reverse 0x8005
  329. else
  330. crc = (crc >> 1);
  331. }
  332. }
  333. return ~crc; // crc^0xffff
  334. }
  335. /******************************************************************************
  336. * Name: CRC-16/USB x16+x15+x2+1
  337. * Poly: 0x8005
  338. * Init: 0xFFFF
  339. * Refin: True
  340. * Refout: True
  341. * Xorout: 0xFFFF
  342. * Note:
  343. *****************************************************************************/
  344. uint16_t crc16_usb(uint8_t *data, uint_len length)
  345. {
  346. uint8_t i;
  347. uint16_t crc = 0xffff; // Initial value
  348. while(length--)
  349. {
  350. crc ^= *data++; // crc ^= *data; data++;
  351. for (i = 0; i < 8; ++i)
  352. {
  353. if (crc & 1)
  354. crc = (crc >> 1) ^ 0xA001; // 0xA001 = reverse 0x8005
  355. else
  356. crc = (crc >> 1);
  357. }
  358. }
  359. return ~crc; // crc^0xffff
  360. }
  361. /******************************************************************************
  362. * Name: CRC-16/MODBUS x16+x15+x2+1
  363. * Poly: 0x8005
  364. * Init: 0xFFFF
  365. * Refin: True
  366. * Refout: True
  367. * Xorout: 0x0000
  368. * Note:
  369. *****************************************************************************/
  370. uint16_t crc16_modbus(uint8_t *data, uint_len length)
  371. {
  372. uint8_t i;
  373. uint16_t crc = 0xffff; // Initial value
  374. while(length--)
  375. {
  376. crc ^= *data++; // crc ^= *data; data++;
  377. for (i = 0; i < 8; ++i)
  378. {
  379. if (crc & 1)
  380. crc = (crc >> 1) ^ 0xA001; // 0xA001 = reverse 0x8005
  381. else
  382. crc = (crc >> 1);
  383. }
  384. }
  385. return crc;
  386. }
  387. /******************************************************************************
  388. * Name: CRC-16/CCITT x16+x12+x5+1
  389. * Poly: 0x1021
  390. * Init: 0x0000
  391. * Refin: True
  392. * Refout: True
  393. * Xorout: 0x0000
  394. * Alias: CRC-CCITT,CRC-16/CCITT-TRUE,CRC-16/KERMIT
  395. *****************************************************************************/
  396. uint16_t crc16_ccitt(uint8_t *data, uint_len length)
  397. {
  398. uint8_t i;
  399. uint16_t crc = 0; // Initial value
  400. while(length--)
  401. {
  402. crc ^= *data++; // crc ^= *data; data++;
  403. for (i = 0; i < 8; ++i)
  404. {
  405. if (crc & 1)
  406. crc = (crc >> 1) ^ 0x8408; // 0x8408 = reverse 0x1021
  407. else
  408. crc = (crc >> 1);
  409. }
  410. }
  411. return crc;
  412. }
  413. /******************************************************************************
  414. * Name: CRC-16/CCITT-FALSE x16+x12+x5+1
  415. * Poly: 0x1021
  416. * Init: 0xFFFF
  417. * Refin: False
  418. * Refout: False
  419. * Xorout: 0x0000
  420. * Note:
  421. *****************************************************************************/
  422. uint16_t crc16_ccitt_false(uint8_t *data, uint_len length)
  423. {
  424. uint8_t i;
  425. uint16_t crc = 0xffff; //Initial value
  426. while(length--)
  427. {
  428. crc ^= (uint16_t)(*data++) << 8; // crc ^= (uint6_t)(*data)<<8; data++;
  429. for (i = 0; i < 8; ++i)
  430. {
  431. if ( crc & 0x8000 )
  432. crc = (crc << 1) ^ 0x1021;
  433. else
  434. crc <<= 1;
  435. }
  436. }
  437. return crc;
  438. }
  439. /******************************************************************************
  440. * Name: CRC-16/X25 x16+x12+x5+1
  441. * Poly: 0x1021
  442. * Init: 0xFFFF
  443. * Refin: True
  444. * Refout: True
  445. * Xorout: 0XFFFF
  446. * Note:
  447. *****************************************************************************/
  448. uint16_t crc16_x25(uint8_t *data, uint_len length)
  449. {
  450. uint8_t i;
  451. uint16_t crc = 0xffff; // Initial value
  452. while(length--)
  453. {
  454. crc ^= *data++; // crc ^= *data; data++;
  455. for (i = 0; i < 8; ++i)
  456. {
  457. if (crc & 1)
  458. crc = (crc >> 1) ^ 0x8408; // 0x8408 = reverse 0x1021
  459. else
  460. crc = (crc >> 1);
  461. }
  462. }
  463. return ~crc; // crc^Xorout
  464. }
  465. /******************************************************************************
  466. * Name: CRC-16/XMODEM x16+x12+x5+1
  467. * Poly: 0x1021
  468. * Init: 0x0000
  469. * Refin: False
  470. * Refout: False
  471. * Xorout: 0x0000
  472. * Alias: CRC-16/ZMODEM,CRC-16/ACORN
  473. *****************************************************************************/
  474. uint16_t crc16_xmodem(uint8_t *data, uint_len length)
  475. {
  476. uint8_t i;
  477. uint16_t crc = 0; // Initial value
  478. while(length--)
  479. {
  480. crc ^= (uint16_t)(*data++) << 8; // crc ^= (uint16_t)(*data)<<8; data++;
  481. for (i = 0; i < 8; ++i)
  482. {
  483. if ( crc & 0x8000 )
  484. crc = (crc << 1) ^ 0x1021;
  485. else
  486. crc <<= 1;
  487. }
  488. }
  489. return crc;
  490. }
  491. /******************************************************************************
  492. * Name: CRC-16/DNP x16+x13+x12+x11+x10+x8+x6+x5+x2+1
  493. * Poly: 0x3D65
  494. * Init: 0x0000
  495. * Refin: True
  496. * Refout: True
  497. * Xorout: 0xFFFF
  498. * Use: M-Bus,ect.
  499. *****************************************************************************/
  500. uint16_t crc16_dnp(uint8_t *data, uint_len length)
  501. {
  502. uint8_t i;
  503. uint16_t crc = 0; // Initial value
  504. while(length--)
  505. {
  506. crc ^= *data++; // crc ^= *data; data++;
  507. for (i = 0; i < 8; ++i)
  508. {
  509. if (crc & 1)
  510. crc = (crc >> 1) ^ 0xA6BC; // 0xA6BC = reverse 0x3D65
  511. else
  512. crc = (crc >> 1);
  513. }
  514. }
  515. return ~crc; // crc^Xorout
  516. }
  517. /******************************************************************************
  518. * Name: CRC-32 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
  519. * Poly: 0x4C11DB7
  520. * Init: 0xFFFFFFF
  521. * Refin: True
  522. * Refout: True
  523. * Xorout: 0xFFFFFFF
  524. * Alias: CRC_32/ADCCP
  525. * Use: WinRAR,ect.
  526. *****************************************************************************/
  527. uint32_t crc32(uint8_t *data, uint_len length)
  528. {
  529. uint8_t i;
  530. uint32_t crc = 0xffffffff; // Initial value
  531. while(length--)
  532. {
  533. crc ^= *data++; // crc ^= *data; data++;
  534. for (i = 0; i < 8; ++i)
  535. {
  536. if (crc & 1)
  537. crc = (crc >> 1) ^ 0xEDB88320;// 0xEDB88320= reverse 0x04C11DB7
  538. else
  539. crc = (crc >> 1);
  540. }
  541. }
  542. return ~crc;
  543. }
  544. /******************************************************************************
  545. * Name: CRC-32/MPEG-2 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
  546. * Poly: 0x4C11DB7
  547. * Init: 0xFFFFFFF
  548. * Refin: False
  549. * Refout: False
  550. * Xorout: 0x0000000
  551. * Note:
  552. *****************************************************************************/
  553. uint32_t crc32_mpeg_2(uint8_t *data, uint_len length)
  554. {
  555. uint8_t i;
  556. uint32_t crc = 0xffffffff; // Initial value
  557. while(length--)
  558. {
  559. crc ^= (uint32_t)(*data++) << 24;// crc ^=(uint32_t)(*data)<<24; data++;
  560. for (i = 0; i < 8; ++i)
  561. {
  562. if ( crc & 0x80000000 )
  563. crc = (crc << 1) ^ 0x04C11DB7;
  564. else
  565. crc <<= 1;
  566. }
  567. }
  568. return crc;
  569. }

最后附上看着原理写的不错的链接 :https://segmentfault.com/a/1190000018094567
﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌
免责声明:本文部分内容来源网络,版权归原作者所有,如涉及作品版权问题,请及时与我们联系,谢谢!

作者: jinsheng, 来源:面包板社区

链接: https://mbb.eet-china.com/blog/uid-me-425232.html

版权声明:本文为博主原创,未经本人允许,禁止转载!

文章评论2条评论)

登录后参与讨论

intel001 2020-9-2 10:46

厉害

Evan.i 2020-8-24 09:53

感谢分享
相关推荐阅读
jinsheng 2020-08-23 17:10
十二、freeRTOS 软件定时器
定时器硬件定时器:CPU内部自带的定时器模块,通过初始化、配置可以实现定时,定时时间到以后就会执行相应的定时器中断处理函数。硬件定时器一般都带有其他功能,比如PWM输出、输入捕获等功能。但缺点是硬件定...
jinsheng 2020-08-23 17:07
十一、freeRTOS 优先级翻转与互斥信号量
优先级翻转优先级翻转简介:就是高优先级的任务运行起来的效果好像成了低优先级,而低优先级比高优先级先运行。优先级翻转如下所示:优先级翻转过程:为什么会发生优先级翻转?因为两个任务(L和H)使用了同一个二...
jinsheng 2020-08-23 17:05
十、freeRTOS 计数型信号量
计数型信号量简介:计数型信号量的创建:计数型信号量动态创建函数:释放和获取信号量(与二值信号量相同)释放信号量:获取信号量: 测试实验用按键来模拟事件,按键按下后表示有事件发生,则释放计数型...
jinsheng 2020-08-23 16:54
九、freeRTOS 二值信号量
信号量1 信号量用于共享资源的访问:2 信号量用于任务同步:为什么一直说在中断服务函数中,不能够做太多的事情?在进入中断服务函数时,低优先级的中断就不能响应,同类型的中断也无法响应,所以就要求ISR一...
jinsheng 2020-08-23 16:49
八、freeRTOS 队列
队列简介:注意,队列长度并不是每个队列的字节数,而是能存多少条数据。如我们创建一个队列,每条消息最大10字节,队列可以保存4条消息,那么队列的长度为4。队列的功能:1 数据拷贝为什么一定要使用数据拷贝...
jinsheng 2020-08-23 16:45
七、FreeRTOS时间管理
FreeRTOS时间管理FreeRTOS的两个延时函数:vTaskDelay()          相对延时vTaskDelayUntil()&nbs...
广告
EE直播间
更多
我要评论
2
15
广告
关闭 热点推荐上一条 /4 下一条