AnsweredAssumed Answered

USART1 interrupt issues, seems to get stuck after 2 or 3 triggers...

Question asked by chinniwhites on Sep 13, 2012
Latest reply on Sep 25, 2012 by chinniwhites
I have an STM32F0 discovery board.  Below is the interrupt code and main.  I am talking via st485 chip to sensor.  When sensor comes on it spits out an initial message letting the attached controller know it alive.  Program executes just fine until I turn sensor on.  The interrupt seems to get triggered mulitple times in a row (make sense, sensor initial message is in three burst 0xAA, 0x00, 0xAA) but then hangs constantly spitting out returning via hyperterminal (before i commented out).  I thought calling ReceiveData was enough to clear the flag.

void USART1_IRQHandler(void)
{    
    unsigned char rxData[4];
  uint8_t rxDataCount = 0;
  //static unsigned char errorCount;
    FILE *p = NULL;
    
    if(USART_GetITStatus(USART1, USART_IT_RXNE) == RESET){
        //USART_SendString(USART2, "Returning\r\n");
        return;
    }
    else{
        rxData[0] = rxData[1] = rxData[2] = rxData[3] = NULL;
        
        while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) != RESET){
            rxData[rxDataCount++] = fgetc(p);
        }
    }
    
    USART_SendString(USART2, "\r\nInterrupt routine finished\r\n");
}

/**
  ******************************************************************************
  * @file    IO_Toggle/main.c
  * @author  MCD Application Team
  * @version V1.0.0
  * @date    23-March-2012
  * @brief   Main program body
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2012 STMicroelectronics</center></h2>
  *
  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  * You may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
  *
  *        http://www.st.com/software_license_agreement_liberty_v2
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "stm32f0xx.h"
#include <stdio.h>
#include <rt_misc.h>
 
#pragma import(__use_no_semihosting_swi)
 
struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;
FILE __stdin;

/** @addtogroup STM32F0_Discovery_Peripheral_Examples
  * @{
  */

/** @addtogroup IO_Toggle
  * @{
  */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
#define BSRR_VAL                    0x0300
#define    TIMERSIZE                            5
#define IS_AF(c)             ((c >= 'A') && (c <= 'F'))
#define IS_af(c)             ((c >= 'a') && (c <= 'f'))
#define IS_09(c)             ((c >= '0') && (c <= '9'))
#define ISVALIDHEX(c)        IS_AF(c) || IS_af(c) || IS_09(c)
#define ISVALIDDEC(c)        IS_09(c)
#define CONVERTDEC(c)        (c - '0')

#define CONVERTHEX_alpha(c)  (IS_AF(c) ? (c - 'A'+10) : (c - 'a'+10))
#define CONVERTHEX(c)        (IS_09(c) ? (c - '0') : CONVERTHEX_alpha(c))

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
GPIO_InitTypeDef        GPIO_InitStructure;
NVIC_InitTypeDef     NVIC_InitStructure;
static __IO uint32_t TimingDelay;
static __IO uint32_t TimerTicks;
/* Private function prototypes -----------------------------------------------*/
void Delay(__IO uint32_t nTime);
void Int2Str(int32_t intnum, uint8_t* str);
uint32_t Str2Int(uint8_t *inputstr, int32_t *intnum);
void USART_SendChar(USART_TypeDef* USARTx, uint8_t Data);
void USART_SendString(USART_TypeDef* USARTx, uint8_t *s);
int fputc(int ch, FILE *f);
int fgetc(FILE *f);
int ferror(FILE *f);
void _ttywrch(int ch);
void _sys_exit(int return_code);
/* Private functions ---------------------------------------------------------*/


/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
int main(void)
{
  /*!< At this stage the microcontroller clock setting is already configured,
       this is done through SystemInit() function which is called from startup
       file (startup_stm32f0xx.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f0xx.c file
  */
    uint32_t time = 0, lastTime = 0, timeDiff = 0;
    uint16_t tmrOn[TIMERSIZE], tmrTicks[TIMERSIZE];
    uint8_t on = 0, loop = 0;
    uint8_t test = 250;
    uint8_t testStr[10] = {0};

    USART_InitTypeDef USART_InitStructure;
    
    /* SysTick end of count event each 1ms */
    RCC_ClocksTypeDef RCC_Clocks;
    RCC_GetClocksFreq(&RCC_Clocks);
  SysTick_Config(RCC_Clocks.HCLK_Frequency / 1000);
    
    //IO Port Config
  /* GPIOC Periph clock enable */
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
    
    /* Configure PA0 and PA1 in output pushpull mode for LED1 and LED2 */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    /* Configure PC0, PC2, PC4, PC6, PC8 in output pushpull mode for 485 output enables DE */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_4 | GPIO_Pin_6 | GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
    
    /* Configure PC1, PC3, PC5, PC7, PC9 in output pushpull mode for 485 input enables RE'*/
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_3 | GPIO_Pin_5 | GPIO_Pin_7 | GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
    //End of IO Port Config
    
    //USART Configuration
    /* GPIOC Periph clock enable */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
    
    /* Connect PA9, PA10, and PA2, PA3 pins to AF (USART1/USART2*/
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_1);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_1);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_1);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_1);
    
    /* Configure USART1 Tx as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    /* Configure USART1 Rx as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    /* Configure USART2 Tx as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    /* Configure USART2 Rx as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    /* Enable the USART1 Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    /* Enable the USART2 Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    // Configure USART
    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(USART1, &USART_InitStructure);
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    USART_Cmd(USART1, ENABLE);
    
    USART_InitStructure.USART_BaudRate = 9600;
  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_ITConfig(USART2, USART_IT_RXNE, ENABLE);
    USART_Cmd(USART2, ENABLE);
    //End of USART Config
    
    //initalize timers
    for (loop = 0; loop < TIMERSIZE; loop++){
        tmrOn[loop] = 0;
        tmrTicks[loop] = 0;
    }
 
  while (1)
  {
        time = TimerTicks;
        if (time >= lastTime){
            timeDiff = time - lastTime;
        }
        else{
            timeDiff = (4294967295u - lastTime) + time;
        }
        
        if (timeDiff >= 1000){
            for (loop = 0; loop < TIMERSIZE; loop++){
                if (tmrOn[loop] > 0){
                    on = 1;
                }
                else{
                    on = 0;
                }
                if (tmrTicks[loop] > 65535u){
                    tmrTicks[loop] = 65535u;
                }
                tmrTicks[loop] = on * (tmrTicks[loop] + 1);
            }
            lastTime = time;
            timeDiff = 0;
        }
        
        tmrOn[0] = 1;
        if ((tmrTicks[0] >= 1) && (tmrTicks[0] < 2)){
            // Turn ON LED1
            GPIO_SetBits(GPIOA, GPIO_Pin_0);
        }
        if ((tmrTicks[0] >= 2) && (tmrTicks[0] < 3)){
            // Turn ON LED2
            GPIO_SetBits(GPIOA, GPIO_Pin_1);
        }
        if (tmrTicks[0] > 3){
            GPIO_ResetBits(GPIOA, GPIO_Pin_0);
            GPIO_ResetBits(GPIOA, GPIO_Pin_1);
            
            //Sensor 1 - 485 receive enable
            GPIOC->BSRR = 0x0000;
            
            //printf("%c%c%c", 0xAA, 0x01, 0xAB);
            USART_SendString(USART2, "Waiting for Receive\r\n");
            
            tmrTicks[0] = 0;
            //test++;
        }
  }
}
/*-------------------------------------------End of Main----------------------------------------------------------*/

/**
  * @brief  Inserts a delay time.
  * @param  nTime: specifies the delay time length, in 1 ms.
  * @retval None
  */
void Delay(__IO uint32_t nTime)
{
  TimingDelay = nTime;

  while(TimingDelay != 0);
}

/**
  * @brief  Decrements the TimingDelay variable.
  * @param  None
  * @retval None
  */
void TimingDelay_Decrement(void)
{
  if (TimingDelay != 0x00)
  {
    TimingDelay--;
  }
}

/**
  * @brief  Increments Timer Tick by 1 ms.
  * @param  None
  * @retval None
  */
void TimerTick_Increment(void)
{
    TimerTicks++;
    
    /*
  if (TimerTicks >= 4294967295u)
  {
    TimerOver = TimerTicks - 1000;
        TimerTicks = 0;
  }
    */
}

/**
  * @brief  Convert an Integer to a string
  * @param  str: The string
  * @param  intnum: The intger to be converted
  * @retval None
  */
void Int2Str(int32_t intnum, uint8_t* str)
{
  uint32_t i, Div = 1000000000, j = 0, Status = 0;
    
    for (i = 0; i < 10; i++){
        str[i] = '\0';
    }

  for (i = 0; i < 10; i++)
  {
    str[j++] = (intnum / Div) + 48;

    intnum = intnum % Div;
    Div /= 10;
    if ((str[j-1] == '0') & (Status == 0))
    {
      j = 0;
    }
    else
    {
      Status++;
    }
  }
}

/**
  * @brief  Convert a string to an integer
  * @param  inputstr: The string to be converted
  * @param  intnum: The intger value
  * @retval 1: Correct
  *         0: Error
  */
uint32_t Str2Int(uint8_t *inputstr, int32_t *intnum)
{
  uint32_t i = 0, res = 0;
  uint32_t val = 0;

  if (inputstr[0] == '0' && (inputstr[1] == 'x' || inputstr[1] == 'X'))
  {
    if (inputstr[2] == '\0')
    {
      return 0;
    }
    for (i = 2; i < 11; i++)
    {
      if (inputstr[i] == '\0')
      {
        *intnum = val;
        /* return 1; */
        res = 1;
        break;
      }
      if (ISVALIDHEX(inputstr[i]))
      {
        val = (val << 4) + CONVERTHEX(inputstr[i]);
      }
      else
      {
        /* return 0, Invalid input */
        res = 0;
        break;
      }
    }
    /* over 8 digit hex --invalid */
    if (i >= 11)
    {
      res = 0;
    }
  }
  else /* max 10-digit decimal input */
  {
    for (i = 0;i < 11;i++)
    {
      if (inputstr[i] == '\0')
      {
        *intnum = val;
        /* return 1 */
        res = 1;
        break;
      }
      else if ((inputstr[i] == 'k' || inputstr[i] == 'K') && (i > 0))
      {
        val = val << 10;
        *intnum = val;
        res = 1;
        break;
      }
      else if ((inputstr[i] == 'm' || inputstr[i] == 'M') && (i > 0))
      {
        val = val << 20;
        *intnum = val;
        res = 1;
        break;
      }
      else if (ISVALIDDEC(inputstr[i]))
      {
        val = val * 10 + CONVERTDEC(inputstr[i]);
      }
      else
      {
        /* return 0, Invalid input */
        res = 0;
        break;
      }
    }
    /* Over 10 digit decimal --invalid */
    if (i >= 11)
    {
      res = 0;
    }
  }

  return res;
}

/**************************************************************************
  * @descr  Envoie d'un caractere via l'UARTx
  * @param  USARTx  definie l'uart à utiliser (1,2,3,4,5,6)
  * @param  Data    caractere à transferer
  * @retval None
  *************************************************************************/
void USART_SendChar(USART_TypeDef* USARTx, uint8_t Data)
{
  /* Check the parameters */
  assert_param(IS_USART_ALL_PERIPH(USARTx));
 
  /* Transmit Data */
  USART_SendData(USARTx, Data);
    while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET);
}
 
/**************************************************************************
  * @descr  Envoie d'une chaine de caracteres via l'UARTx
  * @param  USARTx  definie l'uart à utiliser (1,2,3,4,5,6)
  * @param  s       chaine de caracteres à transferer
  * @retval None
  *************************************************************************/
void USART_SendString(USART_TypeDef* USARTx, uint8_t *s)
{
    /* Check the parameters */
    assert_param(IS_USART_ALL_PERIPH(USARTx));
 
    while (*s != '\0')
        {
            USART_SendChar(USARTx, *s);
            s++;
        }
}

#ifdef  USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif

int fputc(int ch, FILE *f)
{
    static int last;
 
    if ((ch == (int)'\n') && (last != (int)'\r'))
    {
        last = (int)'\r';
 
    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
 
      USART_SendData(USART1, last);
    }
    else
        last = ch;
 
    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
 
  USART_SendData(USART1, ch);
 
  return(ch);
}
 
int fgetc(FILE *f)
{
    char ch;
 
    while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);
 
    ch = USART_ReceiveData(USART1);
 
  return((int)ch);
}
 
int ferror(FILE *f)
{
  /* Your implementation of ferror */
  return EOF;
}
 
void _ttywrch(int ch)
{
    static int last;
 
    if ((ch == (int)'\n') && (last != (int)'\r'))
    {
        last = (int)'\r';
 
    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
 
      USART_SendData(USART1, last);
    }
    else
        last = ch;
 
    while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
 
  USART_SendData(USART1, ch);
}
 
void _sys_exit(int return_code)
{
label:  goto label;  /* endless loop */
}

/**
  * @}
  */

/**
  * @}
  */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/


Outcomes