Sistemas Digitales Título: Mouse Century para el microcontrolador MC68HC11. Profesor: Fernando Álvarez Alumna: Mónica Kudzu Ingeniería en Automatización y Control Industrial Universidad Nacional de Quilmes Índice: Datos personales...................................................................................... 1 Objetivos..................................................................................................... 1 Conexionado del proyecto.......................................................................... 1 Descripción del proyecto............................................................................. 1 Hardware........................................................................................ 1 Microcontrolador.................................................................... 1 Mouse.................................................................................... 2 Cable para comunicación PC-microcontrolador.................... 2 Cable serie cruzado............................................................... 3 Estructura interna del mouse................................................. 4 Software........................................................................................... 4 Datos del mouse.................................................................... 5 Procesamiento de datos........................................................ 5 Diagramas de estados........................................................... 6 Diagrama de estados de la interrupción...................... 6 Diagramas de flujo................................................................. 7 Diagrama de flujo principal.......................................... 7 Rutinas e interrupciones........................................................ 8 Rutinas........................................................................ 8 Filtrado.............................................................. 8 Reconstrucción de datos.................................. 8 Interrupción RS-232.................................................... 9 Código.................................................................................... 9 Variables................................................................................ 12 Variables volatile............................................... 12 Variables globales............................................ 13 Variables locales............................................... 13 Registros del microcontrolador.............................................. 14 SCSR................................................................ 14 BAUD……………………………………………... 14 SCCR2…………………………………………… 15 SCDR................................................................ 16 Mapa de memoria.................................................................. 16 Diagrama de flujo de la interrupción...................................... 17 Interface con la PC-Programa mouse.exe............................. 18 Código......................................................................... 18 Conclusiones............................................................................................... 20 2 Ingeniería en Automatización y Control Industrial Universidad Nacional de Quilmes Informe Sistemas Digitales Datos Personales: Alumna: Mónica Kudzu N° de Legajo: 4553 Objetivo: El objetivo de este proyecto es implementar un mouse Century para el microcontrolador MC68HC11, la posición del mismo deberá mostrarse por display, y en la pantalla de la PC se podrá dibujar mediante el programa mouse.exe, desarrollado en Borlandc. Esquema de conexionado del proyecto: Descripción del proyecto: Hardware Kit Microcontrolador MC68HC11 de Motorola (fig. 1) Cable serie cruzado (fig. 4) Cable para alimentación del mouse, conexión entre el mouse, el microcontrolador y la PC (fig. 3) Display WM-C0801M PC Se utilizará el Kit con el microcontrolador MC68HC11 (fig. 1), de este Kit usaremos el microcontrolador; el conector DB9, para la 3 Ingeniería en Automatización y Control Industrial Universidad Nacional de Quilmes comunicación por RS-232; el puerto A y el puerto F, para el pasaje de datos al Display. Fig.1 El conector DB9 del mouse Century (fig. 2) esta configurado de la siguiente forma: Pin 7 +5V Pin 3 –5V Pin 2 datos Pin 5 masa Fig. 2 La conexión del mouse con el microcontrolador se realizará mediante un cable que consta de tres conectores DB9. (fig. 3) 4 Ingeniería en Automatización y Control Industrial Universidad Nacional de Quilmes Fig. 3 Conector A (macho): del microcontrolador al mouse y al cable serie cruzado. El pin 3 va conectado al pin 2 y el pin 5 al pin 5, del conector B. El pin 2 va conectado al pin 3, y el pin 5 al pin 5, del conector C. Conector B (macho): del mouse al microcontrolador. Los pines 2 y 5 van conectados al conector A, el pin 5 va conectado a +5 V de la fuente de tensión, el pin 7 a +5V del Kit y el pin 3 a la masa de la fuente. Al conectar el pin 5 a +5 y el pin 3 a masa de la fuente se logra que al mouse lleguen –5V. Conector C (macho): del cable serie cruzado al microcontrolador. Los pines 3 y 5 van conectados al conector A. El cable serie cruzado (fig. 4) tiene dos DB9 hembra, uno para la conexión con el COM1 de la PC y el otro para la conexión con el cable de tres conectores DB9. 5 Ingeniería en Automatización y Control Industrial Universidad Nacional de Quilmes Fig. 4 El Display se conecta al port A para el pasaje de datos, y al port F para la configuración. Estructura interna del mouse: Fig. 5 Software Descripción general de los datos enviados por el mouse 6 Ingeniería en Automatización y Control Industrial Universidad Nacional de Quilmes El mouse envía tres bytes seguidos, cada vez que se mueve. El primer byte indica si el movimiento fue positivo o negativo, y si los botones fueron presionados. Los dos primeros bits indican el comienzo del byte, ambos deben estar en uno. El tercer y cuarto bit, indican si se presiono algún botón. Quinto y sexto bit, dependen del sentido de desplazamiento en x (encoder 1 fig. 5), de la siguiente manera: 00 = +x (x mayor que 64) 01 = +x (x menor que 64) 10 = -x (x mayor que 64) 11 = -x (x menor que 64) Séptimo y octavo bit, igual a los dos anteriores pero para y (encoder 2 fig. 5). El segundo byte indica el desplazamiento en x. Los dos primeros bits son el comienzo del byte, siempre deben estar en uno y cero, respectivamente, los seis bits restantes son el desplazamiento en complemento a 2. El tercer byte es igual al segundo pero para el desplazamiento en y. La forma de rearmar esta información para poder procesarla es la siguiente: x_c = ((byte1&0x03)<<6)|(byte2&0x3F); fig. 6 Lo mismo se hace para y, pero de la siguiente manera: y_c = ((byte1&0xC)<<4)|(byte3&0x3F); 7 Ingeniería en Automatización y Control Industrial Universidad Nacional de Quilmes fig. 7 Donde x_c e y_c son variables del tipo char, que luego al hacer una igualación con variables del tipo int se tiene el desplazamiento con signo. Ej. Si x_c = 11000100 x_act = x_c; da como resultado x_act = -60, o sea, el mouse se desplazó 60 unidades hacia la izquierda. El valor x_act se utiliza para ir incrementando el valor de x. Este procedimiento se describe con mas detalles en la sección de rutinas e interrupciones. Diagrama de estados Diagrama de estados de la interrupción intrs: fig. 8 8 Ingeniería en Automatización y Control Industrial Universidad Nacional de Quilmes Diagrama de flujo (fig. 9) Inicio 1 Inicialización de variables Conversión de datos Char a Int 2 Filtro pasa bajos Actualización de variables (SCSR &0x40) ==0 SI Display Interrupción NO RS-232 Recepción de datos Conversión de datos Int a Char Comunicación RS-232 Cont=0 Cont== 3 2 NO 1 SI 9 Ingeniería en Automatización y Control Industrial Universidad Nacional de Quilmes Rutinas e Interrupciones Rutinas: En el cuerpo del programa se toma los valores de x o y que llegan desde la interrupción y los pasa a los valores predeterminados de pantalla, x máximo = 640 e y máximo = 480, además considera los valores negativos cuando el cursor esta cerca del borde de la pantalla para que este no pase del límite. Las vaiables x e y pueden variar entre 0-640 ó 0-480, son enteras, y representan el valor total en pantalla, x_ant e y_ant son enteros, y representan los valores anteriores de las variables, son los valores antes de llegar la última interrupción, x_act e y_act, son enteros, y son los incrementos debidos a la última interrupción. Con cada cambio de posición del mouse se incrementa la variable x (y) en el incremento que llega en x_act (y_act), o sea, x = x + x_act; (y = y + y_act;) antes de este paso se guarda el valor de x en x_ant x_ant = x; (y_ant = y;) para poder reconstruir los bytes y para realizar el filtrado de la señal Filtrado: La señal es filtrada para que cuando haya cambios muy rápidos no se produzcan saltos, por ejemplo en la parte gráfica. El filtro utilizado es el siguiente: y = ((x+(9*y_ant))/10); fig. 10 Reconstrucción de los datos: Otra rutina importante es la que una vez filtrado el dato rearma los byte para transmitirlos vía RS-232 a la PC, esta rutina utiliza los valores enteros obtenidos luego de filtrar los datos, se necesitan los valores actuales y los valores anteriores. rel_c = x - x_ant; byte2 = (rel_c|0x80)&0xBF; 10 Ingeniería en Automatización y Control Industrial Universidad Nacional de Quilmes fig. 11 byte1 = ((rel_c&0xC0)>>4)|0xC0; rel_c = y – y_ant; byte3 = (rel_c|0x80)&0xBF; byte1 = ((rel_c&0xC0)>>6)|byte1; Además debemos verificar si los botones fueron presionados, para eso utilizamos dos variables, boton_i y boton_d, que son puestas en 1 si se presionaron los botones izquierdo y/o derecho respectivamente. Con estas variables se hacen dos if(), como mostramos a continuación: If(boton_d==1) If(boton_i==1) byte1=(byte1|0x10); byte1=(byte1|0x20); Esto pone un uno en las posiciones del byte1 correspondientes a los botones. Fig. 12 11 Ingeniería en Automatización y Control Industrial Universidad Nacional de Quilmes Interrupciones: La interrupción utilizada es la interrupción de la comunicación serie RS-232, la misma llega cada vez que se recibe un dato, por lo tanto para armar el paquete de tres byte que transmite el mouse se deberán recibir tres interrupciones antes de tener el dato completo, con la condición de que, primero debe llegar un byte que comience con 0xC0, el segundo y el tercero deben comenzar con 0x80, por lo tanto se utiliza una variable cont, que registra que byte es el que llega. A medida que van llegando los distintos byte se van cargando las variables byte1, byte2 y byte3 con sus respectivos datos, para que al llegar el ultimo la variable cont este en tres y esto habilite el procesamiento de datos en el main. Ver figuras 8 y 13. El código de la interrupción y del main son los siguientes: #include <iof1.h> volatile int cont; volatile unsigned char byte; volatile char byte1,byte2,byte3; char x_c, y_c, rel_c; int x, y, x_act, y_act, x_ant, y_ant, boton_i, boton_d; void main(void) { while((SCSR&0x40)==0); BAUD=0x33; SCCR2=0x2c; _asm("cli"); cont=0; x=0; y=0; x_c=0; y_c=0; x_act=0; y_act=0; x_ant=0; y_ant=0; rel_c=0; boton_d=0; boton_i=0; for( ; ; ) { if(cont==3) { x_c=((byte1&0x03)<<6)|(byte2&0x3F); y_c=((byte1&0x0C)<<4)|(byte3&0x3F); if((byte1&0x20)==0x20) { boton_i=1; } 12 Ingeniería en Automatización y Control Industrial Universidad Nacional de Quilmes else { boton_i=0; } if((byte1&0x10)==0x10) { boton_d=1; } else { boton_d=0; } x_act=x_c; y_act=y_c; x_ant=x; y_ant=y; x=x+x_act; y=y+y_act; if(x>640) x=640; if(x<0) x=0; if(y>480) y=480; if(y<0) y=0; y=((x+(9*y_ant))/10); rel_c=x-x_ant; byte2=(rel_c|0x80)&0xBF; byte1=((rel_c&0xC0)>>4)|0xC0; rel_c=y-y_ant; byte3=(rel_c|0x80)&0xBF; byte1=((rel_c&0xC0)>>6)|byte1; if(boton_d==1) byte1=(byte1|0x10); if(boton_i==1) byte1=(byte1|0x20); SCDR=byte1; while((SCSR&0x80)==0); SCDR=byte2; while((SCSR&0x80)==0); SCDR=byte3; while((SCSR&0x80)==0); cont=0; } } } @interrupt void intrs(void) { char var; SCSR; byte=SCDR; var=(byte&0xC0); switch(var) { case 0xC0: 13 Ingeniería en Automatización y Control Industrial Universidad Nacional de Quilmes if(cont!=3) { byte1=byte; cont=1; } break; case 0x80: if(cont==1) { byte2=byte; cont=2; } else { if(cont==2) { byte3=byte; cont=3; } } break; default: cont=0; break; } } Variables: A continuación se detallan las variables utilizadas, sus tipos y el porque de estos. Variables “Volatile”: Las variables que son utilizadas en el cuerpo principal del programa y en las interrupciones deben ser declaradas como volatile, con esto logramos que sean actualizadas cuando son modificadas desde las interrupciones, de lo contrario serían modificadas en las interrupciones y el programa principal utilizaría valores incorrectos. volatile int cont: Esta variable se utiliza como contador de interrupciones, cuando llega un byte que comienza con 11 se pone en uno, y se va incrementando con la llegada de los otros dos byte, o sea, como máximo toma el valor tres, cuando estos datos son procesados y transmitidos se pone el contador en cero, si no se hiciera esto entrarían las interrupciones pero los valores de los byte que llegan no serían guardados. volatile char byte: En esta variable se gurdan los valores que llegan desde el mouse, aunque no sean correctos, con el dato de esta variable se 14 Ingeniería en Automatización y Control Industrial Universidad Nacional de Quilmes chequea si es un byte valido o no. Debe ser una variable del tipo char ya que los datos que envía el mouse son byte. volatile char byte1,byte2,byte3: En estas variables se guardan los datos del mouse una vez chequeada su validez, es decir, que el primero comienza con 11, y el segundo y el tercero con 10. Cuando llegaron los tres byte estas variables son utilizadas para armar el dato del desplazamiento, y después de filtrar la señal son utilizados para la transmisión de los datos pos RS-232 a la PC. Variables globales: Las variables que se utilizan en el cuerpo principal y en las funciones se declaran en forma global, para poder utilizarlas desde cualquier parte del programa. char x_c, y_c: Las variables x_c e y_c son utilizadas para guardar los datos rearmados con los datos contenidos en byte1, byte2 y byte3, en ellos se concatena el incremento y el signo de los desplazamientos. int x_act, y_act: Estas variables contienen lo mismo que x_c e y_c, pero en formato entero para poder realizar las cuentas y limitar los valores en una forma mas sencilla. int x, y: x e y representan la suma de todos los incrementos en el desplazamiento, pueden variar entre 0 y 640 en x, y 0_480 en y, estas variables junto con los valores anteriores son utilizadas para el filtrado de la señal. int x_ant, y_ant: Son los valores de x e y antes de la última interrupción, antes de sumar el incremento en el desplazamiento. Como ya fue mencionado son utilizadas para el filtrado de la señal. char rel_c: Una vez filtrada la señal se deben reconstruir los byte para luego ser transmitidos a la PC, para esto hace falta obtener el incremento del desplazamiento, la variable rel_c representa este desplazamiento, rel_c = x - x_ant, al ser rel_c una variable del tipo char y x, x_ant, y, o y_ant del tipo entero se obtiene el incremento en complemento a 2, como el incremento no puede superar el tamaño de un byte nos alcanza con un char, y solo se copia la parte baja de la resta de los dos enteros. int boton_i, boton_d: Estas variables se setean en uno si alguno de los botones fue presionado, y en cero cuando estan libres. Variables locales: Las variables locales solo pueden ser utilizadas en la función o interrupción donde son declaradas, una vez que se sale de esta sección la variables locales son destruidas, es decir la memoria reservada para estas es liberada, y se pierden los datos contenidos en ellas. char var: Esta variable se utiliza en la interrupción de la comunicación por RS-232, para poder reconocer que byte es el que llega, se hace una 15 Ingeniería en Automatización y Control Industrial Universidad Nacional de Quilmes mascara con el byte que llega, o sea la variable byte, para obtener solo los dos primeros bits de este byte, y con esta información se realiza un switch case que discrimina entre los distintos byte. Registros del microcontrolador utilizados: Todos los registros del microcontrolador utilizados en este proyecto estan relacionados con la transmisión serie. SCSR = Serial Communication Status Register TDRE = Transmit Data Register Empty Flag TC = Transmit Complete Flag RDRF = Receive Data Register Full Flag IDLE = Idle Line Detected Flag OR = Overrun Error Flag NF = Noise Error Flag FE = Framing Error En este proyecto se utiliza este registro para saber cuando se terminó de transmitir el programa al microcontrolador, se hace una mascara con 0x40, o sea, se chequea que el bit 6 TC, se compara con 0, si es verdadero el programa se termino de bajar. También se utiliza el bit 7 TDRE, este bit indica si el registro SCDR esta vacío, para esto se hace una mascara con 0x80, se compara con 0, si es verdadero el registro esta disponible para que se le ingrese otro byte. Estos flag se borran con 1, y se hace automáticamente cuando se lee el registro SCSR y cuando se escribe el registro SCDR. BAUD = Baud Rate Register TCLR = Clear Baud Rate Counters (Test) SCP[1:0] = SCI Baud Rate Prescaler Selects RCKB = SCI Baud Rate Clock Check (Test) SCR[2:0] = SCI Baud Rate Selects Este registro se utiliza para setear las distintas características de la transmisión serie. En este proyecto se setea con el valor 0x33, es decir: SCP1=1 SCP0=1 SCR1=1 SCR0=1 16 Ingeniería en Automatización y Control Industrial Universidad Nacional de Quilmes Los demás bit en cero. Tabla1 SCP1 SCP0 Divide Internal Clock By 0 0 1 62500 76800 125000 187500 25000 312500 0 1 3 20833 25600 41667 62500 83332 104165 1 0 4 15625 19200 31250 46875 62500 78125 1 1 13 4800 5907 9600 14423 19200 24000 Prescaler Cristal Frequency (MHz) 4.0 4.9152 8.0 12.0 16.0 20.0 Tabla 2 SCR[2:0] Divide Prescaler By Highest Baud Rate (Prescaler Output from Previous Table) 4800 19200 76800 312500 000 1 4800 19200 76800 312500 001 2 2400 9600 38400 156250 010 4 1200 4800 19200 78125 011 8 600 2400 9600 39063 100 16 300 1200 4800 19531 101 32 150 600 2400 9766 110 64 75 300 1200 4883 111 128 ----- 150 600 2441 Con SCP0 y SCP0 estamos seleccionando 9600 MHz, ya que el cristal del microcontrolador es de 8.0 (ver tabla1), y con SCR1 y SCR0 seleccionamos la división por 8 (ver tabla 2), es decir 9600/8=1200 baudios. SCCR2 = Serial Communication Control Register 2 TIE = Transmit Interrupt Enable TCIE = Transmit Complete Interrupt Enable RIE = Receiver Interrupt Enable ILIE = Idle-Line Interrupt Enable TE = Transmitter Enable RE = Receiver Enable RWU = Receiver Wakeup Conrtol SBK = Send Break Seteamos este registro en 0x2c, esto es: 17 Ingeniería en Automatización y Control Industrial Universidad Nacional de Quilmes RIE = 1 TE = 1 RE = 1 Los demás bit en cero. Lo que logramos con esto es habilitar las interrupciones de recepción de datos, habilitar la transmisión y la recepción de datos. SCDR = Serial Communications Data Register En este registro se guardan los datos que llegan mediante la recepción, y también se usa para transmitir, es decir en el se colocan los datos que se quieren transmitir. Mapa de memoria Código Inicio 0x0000 Datos 0x0007 0x0006 0x001C Vector Interrupciones 0x00C4 0x0100 0x0101 Código 0x02D3 Stack 5(main) + 12(int) 0x02D4 0x02E4 0x02E5 0xFFFF 18 Ingeniería en Automatización y Control Industrial Universidad Nacional de Quilmes Diagrama de flujo de la interrupción intrs (fig. 13) interrupción Borrado de flag SCSR Actualización de variables Var==0 xC0 SI NO Var==0 x80 Cont!=3 SI Cont== 1 SI NO NO Retorna NO SI Cont=1 Cont=0 Cont=2 Byte1=byte Byte2=byte Cont== 2 NO SI Cont=3 Byte3=byte Retorna 19 Ingeniería en Automatización y Control Industrial Universidad Nacional de Quilmes Interface con la PC: El programa mouse.exe recibe los datos por el COM1 de la PC, los datos que recibe son exactos a los que envía el mouse, con la diferencia que le llegan filtrados. Lo que hace este programa es muy similar a lo que hace el programa del microcontrolador, espera la llegada de una interrupción de RS-232, una vez que le llega un dato que comienza con dos unos lo toma como comienzo y guarda ese dato, repite esto dos veces mas y comienza a procesar los datos, x_c = ((byte1&0x03)<<6)|(byte2&0x3F); y_c = ((byte1&0xC)<<4)|(byte3&0x3F); guarda los valores anteriores y los actuales para poder dibujar. Dibuja mientras se mantiene el botón derecho presionado, cambia de color cuando se presiona el botón izquierdo y borra todo cuando se presionan los dos botones. El código de este programa es el siguiente: #include "uart.h" #include <dos.h> #include <graphics.h> #include <conio.h> #include <stdlib.h> void interrupt RX(void){} main() { unsigned char a,c; char Byte1,Byte2,Byte3; char x_c,y_c; int boton_d,boton_i,color; int x,y,x_act,y_act,x_ant,y_ant; int gdriver = DETECT, gmode; initgraph(&gdriver, &gmode, ""); base=setbase(1); setport(1,1200); x=0; y=0; x_c=0; y_c=0; x_act=0; y_act=0; x_ant=0; y_ant=0; 20 Ingeniería en Automatización y Control Industrial Universidad Nacional de Quilmes color=10; cleardevice(); while(c!=27) { Byte1=0; while((Byte1&0xC0)!=0xC0) Byte1=rxbyte(); Byte2=rxbyte(); Byte3=rxbyte(); x_c=((Byte1&0x03)<<6)|(Byte2&0x3F); y_c=((Byte1&0x0C)<<4)|(Byte3&0x3F); if((Byte1&0x20)==0x20) { boton_i=1; } else { boton_i=0; } if((Byte1&0x10)==0x10) { boton_d=1; } else { boton_d=0; } x_act=x_c; y_act=y_c; x_ant=x; x=x+x_act; y_ant=y; if(x>640) x=640; if(x<0) x=0; if(y>480) y=480; if(y<0) y=0; if(kbhit()) { c=getch(); } if(boton_i==0&&boton_d==0) { setfillstyle(SOLID_FILL,0); bar(x_ant,y_ant,x_ant+5,y_ant+5); } if(boton_i==0&&boton_d==1) { if(color>15) { color=0; } 21 Ingeniería en Automatización y Control Industrial Universidad Nacional de Quilmes color=color++; } if(boton_i==1&&boton_d==1) { cleardevice(); } setfillstyle(SOLID_FILL,color); bar(x,y,x+5,y+5); } closegraph(); } Conclusiones Los objetivos de este proyecto son mostrar el movimiento del cursor en la pantalla de la PC y la posición en coordenadas x-y en el display, pero por el limitado espacio en memoria esto tal vez no sea posible, además es un tanto insuficiente tener un mouse para utilizar con un microcontrolador y que este no pueda hacer nada mas que comunicarse con el mouse, por lo tanto creo que este microcontrolador no tiene suficiente memoria como para utilizar un mouse y además realizar alguna otra tarea. 22