Mostrando entradas con la etiqueta USART_DR. Mostrar todas las entradas
Mostrando entradas con la etiqueta USART_DR. Mostrar todas las entradas

miércoles, 5 de abril de 2017

Comunicación serial (II) -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", hace un eco del carácter enviado.
- Si es una "c", se envía un mensaje con un retorno de carro.
- En el resto de casos no sucede nada.
(*)Pines: PA2 (Tx) y PA3 (Rx).
*/

#include "stm32f4xx.h"

char caracter;
char *mensaje;                            // Declara un puntero de tipo char

//--- 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 se recibe una 'a' o una 'b', envía al PC el carácter recibido
      if (caracter == 'a' || caracter == 'b') USART2->DR = caracter;         
      if (caracter == 'c'){
        mensaje = " Recibida una c\n";                     // Inicializa el puntero
        USART2->CR1 |= 0x00000080;                  // Habilita interrupción para envío
        USART2->DR = *mensaje++;                     // Envia el 1er. carácter del mensaje
                                                                              // e incrementa el puntero
      }             
  }  
  // Si TXNE = 1 en el registro SR y si no se ha llegado al final del mensaje,
  // envía el siguiente carácter e incrementa el puntero
  if (USART2->SR & USART_SR_TXE){       
    if(*mensaje != '\0') USART2->DR = *mensaje++;
  }
}

//---  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)
    
  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. 

- El programa es igual que el del ejemplo anterior, salvo en lo referente a la recepción del carácter “c”; en ese caso, no se envía un único carácter, sino un string. Los caracteres que componen el string se han de enviar uno a uno y cada vez que se manda un carácter se produce una interrupción.

- La rutina de servicio de interrupción (ISR) atiende a las interrupciones producidas por la recepción de datos y a las producidas por el envío de datos.

- char *mensaje: crea un puntero a la variable mensaje. Con este tipo de declaración se añade un “/0” automáticamente al final del texto del string.

- mensaje = " Recibida una c\n": incicializa el string y el puntero.

- USART2->CR1 |= 0x00000080: esta instrucción escribe un ‘1’ en el bit 7 del registro
USART2_CR1; con ello genera una interrupción de la USART2 cuando, en el registro USART2_SR TXE vale '1' . El bit TXE se pone a ‘1’ por hardware cuando el contenido del registro TDR ha sido transferido al registro de desplazamiento (ver figura 167, arriba). La interrupción generada se deshabilita al escribir un dato en el registro USART2_DR.

- USART2->DR = *mensaje++: carga en el registro
USART2 _DR el siguiente carácter del mensaje (lo envía) e incrementa el puntero.

- if (USART2->SR & USART_SR_TXE){: comprueba si el bit TXE (bit 7) del registro
USART2_SR (Status Register) es igual a ‘1’. Si TXE es igual a 1, quiere decir que el dato ha sido transferido al registro de desplazamiento. Esta comprobación se hace para identificar la fuente de interrupción, dado que se manejan interrupciones por recepción de datos e interrupciones por envío de datos.

- if(*mensaje != '\0') USART2->DR = *mensaje++: si aún no se ha llegado al final del mensaje (debido a que al final del texto del string hay un “/0”), se envía el siguiente carácter y se incrementa el puntero. Escribiendo en el registro USART2_DR se deshabilita la interrupción producida por el bit TXE.

- USART_SR_RXNE y USART_SR_TXE: son unas constantes que están definidas en el archivo stm32f4xx.h.
 

➤ 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.





















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.