HW_UART_ATY.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. /**
  2. * @file HW_UART_ATY.c
  3. *
  4. * @param Project DEVICE_GENERAL_ATY_LIB
  5. *
  6. * @author ATY
  7. *
  8. * @copyright
  9. * - Copyright 2017 - 2026 MZ-ATY
  10. * - This code follows:
  11. * - MZ-ATY Various Contents Joint Statement -
  12. * <a href="https://mengze.top/MZ-ATY_VCJS">
  13. * https://mengze.top/MZ-ATY_VCJS</a>
  14. * - CC 4.0 BY-NC-SA -
  15. * <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
  16. * https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
  17. * - Your use will be deemed to have accepted the terms of this statement.
  18. *
  19. * @brief functions of uart for C platform
  20. *
  21. * @version
  22. * - 1_01_221231 > ATY
  23. * -# Preliminary version, first Release
  24. * - 1_02_240410 > ATY
  25. * -# add multy addr and channel
  26. * -# add lock
  27. * - 1_03_251114 > ATY
  28. * -# remove _printf_ support
  29. * - 1_04_251118 > ATY
  30. * -# finish UartPrintf and test
  31. * @todo over with "\r\n" type
  32. ********************************************************************************
  33. */
  34. #ifndef __HW_UART_ATY_C
  35. #define __HW_UART_ATY_C
  36. #include "HW_UART_ATY.h"
  37. /******************************* For user *************************************/
  38. /******************************************************************************/
  39. /**
  40. * @brief uart send byte and init uart if not initialized
  41. * @param byte byte to send
  42. * @param dev
  43. * @return uint8_t
  44. */
  45. uint8_t UartSendByte(uint8_t byte, struct HW_UART_ATY_Dev* dev){
  46. __ATY_LOCK(dev);
  47. if(dev->uartInitFlag == 0){
  48. dev->uartInitFlag = 1;
  49. dev->uartInit(dev->rx);
  50. }
  51. // while(dev->rxCount)
  52. // dev->rx[dev->rxCount--] = 0;
  53. dev->uartSendByte(byte);
  54. __ATY_UNLOCK(dev);
  55. return 0;
  56. }
  57. /**
  58. * @brief
  59. *
  60. * @param dev
  61. */
  62. void UartRxClear(struct HW_UART_ATY_Dev* dev){
  63. if(!dev->rxCount) return;
  64. while(dev->rxCount)
  65. dev->rx[dev->rxCount--] = 0;
  66. }
  67. /**
  68. * @brief uart send bytes
  69. * @param bytes bytes to send
  70. * @param len bytes to send
  71. * @param dev
  72. */
  73. void UartSendBytes(uint8_t* bytes, uint16_t len, struct HW_UART_ATY_Dev* dev){
  74. while(len--)
  75. UartSendByte(*bytes++, dev);
  76. }
  77. /**
  78. * @brief uart send string
  79. * @param str data to send
  80. * @param dev
  81. */
  82. void UartSendStr(uint8_t* str, struct HW_UART_ATY_Dev* dev){
  83. while(*str)
  84. UartSendByte(*str++, dev);
  85. }
  86. /**
  87. * @brief uart send float data in specified endian
  88. * @param dataFloat float number
  89. * @param endian
  90. * @param dev
  91. */
  92. void UartSendFloat(float dataFloat, uint8_t endian, struct HW_UART_ATY_Dev* dev){
  93. union result{
  94. float temp_f;
  95. uint8_t temp_uint8[4];
  96. }resultA, resultB;
  97. resultA.temp_f = dataFloat;
  98. if(endian == 'B'){
  99. resultB.temp_uint8[0] = resultA.temp_uint8[3];
  100. resultB.temp_uint8[1] = resultA.temp_uint8[2];
  101. resultB.temp_uint8[2] = resultA.temp_uint8[1];
  102. resultB.temp_uint8[3] = resultA.temp_uint8[0];
  103. }
  104. else if(endian == 'L'){
  105. resultB.temp_uint8[0] = resultA.temp_uint8[0];
  106. resultB.temp_uint8[1] = resultA.temp_uint8[1];
  107. resultB.temp_uint8[2] = resultA.temp_uint8[2];
  108. resultB.temp_uint8[3] = resultA.temp_uint8[3];
  109. }
  110. UartSendBytes(resultB.temp_uint8, 4, dev);
  111. }
  112. /**
  113. * @brief uart send float data in ASCII character type
  114. * @param dataFloat number to send, use double to get better
  115. * @param DECIMALS_NUM
  116. * @param dev
  117. * @note float and double is the same in C51
  118. */
  119. void UartSendFloatStr(float dataFloat, uint8_t DECIMALS_NUM, struct HW_UART_ATY_Dev* dev){
  120. uint32_t integerPart, decimalPart;
  121. uint32_t power10 = 1; // Used to compute 10^DECIMALS_NUM
  122. uint8_t i;
  123. // Handle negative numbers
  124. if(dataFloat < 0){
  125. UartSendByte('-', dev);
  126. dataFloat = -dataFloat; // Convert to positive
  127. }
  128. // Extract integer part
  129. integerPart = (uint32_t)dataFloat;
  130. // Compute 10^DECIMALS_NUM
  131. for(i = 0; i < DECIMALS_NUM; i++){
  132. power10 *= 10;
  133. }
  134. // Compute decimal part (avoiding floating-point precision issues, +0.5 for rounding)
  135. decimalPart = (uint32_t)((dataFloat - integerPart) * power10 + 0.5);
  136. // Send integer part
  137. char buf[10]; // Buffer for integer part characters
  138. uint8_t index = 0;
  139. if(integerPart == 0){
  140. buf[index++] = '0'; // Directly send "0"
  141. }
  142. else{
  143. while(integerPart > 0){
  144. buf[index++] = (integerPart % 10) + '0';
  145. integerPart /= 10;
  146. }
  147. // Reverse the integer part before sending
  148. while(index > 0){
  149. UartSendByte(buf[--index], dev);
  150. }
  151. }
  152. // Send decimal point
  153. if(DECIMALS_NUM > 0){
  154. UartSendByte('.', dev);
  155. // Handle leading zeros in the decimal part
  156. for(i = DECIMALS_NUM - 1; i > 0; i--){
  157. if(decimalPart < power10 / 10){
  158. UartSendByte('0', dev); // Send leading zeros
  159. power10 /= 10;
  160. }
  161. }
  162. // Send decimal part
  163. index = 0;
  164. while(decimalPart > 0){
  165. buf[index++] = (decimalPart % 10) + '0';
  166. decimalPart /= 10;
  167. }
  168. while(index > 0){
  169. UartSendByte(buf[--index], dev);
  170. }
  171. }
  172. // Append a space at the end
  173. UartSendByte(' ', dev);
  174. }
  175. /**
  176. * @brief uart receive data process
  177. * @note put at main while
  178. * @param dev
  179. */
  180. void UartReceiveProcess(struct HW_UART_ATY_Dev* dev){
  181. if(dev->uartInitFlag == 0){
  182. dev->uartInitFlag = 1;
  183. dev->uartInit(dev->rx);
  184. }
  185. if(dev->rcvOverTimeOutCount > dev->rcvOverTimeOutCountNum){
  186. dev->rcvOverTimeOutCount = 0;
  187. if(dev->rxCount != 0){
  188. dev->rcvOverFlag = 0;
  189. dev->uartReceiveProcess_User();
  190. while(dev->rxCount){
  191. dev->rx[dev->rxCount--] = 0;
  192. }
  193. }
  194. }
  195. else
  196. dev->rcvOverTimeOutCount++;
  197. }
  198. // UartPrintf ------------------------------------------------------------------
  199. void __uart_put_uint_base(struct HW_UART_ATY_Dev* dev, uint32_t v, uint32_t base, uint8_t upper){
  200. char buf[32];
  201. uint8_t i = 0;
  202. do{
  203. uint32_t d = v % base;
  204. buf[i++] = (char)(d < 10 ? ('0' + d) : ((upper ? 'A' : 'a') + (d - 10)));
  205. v /= base;
  206. } while(v);
  207. while(i){
  208. UartSendByte((uint8_t)buf[--i], dev);
  209. }
  210. }
  211. void __uart_put_int_dec(struct HW_UART_ATY_Dev* dev, int32_t v){
  212. if(v < 0){
  213. UartSendByte('-', dev);
  214. __uart_put_uint_base(dev, (uint32_t)(-v), 10u, 0u);
  215. }
  216. else{
  217. __uart_put_uint_base(dev, (uint32_t)v, 10u, 0u);
  218. }
  219. }
  220. void __uart_put_float(struct HW_UART_ATY_Dev* dev, double v, int decimals){
  221. if(decimals < 0) decimals = 6;
  222. if(v < 0){ UartSendByte('-', dev); v = -v; }
  223. uint32_t ip = (uint32_t)v;
  224. double frac = v - (double)ip;
  225. uint32_t p10 = 1; for(int i = 0; i < decimals; i++) p10 *= 10u;
  226. uint32_t dp = (uint32_t)(frac * (double)p10 + 0.5);
  227. if(dp >= p10){ dp -= p10; ip += 1u; }
  228. __uart_put_uint_base(dev, ip, 10u, 0u);
  229. if(decimals > 0){
  230. UartSendByte('.', dev);
  231. char buf[16];
  232. int idx = 0;
  233. for(int i = 0; i < decimals; i++){ buf[idx++] = (char)('0' + (dp % 10)); dp /= 10; }
  234. while(idx){ UartSendByte((uint8_t)buf[--idx], dev); }
  235. }
  236. }
  237. void __uart_put_sci(struct HW_UART_ATY_Dev* dev, double v, int decimals){
  238. if(decimals < 0) decimals = 6;
  239. if(v == 0.0){
  240. UartSendByte('0', dev);
  241. if(decimals > 0){
  242. UartSendByte('.', dev);
  243. for(int i = 0; i < decimals; i++) UartSendByte('0', dev);
  244. }
  245. UartSendByte('e', dev);
  246. UartSendByte('+', dev);
  247. UartSendByte('0', dev);
  248. UartSendByte('0', dev);
  249. return;
  250. }
  251. if(v < 0){ UartSendByte('-', dev); v = -v; }
  252. int exp = 0;
  253. if(v >= 10.0){ while(v >= 10.0){ v /= 10.0; exp++; } }
  254. else if(v < 1.0){ while(v < 1.0){ v *= 10.0; exp--; } }
  255. uint32_t ip = (uint32_t)v;
  256. double frac = v - (double)ip;
  257. uint32_t p10 = 1; for(int i = 0; i < decimals; i++) p10 *= 10u;
  258. uint32_t dp = (uint32_t)(frac * (double)p10 + 0.5);
  259. if(dp >= p10){ dp -= p10; ip += 1u; if(ip >= 10u){ ip = 1u; exp++; } }
  260. __uart_put_uint_base(dev, ip, 10u, 0u);
  261. if(decimals > 0){
  262. UartSendByte('.', dev);
  263. char buf[16];
  264. int idx = 0;
  265. for(int i = 0; i < decimals; i++){ buf[idx++] = (char)('0' + (dp % 10)); dp /= 10; }
  266. while(idx){ UartSendByte((uint8_t)buf[--idx], dev); }
  267. }
  268. UartSendByte('e', dev);
  269. char sign = (exp >= 0) ? '+' : '-';
  270. if(exp < 0) exp = -exp;
  271. UartSendByte((uint8_t)sign, dev);
  272. char eb[8];
  273. int eidx = 0;
  274. do{ eb[eidx++] = (char)('0' + (exp % 10)); exp /= 10; } while(exp);
  275. while(eidx < 2) eb[eidx++] = '0';
  276. while(eidx){ UartSendByte((uint8_t)eb[--eidx], dev); }
  277. }
  278. void UartPrintf(struct HW_UART_ATY_Dev* dev, ...){
  279. va_list ap;
  280. va_start(ap, dev);
  281. const char* fmt = va_arg(ap, const char*);
  282. while(*fmt){
  283. char c = *fmt++;
  284. if(c != '%'){
  285. UartSendByte((uint8_t)c, dev);
  286. continue;
  287. }
  288. c = *fmt++;
  289. if(!c) break;
  290. int __aty_width = 0;
  291. int __aty_prec = -1;
  292. while(c >= '0' && c <= '9'){ __aty_width = __aty_width * 10 + (c - '0'); c = *fmt++; }
  293. if(c == '.'){ c = *fmt++; __aty_prec = 0; while(c >= '0' && c <= '9'){ __aty_prec = __aty_prec * 10 + (c - '0'); c = *fmt++; } }
  294. switch(c){
  295. case '%':
  296. UartSendByte('%', dev);
  297. break;
  298. case 'c': {
  299. int v = va_arg(ap, int);
  300. UartSendByte((uint8_t)v, dev);
  301. break;
  302. }
  303. case 's': {
  304. const char* s = va_arg(ap, const char*);
  305. if(!s) s = "(null)";
  306. UartSendStr((uint8_t*)s, dev);
  307. break;
  308. }
  309. case 'd': {
  310. int v = va_arg(ap, int);
  311. __uart_put_int_dec(dev, (int32_t)v);
  312. break;
  313. }
  314. case 'u': {
  315. unsigned int v = va_arg(ap, unsigned int);
  316. __uart_put_uint_base(dev, (uint32_t)v, 10u, 0u);
  317. break;
  318. }
  319. case 'x': {
  320. unsigned int v = va_arg(ap, unsigned int);
  321. __uart_put_uint_base(dev, (uint32_t)v, 16u, 0u);
  322. break;
  323. }
  324. case 'X': {
  325. unsigned int v = va_arg(ap, unsigned int);
  326. __uart_put_uint_base(dev, (uint32_t)v, 16u, 1u);
  327. break;
  328. }
  329. case 'f':
  330. case 'F': {
  331. double dv = va_arg(ap, double);
  332. __uart_put_float(dev, dv, __aty_prec);
  333. break;
  334. }
  335. case 'p': {
  336. void* pv = va_arg(ap, void*);
  337. UartSendStr((uint8_t*)"0x", dev);
  338. __uart_put_uint_base(dev, (uint32_t)pv, 16u, 0u);
  339. break;
  340. }
  341. case 'e': {
  342. double dv = va_arg(ap, double);
  343. __uart_put_sci(dev, dv, __aty_prec);
  344. break;
  345. }
  346. default:
  347. UartSendByte('%', dev);
  348. UartSendByte((uint8_t)c, dev);
  349. break;
  350. }
  351. }
  352. va_end(ap);
  353. }
  354. #ifdef UartPrintf_Test_ATY
  355. /**
  356. * @brief Comprehensive on-board test for UartPrintf, covering all format specifiers
  357. * @note Ensure the serial port is connected and the terminal is open with matching baudrate
  358. * @example Call UartPrintf_Test_All(&HW_UART_ATY_Dev_1) inside main()
  359. */
  360. void UartPrintf_Test_All(struct HW_UART_ATY_Dev* dev){
  361. /* 1. Basic chars and strings */
  362. UartPrintf(dev, "=== 1. Basic chars and strings ===\r\n");
  363. UartPrintf(dev, "char: %c, %c, %c\r\n", 'A', '0', '\n');
  364. UartPrintf(dev, "str: %s, %s, %s\r\n", "Hello", "", "STC51");
  365. /* 2. Integers (decimal) */
  366. UartPrintf(dev, "=== 2. Integers (decimal) ===\r\n");
  367. UartPrintf(dev, "int: %d, %d, %d, %d\r\n", 0, 123, -456, 2147483647);
  368. UartPrintf(dev, "uint: %u, %u, %u\r\n", 0, 65535, 4294967295UL);
  369. /* 3. Hexadecimal */
  370. UartPrintf(dev, "=== 3. Hexadecimal ===\r\n");
  371. UartPrintf(dev, "lowercase: %x, %x, %x\r\n", 0, 0x5F, 0xDEADBEEF);
  372. UartPrintf(dev, "uppercase: %X, %X, %X\r\n", 0, 0x5F, 0xDEADBEEF);
  373. /* 4. Floating point */
  374. UartPrintf(dev, "=== 4. Floating point ===\r\n");
  375. UartPrintf(dev, "default: %f, %f\r\n", 0.0, -3.1415926);
  376. UartPrintf(dev, "precision: %.2f, %.6f, %.0f\r\n", 3.1415926, 3.1415926, 3.1415926);
  377. UartPrintf(dev, "large: %f\r\n", 1e6);
  378. UartPrintf(dev, "small: %f\r\n", 1e-6);
  379. /* 5. Pointers */
  380. UartPrintf(dev, "=== 5. Pointers ===\r\n");
  381. void* p = (void*)0x1234;
  382. UartPrintf(dev, "ptr: %p\r\n", p);
  383. /* 6. Specials and escapes */
  384. UartPrintf(dev, "=== 6. Special characters ===\r\n");
  385. UartPrintf(dev, "%% %%\r\n");
  386. UartPrintf(dev, "mixed: %d|%u|%x|%X|%c|%s|%f\r\n", -1, 255, 255, 255, 'X', "END", 2.718);
  387. /* 7. Scientific notation */
  388. UartPrintf(dev, "=== 7. Scientific notation ===\r\n");
  389. UartPrintf(dev, "%.2e, %.6e, %.0e\r\n", 12345.6789, 0.000012345, 12345.0);
  390. /* End marker */
  391. UartPrintf(dev, "=== UartPrintf test completed ===\r\n");
  392. }
  393. /**
  394. * @brief Quickly verify UartPrintf basic functions with minimal ROM/RAM usage
  395. */
  396. void UartPrintf_Test_Quick(struct HW_UART_ATY_Dev* dev){
  397. UartPrintf(dev, "QuickTest: %c %s %d %u %x %X %.3f %p %e\r\n",
  398. 'Q',
  399. "OK",
  400. -123,
  401. 123,
  402. 0xAB,
  403. 0xAB,
  404. 3.14,
  405. (void*)0x2025,
  406. 12345.6789);
  407. }
  408. #endif /* UartPrintf_Test_ATY */
  409. #endif /* __HW_UART_ATY_C */
  410. /************************************ etc *************************************/
  411. /* init */
  412. /* STM32 (Open uart global IT, open rx DMA(Mode Normal, Width Byte) and default DMA IT) */
  413. // Uart ------------------------------------------------------------------------
  414. // #include "HW_UART_ATY.h"
  415. // extern DMA_HandleTypeDef hdma_usart1_rx;
  416. // void UartReceiveProcess_User_1(void);
  417. // void UartInit_1(uint8_t* rx){
  418. // HAL_UARTEx_ReceiveToIdle_DMA(&huart1, rx, UART_RX_MAX_LEN);
  419. // __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
  420. // }
  421. // void UartSendByte_1(uint8_t byte){
  422. // HAL_UART_Transmit(&huart1, (uint8_t*)&byte, 1, 0xFFFF);
  423. // }
  424. // struct HW_UART_ATY_Dev HW_UART_ATY_Dev_1 = {
  425. // // .rx = uartRx1,
  426. // .rx = {0},
  427. // .rxCount = 0,
  428. // .txCount = 0,
  429. // .rcvOverTimeOutCountNum = 1,
  430. // .rcvOverTimeOutCount = 0,
  431. // .rcvOverFlag = 0,
  432. // .uartInitFlag = 0,
  433. // .uartInit = UartInit_1,
  434. // .uartSendByte = UartSendByte_1,
  435. // .uartReceiveProcess_User = UartReceiveProcess_User_1,
  436. // .lock = __ATY_UNLOCKED
  437. // };
  438. // void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef* huart, uint16_t Size){
  439. // if(huart == &huart1){
  440. // HAL_UART_DMAStop(&huart1);
  441. // HW_UART_ATY_Dev_1.rcvOverTimeOutCount = 0;
  442. // HW_UART_ATY_Dev_1.rxCount = UART_RX_MAX_LEN - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
  443. // HW_UART_ATY_Dev_1.rcvOverFlag = 0;
  444. // HAL_UARTEx_ReceiveToIdle_DMA(&huart1, HW_UART_ATY_Dev_1.rx, UART_RX_MAX_LEN);
  445. // __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
  446. // }
  447. // }
  448. /* 51 */
  449. /* use */
  450. // void main()
  451. // {
  452. // UartPrintf(&HW_UART_ATY_Dev_1, "\r\nHello word!\r\n",);
  453. // while (1)
  454. // {
  455. // UartReceiveProcess(&HW_UART_ATY_Dev_1);
  456. // }
  457. // }
  458. // /**
  459. // * @brief uart receive data analysis in user define self
  460. // */
  461. // void UartReceiveProcess_User_1(void){
  462. // if(HW_UART_ATY_Dev_1.rx[0] == 'O'
  463. // && HW_UART_ATY_Dev_1.rx[1] == 'K'
  464. // && HW_UART_ATY_Dev_1.rx[2] == '?')
  465. // printf_ATY("OK!");
  466. // if(HW_UART_ATY_Dev_1.rx[0] == 'P'
  467. // && HW_UART_ATY_Dev_1.rx[1] == 'W'
  468. // && HW_UART_ATY_Dev_1.rx[2] == 'R'
  469. // && HW_UART_ATY_Dev_1.rx[3] == 'O'
  470. // && HW_UART_ATY_Dev_1.rx[4] == 'F'
  471. // && HW_UART_ATY_Dev_1.rx[5] == 'F'
  472. // )
  473. // PWR_BTN_Off(&PWR_BTN_ATY_t_1);
  474. //
  475. // // echo back, both type has tested
  476. // UartSendBytes(HW_UART_ATY_Dev_1.rx, HW_UART_ATY_Dev_1.rxCount, &HW_UART_ATY_Dev_1);
  477. // UartPrintf(&HW_UART_ATY_Dev_1, "\r\n%s\r\n", HW_UART_ATY_Dev_1.rx);
  478. //
  479. // if(HW_UART_ATY_Dev_1.rxCount != 0){
  480. // Modbus_Process(HW_UART_ATY_Dev_1.rx, HW_UART_ATY_Dev_1.rxCount, &MODBUS_S_LOW_ATY_Dev_1);
  481. // if(MODBUS_S_LOW_ATY_Dev_1.setFlag == 1){
  482. // MODBUS_S_LOW_ATY_Dev_1.setFlag = 0;
  483. // TransMbRegsToFloat(mbG, &MODBUS_S_LOW_ATY_Dev_1);
  484. // }
  485. // // memcpy((char*)cdcStr, ((const char*)(HW_UART_ATY_Dev_3.rx)), HW_UART_ATY_Dev_3.rxCount);
  486. // // CDC_Transmit_FS(cdcStr, HW_UART_ATY_Dev_3.rxCount);
  487. // // memset(cdcStr, 0, HW_UART_ATY_Dev_3.rxCount);
  488. // // HW_UART_ATY_Dev_3.rxCount = 0;
  489. // }
  490. // }
  491. /******************************************************************************/
  492. /******************************** End Of File *********************************/