HW_UART_ATY.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  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 - 2025 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 Familiar functions of uart for STC51
  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. * - Undone: over with "\r\n" type
  28. * - todo: printf in multi platform
  29. ********************************************************************************
  30. */
  31. #ifndef __HW_UART_ATY_C
  32. #define __HW_UART_ATY_C
  33. #include "HW_UART_ATY.h"
  34. /******************************* For user *************************************/
  35. /******************************************************************************/
  36. /**
  37. * @brief uart send byte and init uart if not initialized
  38. * @param byte byte to send
  39. * @param dev
  40. * @return uint8_t
  41. */
  42. uint8_t UartSendByte(uint8_t byte, struct HW_UART_ATY_Dev* dev)
  43. {
  44. __ATY_LOCK(dev);
  45. if(dev->uartInitFlag == 0){
  46. dev->uartInitFlag = 1;
  47. dev->uartInit(dev->rx);
  48. }
  49. while(dev->rxCount)
  50. dev->rx[dev->rxCount--] = 0;
  51. dev->uartSendByte(byte);
  52. __ATY_UNLOCK(dev);
  53. return 0;
  54. }
  55. /**
  56. * @brief
  57. *
  58. * @param dev
  59. */
  60. void UartRxClear(struct HW_UART_ATY_Dev* dev)
  61. {
  62. if(!dev->rxCount) return;
  63. while(dev->rxCount)
  64. dev->rx[dev->rxCount--] = 0;
  65. }
  66. /**
  67. * @brief uart send bytes
  68. * @param bytes bytes to send
  69. * @param len bytes to send
  70. * @param dev
  71. */
  72. void UartSendBytes(uint8_t* bytes, uint16_t len, struct HW_UART_ATY_Dev* dev)
  73. {
  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. {
  84. while(*str)
  85. UartSendByte(*str++, dev);
  86. }
  87. /**
  88. * @brief uart send float data in specified endian
  89. * @param dataFloat float number
  90. * @param endian
  91. * @param dev
  92. */
  93. void UartSendFloat(float dataFloat, uint8_t endian, struct HW_UART_ATY_Dev* dev)
  94. {
  95. union result
  96. {
  97. float temp_f;
  98. uint8_t temp_uint8[4];
  99. }resultA, resultB;
  100. resultA.temp_f = dataFloat;
  101. if(endian == 'B'){
  102. resultB.temp_uint8[0] = resultA.temp_uint8[3];
  103. resultB.temp_uint8[1] = resultA.temp_uint8[2];
  104. resultB.temp_uint8[2] = resultA.temp_uint8[1];
  105. resultB.temp_uint8[3] = resultA.temp_uint8[0];
  106. }
  107. else if(endian == 'L'){
  108. resultB.temp_uint8[0] = resultA.temp_uint8[0];
  109. resultB.temp_uint8[1] = resultA.temp_uint8[1];
  110. resultB.temp_uint8[2] = resultA.temp_uint8[2];
  111. resultB.temp_uint8[3] = resultA.temp_uint8[3];
  112. }
  113. UartSendBytes(resultB.temp_uint8, 4, dev);
  114. }
  115. /**
  116. * @brief uart send float data in ASCII character type
  117. * @param dataFloat number to send, use double to get better
  118. * @param DECIMALS_NUM
  119. * @param dev
  120. * @note float and double is the same in C51
  121. */
  122. void UartSendFloatStr(float dataFloat, uint8_t DECIMALS_NUM, struct HW_UART_ATY_Dev* dev)
  123. {
  124. uint32_t integerPart, decimalPart;
  125. uint32_t power10 = 1; // Used to compute 10^DECIMALS_NUM
  126. uint8_t i;
  127. // Handle negative numbers
  128. if (dataFloat < 0) {
  129. UartSendByte('-', dev);
  130. dataFloat = -dataFloat; // Convert to positive
  131. }
  132. // Extract integer part
  133. integerPart = (uint32_t)dataFloat;
  134. // Compute 10^DECIMALS_NUM
  135. for (i = 0; i < DECIMALS_NUM; i++) {
  136. power10 *= 10;
  137. }
  138. // Compute decimal part (avoiding floating-point precision issues, +0.5 for rounding)
  139. decimalPart = (uint32_t)((dataFloat - integerPart) * power10 + 0.5);
  140. // Send integer part
  141. char buf[10]; // Buffer for integer part characters
  142. uint8_t index = 0;
  143. if (integerPart == 0) {
  144. buf[index++] = '0'; // Directly send "0"
  145. } else {
  146. while (integerPart > 0) {
  147. buf[index++] = (integerPart % 10) + '0';
  148. integerPart /= 10;
  149. }
  150. // Reverse the integer part before sending
  151. while (index > 0) {
  152. UartSendByte(buf[--index], dev);
  153. }
  154. }
  155. // Send decimal point
  156. if (DECIMALS_NUM > 0) {
  157. UartSendByte('.', dev);
  158. // Handle leading zeros in the decimal part
  159. for (i = DECIMALS_NUM - 1; i > 0; i--) {
  160. if (decimalPart < power10 / 10) {
  161. UartSendByte('0', dev); // Send leading zeros
  162. power10 /= 10;
  163. }
  164. }
  165. // Send decimal part
  166. index = 0;
  167. while (decimalPart > 0) {
  168. buf[index++] = (decimalPart % 10) + '0';
  169. decimalPart /= 10;
  170. }
  171. while (index > 0) {
  172. UartSendByte(buf[--index], dev);
  173. }
  174. }
  175. // Append a space at the end
  176. UartSendByte(' ', dev);
  177. }
  178. /**
  179. * @brief uart receive data process
  180. * @note put at main while
  181. * @param dev
  182. */
  183. void UartReceiveProcess(struct HW_UART_ATY_Dev* dev)
  184. {
  185. if(dev->uartInitFlag == 0){
  186. dev->uartInitFlag = 1;
  187. dev->uartInit(dev->rx);
  188. }
  189. if(dev->rcvOverTimeOutCount > dev->rcvOverTimeOutCountNum)
  190. {
  191. dev->rcvOverTimeOutCount = 0;
  192. if(dev->rxCount != 0)
  193. {
  194. dev->rcvOverFlag = 0;
  195. dev->uartReceiveProcess_User();
  196. while(dev->rxCount){
  197. dev->rx[dev->rxCount--] = 0;
  198. }
  199. }
  200. }
  201. else
  202. dev->rcvOverTimeOutCount++;
  203. }
  204. /******************************* For user *************************************/
  205. #if defined (__STC51_ATY)
  206. #define BRT (uint32_t)(65536 - (uint32_t)FOSC / BAUD_RATE / 4)
  207. // #define FOSC 5529600UL // 5.5296MHz MCU frequency
  208. #define FOSC 24000000UL // 24MHz MCU frequency
  209. #define BAUD_RATE 115200
  210. /**
  211. * @brief uart hardware init
  212. * @note put at main init
  213. */
  214. void UartInit(void)
  215. {
  216. SCON = 0x50; // 8bit data, variable baud rate
  217. AUXR |= 0x40; // timer clk 1T mode
  218. AUXR &= 0xFE; // user timer 1 as uart1 baud generate
  219. TMOD &= 0x0F; // set timer mode
  220. TL1 = BRT; // set timer origin value
  221. TH1 = BRT >> 8; // set timer origin value
  222. ET1 = 0; // disable timer IT
  223. TR1 = 1; // start timer 1
  224. // TI = 1;
  225. uartMsgStruct_t.rxCount = 0x00;
  226. uartMsgStruct_t.txCount = 0x00;
  227. uartMsgStruct_t.busyFlag = 0;
  228. ES = 1; // UART interrupt enable
  229. EA = 1; // Global interrupt enable
  230. }
  231. /**
  232. * @brief uart IT callback function
  233. */
  234. void UartIsr(void) INTERRUPT(4)
  235. {
  236. if(TI)
  237. {
  238. TI = 0;
  239. uartMsgStruct_t.busyFlag = 0;
  240. }
  241. if(RI)
  242. {
  243. RI = 0;
  244. if(uartMsgStruct_t.rxCount < UART_RX_MAX_LEN)
  245. {
  246. uartMsgStruct_t.overCount = 0;
  247. uartMsgStruct_t.rx[uartMsgStruct_t.rxCount++] = SBUF;
  248. }
  249. }
  250. }
  251. /**
  252. * @brief uart send byte
  253. * @param byte byte to send
  254. */
  255. void UartSendByte(uint8_t byte)
  256. {
  257. uint8_t errCount = 0;
  258. while(uartMsgStruct_t.busyFlag == 1)
  259. {
  260. errCount++;
  261. if(errCount > 200)
  262. break;
  263. }
  264. uartMsgStruct_t.busyFlag = 1;
  265. SBUF = byte;
  266. }
  267. #elif defined(__STM32_HAL_ATY)
  268. #include "usart.h"
  269. #ifndef __MICROLIB
  270. // for standart lib(not use MicroLIB)
  271. #pragma import(__use_no_semihosting)
  272. // define _sys_exit to avoid semi-host mode
  273. void _sys_exit(int x)
  274. {
  275. x = x;
  276. }
  277. struct __FILE
  278. {
  279. int handle;
  280. };
  281. FILE __stdout;
  282. #endif /* __MICROLIB */
  283. /* In gcc, using printf() output, if there is no "\n" in output data, no data
  284. will be printed on the screen until "\n" is encountered or the buffer overflows
  285. Another way to refresh the output data is to run "fflush(stdout)" after
  286. sending the data to force a refresh of the output stream
  287. */
  288. #ifdef __GNUC__
  289. #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
  290. #define GETCHAR_PROTOTYPE int __io_getchar(void)
  291. #else
  292. #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
  293. #define GETCHAR_PROTOTYPE int fgetc(FILE *f)
  294. #endif /* __GNUC__ */
  295. PUTCHAR_PROTOTYPE \
  296. {
  297. #ifdef LL
  298. // LL_USART_TransmitData8(PRINTF_UART, ch);
  299. // while(!LL_USART_IsActiveFlag_TC(PRINTF_UART)){}
  300. #else
  301. // HAL_UART_Transmit(&PRINTF_UART, (uint8_t*)&ch, 1, 0xFFFF);
  302. #endif
  303. return ch;
  304. }
  305. GETCHAR_PROTOTYPE \
  306. {
  307. uint8_t ch = 0;
  308. // HAL_UART_Receive(&PRINTF_UART, &ch, 1, 0xFFFF);
  309. return ch;
  310. }
  311. #endif /* PLATFORM */
  312. /******************************************************************************/
  313. #endif /* __HW_UART_ATY_C */
  314. /************************************ etc *************************************/
  315. /* init */
  316. /* STM32 (Open uart global IT, open rx DMA(Mode Normal, Width Byte) and default DMA IT) */
  317. // // uart2
  318. // extern DMA_HandleTypeDef hdma_usart2_rx;
  319. // void UartReceiveProcess_User_2(void);
  320. // void UartInit_2(uint8_t* rx)
  321. // {
  322. // // __HAL_UART_ENABLE_IT(&huart2, UART_IT_IDLE);
  323. // HAL_UARTEx_ReceiveToIdle_DMA(&huart2, rx, UART_RX_MAX_LEN);
  324. // __HAL_DMA_DISABLE_IT(&hdma_usart2_rx, DMA_IT_HT);
  325. // }
  326. // void UartSendByte_2(uint8_t byte)
  327. // {
  328. // // LL
  329. // // LL_USART_TransmitData8(huart2, byte);
  330. // // while(!LL_USART_IsActiveFlag_TC(huart2)){}
  331. // // HAL
  332. // HAL_UART_Transmit(&huart2, (uint8_t*)&byte, 1, 0xFFFF);
  333. // }
  334. // struct HW_UART_ATY_Dev HW_UART_ATY_Dev_2 = {
  335. // // .rx = uartRx1,
  336. // .rx = {0},
  337. // .rxCount = 0,
  338. // .txCount = 0,
  339. // .rcvOverTimeOutCountNum = 2000,
  340. // .rcvOverTimeOutCount = 0,
  341. // .rcvOverFlag = 0,
  342. // .uartInitFlag = 0,
  343. // .uartInit = UartInit_2,
  344. // .uartSendByte = UartSendByte_2,
  345. // .uartReceiveProcess_User = UartReceiveProcess_User_2,
  346. // .lock = _ATY_UNLOCKED,
  347. // .debugEnable = 0,
  348. // // .LOG = printf
  349. // };
  350. // // uart3
  351. // extern DMA_HandleTypeDef hdma_usart3_rx;
  352. // void UartReceiveProcess_User_3(void);
  353. // void UartInit_3(uint8_t* rx)
  354. // {
  355. // // __HAL_UART_ENABLE_IT(&huart3, UART_IT_IDLE);
  356. // HAL_UARTEx_ReceiveToIdle_DMA(&huart3, rx, UART_RX_MAX_LEN);
  357. // __HAL_DMA_DISABLE_IT(&hdma_usart3_rx, DMA_IT_HT);
  358. // }
  359. // void UartSendByte_3(uint8_t byte)
  360. // {
  361. // // LL
  362. // // LL_USART_TransmitData8(huart3, byte);
  363. // // while(!LL_USART_IsActiveFlag_TC(huart3)){}
  364. // // HAL
  365. // HAL_UART_Transmit(&huart3, (uint8_t*)&byte, 1, 0xFFFF);
  366. // }
  367. // struct HW_UART_ATY_Dev HW_UART_ATY_Dev_3 = {
  368. // // .rx = uartRx1,
  369. // .rx = {0},
  370. // .rxCount = 0,
  371. // .txCount = 0,
  372. // .rcvOverTimeOutCountNum = 2000,
  373. // .rcvOverTimeOutCount = 0,
  374. // .rcvOverFlag = 0,
  375. // .uartInitFlag = 0,
  376. // .uartInit = UartInit_3,
  377. // .uartSendByte = UartSendByte_3,
  378. // .uartReceiveProcess_User = UartReceiveProcess_User_3,
  379. // .lock = _ATY_UNLOCKED,
  380. // .debugEnable = 0,
  381. // // .LOG = printf
  382. // };
  383. // void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef* huart, uint16_t Size)
  384. // {
  385. // if(huart == &huart2){
  386. // HAL_UART_DMAStop(&huart2);
  387. // HW_UART_ATY_Dev_2.rcvOverTimeOutCount = 0;
  388. // HW_UART_ATY_Dev_2.rxCount = UART_RX_MAX_LEN - __HAL_DMA_GET_COUNTER(&hdma_usart2_rx);
  389. // HW_UART_ATY_Dev_2.rcvOverFlag = 0;
  390. // HAL_UARTEx_ReceiveToIdle_DMA(&huart2, HW_UART_ATY_Dev_2.rx, UART_RX_MAX_LEN);
  391. // __HAL_DMA_DISABLE_IT(&hdma_usart2_rx, DMA_IT_HT);
  392. // }
  393. // else if(huart == &huart3){
  394. // HAL_UART_DMAStop(&huart3);
  395. // HW_UART_ATY_Dev_3.rcvOverTimeOutCount = 0;
  396. // HW_UART_ATY_Dev_3.rxCount = UART_RX_MAX_LEN - __HAL_DMA_GET_COUNTER(&hdma_usart3_rx);
  397. // HW_UART_ATY_Dev_3.rcvOverFlag = 0;
  398. // HAL_UARTEx_ReceiveToIdle_DMA(&huart3, HW_UART_ATY_Dev_3.rx, UART_RX_MAX_LEN);
  399. // __HAL_DMA_DISABLE_IT(&hdma_usart3_rx, DMA_IT_HT);
  400. // }
  401. // /* if process is not too long, process function can be used at this call back;
  402. // otherwise put process at other cycle like while or timer cycle */
  403. // // UartReceiveProcess_User_2();
  404. // // UartReceiveProcess_User_3();
  405. // }
  406. /* 51 */
  407. /* use */
  408. // void main()
  409. // {
  410. // UartSendStr("Hello word!", &HW_UART_ATY_Dev_2);
  411. // UartSendStr("Hello word!", &HW_UART_ATY_Dev_3);
  412. // while (1)
  413. // {
  414. // UartReceiveProcess(&HW_UART_ATY_Dev_2);
  415. // UartReceiveProcess(&HW_UART_ATY_Dev_3);
  416. // }
  417. // }
  418. // /**
  419. // * @brief uart receive data analysis in user define self
  420. // */
  421. // void UartReceiveProcess_User_2(void)
  422. // {
  423. // if((HW_UART_ATY_Dev_2.rx[0] == 'O'
  424. // && HW_UART_ATY_Dev_2.rx[1] == 'K'
  425. // && HW_UART_ATY_Dev_2.rx[2] == '?'))
  426. // UartSendStr("OK!", &HW_UART_ATY_Dev_2);
  427. // }
  428. // void UartReceiveProcess_User_3(void)
  429. // {
  430. // if((HW_UART_ATY_Dev_3.rx[0] == 'O'
  431. // && HW_UART_ATY_Dev_3.rx[1] == 'K'
  432. // && HW_UART_ATY_Dev_3.rx[2] == '?'))
  433. // UartSendStr("OK!", &HW_UART_ATY_Dev_3);
  434. //
  435. // Modbus_Process(HW_UART_ATY_Dev_3.rx, HW_UART_ATY_Dev_3.rxCount, &MODBUS_S_LOW_ATY_Dev_1);
  436. //
  437. //
  438. // // UartSendStr(HW_UART_ATY_Dev_1.rx, &HW_UART_ATY_Dev_3);
  439. // if(memcmp("DSTART", (char*)HW_UART_ATY_Dev_1.rx, strlen("DSTART")) == 0)
  440. // {
  441. // printf("\r\nDebug START!");
  442. // }
  443. // else if(memcmp("temp", (char*)HW_UART_ATY_Dev_1.rx, strlen("temp")) == 0)
  444. // {
  445. // printf("\r\ntemp %c%c%c",
  446. // HW_UART_ATY_Dev_1.rx[strlen("temp_")],
  447. // HW_UART_ATY_Dev_1.rx[strlen("temp_") + 1],
  448. // HW_UART_ATY_Dev_1.rx[strlen("temp_") + 2]);
  449. // }
  450. // }
  451. /******************************************************************************/
  452. /******************************** End Of File *********************************/