Psoc4 Rs485 Txbuffer empty interrupt.

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
shanbhagm
Level 2
Level 2
5 questions asked 10 replies posted 10 sign-ins

Hi,

I am new to psoc. On our board we have Rs485 chip connected.

Due to much limitation I can only use SCB UART.

Now in code I need to make sure I set DE pin to high, then Transmit data , then set DE to Low.

I have used the below code to send. 

nRE_MICRO_Write(1);// RE/DE Pin High (Tx Mode)
DE_MICRO_Write(1);// RE/DE Pin High (Tx Mode)
UART_SpiUartPutArray(buf,len);// Send data
//https://lucidar.me/en/serialib/most-used-baud-rates-table/
// int sleepdur = MAX(1,86.06*len*8/1000.0+1);
// CyDelay(sleepdur);
nRE_MICRO_Write(0);// RE/DE Pin Low (Rx Mode)
DE_MICRO_Write(0);// RE/DE Pin Low (Rx Mode)

Now how do I guarantee that whole data is sent(buf,len)and I can set the pin back to Low for receive mode?

A quick response or any example project will be helpful.

 

Regards,

Madhav

 

 

0 Likes
1 Solution
AlenAn14
Moderator
Moderator
Moderator
500 replies posted 100 solutions authored 250 replies posted

Hi @shanbhagm ,

I found that using the TX_EMPTY interrupt will be a little difficult in your case as you will have to enable this interrupt just before you do the transmission and disable it afterwards , else when the TX FIFO is empty, the TX EMPTY interrupt will keep firing continuously.

So please use the UART Done interrupt instead of the earlier suggested TX_Empty interrupt for this purpose:

AlenAn14_0-1646895405664.png


The ISR code for the same for this will be as follows

#include "project.h"


void UART_ISR_HANDLER()
{
    //Check if Transmission was complete
    if (0u != (UART_GetTxInterruptSourceMasked() & UART_INTR_TX_UART_DONE))
    {
        UART_ClearTxInterruptSource(UART_INTR_TX_UART_DONE);
        
        /* Write code here to control the DE pin */
        UART_TXEnable_Write(0);// RE/DE Pin Low (Rx Mode)
        UART_RXEnable_Write(0);// RE/DE Pin Low (Rx Mode)
    }

}
int main(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */
    
    // Register the ISR
    UART_SetCustomInterruptHandler(UART_ISR_HANDLER);
    
    UART_Start();

    UART_TXEnable_Write(0);// RE/DE Pin Low (Rx Mode)
    UART_RXEnable_Write(0);// RE/DE Pin Low (Rx Mode)

    for(;;)
    {
        /* Set DE Pin High here before sending data */
        UART_TXEnable_Write(1);// RE/DE Pin High (Tx Mode)
        UART_RXEnable_Write(1);// RE/DE Pin High (Tx Mode)
        /* Transmit the data*/
        UART_UartPutString("Hello there, I sent data\r\n");
        CyDelay(1000);
    }
}

 

Warm Regards
Alen

View solution in original post

7 Replies
AlenAn14
Moderator
Moderator
Moderator
500 replies posted 100 solutions authored 250 replies posted

Hi @shanbhagm ,

You can use the UART_Full_Duplex code example for this purpose:

AlenAn14_0-1646846051850.png

Here you have 2 options to control the DE Pin of RS485 as follows:

#Option 1

After creating this project, you can navigate to the schematic page and you will be able to observe a pin on the UART component called tx_en as shown below:

AlenAn14_2-1646846642802.png

 

The tx_en pin goes high when a transmission starts and goes low after the transmission has completed.
You can refer to the component data sheet for more details on this:

AlenAn14_3-1646846695884.png

You can go ahead and connect an output pin to this and connect this pin to your RS485 IC DE pin to control the same with it.

#Option 2
A secondary option is to go for a Transmission interrupt , which can be done by connecting an "interrupt" component as shown below:

AlenAn14_4-1646846884831.png

After this you can enable the interrupt for TX completion from the Advanced tab of the component as shown below:

AlenAn14_5-1646846949207.png

Please follow the steps for creating the ISR handler in main.c file as done for the isr_rx component (isr_Tx was added by me to demonstrate).
In the ISR handler you can set the DE pin back to low for receive operations over UART

Hope this helps.

Warm Regards
Alen

 

 

0 Likes

Thanks for the answer .

I can only use SCB UART as I have resource limitation.

The answer you gave would have worked if I didn't had resource limitation.

 

Screenshot 2022-03-09 231909.png

.

 

0 Likes
AlenAn14
Moderator
Moderator
Moderator
500 replies posted 100 solutions authored 250 replies posted

Hi @shanbhagm ,

For the SCB UART, the best option is to use the Tx FIFO Empty interrupt:

AlenAn14_0-1646883913297.png

Warm Regards
Alen

 

0 Likes
lock attach
Attachments are accessible only for community members.

In my interrupt will this hold good ?

CY_ISR(MyRx1Int){
uint8_t int_flag ;
if ((UART_GetTxInterruptSourceMasked() & UART_INTR_TX_EMPTY) != 0){
UART_ClearTxInterruptSource(UART_INTR_TX_EMPTY);
UART_TXEnable_Write(0);// RE/DE Pin Low (Rx Mode)
UART_RXEnable_Write(0);// RE/DE Pin Low (Rx Mode)
}

if ((UART_GetRxInterruptSourceMasked() & UART_INTR_RX_NOT_EMPTY) != 0){
UART_ClearRxInterruptSource(UART_INTR_RX_NOT_EMPTY) ; /* for PSoC 4 */
if (UART_SpiUartGetRxBufferSize()) {
int_flag = CyEnterCriticalSection() ;
uint8 rxData = UART_UartGetByte() ;
RB_push(&mRingBuffer,rxData);
CyExitCriticalSection(int_flag) ;
}
}
}

main(){

RB_init(&mRingBuffer,256);
UART_SpiUartClearRxBuffer() ;
UART_SpiUartClearTxBuffer();
UART_ClearTxInterruptSource(UART_INTR_TX_EMPTY) ;
UART_ClearRxInterruptSource(UART_INTR_RX_NOT_EMPTY) ;
UART_SetCustomInterruptHandler(MyRx1Int);
//UART_Set
//SetCustomInterruptHandler
//Uart_Interrupt_StartEx(MyRx1Int);
UART_Start();

UART_TXEnable_Write(0);// RE/DE Pin Low (Rx Mode)
UART_RXEnable_Write(0);// RE/DE Pin Low (Rx Mode)

}

 

The code now is always in ISR with FIFO Empty in line " if ((UART_GetTxInterruptSourceMasked() & UART_INTR_TX_EMPTY) != 0)" of ISR

0 Likes
AlenAn14
Moderator
Moderator
Moderator
500 replies posted 100 solutions authored 250 replies posted

Hi @shanbhagm ,

I found that using the TX_EMPTY interrupt will be a little difficult in your case as you will have to enable this interrupt just before you do the transmission and disable it afterwards , else when the TX FIFO is empty, the TX EMPTY interrupt will keep firing continuously.

So please use the UART Done interrupt instead of the earlier suggested TX_Empty interrupt for this purpose:

AlenAn14_0-1646895405664.png


The ISR code for the same for this will be as follows

#include "project.h"


void UART_ISR_HANDLER()
{
    //Check if Transmission was complete
    if (0u != (UART_GetTxInterruptSourceMasked() & UART_INTR_TX_UART_DONE))
    {
        UART_ClearTxInterruptSource(UART_INTR_TX_UART_DONE);
        
        /* Write code here to control the DE pin */
        UART_TXEnable_Write(0);// RE/DE Pin Low (Rx Mode)
        UART_RXEnable_Write(0);// RE/DE Pin Low (Rx Mode)
    }

}
int main(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */
    
    // Register the ISR
    UART_SetCustomInterruptHandler(UART_ISR_HANDLER);
    
    UART_Start();

    UART_TXEnable_Write(0);// RE/DE Pin Low (Rx Mode)
    UART_RXEnable_Write(0);// RE/DE Pin Low (Rx Mode)

    for(;;)
    {
        /* Set DE Pin High here before sending data */
        UART_TXEnable_Write(1);// RE/DE Pin High (Tx Mode)
        UART_RXEnable_Write(1);// RE/DE Pin High (Tx Mode)
        /* Transmit the data*/
        UART_UartPutString("Hello there, I sent data\r\n");
        CyDelay(1000);
    }
}

 

Warm Regards
Alen

Thanks Alen for a quick turnaround. This helped us a lot.

Thank You.

0 Likes
AlenAn14
Moderator
Moderator
Moderator
500 replies posted 100 solutions authored 250 replies posted

Hi @shanbhagm ,

Glad your query is resolved,
Please feel free to post any queries or issues you may have on Infineon products in the Community and we will be happy to help.

Warm Regards
Alen

0 Likes