📄 uart.c
字号:
}
if (index == SIZE_UART_OUT_ARRAY) // If we go past the end ...
{
index = 0; // ... start over at the beginning
}
}
if(returnValue != 0)
{
// Do something...
}
return (returnValue);
}
//==========================================================================================
// Function: WriteUARTString()
//
// Description: This function is used to interface between the code and the function
// which sends data to the UART (SendUART()).
//
// This routine accepts a count, and a pointer to the start of data. It
// then inserts an entry into the array UARTDataOut which TaskWriteUART
// uses to send out data.
// Note that it will store the count and pointer, not buffer the actual
// data, so the calling function must keep the variable around (static or
// global), or else use the function WriteUARTValue().
//
// Input: s16 count; Number of words to transfer.
// u16* dataPtr; Pointer to start of data.
//
// Return: SUCCESS Added to list. (not necesarily sent yet)
// ERR_LIST_FULL No buffer space.
//
// Revision History:
//==========================================================================================
s16 WriteUARTString(u16* msgString)
{
#define UART_OUT_BUFF_SIZE 256
static u16 UARTOutBuff[UART_OUT_BUFF_SIZE];
static s16 indexS = 0; // Index into UARTOutBuff
s16 returnValue; // Function return value
s16 msgLen=-1; // Length of message string
u16 uLengthFound=0; // Flag used to find string length.
u16 i; // Loop index
// We don't want to sent a trailing NULL, so start the count at -1, so it doesn't show up in the count
while( (uLengthFound==0) && (msgLen<20) )
{
if(msgString[++msgLen] == 0) // Found string terminator
{
uLengthFound = 1;
}
}
// Append the msgString to the end of UARTOutBuff if there is room, otherwise start back at the beginning
if (indexS + msgLen + 1 >= UART_OUT_BUFF_SIZE)
{
indexS = 0;
}
// Copy received string into UARTOutBuff.
for(i=0; i<msgLen; i++)
{
UARTOutBuff[indexS + i] = msgString[i];
}
returnValue = WriteUART(UART_TARGET_EMETER, msgLen, &UARTOutBuff[indexS]); // target,count,pointer
indexS += msgLen; // Point to next available location for next pass.
if(returnValue != 0)
{
// Do something...
}
return (returnValue);
}
//==========================================================================================
// Function: uart_read()
//
// Description: This routine recieves data into the supplied buffer.
//
// Parameters: buf - buffer to read data into.
// offset - byte offset in buf to begin receiving chars.
// cnt - number of data samples to capture into buffer.
//
// Return: Last character read.
//
// Revision History:
//==========================================================================================
u16 uart_read(u16* pBuf, u16 offset, u16 cnt)
{
u16 uReturnChar;
INTR_GLOBAL_DISABLE();
while (cnt--)
{
while (uUartBufferPointerIn == uUartBufferPointerOut)
{
// Wait for RX data ready.
}
uReturnChar = upUartBufferFifo[uUartBufferPointerOut];
if(++uUartBufferPointerOut >= UART_BUFFER_SIZE)
{
uUartBufferPointerOut = 0;
}
// even byte? (first half goes in high nibble)
if(offset/2 == (offset+1)/2)
{
pBuf[offset/2] &= 0x00FF; // Clear bits
pBuf[offset/2] |= (u8) (uReturnChar & 0x00FF)<<8;
}
else // odd.
{
pBuf[offset/2] &= 0xFF00;
pBuf[offset/2] |= (u8) (uReturnChar & 0x00FF);
}
offset++;
}
INTR_GLOBAL_ENABLE();
return(uReturnChar);
}
//==========================================================================================
// Function: SelectUARTTarget()
//
// Description: This function selects the target for UART communication.
// Choices are UART_TARGET_HOST (1) or UART_TARGET_EMETER (0).
//
// Revision History:
//==========================================================================================
void SelectUARTTarget(u16 UARTTarget)
{
uUARTTarget = UARTTarget; // Set global variable
AssignBits(GPIOSR, 1<<5, UARTTarget<<5); // Send target receive select signal via DSP GPIO pin
if(UARTTarget == UART_TARGET_HOST) // 1
{
AssignBits(UART_MCR_REG, 1<<3, 0); // Send target transmit select signal via OUT2 pin on 16C550
}
else
{
AssignBits(UART_MCR_REG, 1<<3, 1<<3); // Send target transmit select signal via OUT2 pin on 16C550
}
AssignBits(UART_MCR_REG, 1<<2, UARTTarget<<2); // Send target transmit select signal via OUT2 pin on 16C550
DebugDelay(); // Flush C54x if in debug mode.
DelayNus(100); // Improves errors related to RS232/RS485 switching.
}
//==========================================================================================
// Function: SelectRS485Direction()
//
// Description: This function selects the data flow direction of the RS485 connection.
// Choices are RS485_TALK (3) or RS485_LISTEN (0).
//
// Note that the default direction is LISTEN. Code that changes it to
// TALK, MUST restore it.
//
// Revision History:
//==========================================================================================
void SelectRS485Direction(u16 RS485Dir)
{
AssignBits(GPIOSR, 3<<3, RS485Dir<<3); // Send direction control signal via GPIO pins
DebugDelay(); // Flush C54x if in debug mode.
// Give drives time to get up.
DelayNus(25);
}
//==========================================================================================
// Function: UartISR()
//
// Description: This is the Interrupt Service Routine for INT1 which is tied to the
// 16C550. It handles switching RS485 direction between talk and listen
// after the transmit message has been sent, along with source switching
// between the host and emeter if required.
//
// Revision History:
//==========================================================================================
interrupt void UartISR(void)
{
// Check reason for interrupt.
if(UART_IIR_REG & UART_IIR_TRANSMIT_EMPTY == UART_IIR_TRANSMIT_EMPTY) // Data has gone out
{
// To get to this point, means we've just finished sending a string to the emeter.
// Now reconfigure the 485 to listen, and if we're not expecting a return value from the
// emeter, set the 16C550 to listen to the host, not the meter. If we are expecting an
// emter reply, the switch back to the host will be handled after receiving the emeter data.
DelayNus(10); // Time for last bit to get transfered. Probably not needed, but 10 usec won't hurt anything.
// We turn off PLC traffic while the last byte is transferred to make sure that the plc
// traffic doesn't hold off this interrupt and prevent us from switching back to LISTEN.
// The same flag (uHoldOffPLC) is also used to disable PLC traffic during an flash
// update, so only Re-enable it here if we were stopped for the last byte.
if(uLastByteFlag == 1)
{
uHoldOffPLC = 0; // Allow PLC to continue.
uLastByteFlag = 0; // Reset for next time.
}
SelectRS485Direction(RS485_LISTEN); // Set RS485 to listen to e-meter.
if (uBoard == BOARD_MASTER)
{
if(uUartState == UART_RECEIVE_COMMAND) // This gets set by ProcessMasterCommand() before command is issued
{ // It covers the problem of the EMeter not sending anything back
// but the host still needing a response.
SelectUARTTarget(UART_TARGET_HOST);
if(uAckAfter485 == 1)
{
// No real status to send back, this just lets the host know that we're ready
// for the next command.
WriteUARTValue(UART_TARGET_HOST, SUCCESS);
uAckAfter485 = 0;
ulAutoPollCounter = 0L;
uAutoPollPause = 0;
}
}
//else // uUartState == UART_RECEIVE_RESPONSE. We're expecting to get data back
//{ // from the emeter. Nothing else to do other than switch to RS485_LISTEN.
//} // which was done above.
}
else // board == slave.
{
if(uAckAfter485 == 1)
{
// Note that this response isn't actually from the emeter.
uAckAfter485 = 0;
uTransmitPacketReady = 1;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -