Estoy tratando de programar un PIC10f202 usando el compilador XC8 para comparar el valor de un temporizador con una variable que será una función de una tabla de búsqueda. Aquí hay un código de muestra:
#include <xc.h>
#pragma config MCLRE = OFF
#pragma config CP = OFF
#pragma config WDTE = OFF
Init(void){
TRIS=0;
GPIO=0;
TMR0 = 0;
OPTION = 0b00000011;
}
const unsigned char LUT[250] = {
0b00000000, 0b00000001, 0b00000001, 0b00000001, 0b00000001,
0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000001,
0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000001,
0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000001,
0b00000001, 0b00000001, 0b00000001, 0b00000010, 0b00000010,
0b00000010, 0b00000010, 0b00000010, 0b00000010, 0b00000011,
0b00000011, 0b00000011, 0b00000011, 0b00000011, 0b00000100,
0b00000100, 0b00000100, 0b00000101, 0b00000101, 0b00000101,
0b00000110, 0b00000110, 0b00000110, 0b00000111, 0b00000111,
0b00001000, 0b00001000, 0b00001001, 0b00001001, 0b00001010,
0b00001010, 0b00001011, 0b00001100, 0b00001100, 0b00001101,
0b00001101, 0b00001110, 0b00001111, 0b00010000, 0b00010000,
0b00010001, 0b00010010, 0b00010011, 0b00010011, 0b00010100,
0b00010101, 0b00010110, 0b00010111, 0b00011000, 0b00011001,
0b00011010, 0b00011011, 0b00011100, 0b00011101, 0b00011110,
0b00011111, 0b00100000, 0b00100001, 0b00100010, 0b00100100,
0b00100101, 0b00100110, 0b00100111, 0b00101001, 0b00101010,
0b00101011, 0b00101100, 0b00101110, 0b00101111, 0b00110000,
0b00110010, 0b00110011, 0b00110101, 0b00110110, 0b00111000,
0b00111001, 0b00111011, 0b00111100, 0b00111110, 0b00111111,
0b01000001, 0b01000010, 0b01000100, 0b01000110, 0b01000111,
0b01001001, 0b01001011, 0b01001100, 0b01001110, 0b01010000,
0b01010001, 0b01010011, 0b01010101, 0b01010111, 0b01011000,
0b01011010, 0b01011100, 0b01011110, 0b01100000, 0b01100001,
0b01100011, 0b01100101, 0b01100111, 0b01101001, 0b01101010,
0b01101100, 0b01101110, 0b01110000, 0b01110010, 0b01110100,
0b01110110, 0b01111000, 0b01111001, 0b01111011, 0b01111101,
0b01111111, 0b10000001, 0b10000011, 0b10000101, 0b10000111,
0b10001000, 0b10001010, 0b10001100, 0b10001110, 0b10010000,
0b10010010, 0b10010100, 0b10010110, 0b10010111, 0b10011001,
0b10011011, 0b10011101, 0b10011111, 0b10100000, 0b10100010,
0b10100100, 0b10100110, 0b10101000, 0b10101001, 0b10101011,
0b10101101, 0b10101111, 0b10110000, 0b10110010, 0b10110100,
0b10110101, 0b10110111, 0b10111001, 0b10111010, 0b10111100,
0b10111110, 0b10111111, 0b11000001, 0b11000010, 0b11000100,
0b11000101, 0b11000111, 0b11001000, 0b11001010, 0b11001011,
0b11001101, 0b11001110, 0b11010000, 0b11010001, 0b11010010,
0b11010100, 0b11010101, 0b11010110, 0b11010111, 0b11011001,
0b11011010, 0b11011011, 0b11011100, 0b11011110, 0b11011111,
0b11100000, 0b11100001, 0b11100010, 0b11100011, 0b11100100,
0b11100101, 0b11100110, 0b11100111, 0b11101000, 0b11101001,
0b11101010, 0b11101011, 0b11101100, 0b11101101, 0b11101101,
0b11101110, 0b11101111, 0b11110000, 0b11110000, 0b11110001,
0b11110010, 0b11110011, 0b11110011, 0b11110100, 0b11110100,
0b11110101, 0b11110110, 0b11110110, 0b11110111, 0b11110111,
0b11111000, 0b11111000, 0b11111001, 0b11111001, 0b11111010,
0b11111010, 0b11111010, 0b11111011, 0b11111011, 0b11111011,
0b11111100, 0b11111100, 0b11111100, 0b11111101, 0b11111101,
0b11111101, 0b11111101, 0b11111101, 0b11111110, 0b11111110,
0b11111110, 0b11111110, 0b11111110, 0b11111110, 0b11111111};
unsigned char cnt1=0;
void main(){
Init();
for(;;){
cnt1 = LUT[100];
while(TMR0 > 100){
GPIO=0b00000001;
}
GPIO=0b00000000;
}
}
La tabla de búsqueda tiene 250 caracteres porque este es el tamaño máximo permitido por el compilador antes de que me diera un error "No se pueden encontrar palabras x0FF (x0ff con total) para psect "stringtext1" en la clase "Entrada"". El código se compila bien, con MPLAB X indicando un uso de memoria flash del 55 % y un uso de RAM del 0 %. Si cambio la condición "mientras" a esto:
while(TMR0 > cnt1)
El compilador volverá a darme un error similar: "No se pueden encontrar palabras x0FA (x0fa con total) para psect "stringtext1" en la clase "Entrada"". Entiendo que el compilador no puede encontrar suficiente memoria para escribir el código, pero no veo cómo el 45 % de espacio libre no es suficiente para esta tarea. Además, ¿por qué no puedo crear una matriz con 255 elementos? El PIC10f202 tiene 512 palabras de memoria, debería ser posible.
¿Por qué el compilador da esos errores?
Este es un ejemplo perfecto de cómo usar un compilador a ciegas en un sistema pequeño con recursos limitados sin comprender realmente las limitaciones de la máquina puede causarle problemas.
Primero, observe cómo se necesitaría implementar una tabla de constantes en la memoria del programa. Vaya a leer la hoja de datos. No, de verdad, ve a leerlo. ¿Cómo se necesitaría hacer esto también? ¿Ve alguna forma de leer la memoria del programa, como un mecanismo de lectura de tablas que tienen algunos otros PIC? La única forma de sacar constantes de la memoria del programa es con instrucciones que contengan literales. ¿Cómo se implementa una tabla con eso? No, en realidad piensaal respecto antes de seguir leyendo. Echa un vistazo a la lista de instrucciones. La única forma de implementar una tabla de búsqueda es con la instrucción RETLW. Eso significa que básicamente realiza una llamada de subrutina a la entrada de la tabla, que devuelve el valor de esa entrada en W. Ahora mire el mecanismo de llamada de subrutina. Después de haber hecho la lectura que debe tener antes de escribir la primera línea de código, debería ser obvio por qué no puede tener más de 256 entradas de tabla con algunas de esas posibles entradas de tabla que deben usarse para el código.
Muestre que ha leído un poco la hoja de datos y puedo entrar en más detalles.
lp: call retAddr
/ retAddr: btfsc temp,7
/ goto gotValue
/ decfsz temp
/ goto lp
para forzar todas las ranuras de pila a retAddr conocido. Establecer el bit 7 temp
y escribir en PCL leería un valor en W y saltaría a gotValue
. No es lo que esperaría de un compilador, pero es posible.Como los números en la LUT no son únicos, los números aumentan de forma monótona y, de hecho, los cambios parecen bastante escasos, ¿es posible escribir una pequeña función para reemplazar la LUT?
por ejemplo, y= x>=1 + x>=23 + .....
Te dejaré a ti determinar cuánta memoria, si es que hay alguna, se puede guardar de esta manera.
Quizás haya otras algs que usen técnicas dispersas que también podrían ayudar, tal vez almacenando los diferentes valores únicos y los valores de x donde ocurren las transiciones.
PIC10f202 tiene 24 bytes de RAM y 750 bytes de flash, según este resumen de Microchip. Si es posible mantener y ejecutar una tabla en flash, es posible que pueda instalar un programa pequeño utilizando el resto de la memoria del programa. Pero no veo nada en la declaración de su tabla que parezca una directiva para usar flash, y la tabla ahora tiene aproximadamente 12 veces el tamaño de la RAM disponible, incluso si no hubiera ninguna otra demanda (como la pila...) .
const
. En algunos compiladores de C para PIC, esto coloca la constante en Flash. Pero no sé si esto se aplica a XC8, porque nunca lo he usado.No he verificado todas las entradas en la tabla, pero parece que las entradas solo cambian en 1 (después de varias entradas seguidas que son iguales). Creo que, en cambio, podría reorganizar la tabla de la siguiente manera, en la que cada tnery es el punto en el que se incrementa el valor en la tabla anterior.
const unsigned char LUT[nn] = {
0, 23, 29, 34, ...
El índice en la nueva tabla es el valor con el que habría hecho coincidir antes (ahora es una búsqueda de tabla), y el valor devuelto por la tabla es el mismo que el índice que habría estado en la tabla anterior.
Debería ser mucho más rápido, y la tabla será mucho más corta.
julio059
usuario3624