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.





















No hay comentarios: