2025-03-30 16:23:29 +08:00
|
|
|
/*
|
|
|
|
Software Uart For Stm32
|
|
|
|
By Liyanboy74
|
|
|
|
https://github.com/liyanboy74
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "softuart.h"
|
|
|
|
|
|
|
|
// Some internal define
|
|
|
|
#if (SoftUart_PARITY)
|
|
|
|
#define SoftUart_IDEF_LEN_C1 (SoftUart_DATA_LEN + 2)
|
|
|
|
#else
|
|
|
|
#define SoftUart_IDEF_LEN_C1 (SoftUart_DATA_LEN + 1)
|
|
|
|
#endif
|
|
|
|
#define SoftUart_IDEF_LEN_C2 (SoftUart_IDEF_LEN_C1 + SoftUart_STOP_Bit)
|
|
|
|
|
|
|
|
// All Soft Uart Config and State
|
2025-03-30 18:36:35 +08:00
|
|
|
SoftUart_S SUart;
|
2025-03-30 16:23:29 +08:00
|
|
|
|
|
|
|
// TX RX Data Buffer
|
2025-03-30 18:36:35 +08:00
|
|
|
SoftUartBuffer_S SUBuffer;
|
2025-03-30 16:23:29 +08:00
|
|
|
|
|
|
|
// For timing division
|
2025-03-30 18:36:35 +08:00
|
|
|
uint8_t SU_Timer = 0;
|
2025-03-30 16:23:29 +08:00
|
|
|
|
|
|
|
// Parity var
|
|
|
|
static uint8_t DV, PCount;
|
|
|
|
|
|
|
|
// Initial Soft Uart
|
2025-03-30 18:36:35 +08:00
|
|
|
SoftUart_S *SoftUartInit() {
|
|
|
|
SUart.TxNComplated = 0;
|
2025-03-30 16:23:29 +08:00
|
|
|
|
2025-03-30 18:36:35 +08:00
|
|
|
SUart.RxBitCounter = 0;
|
|
|
|
SUart.RxBitShift = 0;
|
|
|
|
SUart.RxIndex = 0;
|
2025-03-30 16:23:29 +08:00
|
|
|
|
2025-03-30 18:36:35 +08:00
|
|
|
SUart.TxEnable = 0;
|
|
|
|
SUart.RxEnable = 0;
|
2025-03-30 16:23:29 +08:00
|
|
|
|
2025-03-30 18:36:35 +08:00
|
|
|
SUart.TxBitCounter = 0;
|
|
|
|
SUart.TxBitShift = 0;
|
|
|
|
SUart.TxIndex = 0;
|
2025-03-30 16:23:29 +08:00
|
|
|
|
2025-03-30 18:36:35 +08:00
|
|
|
SUart.TxSize = 0;
|
2025-03-30 16:23:29 +08:00
|
|
|
|
2025-03-30 18:36:35 +08:00
|
|
|
SUart.Buffer = &SUBuffer;
|
2025-03-30 16:23:29 +08:00
|
|
|
|
2025-03-30 18:36:35 +08:00
|
|
|
SUart.RxTimingFlag = 0;
|
|
|
|
SUart.RxBitOffset = 0;
|
2025-03-30 16:23:29 +08:00
|
|
|
|
2025-03-30 18:36:35 +08:00
|
|
|
return &SUart;
|
2025-03-30 16:23:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Send one bit to TX pin
|
|
|
|
void SoftUartTransmitBit(SoftUart_S *SU, uint8_t Bit0_1) {
|
2025-03-30 18:36:35 +08:00
|
|
|
SU->TxPinValue = Bit0_1;
|
2025-03-30 16:23:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Enable Soft Uart Receiving
|
2025-03-30 18:36:35 +08:00
|
|
|
SoftUartState_E SoftUartEnableRx() {
|
|
|
|
SUart.RxEnable = 1;
|
2025-03-30 16:23:29 +08:00
|
|
|
return SoftUart_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Disable Soft Uart Receiving
|
2025-03-30 18:36:35 +08:00
|
|
|
SoftUartState_E SoftUartDisableRx() {
|
|
|
|
SUart.RxEnable = 0;
|
2025-03-30 16:23:29 +08:00
|
|
|
return SoftUart_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Read Size of Received Data in buffer
|
2025-03-30 18:36:35 +08:00
|
|
|
uint8_t SoftUartRxAlavailable() { return SUart.RxIndex; }
|
2025-03-30 16:23:29 +08:00
|
|
|
|
|
|
|
// Move Received Data to Another Buffer
|
2025-03-30 18:36:35 +08:00
|
|
|
SoftUartState_E SoftUartReadRxBuffer(uint8_t *Buffer, uint8_t Len) {
|
2025-03-30 16:23:29 +08:00
|
|
|
int i;
|
|
|
|
for (i = 0; i < Len; i++) {
|
2025-03-30 18:36:35 +08:00
|
|
|
Buffer[i] = SUart.Buffer->Rx[i];
|
2025-03-30 16:23:29 +08:00
|
|
|
}
|
2025-03-30 18:36:35 +08:00
|
|
|
for (i = 0; i < SUart.RxIndex; i++) {
|
|
|
|
SUart.Buffer->Rx[i] = SUart.Buffer->Rx[i + Len];
|
2025-03-30 16:23:29 +08:00
|
|
|
}
|
2025-03-30 18:36:35 +08:00
|
|
|
SUart.RxIndex -= Len;
|
2025-03-30 16:23:29 +08:00
|
|
|
return SoftUart_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Soft Uart Transmit Data Process
|
|
|
|
void SoftUartTxProcess(SoftUart_S *SU) {
|
|
|
|
if (SU->TxEnable) {
|
|
|
|
// Start
|
|
|
|
if (SU->TxBitCounter == 0) {
|
|
|
|
SU->TxNComplated = 1;
|
|
|
|
SU->TxBitShift = 0;
|
|
|
|
SoftUartTransmitBit(SU, 0);
|
|
|
|
SU->TxBitCounter++;
|
|
|
|
PCount = 0;
|
|
|
|
}
|
|
|
|
// Data
|
|
|
|
else if (SU->TxBitCounter < (SoftUart_DATA_LEN + 1)) {
|
|
|
|
DV = ((SU->Buffer->Tx[SU->TxIndex]) >> (SU->TxBitShift)) & 0x01;
|
|
|
|
SoftUartTransmitBit(SU, DV);
|
|
|
|
SU->TxBitCounter++;
|
|
|
|
SU->TxBitShift++;
|
|
|
|
|
|
|
|
if (DV) PCount++;
|
|
|
|
}
|
|
|
|
// Parity
|
|
|
|
else if (SU->TxBitCounter < SoftUart_IDEF_LEN_C1) {
|
|
|
|
// Check Even or Odd
|
|
|
|
DV = PCount % 2;
|
|
|
|
|
|
|
|
// if Odd Parity
|
|
|
|
if (SoftUart_PARITY == 1) DV = !DV;
|
|
|
|
|
|
|
|
SoftUartTransmitBit(SU, DV);
|
|
|
|
SU->TxBitCounter++;
|
|
|
|
}
|
|
|
|
// Stop
|
|
|
|
else if (SU->TxBitCounter < SoftUart_IDEF_LEN_C2) {
|
|
|
|
SoftUartTransmitBit(SU, 1);
|
|
|
|
SU->TxBitCounter++;
|
|
|
|
}
|
|
|
|
// Complete
|
|
|
|
else if (SU->TxBitCounter == SoftUart_IDEF_LEN_C2) {
|
|
|
|
// Reset Bit Counter
|
|
|
|
SU->TxBitCounter = 0;
|
|
|
|
|
|
|
|
// Ready To Send Another Data
|
|
|
|
SU->TxIndex++;
|
|
|
|
|
|
|
|
// Check Size of Data
|
|
|
|
if (SU->TxSize > SU->TxIndex) {
|
|
|
|
// Continue Sending
|
|
|
|
SU->TxNComplated = 1;
|
|
|
|
SU->TxEnable = 1;
|
|
|
|
} else {
|
|
|
|
// Finish
|
|
|
|
SU->TxNComplated = 0;
|
|
|
|
SU->TxEnable = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Soft Uart Receive Data Process
|
|
|
|
void SoftUartRxDataBitProcess(SoftUart_S *SU, uint8_t B0_1) {
|
|
|
|
if (SU->RxEnable) {
|
|
|
|
// Start
|
|
|
|
if (SU->RxBitCounter == 0) {
|
|
|
|
// Start Bit is 0
|
|
|
|
if (B0_1) return;
|
|
|
|
|
|
|
|
SU->RxBitShift = 0;
|
|
|
|
SU->RxBitCounter++;
|
|
|
|
SU->Buffer->Rx[SU->RxIndex] = 0;
|
|
|
|
}
|
|
|
|
// Data
|
|
|
|
else if (SU->RxBitCounter < (SoftUart_DATA_LEN + 1)) {
|
|
|
|
SU->Buffer->Rx[SU->RxIndex] |= ((B0_1 & 0x01) << SU->RxBitShift);
|
|
|
|
SU->RxBitCounter++;
|
|
|
|
SU->RxBitShift++;
|
|
|
|
}
|
|
|
|
// Parity
|
|
|
|
else if (SU->RxBitCounter < SoftUart_IDEF_LEN_C1) {
|
|
|
|
// Need to be check
|
|
|
|
// B0_1;
|
|
|
|
SU->RxBitCounter++;
|
|
|
|
}
|
|
|
|
// Stop & Complete
|
|
|
|
else if (SU->RxBitCounter < SoftUart_IDEF_LEN_C2) {
|
|
|
|
SU->RxBitCounter = 0;
|
|
|
|
SU->RxTimingFlag = 0;
|
|
|
|
|
|
|
|
// Stop Bit must be 1
|
|
|
|
if (B0_1) {
|
|
|
|
// Received successfully
|
|
|
|
// Change RX Buffer Index
|
|
|
|
if ((SU->RxIndex) < (SoftUartRxBufferSize - 1)) (SU->RxIndex)++;
|
|
|
|
}
|
|
|
|
// if not : ERROR -> Overwrite data
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Wait Until Transmit Completed
|
|
|
|
// You do not usually need to use this function!
|
2025-03-30 18:36:35 +08:00
|
|
|
void SoftUartWaitUntilTxComplate() { while (SUart.TxNComplated); }
|
2025-03-30 16:23:29 +08:00
|
|
|
|
|
|
|
// Copy Data to Transmit Buffer and Start Sending
|
2025-03-30 18:36:35 +08:00
|
|
|
SoftUartState_E SoftUartPuts(uint8_t *Data, uint8_t Len) {
|
2025-03-30 16:23:29 +08:00
|
|
|
int i;
|
2025-03-30 18:36:35 +08:00
|
|
|
if (SUart.TxNComplated) return SoftUart_Error;
|
|
|
|
SUart.TxIndex = 0;
|
|
|
|
SUart.TxSize = Len;
|
2025-03-30 16:23:29 +08:00
|
|
|
for (i = 0; i < Len; i++) {
|
2025-03-30 18:36:35 +08:00
|
|
|
SUart.Buffer->Tx[i] = Data[i];
|
2025-03-30 16:23:29 +08:00
|
|
|
}
|
2025-03-30 18:36:35 +08:00
|
|
|
SUart.TxNComplated = 1;
|
|
|
|
SUart.TxEnable = 1;
|
2025-03-30 16:23:29 +08:00
|
|
|
return SoftUart_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Capture RX and Get BitOffset
|
2025-03-30 18:36:35 +08:00
|
|
|
uint8_t SoftUartScanRxPorts(SoftUart_S *SU) {
|
2025-03-30 16:23:29 +08:00
|
|
|
uint8_t Buffer = 0x00, Bit;
|
2025-03-30 18:36:35 +08:00
|
|
|
// Read RX GPIO Value
|
|
|
|
Bit = SU->RxPinValue;
|
|
|
|
// Starting conditions
|
|
|
|
if (!SUart.RxBitCounter && !SUart.RxTimingFlag && !Bit) {
|
|
|
|
// Save RX Bit Offset
|
|
|
|
// Calculate middle position of data puls
|
|
|
|
SUart.RxBitOffset = ((SU_Timer + 2) % 5);
|
|
|
|
// Timing Offset is Set
|
|
|
|
SUart.RxTimingFlag = 1;
|
2025-03-30 16:23:29 +08:00
|
|
|
}
|
2025-03-30 18:36:35 +08:00
|
|
|
// Add all RX GPIO State to Buffer
|
|
|
|
Buffer |= (Bit & 0x01);
|
2025-03-30 16:23:29 +08:00
|
|
|
return Buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
// SoftUartHandler must call in interrupt every 0.2*(1/BR)
|
|
|
|
// if BR=9600 then 0.2*(1/9600)=20.8333333 uS
|
|
|
|
void SoftUartHandler(void) {
|
|
|
|
uint8_t SU_DBuffer;
|
|
|
|
|
|
|
|
// Capture RX and Get BitOffset
|
2025-03-30 18:36:35 +08:00
|
|
|
SU_DBuffer = SoftUartScanRxPorts(&SUart);
|
|
|
|
// Receive Data if we in middle data pulse position
|
|
|
|
if (SUart.RxBitOffset == SU_Timer) {
|
|
|
|
SoftUartRxDataBitProcess(&SUart, (SU_DBuffer & 0x01));
|
2025-03-30 16:23:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Sending always happens in the first time slot
|
|
|
|
if (SU_Timer == 0) {
|
|
|
|
// Transmit Data
|
2025-03-30 18:36:35 +08:00
|
|
|
SoftUartTxProcess(&SUart);
|
2025-03-30 16:23:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Timing process
|
|
|
|
SU_Timer++;
|
|
|
|
if (SU_Timer >= 5) SU_Timer = 0;
|
|
|
|
}
|