STM32 USART Rx Interrupts

3

Estoy intentando configurar la comunicación UART con el STM32F0 Discovery Board, pero tengo dificultades para adaptar el lado Rx de las cosas a mis necesidades.

El STM32 recibirá un mensaje (4-6 bytes sin carácter final) del dispositivo UART cada pocos segundos y luego deberá enviar una respuesta.

¿Cómo debo manejar la recepción de mensajes para que no esté limitado a un tamaño de mensaje fijo, para que no tenga que buscar un carácter final (tal vez usando un temporizador) y para que no se produzcan fallos? ¿Mis comunicaciones completas?

Estoy depurando el código de abajo con un cable FTDI USB-UART en este momento y la interrupción solo se dispara para el primer carácter que envío a través del terminal y luego no volveré a disparar.

//This function handles USART1 global interrupt request.
void USART1_IRQHandler(void)
{
  if( USART_GetITStatus(PMIC_COM1, USART_IT_RXNE))
  {
    char t = USART_ReceiveData(PMIC_COM1);

    //Check if received character is end character
    if( (t != 'x') && (cnt < MAX_STRLEN) ){
      received_string[cnt] = t;
      cnt++;
    }
    else{ // otherwise reset the character counter and print the received string
      cnt = 0;
      printf("UART Message: %c", received_string);
    }
  }
}
    
pregunta spizzak

5 respuestas

3

¿Borraste el bit de interrupción? Intenta llamar a void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT) después de haber procesado el evento.

Si fuera tú, solo incluiría las líneas de alimentación como el separador de comandos, pero ciertamente podrías establecer un temporizador.

    
respondido por el joeforker
0

Para la separación de mensajes, hay varias cosas que puedes hacer. Ha declarado que no le gustan los caracteres de formato de longitud fija y de terminación de fin de mensaje, por lo que mi siguiente sugerencia sería hacer que el primer byte transmitido sea el número de caracteres a seguir. Alternativamente, puede forzar una pausa entre los mensajes, de modo que si la línea de recepción está inactiva durante, por ejemplo, 16 bits después de un carácter, esa pausa delimita el final de un mensaje. Personalmente, combinaría los dos: establece el primer byte como un byte de longitud y luego lo utilizo para determinar cuánto tiempo debería tardar en recibir todo el mensaje. Si ese tiempo expira y no ha recibido el número correcto de bytes, entonces tiene un mensaje roto y puede simplemente descartarlo.

    
respondido por el Chris Ryding
0

Tenga un búfer de tamaño fijo, digamos 64 bytes, y lea hasta 64 bytes a la vez, luego aliméntelos a una máquina de estado. De esa manera, no importa si lee más allá del final de un mensaje y solo una parte del siguiente, por ejemplo.

    
respondido por el Dan Ellis
-1

Muestra: > :

////// The above comment is automatically generated by CoIDE ///////////////////

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_usart.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "misc.h"

#define NUM 10

int i,j;
char name[NUM+1] = {'
////// The above comment is automatically generated by CoIDE ///////////////////

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_usart.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"
#include "misc.h"

#define NUM 10

int i,j;
char name[NUM+1] = {'%pre%'}; 

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
ErrorStatus HSEStartUpStatus;

/* Private function prototypes -----------------------------------------------*/
void NVIC_Configuration(void);
void GPIO_Configuration(void);
void USART_Configuration(void);
void USART1_IRQHandler(void);
void UARTSend(const unsigned char *pucBuffer, unsigned long ulCount);

/******************************************************************************/
/*            STM32F10x Peripherals Interrupt Handlers                        */
/******************************************************************************/

/**
  * @brief  This function handles USARTx global interrupt request.
  * @param  None
  * @retval None
  */
void USART1_IRQHandler(void)
{
    if ((USART1->SR & USART_FLAG_RXNE) != (u16)RESET)           
    {          
            i = USART_ReceiveData(USART1);
            if(j == NUM)
            {
                name[j] = i;
                j = 0;
            }
            else
            {
                name[j++] = i;
            }
            name[j] = '%pre%';
    }   
}

/* Private functions ---------------------------------------------------------*/

/*******************************************************************************
* Function Name  : usart_rxtx
* Description    : Print "Welcome to CooCox!"  on Hyperterminal via USART1.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void usart_init(void)
{
        const unsigned char menu[] = " Welcome to CooCox!\r\n";

        /* Enable USART1 and GPIOA clock */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);

        /* NVIC Configuration */
        NVIC_Configuration();


        /* Configure the GPIOs */
        GPIO_Configuration();

        /* Configure the USART1 */
        USART_Configuration();

        /* Enable the USART1 Receive interrupt: this interrupt is generated when the
             USART1 receive data register is not empty */
        USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

        /* print welcome information */
        UARTSend(menu, sizeof(menu));



        while(1)
        {
        }
}

/*******************************************************************************
* Function Name  : GPIO_Configuration
* Description    : Configures the different GPIO ports.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  /* Configure USART1 Tx (PA.09) as alternate function push-pull */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  /* Configure USART1 Rx (PA.10) as input floating */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
}

/*******************************************************************************
* Function Name  : USART_Configuration
* Description    : Configures the USART1.
* Input          : None
* Output         : None
* Return         : None
*******************************************************************************/
void USART_Configuration(void)
{
  USART_InitTypeDef USART_InitStructure;

/* USART1 configuration ------------------------------------------------------*/
  /* USART1 configured as follow:
        - BaudRate = 115200 baud  
        - Word Length = 8 Bits
        - One Stop Bit
        - No parity
        - Hardware flow control disabled (RTS and CTS signals)
        - Receive and transmit enabled
        - USART Clock disabled
        - USART CPOL: Clock is active low
        - USART CPHA: Data is captured on the middle 
        - USART LastBit: The clock pulse of the last data bit is not output to 
                         the SCLK pin
  */
  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(USART1, &USART_InitStructure);

  /* Enable USART1 */
  USART_Cmd(USART1, ENABLE);
}

/**
  * @brief  Configures the nested vectored interrupt controller.
  * @param  None
  * @retval None
  */
void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

  /* Enable the USARTx Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

/*******************************************************************************
* Function Name  : UARTSend
* Description    : Send a string to the UART.
* Input          : - pucBuffer: buffers to be printed.
*                : - ulCount  : buffer's length
* Output         : None
* Return         : None
*******************************************************************************/
void UARTSend(const unsigned char *pucBuffer, unsigned long ulCount)
{
    //
    // Loop while there are more characters to send.
    //
    while(ulCount--)
    {
        USART_SendData(USART1, *pucBuffer++);// Last Version USART_SendData(USART1,(uint16_t) *pucBuffer++);
        /* Loop until the end of transmission */
        while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET)
        {
        }
    }
}
'}; /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ ErrorStatus HSEStartUpStatus; /* Private function prototypes -----------------------------------------------*/ void NVIC_Configuration(void); void GPIO_Configuration(void); void USART_Configuration(void); void USART1_IRQHandler(void); void UARTSend(const unsigned char *pucBuffer, unsigned long ulCount); /******************************************************************************/ /* STM32F10x Peripherals Interrupt Handlers */ /******************************************************************************/ /** * @brief This function handles USARTx global interrupt request. * @param None * @retval None */ void USART1_IRQHandler(void) { if ((USART1->SR & USART_FLAG_RXNE) != (u16)RESET) { i = USART_ReceiveData(USART1); if(j == NUM) { name[j] = i; j = 0; } else { name[j++] = i; } name[j] = '%pre%'; } } /* Private functions ---------------------------------------------------------*/ /******************************************************************************* * Function Name : usart_rxtx * Description : Print "Welcome to CooCox!" on Hyperterminal via USART1. * Input : None * Output : None * Return : None *******************************************************************************/ void usart_init(void) { const unsigned char menu[] = " Welcome to CooCox!\r\n"; /* Enable USART1 and GPIOA clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE); /* NVIC Configuration */ NVIC_Configuration(); /* Configure the GPIOs */ GPIO_Configuration(); /* Configure the USART1 */ USART_Configuration(); /* Enable the USART1 Receive interrupt: this interrupt is generated when the USART1 receive data register is not empty */ USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); /* print welcome information */ UARTSend(menu, sizeof(menu)); while(1) { } } /******************************************************************************* * Function Name : GPIO_Configuration * Description : Configures the different GPIO ports. * Input : None * Output : None * Return : None *******************************************************************************/ void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; /* Configure USART1 Tx (PA.09) as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure USART1 Rx (PA.10) as input floating */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); } /******************************************************************************* * Function Name : USART_Configuration * Description : Configures the USART1. * Input : None * Output : None * Return : None *******************************************************************************/ void USART_Configuration(void) { USART_InitTypeDef USART_InitStructure; /* USART1 configuration ------------------------------------------------------*/ /* USART1 configured as follow: - BaudRate = 115200 baud - Word Length = 8 Bits - One Stop Bit - No parity - Hardware flow control disabled (RTS and CTS signals) - Receive and transmit enabled - USART Clock disabled - USART CPOL: Clock is active low - USART CPHA: Data is captured on the middle - USART LastBit: The clock pulse of the last data bit is not output to the SCLK pin */ 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(USART1, &USART_InitStructure); /* Enable USART1 */ USART_Cmd(USART1, ENABLE); } /** * @brief Configures the nested vectored interrupt controller. * @param None * @retval None */ void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; /* Enable the USARTx Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } /******************************************************************************* * Function Name : UARTSend * Description : Send a string to the UART. * Input : - pucBuffer: buffers to be printed. * : - ulCount : buffer's length * Output : None * Return : None *******************************************************************************/ void UARTSend(const unsigned char *pucBuffer, unsigned long ulCount) { // // Loop while there are more characters to send. // while(ulCount--) { USART_SendData(USART1, *pucBuffer++);// Last Version USART_SendData(USART1,(uint16_t) *pucBuffer++); /* Loop until the end of transmission */ while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) { } } }
    
respondido por el Hamed
-1

Ciertamente, usted utiliza una velocidad de transmisión específica. Configurar un temporizador de 'n' milisegundos. Restablecer el temporizador después de cada byte recibido. el temporizador activará su actualización. Interrupción después de que hayan transcurrido 'n' milisegundos después del último byte recibido. (porque después de que se recibe el último byte, no hay nadie que pueda restablecer el temporizador).

De esta manera el temporizador le avisará cuando el mensaje haya terminado. Los 'n' milisegundos dependen de la ventana de tiempo que puede tener entre dos mensajes. P.ej. para 9600 bps puedes usar 5 mseg. Si no aparece ningún otro byte después de 'n' milisegundos después del anterior, considere que el mensaje ha finalizado (todos los bytes que ha esperado han llegado).

    
respondido por el ionut

Lea otras preguntas en las etiquetas