14
Microcontroladores Grado en Ingeniería de Tecnologías de Telecomunicación Práctica 6: Comunicación serie asíncrona: la UART CURSO ACADÉMICO 2012/2013

Practica 6 Uart Nhr

Embed Size (px)

Citation preview

Page 1: Practica 6 Uart Nhr

Microcontroladores

Grado en Ingeniería de Tecnologías de Telecomunicación

Práctica 6:

Comunicación serie

asíncrona: la UART

CURSO ACADÉMICO 2012/2013

Page 2: Practica 6 Uart Nhr
Page 3: Practica 6 Uart Nhr

Práctica 6: Comunicación serie asíncrona: la UART Curso 2012/2013

i

ÍNDICE

1 Introducción ............................................................................................................................. 1

1.1 Objetivo ............................................................................................................................ 1

1.2 Instalación del programa en el PC .................................................................................... 1

1.3 Configuración de la placa LaunchPad .............................................................................. 2

1. PRÁCTICA 6: COMUNICACIÓN SERIE A TRAVÉS DE LA UART ....................................................... 4

Page 4: Practica 6 Uart Nhr
Page 5: Practica 6 Uart Nhr

Práctica 6: Comunicación serie asíncrona: la UART Curso 2012/2013

1

1 INTRODUCCIÓN

Este documento describe la Práctica 6 de la asignatura, la cual pretende ofrecer una visión

general de la comunicación serie a través de la UART.

Para ello se parte de los conocimientos adquiridos en las prácticas anteriores, por lo que puede

ser necesaria su consulta para desarrollar algunos aspectos básicos que ya se han tratado

anteriormente.

La práctica establece una comunicación serie entre una aplicación que se ejecuta en el PC y un

programa que se ejecuta en el microcontrolador:

1.1 Objetivo

En numerosas aplicaciones el microcontrolador cumple una función de interfaz entre un conjunto

de sensores o actuadores y otro procesador más potente que realiza el tratamiento de los datos,

como, por ejemplo un PC. La forma de comunicación más extendida entre microcontrolador y el

PC es la comunicación serie asíncrona: “el puerto serie”.

Esta práctica tiene como objetivo básico ofrecer un primer contacto con la utilización de la UART

para realizar una comunicación serie asíncrona entre un PC y el microcontrolador.

1.2 Instalación del programa en el PC

1) Accede al campus virtual y descargue el fichero

“Inst Practica 6.msi”:

2) Ejecute el instalador (sólo para Windows) y acepte

todos los pasos que va indicándole el mismo.

3) Si todo ha ido bien, debería haberse creado una

nueva entrada en el menú de inicio y un acceso

directo en el escritorio:

Nuevo grupo “Microcontroladores” conteniendo acceso directo al

programa “Práctica 6” en el menú Inicio de Windows.

Acceso directo al programa

“Práctica 6” en el escritorio.

Page 6: Practica 6 Uart Nhr

Microcontroladores Grado en Ingeniería de Tecnologías de Telecomunicación

2

4) Desconecte la placa LaunchPad si la tiene conectada

al PC y arranque la aplicación. Debería ver una

ventana informando de que no se detecta ninguna

placa conectada.

5) Pulse “OK”. Debería entonces ver la ventana de

la aplicación “ComSerie”:

6) Cierre la aplicación.

1.3 Configuración de la placa LaunchPad

La versión 1.4 de la placa MSP EXP430G2 LaunchPad se comercializaba con Microcontroladores

de la familia MSP430G2XX como el MSP430G2231 que no disponían de periféricos de tipo USCI,

que implementan la UART en hardware. La versión 1.5 ya se comercializa con MSP430G2553,

que sí dispone de este periférico.

Diagrama de bloques del MSP43G2231, (sin USCI) Diagrama de bloques del MSP430G2553, (con USCI)

Para realizar una comunicación serie asíncrona con el PC en el MSP430G2231 se utiliza lo que

se llama una Software UART (UART hecha en software), implementada por medio del

temporizador y bloque de salida (para la transmisión msp430 → PC) y su bloque de captura

(para la recepción PC → msp430)

Page 7: Practica 6 Uart Nhr

Práctica 6: Comunicación serie asíncrona: la UART Curso 2012/2013

3

En los dispositivos MSP430G2533 (los que ponemos en las placas de laboratorio Rev 1.4) y en

los MSP430G2553 (los que traen las placas Rev 1.5), los terminales de entrada y salida del

temporizador que se utilizan para hace la UART software y los de entrada y salida de la USCI (la

UART hardware), son los mismos pero están invertidos. Por tanto, para que la comunicación entre

PC y microcontrolador se produzca correctamente, es necesario invertir las conexiones TXD y

RXD en los jumpers J3 de la placa LaunchPad.

Esta se realiza de distinta manera dependiendo de si utilizas una de las LaunchPad del

laboratorio (1.4) o una que hayas adquirido más recientemente (1.5). En la versión 1.4 es

necesario utilizar dos cables para invertir las conexiones. En la versión 1.5, esto ya está

previsto y basta con girar noventa grados los conectores, como indica la impresión de la

placa, para que estos queden según la configuración “HW UART”1:

Configuración HW UART en la LaunchPad Rev 1.4 Configuración HW UART en la LaunchPad Rev 1.5

1 Para los que tengáis curiosidad: esta solución no se le ocurrió a Texas Instruments, si no a un

aficionado a la electrónica de la comunidad de usuarios de la LaunchPad. Texas Instruments

preguntó a la comunidad de usuarios a través de sus foros cómo querían que fuera el diseño de la

versión 1.5, dando varias opciones. Finalmente no adoptaron ninguna de ellas, sino que optaron

por la sugerida por uno de los miembros de esta comunidad. ¿Diseño electrónico 2.0?

http://e2e.ti.com/support/microcontrollers/msp430/f/166/t/86277.aspx?pi77810=3

TTEESSTT

RRXXDD

VVCCCC

TTXXDD RREESSEETT

Page 8: Practica 6 Uart Nhr

Microcontroladores Grado en Ingeniería de Tecnologías de Telecomunicación

4

2 PRÁCTICA 6: COMUNICACIÓN SERIE A TRAVÉS DE LA UART

2.1 Descripción

El programa siguiente establece una comunicación serie asíncrona full dúplex entre el

microcontrolador y la aplicación “Practica 6” instalada anteriormente en el PC. Existen tres tipos

de mensajes que se pueden enviar:

• Dos tipos de mensajes entre el PC y el microcontrolador, uno para variar la frecuencia de

parpadeo del LED2 y otro para variar su ciclo de trabajo.

• Un tipo de mensaje entre el microcontrolador y el PC, para avisar al PC de que la

recepción de mensajes está habilitada o deshabilitada.

2.2 Código

A continuación se muestra el fichero “Practica_06a.c”.

Cuadro 1. Código del programa Practica_06a.c

/* ************************************************************************** */ /* UNIVERSIDAD DE MALAGA DEPARTAMENTO DE TECNOLOGIA ELECTRONICA */ /* http://www.uma.es http://www.dte.uma.es */ /* ========================================================================== */ /* PROGRAMA : Practica6a.c */ /* VERSION : 1.0 */ /* TARGET : Kit LaunchPad - Microcontrolador MSP430G2533 */ /* DESCRIPCION : Codigo de la Practica 6 */ /* Si se utiliza el comportamiento simple del pulsador S2 */ /* conmuta el LED1 al ser S2 soltado. */ /* Si se utiliza el comportamiento multifunción del pulsador */ /* S2 conmuta el parpadeo del LED2 mediante un PWM. */ /* Se utiliza un antirrebote para el pulsador S2. */ /* RECURSOS : Watchdog (WD), Temporizadores (T0,T1), USCIs (UA), */ /* Pulsadores (S2), LEDs (LED1, LED2) */ /* AUTOR : Eduardo Javier Perez Rodriguez ([email protected]) */ /* FECHA : 29/04/13 */ /* COMENTARIOS : 1 tabulador = 8 espacios */ /* ************************************************************************** */ /* ========================================================================== */ /* ============ INCLUDES ==================================================== */ /* ========================================================================== */ #include "io430g2533.h" // MSP430G2533 #include <math.h> // rint #include <stdlib.h> // atoi #include <stdio.h> // sprintf /* ========================================================================== */ /* ============ CONSTANTES ================================================== */ /* ========================================================================== */ #define ON 1 // Activo #define OFF 0 // Desactivo #define PULS_ON 0 // Pulsador presionado #define PULS_OFF 1 // Pulsador soltado #define LED_ON 1 // LED encendido #define LED_OFF 0 // LED apagado #define RX_BUFFER_SIZE 3 // Tamano buffer recepcion #define TX_BUFFER_SIZE 2 // Tamano buffer transmision /* ========================================================================== */

Page 9: Practica 6 Uart Nhr

Práctica 6: Comunicación serie asíncrona: la UART Curso 2012/2013

5

/* ============ TIPOS DATOS ================================================= */ /* ========================================================================== */ typedef union { // Flags unsigned char total; // Todos struct { unsigned char f0 : 1; // Flag 0 unsigned char f1 : 1; // Flag 1 unsigned char f2 : 1; // Flag 2 unsigned char f3 : 1; // Flag 3 unsigned char f4 : 1; // Flag 4 unsigned char f5 : 1; // Flag 5 unsigned char f6 : 1; // Flag 6 unsigned char f7 : 1; // Flag 7 }; } flags; /* ========================================================================== */ /* ============ VARIABLES GLOBALES ========================================== */ /* ========================================================================== */ flags tareas; // Flags activacion tareas: // BIT0: Tarea_0 -> Pulsador S2 // BIT1: Tarea_1 -> Recepcion datos char rx_buffer[RX_BUFFER_SIZE+1]; // Buffer recepcion + '\0' char tx_buffer[TX_BUFFER_SIZE+1]; // Buffer transmision + '\0' /* ========================================================================== */ /* ============ PROTOTIPOS ================================================== */ /* ========================================================================== */ void Config_uC(void); void Config_Perifericos(); /* ========================================================================== */ /* ============ PROGRAMA PRINCIPAL ========================================== */ /* ========================================================================== */ int main(void) { /* ------------ Variables --------------------------------------------------- */ unsigned char frec, ciclo; // PWM LED2: frecuencia y ciclo int val; // Valor recibido unsigned char cont_buff; // Contador /* ------------ Configuracion microcontrolador ------------------------------ */ Config_uC(); /* ------------ Configuracion perifericos ----------------------------------- */ Config_Perifericos(); /* ------------ Inicializacion variables ------------------------------------ */ tareas.total = 0; for (cont_buff = 0; cont_buff < RX_BUFFER_SIZE; cont_buff++) { rx_buffer[cont_buff] = 0; } // for (cont_buff = 0; cont_buff < RX_BUFFER_SIZE; cont_buff++) rx_buffer[RX_BUFFER_SIZE] = '\0'; for (cont_buff = 0; cont_buff < TX_BUFFER_SIZE; cont_buff++) { tx_buffer[cont_buff] = 0; } // for (cont_buff = 0; cont_buff < TX_BUFFER_SIZE; cont_buff++) tx_buffer[TX_BUFFER_SIZE] = '\0'; frec = 1; ciclo = 50; TA0CCR0 = (unsigned int) rint(62500.0/frec); TA0CCR1 = (unsigned int) rint(625.0*ciclo/frec);

Page 10: Practica 6 Uart Nhr

Microcontroladores Grado en Ingeniería de Tecnologías de Telecomunicación

6

/* ------------ Inicio ------------------------------------------------------ */ __enable_interrupt(); // Habilita interrupciones /* ------------ Bucle principal --------------------------------------------- */ for (;;) { // ------------ Bajo consumo __low_power_mode_0(); // Bajo consumo (LPM0) // ------------ Tareas activas while (tareas.total != OFF) { // Mientras alguna tarea activa // ------------ [Tarea_0 -> Pulsador S2] if (tareas.f0 == ON) { // Si Tarea_0 activa tareas.f0 = OFF; // Limpia flag Tarea_0 P1OUT_bit.P0 = ~(P1OUT_bit.P0); // Conmuta LED1 IE2_bit.UCA0RXIE = ~(IE2_bit.UCA0RXIE); // Conmuta interrupcion USCI_A0 RX sprintf(tx_buffer, "S%d", IE2_bit.UCA0RXIE); IE2_bit.UCA0TXIE = ON; // Habilita interrupcion USCI_A0 TX } // if (tareas.f0 == ON) // ------------ [Tarea_1 -> Recepcion datos] if (tareas.f1 == ON) { // Si Tarea_1 activa tareas.f1 = OFF; // Limpia flag Tarea_1 val = atoi(&rx_buffer[1]); // Valor recibido switch (rx_buffer[0]) { case 'F': case 'f': { if ((val >= 0) && (val <= 50)) { // Si valor de frecuencia valido frec = val; TA0CCR0 = (unsigned int) rint(62500.0/frec); TA0CCR1 = (unsigned int) rint(625.0*ciclo/frec); } // if ((val >= 0) && (val <= 50)) break; } // case 'F' - case 'f' case 'C': case 'c': { if ((val >= 1) && (val <= 99)) { // Si valor de ciclo valido ciclo = val; TA0CCR1 = (unsigned int) rint(625.0*ciclo/frec); } // if ((val >= 1) && (val <= 99)) break; } // case 'C' - case 'c' } // switch (rx_buffer[0]) } // if (tareas.f1 == ON) } // while (tareas.total != OFF) } // for (;;) } // int main(void) /* ========================================================================== */ /* ============ FUNCIONES =================================================== */ /* ========================================================================== */ /* -------------------------------------------------------------------------- */ /* Funcion : void Config_uC(void) */ /* Descripcion : Configuracion del microcontrolador */ /* Argumentos : */

Page 11: Practica 6 Uart Nhr

Práctica 6: Comunicación serie asíncrona: la UART Curso 2012/2013

7

/* Devuelve : */ /* Llamada desde: main */ /* Llama a : */ /* -------------------------------------------------------------------------- */ void Config_uC(void) { /* ------------ Variables --------------------------------------------------- */ /* ------------ Inicio ------------------------------------------------------ */ WDTCTL = WDTPW + WDTHOLD; // Detiene watchdog DCOCTL = 0; // Frecuencia DCO (1MHz) BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; } // void Config_uC(void) /* -------------------------------------------------------------------------- */ /* Funcion : void Config_Perifericos(void) */ /* Descripcion : Configuracion de los perifericos */ /* Argumentos : */ /* Devuelve : */ /* Llamada desde: main */ /* Llama a : */ /* -------------------------------------------------------------------------- */ void Config_Perifericos(void) { /* ------------ Inicio ------------------------------------------------------ */ // ------------ [LED1, LED2] P1DIR_bit.P0 = P1DIR_bit.P6 = ON; // P1.0 -> Salida (LED1) // P1.6 -> Salida (LED2) P1OUT_bit.P0 = LED_ON; // P1.0 -> Enciende LED1 P1OUT_bit.P6 = LED_OFF; // P1.6 -> Apaga LED2 // ------------ [Pulsador S2] P1DIR_bit.P3 = OFF; // P1.3 -> Entrada (S2) P1REN_bit.P3 = ON; // P1.3 -> Resistencia activa P1OUT_bit.P3 = ON; // P1.3 -> Resistencia pullup P1IES_bit.P3 = ON; // P1.3 -> Flanco bajada P1IFG_bit.P3 = OFF; // Limpia flag P1.3 P1IE_bit.P3 = ON; // Habilita interrupcion P1.3 // ------------ [Temporizador T0] TA0CCR0 = 0x0000; TA0CCR1 = 0x0000; TA0CCTL1 = OUTMOD_2; // toggle/reset TA0CTL = TASSEL_2 + ID_3 + MC_3; // SMCLK + /8 + up/down P1SEL_bit.P6 = ON; // P1.6 -> TA0.1 (PWM) P1SEL2_bit.P6 = OFF; // ------------ [USCI UA] P1SEL_bit.P1 = P1SEL_bit.P2 = 1; // P1.1 -> RX ; P1.2 -> TX P1SEL2_bit.P1 = P1SEL2_bit.P2 = 1; UCA0CTL1_bit.UCSWRST = ON; // Detiene USCI_A0 UCA0CTL1_bit.UCSSEL1 = ON; // SMCLK: 1 MHz UCA0BR1 = 0x00; // 9600 baudios UCA0BR0 = 0x68; UCA0MCTL = 0x02; UCA0CTL1_bit.UCSWRST = OFF; // Inicia USCI_A0 IFG2_bit.UCA0RXIFG = OFF; // Limpia flag interrupcion USCI_A0 RX IE2_bit.UCA0RXIE = ON; // Habilita interrupcion USCI_A0 RX WDTCTL = WDT_MDLY_32; // Configura watchdog ~ 32 ms while (IFG1_bit.WDTIFG != ON) { // Mientras interrupcion watchdog no activa } WDTCTL = WDTPW + WDTHOLD; // Detiene watchdog IFG1_bit.WDTIFG = OFF; // Limpia flag interrupcion watchdog

Page 12: Practica 6 Uart Nhr

Microcontroladores Grado en Ingeniería de Tecnologías de Telecomunicación

8

} // void Config_Perifericos(void) /* ========================================================================== */ /* ============ RUTINAS TRATAMIENTO INTERRUPCION ============================ */ /* ========================================================================== */ /* -------------------------------------------------------------------------- */ /* Funcion : void RTI_WD(void) */ /* Descripcion : Antirrebote del pulsador S2 */ /* Argumentos : */ /* Devuelve : */ /* Fuentes : WDTIFG */ /* Llama a : */ /* -------------------------------------------------------------------------- */ #pragma vector = WDT_VECTOR __interrupt void RTI_WD(void) { /* ------------ Variables --------------------------------------------------- */ /* ------------ Inicio ------------------------------------------------------ */ WDTCTL = WDTPW + WDTHOLD; // Detiene watchdog P1IFG_bit.P3 = OFF; // Limpia flag interrupcion P1.3 P1IE_bit.P3 = ON; // Habilita interrupcion P1.3 } // __interrupt void RTI_WD(void) /* -------------------------------------------------------------------------- */ /* Funcion : void RTI_USCIA0RX(void) */ /* Descripcion : Recepcion de datos serie */ /* Argumentos : */ /* Devuelve : */ /* Fuentes : UCA0RXIFG */ /* Llama a : */ /* -------------------------------------------------------------------------- */ #pragma vector=USCIAB0RX_VECTOR __interrupt void RTI_USCIA0RX(void) { /* ------------ Variables --------------------------------------------------- */ static unsigned int cont_rx = 0; // Numero datos RX /* ------------ Inicio ------------------------------------------------------ */ rx_buffer[cont_rx] = UCA0RXBUF; // RX dato cont_rx++; if (cont_rx == RX_BUFFER_SIZE) { // Si recibidos todos los datos cont_rx = 0; tareas.f1 = ON; // Activa Tarea_1 } // if (cont_rx == RX_BUFFER_SIZE) IFG2_bit.UCA0RXIFG = OFF; // Limplia flag interrupcion USCI_A0 RX if (tareas.total != OFF) { // Si alguna tarea activa __low_power_mode_off_on_exit(); // Sale bajo consumo (LPM0) } // if (tareas.total != OFF) } // __interrupt void RTI_USCIA0RX(void) /* -------------------------------------------------------------------------- */ /* Funcion : void RTI_USCIA0TX(void) */ /* Descripcion : Transmision de datos serie */ /* Argumentos : */ /* Devuelve : */ /* Fuentes : UCA0RXIFG */ /* Llama a : */ /* -------------------------------------------------------------------------- */ #pragma vector=USCIAB0TX_VECTOR __interrupt void RTI_USCIA0TX(void) { /* ------------ Variables --------------------------------------------------- */ static unsigned int cont_tx = 0; // Numero datos TX

Page 13: Practica 6 Uart Nhr

Práctica 6: Comunicación serie asíncrona: la UART Curso 2012/2013

9

/* ------------ Inicio ------------------------------------------------------ */ UCA0TXBUF = tx_buffer[cont_tx]; // TX dato cont_tx++; if (cont_tx == TX_BUFFER_SIZE) { // Si transmitidos todos los datos cont_tx = 0; IE2_bit.UCA0TXIE = OFF; // Deshabilita interrupcion USCI_A0 TX } // if (cont_tx == TX_BUFFER_SIZE) IFG2_bit.UCA0TXIFG = OFF; // Limplia flag interrupcion USCI_A0 TX } // __interrupt void RTI_USCIA0TX(void) /* -------------------------------------------------------------------------- */ /* Funcion : void RTI_P1(void) */ /* Descripcion : Rutina tratamiento interrupcion puerto P1 */ /* Argumentos : */ /* Devuelve : */ /* Fuentes : P1IFG.P3 */ /* Llama a : */ /* -------------------------------------------------------------------------- */ #pragma vector = PORT1_VECTOR __interrupt void RTI_P1(void) { /* ------------ Variables --------------------------------------------------- */ /* ------------ Inicio ------------------------------------------------------ */ P1IE_bit.P3 = OFF; // Deshabilita interrupcion P1.3 // ------------ Antirrebote WDTCTL = WDT_MDLY_32; // Configura watchdog IFG1_bit.WDTIFG = OFF; // Limpia flag interrupcion watchdog IE1_bit.WDTIE = ON; // Habilita interrupcion watchdog // ------------ Antirrebote if (P1IES_bit.P3 == ON) { // Si flanco de bajada (pulsador presionado) } // if (P1IES_bit.P3 == ON) else { // Si flanco de subida (pulsador soltado) tareas.f0 = ON; // Activa Tarea_0 } // else: if (P1IES_bit.P3 == ON) P1IES_bit.P3 = ~(P1IES_bit.P3); // P1.3 -> Conmuta flanco P1IFG_bit.P3 = OFF; // Limpia flag interrupcion P1.3 if (tareas.total != OFF) { // Si alguna tarea activa __low_power_mode_off_on_exit(); // Sale bajo consumo (LPM0) } // if (tareas.total != OFF) } // void RTI_P1(void)

7) Analiza el programa e intenta entender su funcionamiento antes de ejecutarlo. Se

recomienda dibujar un flujograma como ayuda.

8) Realiza los pasos necesarios para compilar, cargar y ejecutar el programa Practica6a.c en

la placa LaunchPad.

9) Ejecuta el programa en el PC “Practica 6”. Esta vez, al estar la placa LaunchPad

conectada al PC, la aplicación debería detectar su presencia. Conecta eligiendo primero el

puerto adecuado y luego pulsando “Conectar”:

Page 14: Practica 6 Uart Nhr

Microcontroladores Grado en Ingeniería de Tecnologías de Telecomunicación

10

10) Observa el comportamiento del LED2 (verde) en la placa LaunchPad mientras cambias el

valor de los discos “Frecuencia” y “Ciclo de Trabajo” en la aplicación “ComSerie”.

11) Responde a las siguientes preguntas. Para ello es posible que tengas que utilizar el

depurador y colocar puntos de ruptura en distintos puntos del programa Practica6a.c que

se ejecuta en el microcontrolador.

Pregunta 1. ¿Qué caracteres se envían desde el PC cuando se modifica la frecuencia de

parpadeo?:

Pregunta 2. ¿Qué caracteres se envían desde el PC cuando se modifica el ciclo de trabajo?

12) Acciona el pulsador S2 y observa el comportamiento del programa “ComSerie”.

Pregunta 3. ¿Qué caracteres se envían hacia el PC cuando se acciona el pulsador S2?

El programa “ComSerie” está preparado para reconfigurar los discos de selección a los valores

1Hz y 50% cuando recibe el comando “S3”. Sin embargo el código Practica6a.c nunca envía

estos comandos.

Pregunta 4. ¿Qué modificaciones se han de producir en el programa Practica6a.c para que se

envíe el comando “S3” cuando se acciona el pulsador S1 (RESET)? Realiza estas

modificaciones.