1 /******************************************************************************/
5 /******************************************************************************/
7 unsigned char codigo(unsigned char, unsigned char, unsigned char, unsigned char);
9 void inicializar_registros();
11 unsigned char recibir_trama();
12 unsigned char contestar_si_error();
13 void configurar_haz0(unsigned char, unsigned char);
14 void configurar_haz1(unsigned char, unsigned char);
15 void telec_actualizacion();
16 void telec_conformacion(unsigned char);
17 void telec_temperatura();
18 void telec_pet_Estado();
20 /* Fichero de definición de direcciones de memoria
21 asignadas a los diferentes registros */
24 /* Direcciones de los puertos P4 y P5 y del TIMER3*/
31 /* Dirección del bit que indica que hay una conversión A/D preparada */
35 Valores que utilizamos para obtener el código de Hamming de los mensajes.
36 El mensaje es de 29 bits (4 bytes) y la redundancia la tomamos de 11 bits.
37 La matriz de Hamming asociada será por tanto de tamaño (11x29) bits.
38 En las matrices siguiente colocamos la expresión hexadecimal de cada
39 una de las columnas de la matriz de Hamming. La obtención de los bits de
40 redundancia asociados a un mensaje los obtendremos haciendo la operación XOR
41 entre las columnas de la matriz de Hamming correspondientes a los '1' de los 29
42 bits del mensaje. Esto es más eficiente que realizar el producto matricial.
43 Como la memoria está organizada en bytes, utilizamos dos matrices. En una de ellas,
44 "Hamming_H", colocamos las tres primeras filas de la matriz de Hamming y en la otra,
45 "Hamming_L", las 8 filas restantes.
48 #define Hamming_H0 0x0
49 #define Hamming_H1 0x1
50 #define Hamming_H2 0x2
51 #define Hamming_H3 0x1
52 #define Hamming_H4 0x6
53 #define Hamming_H5 0x5
54 #define Hamming_H6 0x2
55 #define Hamming_H7 0x7
56 #define Hamming_H8 0x8
57 #define Hamming_H9 0x3
58 #define Hamming_H10 0x9
59 #define Hamming_H11 0x6
60 #define Hamming_H12 0x2
61 #define Hamming_H13 0x9
62 #define Hamming_H14 0x4
63 #define Hamming_H15 0x4
64 #define Hamming_H16 0x3
65 #define Hamming_H17 0x8
66 #define Hamming_H18 0x7
67 #define Hamming_H19 0x6
68 #define Hamming_H20 0x0
69 #define Hamming_H21 0x8
70 #define Hamming_H22 0x7
71 #define Hamming_H23 0x6
72 #define Hamming_H24 0x9
73 #define Hamming_H25 0x2
74 #define Hamming_H26 0x3
75 #define Hamming_H27 0x7
76 #define Hamming_H28 0x3
77 #define Hamming_H29 0x3
78 #define Hamming_H30 0x3
79 #define Hamming_H31 0x3
82 /* Dirección del bit que inicia la conversión A/D */
86 /* Valores booleanos */
91 /* Máscaras utilizadas para identificar los telecomandos */
92 #define CONFORMACION 0xC0
93 /* Telecomando que procesan todos los Subarrays. Se cambia el apuntamiento de la antena */
95 #define ACTUALIZACION 0x80
96 /* Telecomando en el que se envía a un Subarray el próximo estado de uno de los haces */
98 #define TEMPERATURA 0x00
99 /* Telecomando en el que se solicita a un Subarray la temperatura del módulo T/R */
101 #define PETICION_ESTADO 0x40
102 /* Telecomando en el que se solicita a un Subarray el estado de programación de un haz */
105 /* Valores booleanos utilizados en las rutinas de recepción de tramas */
106 #define TIEMPO_EXCEDIDO 0x01
107 #define TIEMPO_NO_EXCEDIDO 0x00
110 /* Asociamos etiquetas a los identificadores que utiliza el
111 compilador para designar algunos registros del micro */
112 #define ACUMULADOR ACC
113 #define BUFFER_SERIE SBUF
114 #define DATO_RECIBIDO RI
115 #define DATO_ENVIADO TI
116 #define PARIDAD_ACC P
117 #define BIT_PARIDAD_REC RB8
118 #define BIT_PARIDAD_TRA TB8
121 /* Sustituimos por etiquetas algunas operaciones sencillas */
122 #define obtener_direc_mensaje (BYTE[0] & 0x3F)
123 #define direccion_CONFORMACION (BYTE[1] & 0x3F)
124 #define obtener_tipo_mensaje (BYTE[0] & 0xC0)
125 #define direc_subarray ((P5 & 0x7E) >> 1)
128 /* DECLARACION DE VARIABLES */
129 volatile unsigned char int_serie;
130 unsigned char BYTE[5];
131 unsigned char BYTE_MENSAJE[3];
132 volatile unsigned char ERROR_PARIDAD;
136 Matriz que utilizamos para almacenar los estados predefinidos.
137 En las posiciones pares (0,2,4,...) están los códigos de amplitud y en las
138 impares (1,3,5,...) los de fase.
140 unsigned char tabla_estados[20];
144 Matriz en la que almacenamos los índices a la tabla de estados correspondientes a la programación
145 actual de los dos haces. Los índices tienen 11 bits de longitud. El contenido de la matriz es
147 estado_haces[0] --> haz 0, i10...i3
148 estado_haces[1] --> haz 0, i2...i0
149 estado_haces[2] --> haz 1, i10...i3
150 estado_haces[3] --> haz 1, i2...i0
152 unsigned char estado_haces[4];
160 unsigned char direc_mensaje;
161 unsigned char TIMEOUT;
162 unsigned char mensaje;
164 unsigned char DIRECCION_SUBARRAY;
166 inicializar_registros();
168 /* Obtenemos la dirección del subarray */
169 DIRECCION_SUBARRAY = direc_subarray;
171 /* bucle del programa */
174 /* Bandera que utilizamos para determinar si la interrupción
175 que se produce se ha originado en el puerto serie */
178 /* El micro entra en modo de bajo consumo mientras no se
179 produzca actividad en el puerto serie */
180 while(int_serie == 0)
183 /* Se ha detectado actividad en el bus de telecomandos. Capturamos la trama */
184 TIMEOUT = recibir_trama();
186 /* Si no se ha excedido el tiempo límite se procede a identificar el mensaje recibido */
187 if (TIMEOUT == FALSE)
189 mensaje = obtener_tipo_mensaje;
190 direc_mensaje = obtener_direc_mensaje;
192 if (direc_mensaje == DIRECCION_SUBARRAY)
193 ERROR = contestar_si_error();
195 /* Si no ha habido error en la recepción se procesa el telecomando */
200 case CONFORMACION : telec_conformacion(DIRECCION_SUBARRAY);
204 case ACTUALIZACION : if (direc_mensaje == DIRECCION_SUBARRAY)
205 telec_actualizacion();
209 case TEMPERATURA : if (direc_mensaje == DIRECCION_SUBARRAY)
214 case PETICION_ESTADO : if (direc_mensaje == DIRECCION_SUBARRAY)
227 Subrutina que actualiza el TIMER3 con el que se implementa la función WATCHDOG.
228 Esta función se habilita conectando un pin externo a nivel bajo, y funciona de
229 forma independiente al código que se ejecuta en el micro. Cuando el TIMER3 llega
230 al final de la cuenta se produce un RESET del micro, por tanto, hay que habilitar
231 un mecanismo de recarga del CONTADOR de forma que entre dos recargas no medie un
232 tiempo mayor al que emplea la cuenta.
233 Este tiempo oscila (para la frecuencia de reloj que utilizamos, 11.059 MHz) entre
234 2.22 ms para una cuenta mínima y 569 ms para una cuenta máxima.
235 Aquí usaremos el CONTADOR con cuenta máxima, para lo cual, dado que la cuenta
236 es ascendente, el valor de recarga es 0.
237 La recarga la haremos utilizando la interrupción que provoca el TIMER0 al llegar al
248 Subrutina que atiende a la interrupción provocada por la UART del puerto serie
249 cuando se ha recibido o enviado un carácter.
250 En esta subrutina lo único que hacemos es poner el valor 1 en la variable 'int_serie'
251 para indicar que la interrupción ocurrida es debida al puerto serie. Esto es necesario
252 porque el micro sale del estado de bajo consumo mediante cualquier interrupción, y sólo
253 queremos que lo haga cuando haya actividad en el puerto serie, de forma que si se produce
254 alguna otra interrupción el micro chequea esta variable y si está a 0 vuelve a entrar en
255 el estado de bajo consumo.
257 La variable 'int_serie' se pone a cero siempre justo antes de entrar en el modo de bajo
258 consumo, y es únicamente en esta subrutina donde se pone a valor uno.
260 void sint(void) interrupt 4 using 2
267 Subrutina que atiende a la interrupción provocada por el TIMER0.
268 Utilizamos esta interrupción para recargar el TIMER3 que relacionado con la operación del
270 Esta interrupción se produce (para la frecuencia de reloj que utilizamos, 11.059 MHz) cada
271 71.12 ms, lo que supone un margen de seguridad amplio frente a los 569 ms que emplea el
272 TIMER3 en realizar una cuenta.
274 void tint() interrupt 1 using 1
276 /* Llamamos a la subrutina que actualiza el TIMER3 del 'watchdog' */
282 Función que implementa la codificación de Hamming (40,32) del mensaje
283 (tc1, tc2, tc3, tc4).
284 La función devuelve la redundancia del mensaje de entrada en las variables "red"
285 Como ya hemos comentado al declarar la matriz 'Hamming', para no realizar producto de matriz
286 por vector para calcular la redundancia, almacenamos la matriz generadora de Hamming como dos
287 vectores de valores hexadecimales de longitud 29.
288 Para obtener la redundancia lo que hacemos es realizar la operación XOR entre los valores del
289 vectores "Hamming_H" cuyo índice coincide con los índices de los dígitos igual a '1'
290 en la palabra mensaje.
291 Para encontrar estos índices comparamos cada uno de los 4 bytes de que se compone el mensaje
292 con las potencias de dos (2^7, 2^6, ... , 2^1, 2^0).
294 unsigned char codigo(unsigned char tc1,unsigned char tc2,unsigned char tc3,unsigned char tc4)
300 if (tc1 & 128) red ^= Hamming_H0;
301 if (tc1 & 64 ) red ^= Hamming_H1;
302 if (tc1 & 32 ) red ^= Hamming_H2;
303 if (tc1 & 16 ) red ^= Hamming_H3;
304 if (tc1 & 8 ) red ^= Hamming_H4;
305 if (tc1 & 4 ) red ^= Hamming_H5;
306 if (tc1 & 2 ) red ^= Hamming_H6;
307 if (tc1 & 1 ) red ^= Hamming_H7;
312 if (tc2 & 128) red ^= Hamming_H8;
313 if (tc2 & 64 ) red ^= Hamming_H9;
314 if (tc2 & 32 ) red ^= Hamming_H10;
315 if (tc2 & 16 ) red ^= Hamming_H11;
316 if (tc2 & 8 ) red ^= Hamming_H12;
317 if (tc2 & 4 ) red ^= Hamming_H13;
318 if (tc2 & 2 ) red ^= Hamming_H14;
319 if (tc2 & 1 ) red ^= Hamming_H15;
324 if (tc3 & 128) red ^= Hamming_H16;
325 if (tc3 & 64 ) red ^= Hamming_H17;
326 if (tc3 & 32 ) red ^= Hamming_H18;
327 if (tc3 & 16 ) red ^= Hamming_H19;
328 if (tc3 & 8 ) red ^= Hamming_H20;
329 if (tc3 & 4 ) red ^= Hamming_H21;
330 if (tc3 & 2 ) red ^= Hamming_H22;
331 if (tc3 & 1 ) red ^= Hamming_H23;
336 if (tc4 & 128) red ^= Hamming_H24;
337 if (tc4 & 64 ) red ^= Hamming_H25;
338 if (tc4 & 32 ) red ^= Hamming_H26;
339 if (tc4 & 16 ) red ^= Hamming_H27;
340 if (tc4 & 8 ) red ^= Hamming_H28;
341 if (tc4 & 4 ) red ^= Hamming_H29;
342 if (tc4 & 2 ) red ^= Hamming_H30;
343 if (tc4 & 1 ) red ^= Hamming_H31;
351 Subrutina que implementa el envío de mensajes en respuesta a los telecomandos recibidos.
352 Los mensajes enviados son siempre de dos bytes más el byte de redundancia del código de Hamming.
353 Para utilizar el mismo código en transmisión que en recepción, se añade un tercer byte con valor
354 0 cuando se calcula la redundancia del mensaje a enviar. Esto mismo hace el módulo que recibe
355 los mensajes que envían los subarrays para chequear la corrección de dichos mensajes.
357 El proceso de envío es el siguiente.
359 - Activar el 'driver' de transmisión.
361 - Enviar 3 bytes del mensaje:
362 * Calcular la paridad de cada byte y colarla en el registro de la UART etiquetado como
364 * Colocar el byte a transmitir en el registro de salida 'BUFFER_SERIE'.
365 * Esperar que la UART indique en la bandera 'DATO_ENVIADO' que se ha enviado un byte
366 antes de enviar el siguiente.
368 - Desactivar el 'driver' de transmisión.
370 Para evitar que por alguna eventualidad la UART no actualice la bandera 'DATO_ENVIADO' y el
371 programa quede indefinidamente esperando, utilizamos la variable 'CONTADOR' que se incrementa
372 cada vez que hacemos una comprobación de la bandera. Cuando se llega a un valor límite no
373 se hacen mas comprobaciones y se sigue enviando el resto del mensaje.
374 Podríamos haber optado por abortar la transmisión en el caso de se llegue al valor límite de
375 la cuenta, porque esto indicaría que se ha producido un error. Sin embargo continuamos la
376 transmisión dejando que recaiga sobre el módulo que recibe los mensajes la responsabilidad de
377 actuar frente a la detección de un error.
378 Esto no supone ningún riesgo grave porque los mensajes de respuesta a telecomandos no afectan
379 al estado de apuntamiento de la antena.
383 unsigned char CONTADOR;
386 Paridad impar. Metemos el bit de paridad en BIT_PARIDAD_TRA antes de mandar un byte.
387 En el "flag" PARIDAD_ACC tenemos la paridad del dato que hay en el ACUMULADOR.
388 Como la paridad es impar lo negamos
391 /* Activar driver transmisión:
395 for (num_byte = 0; num_byte <3; num_byte ++)
397 ACUMULADOR = BYTE_MENSAJE[num_byte];
398 BIT_PARIDAD_TRA = ~PARIDAD_ACC;
399 BUFFER_SERIE = ACUMULADOR;
401 /* Esperamos que el dato sea enviado */
403 while ((DATO_ENVIADO == 0) && (CONTADOR < 254))
406 /* Desactivamos el flag */
410 /* Desactivar driver */
416 Subrutina que se ejecuta al comenzar a funcionar el microcontrolador
417 y que adecua al cometido que ha de realizar el micro los valores en
420 void inicializar_registros()
422 /* Registro de interrupciones:
423 habilitamos la interrupción del TIMER0 */
427 /* fosc = 11.059 MHz */
428 /* Transmisión a 9600 baudios */
433 /* Registros de los 'timers' */
434 /* Timer 1 en 'auto-reload' para generar velocidad transmisión */
435 /* Usamos el TIMER0 para recargar el TIMER3 mientras se */
436 /* espera un nuevo comando */
437 /* El TIMER1 se usa para generar el 'baud-rate' */
438 /* Los timers son de 16 bits. */
444 /* Activamos los 'timers' */
451 Subrutina que hace que el micro entre en estado de bajo consumo
455 /* Habilitamos la interrupción del puerto serie */
458 /* Activamos el modo 'idle' de bajo consumo. De este modo se sale
459 cuando se produce alguna interrupción */
462 /* Esta instrucción se ejecuta una vez que se ha salido del modo 'idle'
463 Deshabilitamos la interrupción del puerto serie */
468 Subrutina que realiza la recepción de los telecomandos. Todos tienen una longitud de 4 bytes
469 más el byte del código de Hamming.
470 Los bytes recibidos los coloca la UART en el registro 'BUFFER_SERIE', y el programa los coloca en las
471 variables 'BYTE0...4'.
472 La recepción de cada byte supone esperar que la bandera 'DATO_RECIBIDO' sea actualizada por la UART.
473 Para evitar que por alguna eventualidad el programa pudiera quedar indefinidamente esperando que se
474 actualizara dicha bandera se utiliza el mismo método que en la subrutina de enviar mensajes, la variable
475 'CONTADOR' se incrementa a cada comprobación que se hace de la bandera. Si se alcanza un valor límite,
476 en este caso, y a diferencia de la subrutina de transmisión, se aborta la recepción y se devuelve el valor
477 'TIEMPO_EXCEDIDO' indicando que ha habido un error en la recepción.
478 En este caso si que es obligado abortar el proceso puesto que de no hacerlo se podría provocar un
479 funcionamiento incorrecto de la antena al ejecutar comandos erróneos.
481 A cada byte recibido se le comprueba si la paridad es la correcta. Caso de no serlo se actualiza la variable
482 global 'ERROR_PARIDAD' que evitará que se procesen telecomandos erróneos. Un error de paridad detectado no
483 aborta la recepción. Lo que se hace es que una vez acabada se envía un mensaje indicando el error detectado.
485 unsigned char recibir_trama()
488 Variable que utilizaremos para evitar que el programa
489 se quede esperando si se produce una interrupción en
490 el puerto serie, pero no llega ningún dato
492 unsigned char CONTADOR;
494 /* Indice del byte que se está recibiendo */
495 unsigned char num_byte;
497 /* Ponemos a cero el indicador de error en la paridad de los datos recibidos */
500 /* Bucle de recepción */
501 for (num_byte = 0; num_byte < 5; num_byte ++)
505 /* esperamos que haya un dato válido */
506 while((DATO_RECIBIDO == 0) && (CONTADOR < 254))
509 /* Si no ha llegado ningún dato salimos de la función y devolvemos una señal indicándolo */
511 return TIEMPO_EXCEDIDO;
513 /* Desactivamos el "flag" */
516 /* Almacenamos el dato que ha llegado */
517 BYTE[num_byte] = BUFFER_SERIE;
518 ACUMULADOR = BYTE[num_byte];
520 /* Determinamos la paridad del dato recibido. 'PARIDAD_ACC' indica si el dato en el acumulador
521 tiene paridad par. Por tanto, habrá un error de paridad cuando la paridad recibida sea la misma
522 que indica 'PARIDAD_ACC' */
523 if (BIT_PARIDAD_REC == PARIDAD_ACC)
528 /* transmisión terminada */
529 return TIEMPO_NO_EXCEDIDO;
534 Subrutina que envía un mensaje de error si ha ocurrido alguna de las dos situaciones siguientes:
536 - Se ha detectado un error de paridad en al recepción de algún byte del último telecomando.
538 - El código de Hamming recibido no coincide con el que realmente corresponde a los cuatro bytes
539 del mensaje recibido.
541 En cada ocasión únicamente contesta un Subarray puesto que cada telecomando lleve incluido un campo
542 que identifica al Subarray direccionado, incluso cuando el telecomando es global. En este último caso
543 la dirección del Subarray está en el segundo byte del mensaje y en el resto de los casos en el primero.
544 La subrutina devuelve un indicador de si ha habido error.
546 unsigned char contestar_si_error()
548 BYTE_MENSAJE[2] = codigo(BYTE[0], BYTE[1], BYTE[2], BYTE[3]);
550 if ((ERROR_PARIDAD == 1) || (BYTE[4] != BYTE_MENSAJE[2]))
552 BYTE_MENSAJE[0] = BYTE_MENSAJE[1] = BYTE_MENSAJE[1] = 0x00;
562 /**********************************************************************************/
563 /* MAPEADO DE LAS LINEAS DE CONTROL DE LOS DOS HACES CON LOS PUERTOS DEL MICRO */
565 /* Simbolización: Haz 1, bit 2 de Amplitud -> H1A2 */
566 /* Haz 0, bit 0 de Fase -> H0F0 */
568 /* | BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7 | */
569 /* | | | | | | | | | */
570 /* PUERTO 0 -> P0 | H0A9 | | | | | | | | */
571 /* | | | | | | | | | */
572 /* PUERTO 1 -> P1 | H1F0 | H1F1 | H1F2 | H1F3 | H1F4 | H0F0 | H0F1 | H0F2 | */
573 /* | | | | | | | | | */
574 /* PUERTO 2 -> P2 | H0A0 | H0A1 | H0A2 | H0A3 | H0A4 | H0A5 | H0A6 | H0A7 | */
575 /* | | | | | | | | | */
576 /* PUERTO 3 -> P3 | | | | H1A8 | H1A9 | H0F3 | H0F4 | H0A8 | */
577 /* | | | | | | | | | */
578 /* PUERTO 4 -> P4 | H1A0 | H1A1 | H1A2 | H1A3 | H1A4 | H1A5 | H1A6 | H1A7 | */
580 /**********************************************************************************/
584 Subrutina que configura el HAZ 0.
585 Los valores de las líneas H9..H0 se obtienen según las siguientes expresiones:
588 H8 <-- (~A3 & A2) | (A3 & A1)
589 H7 <-- (~A3 & A1) | (A3 & A2)
590 H6 <-- A3 | (A1 & ~A2)
598 donde, '~', '|' y '&' representan la negación, la operación OR y la operación AND
599 binaria, respectivamente.
601 void configurar_haz0(unsigned char amplitud, unsigned char fase)
603 unsigned char conf_P2 = 0x00;
605 /* ponemos a cero los bits de los puertos que vamos a cambiar mediante una operación 'OR' */
611 conf_P2 |= (~(amplitud & 0x10))* 0x01;
614 conf_P2 |= (amplitud & 0x10) * 0x02;
617 conf_P2 |= (~(amplitud & 0x08))* 0x04;
620 conf_P2 |= (~(amplitud & 0x04))* 0x08;
623 conf_P2 |= (~(amplitud & 0x02))* 0x10;
626 conf_P2 |= ((amplitud & 0x08) | (amplitud & 0x04))* 0x20;
629 conf_P2 |= ((amplitud & 0x08) | ((amplitud & 0x02)&(~(amplitud & 0x04))))* 0x40;
632 conf_P2 |= (((amplitud & 0x08)&(amplitud & 0x04)) | ((amplitud & 0x02)&(~(amplitud & 0x08))))* 0x80;
635 P3 |= (((amplitud & 0x08)&(amplitud & 0x02)) | ((amplitud & 0x04)&(~(amplitud & 0x08))))* 0x80;
637 P0 |= (~(amplitud & 0x01)) * 0x01;
639 /* Actualizamos el puerto P2 */
642 /* Actualizamos el puerto P1 */
643 P1 |= (fase & 0x07) << 5;
645 /* Actualizamos el puerto P3 */
646 P3 |= (fase & 0x18) << 2;
651 Subrutina que configura el HAZ 1.
653 void configurar_haz1(unsigned char amplitud, unsigned char fase)
655 unsigned char conf_P4 = 0x00;
657 /* ponemos a cero los bits de los puertos que vamos a cambiar mediante una operación 'OR' */
662 conf_P4 |= (~(amplitud & 0x10))* 0x01;
665 conf_P4 |= (amplitud & 0x10) * 0x02;
668 conf_P4 |= (~(amplitud & 0x08))* 0x04;
671 conf_P4 |= (~(amplitud & 0x04))* 0x08;
674 conf_P4 |= (~(amplitud & 0x02))* 0x10;
677 conf_P4 |= ((amplitud & 0x08) | (amplitud & 0x04))* 0x20;
680 conf_P4 |= ((amplitud & 0x08) | ((amplitud & 0x02)&(~(amplitud & 0x04))))* 0x40;
683 conf_P4 |= (((amplitud & 0x08)&(amplitud & 0x04)) | ((amplitud & 0x02)&(~(amplitud & 0x08))))* 0x80;
686 P3 |= (((amplitud & 0x08)&(amplitud & 0x02)) | ((amplitud & 0x04)&(~(amplitud & 0x08))))* 0x08;
688 P3 |= (~(amplitud & 0x01)) * 0x10;
690 /* Actualizamos el puerto P4 */
693 /* Actualizamos el puerto P1 */
699 Telecomando en el que se envía a un Subarray concreto para actualizar uno de los estados de programación
701 El índice del estado consta de bits contenidos en BYTE1
702 Los 10 bits de la palabra del nuevo estado están en:
703 5 bits de amplitud en BYTE2[4..0]
704 5 bits de fase en BYTE3[7..3]
706 void telec_actualizacion()
708 unsigned char fase, amplitud, fila, columna, i, p;
710 /* Obtenemos la columna correspondiente al estado que se actualiza */
711 /* dentro de la matriztabla_estados */
712 columna = 1 << (BYTE[1] & 0x07);
714 /* Obtenemos la fila */
715 fila = (BYTE[1] >> 3) * 0x0A;
717 /* Obtenemos el valor de la fase */
720 /* Obtenemos el valor de la amplitud */
723 /* Actualizamos la tabla */
724 for (i = 0x00, p = 0x01; i < 0x05; i++, p <<= 1)
726 /* Colocamos un '0' en todas las posiciones correspondientes */
728 tabla_estados[fila+i ] &= 0xFF ^ columna;
729 tabla_estados[fila+i+5] &= 0xFF ^ columna;
731 /* Según el valor de amplitud y fase colocamos un '1' en las */
732 /* posiciones correspondientes */
733 if (amplitud & p) tabla_estados[fila+i ] |= columna;
734 if (fase & p) tabla_estados[fila+i+5] |= columna;
738 /* Contestamos indicando que no ha habido error.
739 Los bytes del mensaje de respuesta son 0xFC y 0x00,
740 y completa la palabra código Hamming el byte 0x76.
742 BYTE_MENSAJE[0] = 0xFF;
743 BYTE_MENSAJE[1] = 0x00;
744 BYTE_MENSAJE[2] = 0x76;
750 Subrutina que actualiza con la nueva programación las líneas de control de la red desfasadora
752 La variable 'haz_conformado' contiene la información sobre el haz que hay que reprogramar.
754 void telec_conformacion(unsigned char DIRECCION_SUBARRAY)
756 unsigned char haz_conformado, amplitud = 0x00, fase = 0x00, fila, columna, i, p;
758 /* Obtenemos la columna dentro de la matriz tabla_estados */
759 columna = 1 << (BYTE[1] & 0x07);
761 /* Obtenemos la fila */
762 fila = (BYTE[1] >> 3) * 0x0A;
764 /* Obtenemos el haz que se reprograma */
765 haz_conformado = BYTE[3];
767 /* Obtenemos los valores de las palabras de amplitud y fase */
768 for (i = 0x00, p = 0x01; i < 0x05; i++, p <<= 1)
770 if (tabla_estados[fila+i ] & columna) amplitud |= p;
771 if (tabla_estados[fila+i+5] & columna) fase |= p;
774 /* Colocamos los valores correspondientes en
775 las líneas de control */
776 if (haz_conformado == 0x00)
778 estado_haces[0] = amplitud;
779 estado_haces[1] = fase;
780 configurar_haz0(amplitud, fase);
783 if (haz_conformado == 0x01)
785 estado_haces[2] = amplitud;
786 estado_haces[3] = fase;
787 configurar_haz1(amplitud, fase);
790 /* Contestar, si corresponde, que no habido error */
791 if (direccion_CONFORMACION == DIRECCION_SUBARRAY)
793 BYTE_MENSAJE[0] = 0xFF;
794 BYTE_MENSAJE[1] = 0x00;
795 BYTE_MENSAJE[2] = 0x76;
802 Subrutina que realiza la adquisición de la temperatura del módulo T/R.
803 La conversión analógica es de 10 bits.
804 El mensaje se compone de dos bytes más el código de Hamming con la siguiente distribución:
807 BYTE1 : 0 0 0 0 0 0 T9 T8
808 BYTE2 : T7 T6 T5 T4 T3 T2 T1 T0
809 BYTE3 : H7 H6 H5 H4 H3 H2 H1 H0
811 donde T9..T0 son los 10 bits de la lectura de la temperatura y
812 H7..H0 son los 8 bits de la redundancia de Hamming.
814 void telec_temperatura()
816 unsigned char CONTADOR;
818 /* Reseteamos el registro de control del conversor A/D */
821 /* Activar la conversión A/D */
822 ADCON = ADCON | AD_INI;
824 /* Esperamos a que termine el muestreo.
825 Con la variable contador establecemos un tiempo límite de espera */
827 while (((ADCON & AD_FIN) == 0) || (CONTADOR == 250))
830 /* Si se ha superado el tiempo de espera enviamos mensaje de error */
833 BYTE_MENSAJE[0] = BYTE_MENSAJE[1] = BYTE_MENSAJE[2] = 0x00;
838 /* Realizamos la lectura del conversor */
839 BYTE_MENSAJE[0] = (ADCON & 0xC0) >> 6;
840 BYTE_MENSAJE[1] = ADAT;
842 /* Calculamos la palabra código */
843 BYTE_MENSAJE[2] = codigo(BYTE_MENSAJE[0], BYTE_MENSAJE[1], 0x00, 0x00);
845 /* Enviamos respuesta */
851 Subrutina que implementa dos funciones:
853 - Envía un mensaje en respuesta a un telecomando de petición de estado con la
854 programación actual del haz solicitado, información que está contenida en la
855 variable 'tabla_estados' en la forma siguiente:
856 * tabla_haces_prog[2*haz] <- Amplitud (5bits)
857 * tabla_haces_prog[2*haz+1] <- Fase (5bits)
859 El mensaje se compone de dos bytes más el código de Hamming con la siguiente distribución:
862 BYTE1 : 0 0 0 A4 A3 A2 A1 A0
863 BYTE2 : 0 0 0 F4 F3 F2 F1 F0
864 BYTE3 : H7 H6 H5 H4 H3 H2 H1 H0
866 - Provoca un RESET del microcontrolador cuando el telecomando de petición de temperatura
867 tiene el segundo byte igual a 0xFF.
868 Este RESET intencionado se utiliza cuando el módulo que distribuye los mensajes a los distintos
869 subarrays detecta que hay un error en el bus de telemedidas que persiste cuando se dirige a un
870 subarray en particular, o bien hay un subarray que no contesta. Estas anomalías posiblemente son
871 debidas a que un subarray por cualquier motivo desconocido ha sufrido un error en la posición de
872 memoria donde almacena la dirección que lo identifica, de forma que hay dos subarrays con la misma
873 dirección o bien un subarray tiene una dirección no válida (superior a 51, dirección máxima).
875 void telec_pet_Estado()
879 /* Comprobamos si se trata de un comando de reset */
880 /* En caso afirmativo entramos en un bucle vacío */
881 /* para que se provoque un reset */
885 Deshabilitamos las interrupciones de forma que el TIMER0 no
886 pueda activar la rutina 'watchdog()' y se produzca un RESET.
895 /* Si el telecomando es efectivamente de petición */
896 /* de estado obtenemos el haz direccionado */
899 /* Construimos los bytes de respuesta */
900 BYTE_MENSAJE[0] = estado_haces[2*haz];
901 BYTE_MENSAJE[1] = estado_haces[2*haz+1];
903 BYTE_MENSAJE[2] = codigo(BYTE_MENSAJE[0], BYTE_MENSAJE[1], 0x00, 0x00);
905 /* Enviamos mensaje de respuesta */