STM32F4 USART communication via RS232 to PC Terminal 1.9b

Started by dvd_video, May 18, 2013, 04:46:44 PM

Previous topic - Next topic

dvd_video

Hello,

I am making magnetic levitation stand for automatic control, so
i need serial communication via Terminal, to get transition
process of the levitating ball with my STM32F4-E407 and send
the data to the PC. I am using PD pins and USART3, one of the 4,
20 pinned connectors as:

TXD  ->  PD8  ->  PD connector 11;
RXD  ->  PD9  ->  PD connector 12;
CTS  ->  PD11 ->  PD connector 14;
RTS  ->  PD12 ->  PD connector 15;
GND  ->  n/a  ->  PD connector 20;

I am not using the USART3_CK, coz my PC does not have such input signal.

The program i am using for terminal is https://sites.google.com/site/terminalbpp/

So far my code is as is

void InitUSART(u32 bauld)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  USART_InitTypeDef USART_InitStructure;
  USART_ClockInitTypeDef USART_ClockInitstructure;

  /* Enable GPIOD clock */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

  /* Enable USART clock */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

  /* Connect PXx to USARTx_Tx*/
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_USART3);

  /* Connect PXx to USARTx_Rx*/
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_USART3);

  /* Connect PXx to USARTx_Ct*/
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource11, GPIO_AF_USART3);

  /* Connect PXx to USARTx_Rt*/
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_USART3);

  /* Configure USART as alternate function  */
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
                                   //  Tx           Rx         Ct             Rt
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_11 | GPIO_Pin_12;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOD, &GPIO_InitStructure);

  USART_InitStructure.USART_BaudRate   = bauld;
  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 Clock Initialization  */
  USART_ClockInitstructure.USART_Clock   = USART_Clock_Disable ;
  USART_ClockInitstructure.USART_CPOL    = USART_CPOL_High ;
  USART_ClockInitstructure.USART_LastBit = USART_LastBit_Disable;
  USART_ClockInitstructure.USART_CPHA    = USART_CPHA_1Edge;

  /* USART configuration */
  USART_Init(USART3, &USART_InitStructure);
  USART_ClockInit(USART3, &USART_ClockInitstructure);

  /* Enable USART */
  USART_Cmd(USART3, ENABLE);
}

An function to send the data:

void TxUSART(char byte)
{
   while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
   USART_SendData(USART2, (uint8_t)byte);
}


MY main.c is:

  InitUSART(9600);

  while(1)
  {
     SetLed(1);
     Delay(1000000);
     SetLed(0);
     Delay(1000000);
     TxUSART(100);
  }


When i try to send some data ( 100 for example as latin letter 'd' ),
it gives me 0x1E 0x00 ( 30 0 as decimal ) as separate bytes instead if
one whole "100" displayed as a letter "d" in the terminal.

Does anyone know how should I init the USART to use it as UART transmitter/ receiver..

Regards DVD!



I am an automation engineer graduated from TU-Sofia, Bulgaria. My passion is Programming, hardware martial arts and cycling.

billr

Generally, if you send one byte and the receiver sees it as two bytes it means you have a baud rate mismatch. Either your PC is set for a faster baud rate (like 19200) or the clock settings on the STM32F4 are incorrect causing the actual baud rate to be slower than the 9600 you requested.

Also, you didn't say anything about having a RS-232 level translator. You can't connect the Port D pins direct to the PC and expect it to work. The STM is outputting 0 to 3.3V levels, while RS-232 is nominal -12 to +12V levels. (Most PC RS-232 ports are pretty tolerant and can go as low as +/- 5V, but don't expect 0-3V to be reliable.)

dvd_video

I am not really sure what's this RS323 translator you are speaking of looks like, but i guess its IC of some kind. Do you know where can i get one. It needs to translate Rx Tx RTC CTS ( GND will may be not bid of a deal ... ). I guess i should power this ting up to translate signals, and hope my E407 can power it with 3.3 or 5 V.

Regards DVD!
I am an automation engineer graduated from TU-Sofia, Bulgaria. My passion is Programming, hardware martial arts and cycling.

billr

Yes, it is an IC. Typically something like a MAX3238, MAX3243, MAX3232 or equivalent. The are powered off 3.3 or 5V and boost the output to +/-15V. You need one for each RS-232 signal line. In most cases, it is sufficient to use just RXD and TXD - so two translators. It is only for special cases that you need to use the additional signals, such as RTS and CTS, but if you do, they need level translation also. Note that the MAX32xx parts above are multi-channel and can cover two channels in one IC package.

As an alternative, you can buy the Olimex MOD-RS232 UEXT module which plugs into the E407 via an included cable and provides a proper RS-232 interface.

dvd_video

I hooked one MAX3232 to the controller and the PC

i am using the scheme on the right

I am sending 100 but still got 254

Also i am using  this http://www.wvshare.com/img/photos/MAX3232CSE.jpg IC. I think if the white bar is on top while looking @ it indicates that on the left upper corner is is 1 ... or i am wrong ...
I am an automation engineer graduated from TU-Sofia, Bulgaria. My passion is Programming, hardware martial arts and cycling.

billr

The circuit looks correct, and yes, with the white bar at the top, pin 1 would be in the upper left corner. At this point, I would connect an oscilloscope to pin 2 of the 9-pin connector and check the timing.

dvd_video

Started working now. Strange, that i have to multiply baudrate * 2 to get the desired bauldrate
Init it for 13200 , connect with 9600 ... it works ... any ideas ???

Also i enabled the intterrupt:

     NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

     /* USART configuration */
     USART_Init(USART3, &USART_InitStructure);
     USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); // Receive interrupt ...
     USART_ClockInit(USART3, &USART_ClockInitstructure);
     NVIC_Init(&NVIC_InitStructure);

With handler :

void USART3_IRQHandler(void){

   // check if the USART3 receive interrupt flag was set
   if( USART_GetITStatus(USART3, USART_IT_RXNE)){
      USART_ClearITPendingBit(USART3, USART_IT_RXNE);

      u8 c = USART3->DR; // the character from the USART3 data register is saved in c
      /* check if the received character is not the LF character (used to determine end of string)
       * or the if the maximum string length has been been reached
       *
       */
      if((c != 0) && (StringLen < MAX_STRLEN)){
         InString[StringCnt] = c;
         StringLen++;
      }
      else{ // otherwise reset the character counter and print the received string
         StringLen = 0;
         PutsUSART(InString);
      }
   }
}

My terminal crashes and my data is not transmitted ( I am sending 255, 254, 253, ... 1, 255 ... and blinking the LED ) or received ... The led Stays turned on ...
I am an automation engineer graduated from TU-Sofia, Bulgaria. My passion is Programming, hardware martial arts and cycling.

billr

1) As to the baud rate problem, did you edit the system_stm32f4xx.c file for your project to set the proper clock speed? Note 4 at the start of the file says:
  * 4. The default value of HSE crystal is set to 25MHz, refer to "HSE_VALUE" define
  *    in "stm32f4xx.h" file. When HSE is used as system clock source, directly or
  *    through PLL, and you are using different crystal you have to adapt the HSE
  *    value to your own configuration.
The crystal frequency on the H407 is 12 MHz, which not quite half the default library clock, which probably accounts for the baud rate problems. Try changing the #define for PLL_M from 25 to 12 in that system file.

2) You typically can't send a complete string out the UART from your interrupt handler. Set a flag and call PutsUSART() from your main loop. Also, the way you typed in the code, you are using two different variables for the string index - StringLen and StringCnt. I'm guessing you typed it in wrong, but if not, that is also a problem. Finally, the way the code is written, the string is not guaranteed to be NUL terminated. I think what you intended is something like this:

int StringLen = 0, StringRdy = 0;

void USART3_IRQHandler(void)
{
   :
   :
  if ((c != '\n') && (StringLen < MAX_STRLEN - 1))
  {
    InString[StringLen++] = c;
  }
  else
  {
    if (StringLen < MAX_STRLEN - 1)
    {
      // save LF as well
      InString[StringLen++] = c;
    }
    InString[StringLen] = 0;
    StringRdy = 1;
    StringLen = 0;
  }
}

Then, in your main loop:

  while (1)
  {
    :
    :
    if (StringRdy)
    {
      PutsUSART(InString);
      StringRdy = 0;
    }
  }

Of course, depending on your actual usage, the InString could get overwritten by new characters coming in before you have the chance to send them out, but for your testing, I'm guessing that is probably not an issue as you are typing some string and echoing the response back, waiting for the response before you start typig other characters.

dvd_video

Yeah baudrate is OK now but if i try ti send sone chars
like "asdfg" and then enter leads to terminal crash i am using your code for the IRQ and main



void InitUSARTIRQ(u32 baudrate){

     GPIO_InitTypeDef GPIO_InitStructure;
     USART_InitTypeDef USART_InitStructure;
     USART_ClockInitTypeDef USART_ClockInitstructure;
     NVIC_InitTypeDef NVIC_InitStructure;

     /* Enable GPIOD clock */
     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

     /* Enable USART clock */
     RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

     /* Connect PXx to USARTx_Tx*/
     GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_USART3);

     /* Connect PXx to USARTx_Rx*/
     GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_USART3);

     /* Connect PXx to USARTx_Ck*/
     GPIO_PinAFConfig(GPIOD, GPIO_PinSource10, GPIO_AF_USART3);

     /* Connect PXx to USARTx_Cts*/
     GPIO_PinAFConfig(GPIOD, GPIO_PinSource11, GPIO_AF_USART3);

     /* Connect PXx to USARTx_Rts*/
     GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_USART3);

     /* Configure USART as alternate function  */
     GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
     GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP;
     GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
                                      //  Tx           Rx         Ct             Rt
     GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_Init(GPIOD, &GPIO_InitStructure);
// USART Init
     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_CTS;
     USART_InitStructure.USART_Mode       =  USART_Mode_Rx | USART_Mode_Tx;

   /* USART Clock Initialization  */
     USART_ClockInitstructure.USART_Clock   = USART_Clock_Disable ;
     USART_ClockInitstructure.USART_CPOL    = USART_CPOL_Low ;
     USART_ClockInitstructure.USART_LastBit = USART_LastBit_Enable;
     USART_ClockInitstructure.USART_CPHA    = USART_CPHA_1Edge;

// USART IRQ init
     NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           //
     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //
     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

     /* USART configuration */
     USART_Init(USART3, &USART_InitStructure);
     USART_ITConfig(USART3,USART_IT_RXNE,ENABLE);
     USART_ClockInit(USART3, &USART_ClockInitstructure);
     NVIC_Init(&NVIC_InitStructure);

     /* Enable USART */
     USART_Cmd(USART3, ENABLE);
}




u32 StringLen = 0;
u32 StringRdy = 0;
u8 InString[MAX_STRLEN_USART];

void USART3_IRQHandler(void)
{

  if( USART_GetITStatus(USART3, USART_IT_RXNE))
  { 
  // Interrupt is executing
  u8 c = USART3->DR;
       if ((c != '\n') && (StringLen < MAX_STRLEN_USART - 1))
       {
          InString[StringLen++] = c;
       }else{
          if (StringLen < MAX_STRLEN_USART - 1)
          {
             // save LF as well
             InString[StringLen++] = c;
          }
       InString[StringLen] = 0;
       StringRdy = 1;
       StringLen = 0;
       }
   // Done
   USART_ClearITPendingBit(USART3, USART_IT_RXNE);
  }
}


int main(void)
{
  InitLed();
  SetLed(0);

  InitUSARTIRQ(115200);
  PutsUSART((u8*)INFO1); // Uart init done !

  SetLed(1);

  while(1)
  {
       if (StringRdy)
       {
         PutsUSART(InString);
         StringRdy = 0;
       }
  }

return 0;
}

Before init I am sending the alphabet capitalized, and getting a fraction of it like "<0><0><0><0><0>FGHIJLLMNO<0><0><0><0><0>"
After init CPU enters while(1). I am sending alphabet again and terminal crashes ...
Wander where it went wrong ...
I am an automation engineer graduated from TU-Sofia, Bulgaria. My passion is Programming, hardware martial arts and cycling.

billr

What does your Puts_USART() function look like? Is it waiting for the transmit buffer to be empty before stuffing the character to send? In the first case, it would appear you are trying to send characters to the USART hardware faster than it can send them out. Not sure why it would hang when calling Puts_USART() after the receive interrupt is enabled, but the clue may be in that Puts_USART() function.

jaykatira23

I applied this code but i cant understand how to receive from pc ? i am getting problem o this

JohnS

I don't understand you at all.  Explain more...

John