cancel
Showing results for 
Search instead for 
Did you mean: 

USART2 Configuration Problem

stenasc
Senior
Posted on January 07, 2013 at 00:23

Hi,

I'm trying to read data from an external modem using USART2. PA2=RXD and PA3=TXD. The RXD only drives to about 1 volt.

which is why I can't read anything. Is the following code setting up the pins correctly or do they need to be swapped around.

I also have my suspicions about the interrupt handler so if someone could check.

Appreciate any help.

Regards

Bob

Here is my configuration...

void Usart2Init(void)

{        

  USART_InitTypeDef USART_InitStructure;

  GPIO_InitTypeDef GPIO_InitStructure;

  NVIC_InitTypeDef NVIC_InitStructure;

 

  /* Enable GPIOA and DMA clock */

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA , ENABLE);

 

  /* Enable USART1 APB clock */

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

 

  /* USART1 Pins configuration **************************************************/

  GPIO_DeInit(GPIOA);

 

  /* Connect pin to Periph */

  GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);    

  GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);

 

  /* Configure pins as AF pushpull */

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;

  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_DOWN;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

 

 

  /* USARTx configured as follow:

  - BaudRate = 19200 baud  

  - Word Length = 8 Bits

  - Stop Bit = 1 Stop Bit

  - Parity = No Parity

  - Hardware flow control disabled (RTS and CTS signals)

  - Receive and transmit enabled

  */

 

//  USART_DeInit(USART2);

  USART_InitStructure.USART_BaudRate = 19200;

  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_None;

  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

  USART_Init(USART2, &USART_InitStructure);

//  /* Enable the CO21 Receive interrupt: this interrupt is generated when the

//  COM1 receive data register is not empty */

  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);

 

  /* USART1 IRQ Channel configuration */

  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPriority = 0x01;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);        

    

    }

void USART2_IRQHandler(void)

{

char rx_byteb;    

    if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)

         {

        rx_byteb = (char)USART_ReceiveData(USART2);

        printf(''%c'',rx_byteb);

         }

}
9 REPLIES 9
Posted on January 07, 2013 at 02:13

The GPIO_PinAFConfig() should perhaps refer to the pins being routed.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
stenasc
Senior
Posted on January 07, 2013 at 11:40

ahhh...sorry about that...didn't solve the problem though. Original code that I inherited was set up as shown below. We could transmit characters, but never receive anything back even though the data was there. (verified witch scope and logic analyzer). However, I can see PA2 and PA3 toggling. However, with the code I posted earlier (with the correction), I cannot see anything on PA2 or PA3.

USART_InitTypeDef USART_InitStructure;

        

  USART_InitStructure.USART_BaudRate = 19200;

  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_None;

  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

  COMInit(COM2, &USART_InitStructure);

int send_data(unsigned char * byte)

 {

  uint16_t data;

  char UART2_RX_buffer[10];

  int U2_rx_count = 0;    

    

  for (;*byte;++byte)

    sendchar (*byte);

         

    while ((U2_rx_count) < 10 ){        

    data = USART_ReceiveData(USART2);

        

    UART2_RX_buffer[U2_rx_count] = (char)data;

    U2_rx_count++;

    }

  if (strstr(UART2_RX_buffer, (const char *)byte) != NULL)

     rx_ack = 1;

  else

     rx_ack = 0;

 return rx_ack;    

 }

void sendchar (uint8_t ch)

{

  USART_SendData(USART2, (uint8_t) ch);

  /* Loop until the end of transmission */

  while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET)

  {}

}

Posted on January 08, 2013 at 02:36

Yeah, that's a bit of a mess.

On the receive side you need to wait on an RXNE status, a strstr() expects a NUL terminated string.

On the transmit side, you should front wait on TXE. Back waiting for TC is the slowest possible strategy.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on January 08, 2013 at 03:04

This should be a workable example for the STM32F0-Discovery

/* USART IRQ TX/RX Loop (USART2 TX PA.2, RX PA.3) STM32F0-Discovery sourcer32@gmail.com */
#include ''stm32f0xx.h''
#include ''stm32f0_discovery.h''
volatile char StringLoop[] = ''The quick brown fox jumps over the lazy dog

'';
/**************************************************************************************/
void RCC_Configuration(void)
{
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
}
/**************************************************************************************/
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the USART2 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/**************************************************************************************/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_1);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_1);
/* Configure USART2 pins: Rx and Tx ----------------------------*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/**************************************************************************************/
void USART2_Configuration(void)
{
USART_InitTypeDef USART_InitStructure;
USART_InitStructure.USART_BaudRate = 115200;
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_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART2, &USART_InitStructure);
USART_Cmd(USART2,ENABLE);
USART_ITConfig(USART2, USART_IT_TXE, ENABLE);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
}
/**************************************************************************************/
void USART2_IRQHandler(void)
{
static int tx_index = 0;
static int rx_index = 0;
if (USART_GetITStatus(USART2, USART_IT_TXE) != RESET) // Transmit the string in a loop
{
USART_SendData(USART2, StringLoop[tx_index++]);
if (tx_index >= (sizeof(StringLoop) - 1))
tx_index = 0;
}
if (USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) // Received characters modify string
{
StringLoop[rx_index++] = USART_ReceiveData(USART2);
if (rx_index >= (sizeof(StringLoop) - 1))
rx_index = 0;
}
}
/**************************************************************************************/
int main(void)
{
RCC_Configuration();
GPIO_Configuration();
NVIC_Configuration();
USART2_Configuration();
while(1);
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
stenasc
Senior
Posted on January 09, 2013 at 17:53

Hi Clive,

Thank you...I did get thr RX side working in the interrupt routine.I tried to post a message to the forum, but sometimes I can't log onto the ST site especially later in the evening. I tested it by receiving keyboard characters on USART1 and printing them out when in the USART2 interrupt routine. This worked fine.

One thing I need to ask...in the existing code USART2 sends characters to the modem outside the interrupt routine. This seemed to work on the TX side but as I mentioned earlier. nothing could be received.  I added the interrupt routine to receive charracters from the modem as I think this will make it more reliable.

Is it possible to have this situation where we transmit data outside the interrupt routine and receive data within it or must we TX and RX in the routine.

Many Thanks

Bob

Posted on January 09, 2013 at 18:32

I would tend to buffer data, and let interrupts collect and dispatch characters. By accumulating characters in the interrupt you're far less likely to miss them, or have previous data overrun.

The size of your buffer would depend on how often your foreground tasks wants to process data, and how fast it's coming in.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
stenasc
Senior
Posted on January 16, 2013 at 11:02

The modem manufacturer recommend that we use CTS/RTS handshaking. I have enabled them sing the following...

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ; // CTS pin

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN ;

  GPIO_Init(GPIOA, &GPIO_InitStructure); /// GPIO D

 

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1  ; // RTS pin

  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN ;

  GPIO_Init(GPIOA, &GPIO_InitStructure);

My question is...does the USART automatically take care of the handshaking or do we need to program the device to assert/deassert these lines?

Thanks

Bob

Posted on January 16, 2013 at 17:33

Yes, that and the GPIO_PinConfigAF() routing.

The USART needs the right

USART_InitStructure.USART_HardwareFlowControl

settings. This will deal with things at a hardware level, but the USART only has a single register so it's rather abrupt and needs to be handling at some level in the buffering you have behind the USART. ie the hardware is impacted by you servicing it promptly, rather than the size of the buffer you have sitting behind it. So if you have RXNE signalling it will KEEP interrupting if you don't read out the DR, this will hold off further reception, but will saturate the processor unless you disable the interrupt. So it makes more sense to drive RTS in software when your input buffer meets some threshold, rather than wait until it can hold no more. This will also stop RTS strobing in an unnecessary fashion. Allowing the hardware to handle CTS does make sense, but you might want to monitor it also in software to stall buffer filling activity. Modems definitely need flow control, they will want you to stop sending data when all the internal buffers are full pending (re)transmission, which might be a lot slower than you can shovel data into it. This might be especially true when using a TCP protocol stack (modem side socket protocol) where a large amount of data might be waiting for successful transmission.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
stenasc
Senior
Posted on January 18, 2013 at 16:40

Thanks Clive..