cancel
Showing results for 
Search instead for 
Did you mean: 

Stumped - USART Interrupts Pls Review this code + Keil bug?

estersci2
Associate III
Posted on September 27, 2015 at 12:19

Hi,

I began by creating some code polling the com port of the g-eval board in a transactional way - easily send a command at will, then in a non-blocking loop check to see if it has received command, compare command to take action. This I can expand and control easily.

I know I haven't  handled buffer overrun or buffer resets yet - but that is easy.

Where I am stumped is in the conversion of this code from a while loop to uart interrupt fired IRQ handlers. 

In the code below, I have tried to move the code for receiving data only (not sending data) from the while loop into a UART interrupt handler, but it does not fire.

If any flaw jumps out, I would be grateful if you could let me know as after two days, I can't seem to get it.

I also discovered a bug in keil i think. If I switch into debugger mode, and click reset before the first run of the code, I somehow loose visibility of my debug variables for the rest of that session. I lost a lot of time before I relaised that. Anyone know the cause?  

#include ''stm32f2xx.h''

#include ''stm322xg_eval.h''

// #include <stdio.h>

#include <stdint.h>

#include <string.h>

void USART_Config(void);

void USART_PutString(char *s);

uint16_t USART_GetChar(void);

void NVIC_Configuration(void);

int myflag = 0x00;

int rxi=0;

char str[] = ''Hello, World!\n'';

char cmd[20];

char ctest[20] = ''brk'';; 

int main(void)

{

NVIC_Configuration();

    // Call USART1 configuration

    USART_Config();

    // Send ''Hello, World!'' to PC

    USART_PutString(str);

    while (1)

    {

}

    

}

void USART_Config(void)

{

GPIO_InitTypeDef GPIO_InitStruct;

USART_InitTypeDef USART_InitStruct;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_USART3);

  GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_USART3);

 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;

    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;

    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;

    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;

    GPIO_Init(GPIOC, &GPIO_InitStruct);

    

    USART_InitStruct.USART_BaudRate = 9600;

    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

    USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;

    USART_InitStruct.USART_Parity = USART_Parity_No;

    USART_InitStruct.USART_StopBits = USART_StopBits_1;

    USART_InitStruct.USART_WordLength = USART_WordLength_8b;

    USART_Init(USART3, &USART_InitStruct);

    USART_Cmd(USART3, ENABLE);

USART_ITConfig(USART3, USART_IT_RXNE | USART_IT_TXE, ENABLE);

}

void USART_PutChar(char c)

{

    // Wait until transmit data register is empty

    while (!USART_GetFlagStatus(USART3, USART_FLAG_TXE));

    // Send a char using USART1

    USART_SendData(USART3, c);

}

void USART_PutString(char *s)

{

    // Send a string

    while (*s)

    {

        USART_PutChar(*s++);

    }

}

uint16_t USART_GetChar(void)

{

    // Wait until data is received

    while (!USART_GetFlagStatus(USART3, USART_FLAG_RXNE));

    // Read received char

    return USART_ReceiveData(USART3);

}

void USART3_IRQHandler(void)

{

if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) // Received characters modify string

  {

  uint16_t data = USART_GetChar();

           

        if (data != 0x0D)

        {

cmd[rxi]=data;

rxi++;

            // If received char is 'H' then turn on orange LED

if(strcmp(cmd, ctest) == 0)

{

myflag=0xfe;

        }

}

    

}

}

void NVIC_Configuration(void)

{

  NVIC_InitTypeDef NVIC_InitStructure;

   

  /* Configure the NVIC Preemption Priority Bits */

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

   

  /* Enable the USART3 Interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

}

3 REPLIES 3
Posted on September 27, 2015 at 17:35

Don't enable the TXE interrupt, and make sure strings are NUL terminated when using the strxxx() functions.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
estersci2
Associate III
Posted on September 27, 2015 at 18:06

Clive,

Thanks - that got rx interrupts working - although I don't understand why having Tx interrupts enabled stopped it from working...could you please explain?

Another major thing i don't get is - why don't these types of ISR have to clear the bit like other examples such as TIMx bits- does the hardware do that automatically as a consequence of being read?

The other thing I don't understand about Tx intterupts is what triggers the first one?

Rx interrupts are, I assume, triggered by the hardware when it receives a character, right?

But what gets the first Tx interrupt going in, for example, the code you posted at the following link?

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/USART%20communication%20via%20RXNE%20interrupt%20only%20reads%20one%20char&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CD...

Thanks again

Posted on September 27, 2015 at 19:00

The TXE/RXNE interrupt bits are a direct reflection of those bits in the status register, they set/clear based on your interaction with the data register. On the TIM peripheral you have to explicitly clear the source, because there's not the same one-to-one relationship between the buffers, and flags reflecting the state of the buffers.

TXE is set whenever the USART doesn't have new data to send, enabling the interrupt will thus immediately result in an interrupt occurring. If you can't service the interrupt by giving the USART data, then it's going to keep asserting that it needs data, and you endlessly enter the interrupt and never run foreground code. If you don't have any data to supply, you must turn OFF the interrupt, until you do.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..