cancel
Showing results for 
Search instead for 
Did you mean: 

USART missing characters stm32f10x

parisa
Senior
Posted on March 07, 2017 at 21:16

Hi,

Here is my transmission code:

void USART1_IRQHandler(void){

  if (USART_GetITStatus(USART1, USART_IT_TXE) != RESET){

        if(Counter<=65 && TX==1){

            if(MESSAGE[Counter]=='\0'){

            USART_ITConfig(USART1, USART_IT_TXE, DISABLE);

            TX=0;

            Counter=0;

            return;

            }            

            USART_SendData(USART1,MESSAGE[Counter]);        

            Counter=Counter+1;             

  }

        else

        {

            USART_ITConfig(USART1, USART_IT_TXE, DISABLE);

        }

}

}

Before Enabling USART Transmission flag I set

    sprintf(MESSAGE,''ABCDEFGHIJKLMNOPQRSWXVZ0123456789>!>!>Hello The world<!<!<\n\r'');

   TX=1;

Counter=1;

However in receiver device I get several strings like these:

0690X00000606UzQAI.png

As you can see I missed one of my sending string.Actually I have changed delay between each string and USART baudrate but it shows me the same result. why did I miss some strings during transmission?

In addition, when I remove interrupt subroutine and send string directly with a simple loop it works better.

1)what is my mistake?

2)would it possible to decrease error with using DMA?

Thanks

4 REPLIES 4
Posted on March 07, 2017 at 21:27

>>

1)what is my mistake?

Don't use delays, understand when transmission is active, and when it has completed.

Code lacks complete context. You could perhaps use 2 stop bits to improve the synchronization on the receiving side. Use volatile variables as appropriate.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
S.Ma
Principal
Posted on March 08, 2017 at 08:34

Start from a polling example from cube. The code does not tell enough. 

I have seen dropped bytes coming from a BT device which converted the UART to BT which is packet oriented: The higher the bit rate the more likely the BT FIFO could get full and trash incoming bytes...

Also, we don't know how you enable interrupts to send a new string. Maybe enable the interrupt AFTER all the global variables are set, otherwise, it could be out of sync. Make sure Counter is not modified elsewhere during the interrupts.

parisa
Senior
Posted on March 08, 2017 at 09:46

Thanks for your contributions

Here is my code:

#include <stdio.h>

#include <string.h>

#include <stm32f10x_rcc.h>

#include <stm32f10x_usart.h>

volatile char MESSAGE[200];

volatile int Counter;

volatile int TX;

void Delay(void){

    int i,j;

    for(i=0;i<1000;i++)

    for(j=0;j<100;j++);

}

void USART1_IRQHandler(void){

  if (USART_GetITStatus(USART1, USART_IT_TXE) != RESET){

        if(Counter<=65 && TX==1){

            

            if(MESSAGE[Counter]=='\0'){

            USART_ITConfig(USART1, USART_IT_TXE, DISABLE);

            TX=0;

            Counter=0;

            return;

            }            

            

            USART_SendData(USART1,MESSAGE[Counter]);        

            Counter=Counter+1;             

  }

        else

        {

            USART_ITConfig(USART1, USART_IT_TXE, DISABLE);

        }

}

}

void USART(void){

    USART_InitTypeDef USA;

    GPIO_InitTypeDef GPIOStruc;

    NVIC_InitTypeDef NVICS;

    

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |RCC_APB2Periph_AFIO,ENABLE);

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);

    

    GPIOStruc.GPIO_Mode=GPIO_Mode_AF_PP ;

    GPIOStruc.GPIO_Speed=GPIO_Speed_10MHz;

    GPIOStruc.GPIO_Pin=GPIO_Pin_9;

    GPIO_Init(GPIOA,&GPIOStruc);

    

    GPIOStruc.GPIO_Mode=GPIO_Mode_IN_FLOATING ;

    GPIOStruc.GPIO_Pin=GPIO_Pin_10;

    GPIO_Init(GPIOA,&GPIOStruc);

    

    USA.USART_BaudRate=115200;

    USA.USART_StopBits=USART_StopBits_1;

    USA.USART_WordLength=USART_WordLength_8b;

    USA.USART_Parity=USART_Parity_No ;

    USA.USART_HardwareFlowControl=USART_HardwareFlowControl_None;

    USA.USART_Mode=USART_Mode_Rx | USART_Mode_Tx;

    USART_Init(USART1,&USA);

    NVIC_EnableIRQ(USART1_IRQn);

    USART_Cmd(USART1,ENABLE);    

    

NVICS.NVIC_IRQChannel =USART1_IRQn ;

NVICS.NVIC_IRQChannelPreemptionPriority = 0;

NVICS.NVIC_IRQChannelSubPriority = 1;

NVICS.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVICS);    

}

int main(){        

    int i,l;

    USART();

    l=456;

    i=789;

    while(1){        

    Delay();

    TX=1;    

    Counter=0;

        

    sprintf(MESSAGE,'ABCDEFGHIJKLMNOPQRSWXVZ0123%d%d>!>!>Hello The world<!<!<\n\r',l,i);

        

//Time-SPI-GPIO interrupt , ....        

        

    USART_ITConfig(USART1, USART_IT_TXE, ENABLE);    

}

}

I think it depends on different situations

1)would it be possible that when 'sprintf' function wants to fill up the MESSAGE variable it misses my string? if yes how can prevent this statues?

2)if we enable USART_IT_TXE flag and an interrupt occurs (for a little time less than 1ms) without any changing the string and it's variables (TX , Counter) may be able to destroy the transmission?

3)when I declare MESSAGE variable as volatile it return this warning:(for sprintf function)

argument of type 'volatile char *' is incompatible with parameter of type 'char *restrict'

4)it is better to usa DMA as transmission channel that prevent wasting cpu time and use RX interrupt in receiving mode ,isn't it?

Thanks in advance

Posted on March 08, 2017 at 18:17

Add a sanity check in the loop, check interrupts are truly disabled before setting PR/Counter. If not, while(1) asm('nop'); 

so in the debugger it can breakpoint on error. Always add checks in the code to speed up debug time. Overall a time saver.