1

I am using an STM32F303RE Nucleo board connected to my own PCB to do RS-232 serial communications, and I can't figure out why this code doesn't work in certain circumstances.

I'm using HAL functions (HAL_UART_Transmit and HAL_UART_Receive) for my communications, using the USB connector on the Nucleo for usart2 and a 9-pin RS-232 serial port on my own PCB for usart1. Both usart configurations have been set up by HAL.

When I communicate (using a Putty terminal) using only the USB connection (usart2), the code works perfectly. When I use usart1 for Tx and usart2 for Rx, still no problems. When I use usart2 for Tx and usart1 for Rx, it also works fine.

The problem is when I try to use usart1 (which is my RS-232 cable) for both Tx and Rx. My processor transmits the initial data fine, but when it's time to receive the data, nothing makes it into the received data register. I have some code to simply echo back any received data on the transmit line, and nothing comes through in this configuration. Once again - the code works fine in every other configuration of usart1 and usart2 for both sending and receiving, but no Rx when I try to do it all on usart1 (RS-232)

Here is the relevant section of code I'm using. COMTYPE is set to either &huart1 or &huart2 (in the problem case, it's set to &huart1)

Main loop (received data used for switch statement in menu system):

    HAL_UART_Transmit(COMTYPE, prompt, sizeof(prompt), TIMEOUT);
    cmd_size = UART_getstr(command);

    cmd_num = parse_menu_input(command, cmd_size);
    converted = (uint8_t)cmd_num + '0';


    // error parsing command for menu selection
    if(cmd_num == -1){
        HAL_UART_Transmit(COMTYPE, parse_error, sizeof(parse_error), TIMEOUT);
    }
    else{
        menu_switch(cmd_num);
    }
}

Function containing Rx function and echo back (Tx) function:

int UART_getstr(uint8_t* command){

int x = 0;              // tracker for buffer pointer
int chars = 0;
uint8_t buffer;     // single char storage for UART receive

while(1){       

    // get single char from UART_Receive
    HAL_UART_Receive(COMTYPE, &buffer, 1, HAL_MAX_DELAY);
    // echo back function
    HAL_UART_Transmit(COMTYPE, &buffer, sizeof(char), TIMEOUT);

    // write value of received char to "command" array
    command[x] = buffer;

    // increment the number of valid chars
    chars++;

    // stop adding chars to command after [Enter] pressed
    if(command[x] == '\r'){
        chars--;
        break;
    }
    // correct for storing DELETE as char in buffer
    if(command[x] == 0x7F){
        command -= 1;
        chars -= 2;
    }
    else{
        x++;
    }
}
command[x] = '\0';

// return length of command buffer
return chars; }

I don't understand why the exact same code would work in 3 out of 4 circumstances, but not the 4th. I've checked the serial cable, and the rest of the RS-232 hardware functions fine when being used ONLY for Tx or ONLY for Rx. But the Rx seems blocked by something when trying to use RS-232 for both.

EDIT: Adding UART initialization code (generated by HAL):

/* USART1 init function */
static void MX_USART1_UART_Init(void)
{

  huart1.Instance = USART1;
  huart1.Init.BaudRate = 115200;
  huart1.Init.WordLength = UART_WORDLENGTH_8B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_NONE;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

/* USART2 init function */
static void MX_USART2_UART_Init(void)
{

  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}
dcprime
  • 21
  • 4
  • I don't completely understand your description. Your are connecting to a PC (I assume by your comment about Putty terminal). but you are mixing the UART connections? You say you use a USB connection (usart2), does this mean this is a USB mapped as a COM port in your embedded program? – Marcos Oct 23 '18 at 20:23
  • When you mix USART ports, for example "usart1 for Tx and usart2 for Rx", what is the value of COMTYPE? – Marcos Oct 23 '18 at 20:30
  • Try to use interrupt base reception. This will be necessary in most applications and I always think it is more robust than using the HAL timeout function. – A.R.C. Oct 24 '18 at 06:47
  • Show the code which initializes the UART and also the implementation of the MSP callback function which initializes the pins and their respective alternate function. – trylimits Oct 24 '18 at 09:35
  • @Marcos: Yes, using a PC to communicate through Putty. I'm mixing the connections for testing purposes. usart2 is indeed a USB mapped as a COM port. When I mix the connections, I set COMTYPE to &husart1 or &husart2, and manually change the first argument of HAL_UART_Receive() to the other type (whatever COMTYPE is not). – dcprime Oct 24 '18 at 14:11
  • @trylimits: The code for UART initialization was generated by the HAL, as well as the pin initializations. I'll add what I can find for the UART initialization to my question above. – dcprime Oct 24 '18 at 14:15
  • Thanks for the edit. The initialization of the USARTs itself seems correct to me. There also has to be the code which initializes the GPIOs (alternate functions for the pins). – trylimits Oct 25 '18 at 07:02
  • @trylimits I would need to dig through the HAL header files to find that GPIO initialization code, but as I mentioned above, the RS-232 interface does work for both sending and receiving data in 2 out of 4 configurations (when it's being used ONLY for sending or ONLY for receiving). If the GPIOs were not configured properly, it should not work at all, no? – dcprime Oct 25 '18 at 09:20
  • You say: "But the Rx seems blocked by something when trying to use RS-232 for both.". How do you know the problem is in the HAL_UART_Receive() and not in the HAL_UART_Transmit()? – Marcos Oct 25 '18 at 17:11
  • In my opinion your code seems to be ok. I would suggest just to change "sizeof(char)" in "HAL_UART_Transmit(COMTYPE, &buffer, sizeof(char), TIMEOUT);" for "1" or "sizeof(uint8_t)" which is the correct type for "buffer". Also, re-check that you don't have a hardware issue. Take some time to debug the code and find out what is exactly happening, you probably need an oscilloscope as well. – Marcos Oct 25 '18 at 17:27
  • @Marcos: I know the HAL_UART_Transmit() is not the problem (at least, not directly) because it works in every circumstance. I still see the output from the Tx code over the RS-232 connection no matter how I'm receiving. It's the Rx code that just stops working. Hardware-wise, as I mentioned before, I am able to both send and receive using this same hardware and code if I'm not attempting to do the Tx and Rx operations both over RS-232. If the hardware works in that circumstance, those connections aren't changing when using RS-232. I've scoped many parts of the transmit line. All normal. – dcprime Oct 26 '18 at 20:44
  • have you ever consider to try DMA, if your hardware works fine there are no possible solution to miss data from any device. If you cannot detect any data on your buffer then you might measure the voltages of both RX and TX channel while connecting because probably its an hardware problem. – Cagri Candan Nov 08 '18 at 06:32

0 Answers0