| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552 |
- /**
- * @file HW_UART_ATY.c
- *
- * @param Project DEVICE_GENERAL_ATY_LIB
- *
- * @author ATY
- *
- * @copyright
- * - Copyright 2017 - 2026 MZ-ATY
- * - This code follows:
- * - MZ-ATY Various Contents Joint Statement -
- * <a href="https://mengze.top/MZ-ATY_VCJS">
- * https://mengze.top/MZ-ATY_VCJS</a>
- * - CC 4.0 BY-NC-SA -
- * <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
- * https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
- * - Your use will be deemed to have accepted the terms of this statement.
- *
- * @brief functions of uart for C platform
- *
- * @version
- * - 1_01_221231 > ATY
- * -# Preliminary version, first Release
- * - 1_02_240410 > ATY
- * -# add multy addr and channel
- * -# add lock
- * - 1_03_251114 > ATY
- * -# remove _printf_ support
- * - 1_04_251118 > ATY
- * -# finish UartPrintf and test
- * @todo over with "\r\n" type
- ********************************************************************************
- */
- #ifndef __HW_UART_ATY_C
- #define __HW_UART_ATY_C
- #include "HW_UART_ATY.h"
- /******************************* For user *************************************/
- /******************************************************************************/
- /**
- * @brief uart send byte and init uart if not initialized
- * @param byte byte to send
- * @param dev
- * @return uint8_t
- */
- uint8_t UartSendByte(uint8_t byte, struct HW_UART_ATY_Dev* dev){
- __ATY_LOCK(dev);
- if(dev->uartInitFlag == 0){
- dev->uartInitFlag = 1;
- dev->uartInit(dev->rx);
- }
- // while(dev->rxCount)
- // dev->rx[dev->rxCount--] = 0;
- dev->uartSendByte(byte);
- __ATY_UNLOCK(dev);
- return 0;
- }
- /**
- * @brief
- *
- * @param dev
- */
- void UartRxClear(struct HW_UART_ATY_Dev* dev){
- if(!dev->rxCount) return;
- while(dev->rxCount)
- dev->rx[dev->rxCount--] = 0;
- }
- /**
- * @brief uart send bytes
- * @param bytes bytes to send
- * @param len bytes to send
- * @param dev
- */
- void UartSendBytes(uint8_t* bytes, uint16_t len, struct HW_UART_ATY_Dev* dev){
- while(len--)
- UartSendByte(*bytes++, dev);
- }
- /**
- * @brief uart send string
- * @param str data to send
- * @param dev
- */
- void UartSendStr(uint8_t* str, struct HW_UART_ATY_Dev* dev){
- while(*str)
- UartSendByte(*str++, dev);
- }
- /**
- * @brief uart send float data in specified endian
- * @param dataFloat float number
- * @param endian
- * @param dev
- */
- void UartSendFloat(float dataFloat, uint8_t endian, struct HW_UART_ATY_Dev* dev){
- union result{
- float temp_f;
- uint8_t temp_uint8[4];
- }resultA, resultB;
- resultA.temp_f = dataFloat;
- if(endian == 'B'){
- resultB.temp_uint8[0] = resultA.temp_uint8[3];
- resultB.temp_uint8[1] = resultA.temp_uint8[2];
- resultB.temp_uint8[2] = resultA.temp_uint8[1];
- resultB.temp_uint8[3] = resultA.temp_uint8[0];
- }
- else if(endian == 'L'){
- resultB.temp_uint8[0] = resultA.temp_uint8[0];
- resultB.temp_uint8[1] = resultA.temp_uint8[1];
- resultB.temp_uint8[2] = resultA.temp_uint8[2];
- resultB.temp_uint8[3] = resultA.temp_uint8[3];
- }
- UartSendBytes(resultB.temp_uint8, 4, dev);
- }
- /**
- * @brief uart send float data in ASCII character type
- * @param dataFloat number to send, use double to get better
- * @param DECIMALS_NUM
- * @param dev
- * @note float and double is the same in C51
- */
- void UartSendFloatStr(float dataFloat, uint8_t DECIMALS_NUM, struct HW_UART_ATY_Dev* dev){
- uint32_t integerPart, decimalPart;
- uint32_t power10 = 1; // Used to compute 10^DECIMALS_NUM
- uint8_t i;
- // Handle negative numbers
- if(dataFloat < 0){
- UartSendByte('-', dev);
- dataFloat = -dataFloat; // Convert to positive
- }
- // Extract integer part
- integerPart = (uint32_t)dataFloat;
- // Compute 10^DECIMALS_NUM
- for(i = 0; i < DECIMALS_NUM; i++){
- power10 *= 10;
- }
- // Compute decimal part (avoiding floating-point precision issues, +0.5 for rounding)
- decimalPart = (uint32_t)((dataFloat - integerPart) * power10 + 0.5);
- // Send integer part
- char buf[10]; // Buffer for integer part characters
- uint8_t index = 0;
- if(integerPart == 0){
- buf[index++] = '0'; // Directly send "0"
- }
- else{
- while(integerPart > 0){
- buf[index++] = (integerPart % 10) + '0';
- integerPart /= 10;
- }
- // Reverse the integer part before sending
- while(index > 0){
- UartSendByte(buf[--index], dev);
- }
- }
- // Send decimal point
- if(DECIMALS_NUM > 0){
- UartSendByte('.', dev);
- // Handle leading zeros in the decimal part
- for(i = DECIMALS_NUM - 1; i > 0; i--){
- if(decimalPart < power10 / 10){
- UartSendByte('0', dev); // Send leading zeros
- power10 /= 10;
- }
- }
- // Send decimal part
- index = 0;
- while(decimalPart > 0){
- buf[index++] = (decimalPart % 10) + '0';
- decimalPart /= 10;
- }
- while(index > 0){
- UartSendByte(buf[--index], dev);
- }
- }
- // Append a space at the end
- UartSendByte(' ', dev);
- }
- /**
- * @brief uart receive data process
- * @note put at main while
- * @param dev
- */
- void UartReceiveProcess(struct HW_UART_ATY_Dev* dev){
- if(dev->uartInitFlag == 0){
- dev->uartInitFlag = 1;
- dev->uartInit(dev->rx);
- }
- if(dev->rcvOverTimeOutCount > dev->rcvOverTimeOutCountNum){
- dev->rcvOverTimeOutCount = 0;
- if(dev->rxCount != 0){
- dev->rcvOverFlag = 0;
- dev->uartReceiveProcess_User();
- while(dev->rxCount){
- dev->rx[dev->rxCount--] = 0;
- }
- }
- }
- else
- dev->rcvOverTimeOutCount++;
- }
- // UartPrintf ------------------------------------------------------------------
- void __uart_put_uint_base(struct HW_UART_ATY_Dev* dev, uint32_t v, uint32_t base, uint8_t upper){
- char buf[32];
- uint8_t i = 0;
- do{
- uint32_t d = v % base;
- buf[i++] = (char)(d < 10 ? ('0' + d) : ((upper ? 'A' : 'a') + (d - 10)));
- v /= base;
- } while(v);
- while(i){
- UartSendByte((uint8_t)buf[--i], dev);
- }
- }
- void __uart_put_int_dec(struct HW_UART_ATY_Dev* dev, int32_t v){
- if(v < 0){
- UartSendByte('-', dev);
- __uart_put_uint_base(dev, (uint32_t)(-v), 10u, 0u);
- }
- else{
- __uart_put_uint_base(dev, (uint32_t)v, 10u, 0u);
- }
- }
- void __uart_put_float(struct HW_UART_ATY_Dev* dev, double v, int decimals){
- if(decimals < 0) decimals = 6;
- if(v < 0){ UartSendByte('-', dev); v = -v; }
- uint32_t ip = (uint32_t)v;
- double frac = v - (double)ip;
- uint32_t p10 = 1; for(int i = 0; i < decimals; i++) p10 *= 10u;
- uint32_t dp = (uint32_t)(frac * (double)p10 + 0.5);
- if(dp >= p10){ dp -= p10; ip += 1u; }
- __uart_put_uint_base(dev, ip, 10u, 0u);
- if(decimals > 0){
- UartSendByte('.', dev);
- char buf[16];
- int idx = 0;
- for(int i = 0; i < decimals; i++){ buf[idx++] = (char)('0' + (dp % 10)); dp /= 10; }
- while(idx){ UartSendByte((uint8_t)buf[--idx], dev); }
- }
- }
- void __uart_put_sci(struct HW_UART_ATY_Dev* dev, double v, int decimals){
- if(decimals < 0) decimals = 6;
- if(v == 0.0){
- UartSendByte('0', dev);
- if(decimals > 0){
- UartSendByte('.', dev);
- for(int i = 0; i < decimals; i++) UartSendByte('0', dev);
- }
- UartSendByte('e', dev);
- UartSendByte('+', dev);
- UartSendByte('0', dev);
- UartSendByte('0', dev);
- return;
- }
- if(v < 0){ UartSendByte('-', dev); v = -v; }
- int exp = 0;
- if(v >= 10.0){ while(v >= 10.0){ v /= 10.0; exp++; } }
- else if(v < 1.0){ while(v < 1.0){ v *= 10.0; exp--; } }
- uint32_t ip = (uint32_t)v;
- double frac = v - (double)ip;
- uint32_t p10 = 1; for(int i = 0; i < decimals; i++) p10 *= 10u;
- uint32_t dp = (uint32_t)(frac * (double)p10 + 0.5);
- if(dp >= p10){ dp -= p10; ip += 1u; if(ip >= 10u){ ip = 1u; exp++; } }
- __uart_put_uint_base(dev, ip, 10u, 0u);
- if(decimals > 0){
- UartSendByte('.', dev);
- char buf[16];
- int idx = 0;
- for(int i = 0; i < decimals; i++){ buf[idx++] = (char)('0' + (dp % 10)); dp /= 10; }
- while(idx){ UartSendByte((uint8_t)buf[--idx], dev); }
- }
- UartSendByte('e', dev);
- char sign = (exp >= 0) ? '+' : '-';
- if(exp < 0) exp = -exp;
- UartSendByte((uint8_t)sign, dev);
- char eb[8];
- int eidx = 0;
- do{ eb[eidx++] = (char)('0' + (exp % 10)); exp /= 10; } while(exp);
- while(eidx < 2) eb[eidx++] = '0';
- while(eidx){ UartSendByte((uint8_t)eb[--eidx], dev); }
- }
- void UartPrintf(struct HW_UART_ATY_Dev* dev, ...){
- va_list ap;
- va_start(ap, dev);
- const char* fmt = va_arg(ap, const char*);
- while(*fmt){
- char c = *fmt++;
- if(c != '%'){
- UartSendByte((uint8_t)c, dev);
- continue;
- }
- c = *fmt++;
- if(!c) break;
- int __aty_width = 0;
- int __aty_prec = -1;
- while(c >= '0' && c <= '9'){ __aty_width = __aty_width * 10 + (c - '0'); c = *fmt++; }
- if(c == '.'){ c = *fmt++; __aty_prec = 0; while(c >= '0' && c <= '9'){ __aty_prec = __aty_prec * 10 + (c - '0'); c = *fmt++; } }
- switch(c){
- case '%':
- UartSendByte('%', dev);
- break;
- case 'c': {
- int v = va_arg(ap, int);
- UartSendByte((uint8_t)v, dev);
- break;
- }
- case 's': {
- const char* s = va_arg(ap, const char*);
- if(!s) s = "(null)";
- UartSendStr((uint8_t*)s, dev);
- break;
- }
- case 'd': {
- int v = va_arg(ap, int);
- __uart_put_int_dec(dev, (int32_t)v);
- break;
- }
- case 'u': {
- unsigned int v = va_arg(ap, unsigned int);
- __uart_put_uint_base(dev, (uint32_t)v, 10u, 0u);
- break;
- }
- case 'x': {
- unsigned int v = va_arg(ap, unsigned int);
- __uart_put_uint_base(dev, (uint32_t)v, 16u, 0u);
- break;
- }
- case 'X': {
- unsigned int v = va_arg(ap, unsigned int);
- __uart_put_uint_base(dev, (uint32_t)v, 16u, 1u);
- break;
- }
- case 'f':
- case 'F': {
- double dv = va_arg(ap, double);
- __uart_put_float(dev, dv, __aty_prec);
- break;
- }
- case 'p': {
- void* pv = va_arg(ap, void*);
- UartSendStr((uint8_t*)"0x", dev);
- __uart_put_uint_base(dev, (uint32_t)pv, 16u, 0u);
- break;
- }
- case 'e': {
- double dv = va_arg(ap, double);
- __uart_put_sci(dev, dv, __aty_prec);
- break;
- }
- default:
- UartSendByte('%', dev);
- UartSendByte((uint8_t)c, dev);
- break;
- }
- }
- va_end(ap);
- }
- #ifdef UartPrintf_Test_ATY
- /**
- * @brief Comprehensive on-board test for UartPrintf, covering all format specifiers
- * @note Ensure the serial port is connected and the terminal is open with matching baudrate
- * @example Call UartPrintf_Test_All(&HW_UART_ATY_Dev_1) inside main()
- */
- void UartPrintf_Test_All(struct HW_UART_ATY_Dev* dev){
- /* 1. Basic chars and strings */
- UartPrintf(dev, "=== 1. Basic chars and strings ===\r\n");
- UartPrintf(dev, "char: %c, %c, %c\r\n", 'A', '0', '\n');
- UartPrintf(dev, "str: %s, %s, %s\r\n", "Hello", "", "STC51");
- /* 2. Integers (decimal) */
- UartPrintf(dev, "=== 2. Integers (decimal) ===\r\n");
- UartPrintf(dev, "int: %d, %d, %d, %d\r\n", 0, 123, -456, 2147483647);
- UartPrintf(dev, "uint: %u, %u, %u\r\n", 0, 65535, 4294967295UL);
- /* 3. Hexadecimal */
- UartPrintf(dev, "=== 3. Hexadecimal ===\r\n");
- UartPrintf(dev, "lowercase: %x, %x, %x\r\n", 0, 0x5F, 0xDEADBEEF);
- UartPrintf(dev, "uppercase: %X, %X, %X\r\n", 0, 0x5F, 0xDEADBEEF);
- /* 4. Floating point */
- UartPrintf(dev, "=== 4. Floating point ===\r\n");
- UartPrintf(dev, "default: %f, %f\r\n", 0.0, -3.1415926);
- UartPrintf(dev, "precision: %.2f, %.6f, %.0f\r\n", 3.1415926, 3.1415926, 3.1415926);
- UartPrintf(dev, "large: %f\r\n", 1e6);
- UartPrintf(dev, "small: %f\r\n", 1e-6);
- /* 5. Pointers */
- UartPrintf(dev, "=== 5. Pointers ===\r\n");
- void* p = (void*)0x1234;
- UartPrintf(dev, "ptr: %p\r\n", p);
- /* 6. Specials and escapes */
- UartPrintf(dev, "=== 6. Special characters ===\r\n");
- UartPrintf(dev, "%% %%\r\n");
- UartPrintf(dev, "mixed: %d|%u|%x|%X|%c|%s|%f\r\n", -1, 255, 255, 255, 'X', "END", 2.718);
- /* 7. Scientific notation */
- UartPrintf(dev, "=== 7. Scientific notation ===\r\n");
- UartPrintf(dev, "%.2e, %.6e, %.0e\r\n", 12345.6789, 0.000012345, 12345.0);
- /* End marker */
- UartPrintf(dev, "=== UartPrintf test completed ===\r\n");
- }
- /**
- * @brief Quickly verify UartPrintf basic functions with minimal ROM/RAM usage
- */
- void UartPrintf_Test_Quick(struct HW_UART_ATY_Dev* dev){
- UartPrintf(dev, "QuickTest: %c %s %d %u %x %X %.3f %p %e\r\n",
- 'Q',
- "OK",
- -123,
- 123,
- 0xAB,
- 0xAB,
- 3.14,
- (void*)0x2025,
- 12345.6789);
- }
- #endif /* UartPrintf_Test_ATY */
- #endif /* __HW_UART_ATY_C */
- /************************************ etc *************************************/
- /* init */
- /* STM32 (Open uart global IT, open rx DMA(Mode Normal, Width Byte) and default DMA IT) */
- // Uart ------------------------------------------------------------------------
- // #include "HW_UART_ATY.h"
- // extern DMA_HandleTypeDef hdma_usart1_rx;
- // void UartReceiveProcess_User_1(void);
- // void UartInit_1(uint8_t* rx){
- // HAL_UARTEx_ReceiveToIdle_DMA(&huart1, rx, UART_RX_MAX_LEN);
- // __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
- // }
- // void UartSendByte_1(uint8_t byte){
- // HAL_UART_Transmit(&huart1, (uint8_t*)&byte, 1, 0xFFFF);
- // }
- // struct HW_UART_ATY_Dev HW_UART_ATY_Dev_1 = {
- // // .rx = uartRx1,
- // .rx = {0},
- // .rxCount = 0,
- // .txCount = 0,
- // .rcvOverTimeOutCountNum = 1,
- // .rcvOverTimeOutCount = 0,
- // .rcvOverFlag = 0,
- // .uartInitFlag = 0,
- // .uartInit = UartInit_1,
- // .uartSendByte = UartSendByte_1,
- // .uartReceiveProcess_User = UartReceiveProcess_User_1,
- // .lock = __ATY_UNLOCKED
- // };
- // void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef* huart, uint16_t Size){
- // if(huart == &huart1){
- // HAL_UART_DMAStop(&huart1);
- // HW_UART_ATY_Dev_1.rcvOverTimeOutCount = 0;
- // HW_UART_ATY_Dev_1.rxCount = UART_RX_MAX_LEN - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
- // HW_UART_ATY_Dev_1.rcvOverFlag = 0;
- // HAL_UARTEx_ReceiveToIdle_DMA(&huart1, HW_UART_ATY_Dev_1.rx, UART_RX_MAX_LEN);
- // __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
- // }
- // }
- /* 51 */
- /* use */
- // void main()
- // {
- // UartPrintf(&HW_UART_ATY_Dev_1, "\r\nHello word!\r\n",);
- // while (1)
- // {
- // UartReceiveProcess(&HW_UART_ATY_Dev_1);
- // }
- // }
- // /**
- // * @brief uart receive data analysis in user define self
- // */
- // void UartReceiveProcess_User_1(void){
- // if(HW_UART_ATY_Dev_1.rx[0] == 'O'
- // && HW_UART_ATY_Dev_1.rx[1] == 'K'
- // && HW_UART_ATY_Dev_1.rx[2] == '?')
- // printf_ATY("OK!");
- // if(HW_UART_ATY_Dev_1.rx[0] == 'P'
- // && HW_UART_ATY_Dev_1.rx[1] == 'W'
- // && HW_UART_ATY_Dev_1.rx[2] == 'R'
- // && HW_UART_ATY_Dev_1.rx[3] == 'O'
- // && HW_UART_ATY_Dev_1.rx[4] == 'F'
- // && HW_UART_ATY_Dev_1.rx[5] == 'F'
- // )
- // PWR_BTN_Off(&PWR_BTN_ATY_t_1);
- //
- // // echo back, both type has tested
- // UartSendBytes(HW_UART_ATY_Dev_1.rx, HW_UART_ATY_Dev_1.rxCount, &HW_UART_ATY_Dev_1);
- // UartPrintf(&HW_UART_ATY_Dev_1, "\r\n%s\r\n", HW_UART_ATY_Dev_1.rx);
- //
- // if(HW_UART_ATY_Dev_1.rxCount != 0){
- // Modbus_Process(HW_UART_ATY_Dev_1.rx, HW_UART_ATY_Dev_1.rxCount, &MODBUS_S_LOW_ATY_Dev_1);
- // if(MODBUS_S_LOW_ATY_Dev_1.setFlag == 1){
- // MODBUS_S_LOW_ATY_Dev_1.setFlag = 0;
- // TransMbRegsToFloat(mbG, &MODBUS_S_LOW_ATY_Dev_1);
- // }
- // // memcpy((char*)cdcStr, ((const char*)(HW_UART_ATY_Dev_3.rx)), HW_UART_ATY_Dev_3.rxCount);
- // // CDC_Transmit_FS(cdcStr, HW_UART_ATY_Dev_3.rxCount);
- // // memset(cdcStr, 0, HW_UART_ATY_Dev_3.rxCount);
- // // HW_UART_ATY_Dev_3.rxCount = 0;
- // }
- // }
- /******************************************************************************/
- /******************************** End Of File *********************************/
|