I am converting a standard UART interface into RS485.
The flow of the program is presented in the flowchart below. The sensor is waiting for a command and when it is received, the sensor sends data continuosly utill a stop command is issued
Both in the sensor and in the RS485 to USB interface the DE pin is connected to the RE pin of the tranceiver. In the sensor the two pins are connected to the CBUS2 pin of the chip FT232RL (this pin is configured as RXLED). In the sensor the two pins are connected to PORTF.3 of TM4C123 microcontroller.
The RS485 link I used in the test is few centimeters long and both the sensor and the interface have 120 Ohm termination resistors. ISL83485 is used as transceiver. Only in the interface the A pin is connected with a 560Ohm pull-up resistor and the B pin with a 560 Ohm pull-down resistor.
The baudrate is 230400 but in the final configuration will be raised to 500k baud
Concerning the firmware side, I have made two tests
1) DE and RE* are low when the program starts. When the command is issued, DE and RE* are driven high at the beginning of the routine UARTSEND() and are driven low at the end of this routine. In this configuration the start command is issued correctly but garbage data are received when sensor is transmitting. Another unexpected behaviour is that the stop command cannot be received correctly by the sensor
2) DE and RE* are low when the program starts. When the command is issued, DE and RE* are driven high at the beginning of the routine UARTSEND() and then are not driven low ath the end of the routine. In this configuration data are received correctly
I attach the most relevant part of the code for the communication point of view?
What I am missing? What is a suitable way of drive RS485 direction control signals for the firmware point of view?
Thanks in advance
void UART1IntHandler(void) { uint32_t ui32StatusRX; RingBufFlush(&rxRingBuf); // // Get the interrupt status. // ui32StatusRX = ROM_UARTIntStatus(UART1_BASE, true); // // Clear the asserted interrupts. // ROM_UARTIntClear(UART1_BASE, ui32StatusRX); // The receive timeout interrupt fires when you have received bytes in your FIFO but have not // gotten enough to fire your Rx interrupt. This is because the FIFO level select determines when that // T_RT) { // While there are bytes to read and there is space in the FIFO. while(UARTCharsAvail(UART1_BASE) && RingBufFull(&rxRingBuf) == false) { uint32_t ch = (uint8_t)ROM_UARTCharGet(UART1_BASE); // Write a byte straight from the hardware FIFO into our Rx FIFO for processing later. RingBufWriteOne(&rxRingBuf, ch); } } if((ui32StatusRX & UART_INT_RX) == UART_INT_RX) { // // Loop while there are characters in the receive FIFO. // while(ROM_UARTCharsAvail(UART1_BASE) && RingBufFull(&rxRingBuf) == false) { // // Read the next character from the UART // uint32_t ch = (uint8_t)ROM_UARTCharGet(UART1_BASE); RingBufWriteOne(&rxRingBuf,ch); } } } void UARTSend(const uint8_t *pui8Buffer, uint32_t ui32Count) { GPIO_PORTF_DATA_R |= TX_EN_RS485; while(ui32Count--) { ROM_UARTCharPut(UART1_BASE, *pui8Buffer++); } GPIO_PORTF_DATA_R &= ~ TX_EN_RS485; } void ADXL357_SendAllAccData(void) { char string[10]; //collect data from sensor; the variable sample_in.z contains sensor data sprintf(string,"%+.6f",sample_in.z); UARTSend((uint8_t *)string,strlen(string)); UARTSend("\n",1); } int main(void){ uint8_t ret = false; uint8_t acc_continuous_scan = 0x00; uint8_t module_continuous_scan = 0x00; ROM_IntMasterDisable(); ConfigureMicroProcessor(); LEDsTest(); ROM_IntMasterEnable(); GPIO_PORTF_DATA_R &= ~ TX_EN_RS485; while(1) { if(RingBufEmpty(&rxRingBuf) == false) { // Did we receive enough bytes that it could be a message? if(RingBufUsed(&rxRingBuf) == sizeof(uint8_t[8])) { uint8_t rec[8]; // Read the bytes into our received message structure. RingBufRead(&rxRingBuf, (uint8_t*)&rec, sizeof(receivedMsg)); // Additional address if (rec[2] == '0' && rec[3] == '1') { ADXL357_SendAllAccData(); } } } } }