/**
* @file HW_UART_ATY.c
*
* @param Project DEVICE_GENERAL_ATY_LIB
*
* @author ATY
*
* @copyright
* - Copyright 2017 - 2023 MZ-ATY
* - This code follows:
* - MZ-ATY Various Contents Joint Statement -
*
* https://mengze.top/MZ-ATY_VCJS
* - CC 4.0 BY-NC-SA -
*
* https://creativecommons.org/licenses/by-nc-sa/4.0/
* - Your use will be deemed to have accepted the terms of this statement.
*
* @brief Familiar functions of uart for STC51
*
* @version
* - 1_01_221231 > ATY
* -# Preliminary version, first Release
* -Undone: over with "\r\n" type
********************************************************************************
*/
#ifndef __HW_UART_ATY_C
#define __HW_UART_ATY_C
#include "HW_UART_ATY.h"
struct _uartMsgStruct uartMsgStruct_t = {0};
/******************************* For user *************************************/
#if defined(__STC51_ATY)
#define BRT (uint32_t)(65536 - (uint32_t)FOSC / BAUD_RATE / 4)
// #define FOSC 5529600UL // 5.5296MHz MCU frequency
#define FOSC 24000000UL // 24MHz MCU frequency
#define BAUD_RATE 115200
/**
* @brief uart hardware init
* @note put at main init
*/
void UartInit(void)
{
SCON = 0x50; // 8bit data, variable baud rate
AUXR |= 0x40; // timer clk 1T mode
AUXR &= 0xFE; // user timer 1 as uart1 baud generate
TMOD &= 0x0F; // set timer mode
TL1 = BRT; // set timer origin value
TH1 = BRT >> 8; // set timer origin value
ET1 = 0; // disable timer IT
TR1 = 1; // start timer 1
// TI = 1;
uartMsgStruct_t.rxCount = 0x00;
uartMsgStruct_t.txCount = 0x00;
uartMsgStruct_t.busyFlag = 0;
ES = 1; // UART interrupt enable
EA = 1; // Global interrupt enable
}
/**
* @brief uart IT callback function
*/
void UartIsr(void) INTERRUPT(4)
{
if(TI)
{
TI = 0;
uartMsgStruct_t.busyFlag = 0;
}
if(RI)
{
RI = 0;
if(uartMsgStruct_t.rxCount < UART_RX_MAX_LEN)
{
uartMsgStruct_t.overCount = 0;
uartMsgStruct_t.rx[uartMsgStruct_t.rxCount++] = SBUF;
}
}
}
/**
* @brief uart send byte
* @param byte byte to send
*/
void UartSendByte(uint8_t byte)
{
uint8_t errCount = 0;
while(uartMsgStruct_t.busyFlag == 1)
{
errCount++;
if(errCount > 200)
break;
}
uartMsgStruct_t.busyFlag = 1;
SBUF = byte;
}
#elif defined(__STM32_HAL_ATY)
#include "usart.h"
void UartSendByte(uint8_t byte)
{
uint8_t i = 0;
for(i = 0; i < uartMsgStruct_t.rxCount; i++)
uartMsgStruct_t.rx[i] = 0;
uartMsgStruct_t.rxCount = 0;
#ifdef LL
LL_USART_TransmitData8(PRINTF_UART, byte);
while(!LL_USART_IsActiveFlag_TC(PRINTF_UART)){}
#else
HAL_UART_Transmit(&PRINTF_UART, (uint8_t*)&byte, 1, 0xFFFF);
#endif
}
/**
* @brief uart hardware init
* @note put at main init
* use DMA IDEL type, open uart IT and add rx dma, mode in Normal(not Circular!), data with byte
*/
void UartInit(void)
{
// __HAL_UART_ENABLE_IT(&PRINTF_UART, UART_IT_IDLE);
HAL_UARTEx_ReceiveToIdle_DMA(&PRINTF_UART, uartMsgStruct_t.rx, UART_RX_MAX_LEN);
__HAL_DMA_DISABLE_IT(&PRINTF_DMA, DMA_IT_HT);
uartMsgStruct_t.rxCount = 0x00;
uartMsgStruct_t.txCount = 0x00;
uartMsgStruct_t.busyFlag = 0;
}
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef* huart, uint16_t Size)
{
if(huart->Instance == USART1){
HAL_UART_DMAStop(&PRINTF_UART);
uartMsgStruct_t.overCount = 0;
uartMsgStruct_t.rxCount = UART_RX_MAX_LEN - __HAL_DMA_GET_COUNTER(&PRINTF_DMA);
HAL_UARTEx_ReceiveToIdle_DMA(&PRINTF_UART, uartMsgStruct_t.rx, UART_RX_MAX_LEN);
__HAL_DMA_DISABLE_IT(&PRINTF_DMA, DMA_IT_HT);
}
/* if process is not too long, process function can be used at this call back;
otherwise put process at other cycle like while or timer cycle */
// PrintfReceiveProcess();
}
#ifndef __MICROLIB
// for standart lib(not use MicroLIB)
#pragma import(__use_no_semihosting)
// define _sys_exit to avoid semi-host mode
void _sys_exit(int x)
{
x = x;
}
struct __FILE
{
int handle;
};
FILE __stdout;
#endif /* __MICROLIB */
/* In gcc, using printf() output, if there is no "\n" in output data, no data
will be printed on the screen until "\n" is encountered or the buffer overflows
Another way to refresh the output data is to run "fflush(stdout)" after
sending the data to force a refresh of the output stream
*/
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#define GETCHAR_PROTOTYPE int __io_getchar(void)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#define GETCHAR_PROTOTYPE int fgetc(FILE *f)
#endif /* __GNUC__ */
PUTCHAR_PROTOTYPE \
{
#ifdef LL
LL_USART_TransmitData8(PRINTF_UART, ch);
while(!LL_USART_IsActiveFlag_TC(PRINTF_UART)){}
#else
HAL_UART_Transmit(&PRINTF_UART, (uint8_t*)&ch, 1, 0xFFFF);
#endif
return ch;
}
GETCHAR_PROTOTYPE \
{
uint8_t ch = 0;
HAL_UART_Receive(&PRINTF_UART, &ch, 1, 0xFFFF);
return ch;
}
#ifdef DEBUG_PRINTF_RECEIVE
uint8_t uartPrintfRxBuf[PRINTF_RX_MAX_LEN];
struct _uartMsgStruct uartPrintfMsgStruct = {*uartPrintfRxBuf, 0};
/**
* @brief init uart IT and DMA etc.
*/
void PrintfReceiveInit(void)
{
HAL_UARTEx_ReceiveToIdle_DMA(&PRINTF_UART, uartPrintfMsgStruct.rx, PRINTF_RX_MAX_LEN);
__HAL_DMA_DISABLE_IT(&PRINTF_DMA, DMA_IT_HT);
}
/**
* @brief uart receive data analysis
* @note put at main while
*/
__WEAK_ATY void PrintfReceiveProcess(void)
{
struct _uartMsgStruct* ptr = &uartPrintfMsgStruct;
if(ptr->rcvOverFlag)
{
ptr->rcvOverFlag = 0;
PrintfReceiveProcess_User(ptr);
PrintfReceiveInit();
}
}
__WEAK_ATY void PrintfReceiveProcess_User(struct _uartMsgStruct* ptr)
{
// if(memcmp("DSTART", (char*)ptr->rx, strlen("DSTART")) == 0)
// {
// printf("\r\nDebug START!");
// }
// else if(memcmp("temp", (char*)ptr->rx, strlen("temp")) == 0)
// {
// printf("\r\ntemp %c%c%c",
// ptr->rx[strlen("temp_")],
// ptr->rx[strlen("temp_") + 1],
// ptr->rx[strlen("temp_") + 2]);
// }
}
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef* huart, uint16_t Size)
{
HAL_UART_DMAStop(&PRINTF_UART);
uartPrintfMsgStruct.rxCount = PRINTF_RX_MAX_LEN - __HAL_DMA_GET_COUNTER(&PRINTF_DMA);
uartPrintfMsgStruct.rcvOverFlag = 1;
/* if process is not too long, process function can be used at this call back;
otherwise put process at other cycle like while or timer cycle */
// PrintfReceiveProcess();
}
#endif /* DEBUG_PRINTF_RECEIVE */
#endif /* PLATFORM */
/******************************************************************************/
/**
* @brief uart send bytes
* @param bytes bytes to send
* @param len bytes to send
*/
void UartSendBytes(uint8_t* bytes, uint16_t len)
{
while(len--)
UartSendByte(*bytes++);
}
/**
* @brief uart send string
* @param str data to send
*/
void UartSendStr(uint8_t* str)
{
while(*str)
UartSendByte(*str++);
}
/**
* @brief uart send float data in little endian
* @param dataFloat float number
*/
void UartSendFloat(float dataFloat)
{
union result
{
float temp_f;
uint8_t temp_uint8[4];
}resultA, resultB;
resultA.temp_f = dataFloat;
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];
UartSendByte(resultB.temp_uint8[3]);
UartSendByte(resultB.temp_uint8[2]);
UartSendByte(resultB.temp_uint8[1]);
UartSendByte(resultB.temp_uint8[0]);
}
/**
* @brief uart send float data in ASCII character type
* @param dataFloat number to send, use double to get better
* @note float and double is the same in C51
*/
// void UartSendFloatStr(double dataFloat)
void UartSendFloatStr(float dataFloat)
{
#define DECIMALS_NUM 4
uint8_t i = 0, j = 0;
uint8_t dataStr[10]; // ulongint 4294967295, 6.4f
unsigned long int tempSaveData = 0;
for(i = 0; i < 10; i++)
dataStr[i] = 0;
if(dataFloat < 0)
{
dataFloat = -dataFloat;
UartSendByte('-');
}
tempSaveData = (dataFloat * 10000) + 0.5;
for(i = 0; tempSaveData != 0; i++)
{
dataStr[10 - 1 - i] = tempSaveData % 10;
tempSaveData /= 10;
}
// UartSendByte(i + 48);
if(i < 5)
i = 5;
while(i--)
{
UartSendByte(dataStr[10 - 1 - i] + 48);
if(i == DECIMALS_NUM)
UartSendByte('.');
}
UartSendByte(' ');
}
/**
* @brief uart receive data process
* @note put at main while
*/
__WEAK_ATY void UartReceiveProcess(void)
{
// if(uartMsgStruct_t.overCount >= 10000)
if(uartMsgStruct_t.overCount > 2000)
{
uartMsgStruct_t.overCount = 0;
if(uartMsgStruct_t.rxCount != 0)
{
// UartSendStr(&uartMsgStruct_t.rxCount);
UartReceiveProcess_User(&uartMsgStruct_t);
while(uartMsgStruct_t.rxCount){
uartMsgStruct_t.rx[uartMsgStruct_t.rxCount--] = 0;
}
}
}
else
uartMsgStruct_t.overCount++;
}
// /**
// * @brief uart receive data analysis in user define self
// */
// void UartReceiveProcess_User(struct _uartMsgStruct* ptr)
// {
// if(ptr->rx[0] == 'O' && ptr->rx[1] == 'K')
// UartSendStr("\r\nRC OK!\r\n");
// // UartSendStr(ptr->rx);
// }
// void main()
// {
// UartInit();
// UartSendStr("Uart Test !\r\n");
// while (1)
// {
// UartReceiveProcess();
// }
// }
#endif /* __HW_UART_ATY_C */
/******************************** End Of File *********************************/