cancel
Showing results for 
Search instead for 
Did you mean: 

stm32f2xx USART RTS/CTS

ho
Associate II
Posted on June 28, 2013 at 07:52

May I know how can I configure my STM32F205 microcontroler for USART RTS/CTS???

I could not find any resource on the net, and my codes are below but it doesnt work: anyone can help me to configure the CTS/RTS UART configuration thanks!!!

// Enable GPIO clock
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOA, ENABLE);
// Enable USART2 clock 
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
// Connect USART pins to AF7 
GPIO_PinAFConfig(GPIOA, GPIO_PinSource0, GPIO_AF_USART2);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_USART2);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_USART2);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_USART2); 
// Configure USART Tx and Rx as alternate function push-pull
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; //USART Tx
GPIO_Init(GPIOA, &GPIO_InitStructure); 
//GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_0; 
//GPIO_Init(GPIOA, &GPIO_InitStructure);
//GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; 
GPIO_Init(GPIOA, &GPIO_InitStructure); 
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; 
GPIO_Init(GPIOA, &GPIO_InitStructure); 
// UART2
NVIC_InitTypeDef NVIC_InitStructure;
// Enable the USARTz Interrupt 
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x4;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
USART_InitTypeDef USART_InitStructure;
USART_StructInit(&USART_InitStructure);
USART_InitStructure.USART_BaudRate = baudrate;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS_CTS;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART2, &USART_InitStructure);
/* Enable USART2 Receive interrupts */
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
/* Enable the USART2 */
USART_Cmd(USART2, ENABLE);

#uart-flow-control #uart.stm32-uart
13 REPLIES 13
jpeacock
Associate III
Posted on September 09, 2015 at 20:06

Flow control has some latency, historically transmissions were never expected to stop immediately.  RTS is a highwater mark, buffer is nearly, not completely, full so the other side (DCE or DTE) should stop sending as soon as possible. 

This comes from how RTS/CTS were  first used with early phone modems like the Bell 202 (DCE or data communications equipment).  These were half duplex, message oriented and needed signals to control when to send and receive.  RTS requested a transmission to the DCE, CTS indicated the DCE could receive data.  There could be a significant delay due to line turnaround but eventually data went in a particular direction until the packet was complete.  The interface was synchronous so there was no byte by byte transfer, data always went in bursts and the application had to have enough room to handle the incoming packets.  RTS and CTS worked at message level, not byte level.

Fast forward 50 years and RTS/CTS sorta follow the same logic except RTS and CTS are decoupled for full duplex (remember the wonders of a Bell 212 modem? full duplex and 1200 baud!).  Deasserting RTS tells the other end to stop as soon as possible, but it may be several bytes, or even the rest of a packet, due to software protocols, hardware FIFOs and at least one extra byte if the shift register is in progress.  So on an STM32 USART you still have to accept data, preferably by DMA but by IRQ otherwise, and save the trailing data bytes until the far end stops.

Most likely that's what you see with the FTDI UART.  It's not a design error, there's no requirement for immediate halt on RTS request.  You see the internal hardware buffers emptying out the last few characters queued to transmit before RTS arrived.

As Clive points out there's only a one byte buffer on the USART RX, but that's not a design error either since DMA is available.  Other vendors rely on hardware FIFOs but DMA is more flexible since there's no fixed  limit on how many bytes can arrive, as long as the DMA buffer is sufficiently large enough to handle it.  I've used both methods, the DMA on an 'F405 is much more flexible than a fixed length FIFO.

  Jack Peacock
gbigden
Associate III
Posted on September 11, 2015 at 11:52

Thanks to you and Clive for clearing that up.

Any DMA code examples for the USART that I can hack (Rx particularly)? My application only requires intermittent 12 byte packets at around 1 packet per second

craig2399
Associate II
Posted on December 31, 2014 at 01:58

Did you ever get this working?  If so could you please share what you found?

Posted on December 31, 2014 at 03:47

Well the complication here is not setting up the pins, although that can always be made more difficult by the inconsistent application of defines.

This issue is that the STM32 has a single byte depth hardware buffer, and in order to throttle received data you have to leave data in the receive buffer (RXNE flagging) and do gyrations about how you want to handle/disable interrupts. But who puts a single byte buffer behind a flow controlled USART implementation? You're typically sending/receiving a LOT of data, and you want it managed in the background. You really have a much deeper buffer, and as it becomes fuller you manually drive RTS.

On the transmit side using CTS makes sense, because otherwise you'd spend your time waiting on the TC flags rather than the TXE flag so you don't overrun the remote device.

You have to understand the contract between your sending/receiving device at a system level, and once you know that you can decide what things you want in hardware, what in software, and how you're going to handle the interrupt and restarting issues, and which flags you're going to poll/monitor vs interrupt against.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..