miércoles, 5 de abril de 2017

Comunicación serial (I) -ARM Cortex-M4-

Programa

/* Marzo de 2016
Tarjeta: STM32 Discovery
Microcontrolador: STM32F411VET6U
IDE: IAR Embedded Workbench
Programa para comunicar la tarjeta Discovery con el PC mediante RS232, usando
la USART2 del microcontrolador (*). El usuario introduce un carácter mediante

el teclado del ordenador:
- Si es una "a", se hace un eco del carácter enviado.
- Si es una "b", se hace hace un eco del carácter enviado.
- En el resto de casos no sucede nada.
(*) Pines: PA2 (Tx) y PA3(Rx).
*/

#include "stm32f4xx.h"

char caracter;
                     

//--- Rutina de servicio de interrupción (ISR) ---
void USART2_IRQHandler (void){
  if (USART2->SR & USART_SR_RXNE){          // Si RXNE = 1 en el registro SR,
    caracter = USART2->DR;                                   // salva el carácter recibido
    // Si la tarjeta recibe una 'a', la envía al PC
    if (caracter == 'a') USART2->DR = caracter;   
    // Si la tarjeta recibe una 'b', la envía al PC
    if (caracter == 'b') USART2->DR = caracter;    
  }
}


//--- Función principal del programa ---
void main (void)  {  
  // Inicialización de la USART2
  RCC->AHB1ENR  |= 0x00000001;        // Habilita el reloj para el puerto A
  RCC->APB1ENR  |= 0x00020000;         // Habilita el reloj para la USART2
  GPIOA->MODER  |= 0x000000A0;       // Configura PA2 y PA3 en modo AF
  GPIOA->AFR[0] |= 0x00007700;           // Selecciona AF7 (UART1..2) para PA2 y PA3
  USART2->CR1   |= 0x0000202C;           // Habilita: USART2,transmisión, recepción e
                                                                    // interrupción para recepción  
  USART2->BRR = 0x1388;                      // Veloc. comunic.: 9600 baudios (fck= 48Mhz)
  //USART2->BRR = 0x00D0;                   // 230400 baudios (fck= 48Mhz)
 
  NVIC->ISER[1] |= 0x00000040;             // Habilita interrupción para USART2 en NVIC
 
 
// Bucle infinito
  while(1){
  }
}




Circuito





 - La comunicación serial se realiza utilizando un módulo UM232R, que sirve para convertir de RS232 a USB (genera un puerto COM virtual al instalar su controlador).

- El jumper J1 (JP1 en la primera figura) del UM232R tiene que estar en posición 1-2, debido a las tensiones que maneja el microcontrolador de la tarjeta Discovery. El jumper J2
(JP2) tiene que estar conectado.

- Para las pruebas se emplean dos cables USB (ver foto y esquema más arriba): el cable USB rojo se utiliza para grabar los programas en la tarjeta Discovery y por el blanco se produce el envío la recepción de datos del programa del microcontrolador, una vez ejecutado éste.




Figuras







➤ Observaciones

- Para probar el programa, además de las conexiones anteriores, es necesario utilizar Monitor Serie (del entorno de programación de Arduino) o alguna aplicación informática similar.

- En el programa se accede a los siguientes registros: RCC_AHB1ENR, RCC_APB1ENR, GPIOA_MODER, GPIOA_AFRLUSART2_CR1 USART2_BRR, NVIC_ISERH, USART2_SR y USART2_DR.

- En la función principal del programa se realiza la configuración de la USART2 del microcontrolador.  

- Además, dentro de la función principal, se habilita una interrupción asociada a la USART2 del microcontrolador, de tal manera que, cada vez que el usuario envíe un carácter desde el ordenador, se ejecutará el código contenido en la función USART2_IRQHandler().

- RCC->AHB1ENR |= 0x00000001: habilita el reloj para el puerto A, para ello pone a ‘1’ el bit 0 del registro RCC_AHB1ENR

 - RCC->APB1ENR |= 0x00020000: habilita el reloj para la USART2, escribiendo un ‘1’ el bit 17 del registro RCC_APB1ENR.

- GPIOA->MODER |= 0x000000A0: configura los pines PA2 (Tx) y PA3 (Rx) en modo AF. La forma de hacerlo es mediante la escritura de ‘10’ en las posiciones MODER3[1:0] y MODER2[1:0] del registro MODER del puerto A.

- GPIOA->AFR[0] |= 0x00007700: asocia PA2 y PA3 con AF7 (función alternativa), la cual está relacionada con la USART1 y la USART2. Esta orden escribe ‘0111’ en las posiciones AFRL2[3:0] y AFRL3[3:0] del registro GPIOA_AFRL.

- USART2->CR1 |= 0x0000202C: con esta instrucción, accediendo al registro USART2_CR1, se habilita la USART2 (bit 13 = 1), se habilitan el emisor (bit 3 = 1) y el receptor de datos (bit 2 = 1). Esta orden también se encarga de poner a ‘1’ el bit 5 del registro USART2_CR1 (RXNEIE) para habilitar la interrupción relacionada con RXNE; es decir, se genera una interrupción relacionada con la USART2 cuando, dentro del registro USART2_SR, ORE = 1 (error de desbordamiento) o cuando RXNE = 1. 

- El bit RXNE (bit 5) del registro USART2_SR se pone a ‘1’ por hardware cuando el contenido del registro de desplazamiento RDR ha sido transferido al registro USART2_DR. Se genera una interrupción si RXNEIE = 1 (bit 5 del registro CR1). El bit RXNE se pone a ‘0’ leyendo el registro USART2_DR o escribiendo ‘0’ en él. Es decir, cuando se lee el registro USART2_DR se anula la interrupción provocada por RXNE.

- USART2->BRR = 0x1117: escribiendo este valor en el registro UART2_BRR, se consigue una velocidad de comunicación de 9600 baudios. Para ello hay que aplicar la siguiente fórmula: baud = fck / (8 x (2 – OVER8) x USARTDIV); donde fck es la frecuencia de reloj con la que está funcionando la USART2 (que es de 48 MHz), baud es igual a 9600 baudios, OVER8 es igual a 0 y USARTDIV es el valor a calcular.

- Lo referente valor de la frecuencia fck será explicado en las siguientes entradas del blog.

 - Despejando USARTDIV se obtiene que su valor es igual a 312,5. La parte entera de este número (312) es 138 en hexadecimal. La parte decimal (0,5) se multiplica por 16, con ello se obtiene 8, que en hexadecimal es el mismo número. La parte entera se guarda en DIV_Mantissa[11:0] y la parte fraccionaria se guarda en DIV_Fraction[3:0]; todo ello, dentro del registro UART2_BRR. De ahí que el número hexadecimal que se guarda en este registro sea 0x1388.

- NVIC->ISER[1] |= 0x00000040: habilita una interrupción para la USART2 en el controlador NVIC. En concreto, lo que se hace es una puesta a ‘1’ del bit 6 del registro NVIC_ISER1, acción que produce la habilitación de la interrupción asociada a la USART2. El registro NVIC_ISER1 tiene que ver con las posiciones comprendidas entre la 32 y la 63 de la tabla de vectores de los microcontroladores STM32F411xC/E (ver tabla 37, arriba). NVIC_ISER0, a su vez, está relacionado con las posiciones entre 0 y 31.  Dicha tabla enumera las fuentes de interrupción del microcontrolador; la interrupción correspondiente a USART2 ocupa la posición número 38 de la tabla, por ello hay que escribir un ‘1’ el bit 6 del registro ISER1. La información sobre el registro NVIC_ISER1 se puede consultar en el documento PM0214 Programming manual.
 
- if (USART2->SR & USART_SR_RXNE){: comprueba si el bit RXNE (bit 5) del registro USART2_SR (Status Register) es igual a ‘1’. Cuando RXNE es igual a 1 quiere decir que el dato recibido está listo para ser leído. Esta comprobación se hace para identificar la fuente de interrupción.

- USART_SR_RXNE: es una constante que está definida en stm32f4xx.h. En este archivo hay muchas otras constantes que pueden emplearse para configuración de los diferentes registros del microcontrolador, en lugar de escribir directamente sus valores numéricos.

- caracter = USART2->DR: con esta instrucción se guarda el carácter recibido en una variable de tipo char. USART2_DR es el registro de datos (data register) y contiene el dato emitido o recibido, dependiendo de si se lee o se escribe. Este registro es de 32 bits, pero los bits del 0 al 31 están reservados y sólo pueden utilizarse los bits comprendidos entre el 0 y el 8. También hay que tener en cuenta que con esta orden se lee USART2_DR; siempre que se lee ese registro se borra el bit RXNE (registro USART2_SR) y, por tanto, se anula la petición de interrupción asociada a RXNE.

- USART2->DR = caracter: envía al PC el carácter previamente guardado con la instrucción anterior.
 

➤ Registros empleados

Las siguientes imágenes representan los registros utilizados en el programa y en ellas están señalados los bits que éste modifica o consulta. Para más información, ver los documentos RM0383 Reference Manual y PM0214 Programming manual.






















No hay comentarios:

Publicar un comentario

Nota: solo los miembros de este blog pueden publicar comentarios.