STM32L031 Nucleo USART Problema

1

Tengo un problema con STM32L031 Nucleo board comunicación USART.

Estoy intentando enviar datos a PC en USART periódicamente y capturar el carácter específico ('a') con Interrupción de Rx y encender el LED interno cuando el microcontrolador recibe alguno de ellos.

Estos son los problemas que encontré durante la prueba:

  • El microcontrolador envió los datos periódicamente a la PC, pero los datos se corrompieron cuando se trataba de PC. La cadena original era " STM32L031 USART Test " pero cuando la recibió de la PC fue " S⸮M3⸮⸮03⸮⸮USA⸮Ԡ⸮e⸮t ".

  • Cuando envío el carácter 'a' de la PC al microcontrolador; el controlador de interrupciones activó y apagó el LED con éxito. Después de recibir los datos, el microcontrolador se detuvo para enviar datos a la PC, pero continúa recibiendo el carácter y activando el controlador de interrupciones con éxito.

Utilicé los Controladores de bajo nivel (LL) de ST en mi programa, aquí están mis rutinas.

Esta es una función para la configuración del reloj del sistema, utilicé HSI (16MHz - Reloj interno de alta velocidad) como fuente de PLL y usé el reloj de 24 MHz PLL como reloj del sistema.

/**
  * @brief  This function configurates the system clock as:
    *         - uses HSI as PLL source
    *         - uses PLL as system clock at 24 MHz
  * @param  none
  * @retval none
  */
void System_ClockConfiguration(void)
{
    LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE3); // regulator configuraiton in order to freq

    /* high speed internal (HSI - 16MHz) system clock avtivating
   * in order to use for PLL source clock   */
    LL_RCC_HSI_Enable(); 
    LL_RCC_HSI_DisableDivider();

    /* PLL configuration */
    LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSI, LL_RCC_PLL_MUL_6, LL_RCC_PLL_DIV_4);
    LL_RCC_PLL_Enable();

    LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); // set system clock source as PLL

    /* peripheral clock divide value configuraiton */
    LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); 
    LL_RCC_SetAPB1Prescaler(LL_RCC_SYSCLK_DIV_1);   
    LL_RCC_SetAPB2Prescaler(LL_RCC_SYSCLK_DIV_2);   

    SystemCoreClockUpdate(); // system clock updating
}

Aquí está mi configuración de USART2:

/**
  * @brief  This function initializes the USART2
  * @param  none
  * @retval none
  */
void USART2_Init(void)
{
    LL_USART_InitTypeDef LL_Usart_InitStruct; // USART initialization struct    
    LL_GPIO_InitTypeDef LL_GPIO_Initstruct; // GPIO initialization struct

    LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA); // Clock freq activated for GPIOA peripheral

    /* GPIO pin configuration */
    LL_GPIO_Initstruct.Alternate = LL_GPIO_AF_4;
    LL_GPIO_Initstruct.Mode = LL_GPIO_MODE_ALTERNATE;
    LL_GPIO_Initstruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    LL_GPIO_Initstruct.Pin = LL_GPIO_PIN_9; // Tx Pin
    LL_GPIO_Initstruct.Pull = LL_GPIO_PULL_UP;
    LL_GPIO_Initstruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;

    LL_GPIO_Init(GPIOA, &LL_GPIO_Initstruct);   // GPIO pin initialize

    LL_GPIO_Initstruct.Alternate = LL_GPIO_AF_4;
    LL_GPIO_Initstruct.Mode = LL_GPIO_MODE_ALTERNATE;
    LL_GPIO_Initstruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    LL_GPIO_Initstruct.Pin = LL_GPIO_PIN_10; // Rx Pin
    LL_GPIO_Initstruct.Pull = LL_GPIO_PULL_UP;
    LL_GPIO_Initstruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;

    LL_GPIO_Init(GPIOA, &LL_GPIO_Initstruct);   // GPIO pin initialize


    /* Important: we need to disable related USART first in order to write 
     * USART segisters properly! */
    LL_USART_Disable(USART2);
    LL_USART_DeInit(USART2);

    LL_RCC_SetUSARTClockSource(LL_RCC_USART2_CLKSOURCE_SYSCLK); // define usart clocksource as system clock

    LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART2); // Clock freq activated for USART2 peripheral

    /* USART initialization struct configurations */
    LL_Usart_InitStruct.BaudRate = 9600;
    LL_Usart_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
    LL_Usart_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
    LL_Usart_InitStruct.Parity = LL_USART_PARITY_NONE;
    LL_Usart_InitStruct.StopBits = LL_USART_STOPBITS_1;
    LL_Usart_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;

    LL_USART_Init(USART2, &LL_Usart_InitStruct); // edit USART registers from related struct    

    /* NVIC Configuration */
    __NVIC_DisableIRQ(USART2_IRQn);
    __NVIC_ClearPendingIRQ(USART2_IRQn);
    __NVIC_SetPriority(USART2_IRQn, 1);
    __NVIC_SetVector(USART2_IRQn, USART2_IRQn);
    __NVIC_EnableIRQ(USART2_IRQn);  

    LL_USART_Enable(USART2); // enable USART

}

Aquí está mi función de controlador de interrupciones:

/**
  * @brief  USART2 interrupt handler
  * @param  none
  * @retval none
  */    
void USART2_IRQHandler(void)
{

    if((USART2->ISR & USART_ISR_RXNE) == USART_ISR_RXNE)
    {
        char t = USART2->RDR;

        if(t == 'a')            
        {           
            LL_GPIO_TogglePin(GPIOB, LL_GPIO_PIN_3);
        }

    }

}

La función que utilicé para enviar los datos en USART:

/**
  * @brief  This function is used for transmit a character array
    *         through USART communication
  * @param  USARTx
    * @param  txArray
  * @retval none
  */    
void USART_Puts(USART_TypeDef* USARTx, volatile char *txArray)
{

    while(*txArray)
    {
        while(!(USARTx ->ISR & 0x0040)); // wait for the USART until its available again (TC bit)
        LL_USART_TransmitData8(USART2, *txArray); // send the data
        *txArray++; // jump to next array member (next character)
    }   

}

Finalmente, aquí está la función principal de mi programa:

char str[50]; // USART buffer string
int32_t i = 0; // general purpose
char t;

/**
  * @brief  Program entry point
  * @param  none
  * @retval none
  */
int main(void)
{
    System_ClockConfiguration(); // system clock configuration 

    LED3_Init(); // on board LED initialization

    USART2_Init(); // USART2 initialization


    /* main loop */
    while(1)
    {

        sprintf(str, "STM32L031 USART Test\n");
        USART_Puts(USART2, str);

        i = 150000;

        /* basic delay */
        while(i)
        {
            i--;
        }   

    }

}   
    
pregunta Batu92k

1 respuesta

0

Encontré la razón exacta del problema ... Parece que todo se trata del modo de optimización del compilador de KEIL. Cuando vi la configuración de optimización en la sección C / C ++ de las "opciones para el menú de destino", se estableció como "nivel 0". Luego cambié el valor a "predeterminado" y todo funcionó como se esperaba.

Aquí está mi función de configuración de trabajo para USART2:

/**
  * @brief  This function initializes the USART2
  * @param  none
  * @retval none
  */
void USART2_Init(void)
{
    LL_USART_InitTypeDef LL_Usart_InitStruct; // USART initialization struct    
    LL_GPIO_InitTypeDef LL_GPIO_Initstruct; // GPIO initialization struct

    LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA); // Clock freq activated for GPIOA peripheral

    /* GPIO pin configuration */
    LL_GPIO_Initstruct.Alternate = LL_GPIO_AF_4;
    LL_GPIO_Initstruct.Mode = LL_GPIO_MODE_ALTERNATE;
    LL_GPIO_Initstruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    LL_GPIO_Initstruct.Pin = LL_GPIO_PIN_9; // Tx Pin
    LL_GPIO_Initstruct.Pull = LL_GPIO_PULL_UP;
    LL_GPIO_Initstruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;

    LL_GPIO_Init(GPIOA, &LL_GPIO_Initstruct);   // GPIO pin initialize

    LL_GPIO_Initstruct.Alternate = LL_GPIO_AF_4;
    LL_GPIO_Initstruct.Mode = LL_GPIO_MODE_ALTERNATE;
    LL_GPIO_Initstruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    LL_GPIO_Initstruct.Pin = LL_GPIO_PIN_10; // Rx Pin
    LL_GPIO_Initstruct.Pull = LL_GPIO_PULL_UP;
    LL_GPIO_Initstruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;

    LL_GPIO_Init(GPIOA, &LL_GPIO_Initstruct);   // GPIO pin initialize


    /* Important: we need to disable related USART first in order to write 
     * USART segisters properly! */
    LL_USART_Disable(USART2);
    LL_USART_DeInit(USART2);

    LL_RCC_SetUSARTClockSource(LL_RCC_USART2_CLKSOURCE_SYSCLK); // define usart clocksource as system clock

    LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_USART2); // clock freq activated for USART2 peripheral

    /* USART initialization struct configurations */
    LL_Usart_InitStruct.BaudRate = 115200;
    LL_Usart_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
    LL_Usart_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
    LL_Usart_InitStruct.Parity = LL_USART_PARITY_NONE;
    LL_Usart_InitStruct.StopBits = LL_USART_STOPBITS_1;
    LL_Usart_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;

    LL_USART_Init(USART2, &LL_Usart_InitStruct); // edit USART registers from related struct    

    /* NVIC Configuration */
    __NVIC_DisableIRQ(USART2_IRQn);
    __NVIC_ClearPendingIRQ(USART2_IRQn);
    __NVIC_SetPriority(USART2_IRQn, 1);
    __NVIC_SetVector(USART2_IRQn, USART2_IRQn);
    __NVIC_EnableIRQ(USART2_IRQn);  

    LL_USART_EnableIT_RXNE(USART2); // Rx buffer not empty interrupt enable

    LL_USART_Enable(USART2); // enable USART

}
    
respondido por el Batu92k

Lea otras preguntas en las etiquetas