| PicManía by RedRaven |
Búsqueda personalizada
|
|
El lenguaje C es el que uso por defecto para el 90% de mis programas.
Aquí os muestro algunos ejemplos de cómo hacer cosas con este idioma.
Todos ejemplos que se muestran en esta sección se han realizado usando el
PCW PICC de CCS (Veriones 3.242 a 4.096 según depende) Más CCS C : 1 2 3 4 |
| Índice Parcial: |
|
|
|
|
|
Leer y Escribir en la EEPROM interna del
PIC variables int 16 bits (2 bytes)
|
|
| Funciones read_eeprom(address) y write_eeprom(address, byte) | ||
| void write_eeprom_16bits(int
address, long* val){ int pLow, pHigh; pLow = val; pHigh = val>>8; write_eeprom(address,pHigh); delay_ms(12); ++address; write_eeprom(address,plow); delay_ms(12); } long read_eeprom_16bits(int address){ int pLow, pHigh; long result; pHigh = read_eeprom(address); ++address; pLow = read_eeprom(address); result=(pHigh<<8); result+=pLow; return result; } |
||
|
Con ellas he escrito un programa de Test que
en el reset guarda un valor de 16 bits en la variable x, llama a la función
write_eeprom_16bits y se queda a la espera "escuchando" la RS232 ... al recibir la tecla 'r' realiza la funciona inversa, lee sobre la variable y, también de 16 bits, desde la misma dirección en la que antes escribimos con read_eeprom_16bits y monitoriza el resultado. Todo este recorrido esta salpicado de printf's para poder ver todo el proceso paso a paso: |
![]() |
|
El programa completo tal como quedó para poder
monitorizar todos los pasos es: |
| eeprom_16bits plus rs232 | ||
| #include
<18f4550.h> #fuses HS,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOPBADEN, NOLVP #use delay(clock=20000000) #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) char Keypress = 0x00; char Command = 0x00; long x,y; #int_rda void serial_isr() { Keypress=0x00; if(kbhit()){ Keypress=getc(); if(Keypress!=0x00){ if(Keypress=='r'){ Command=Keypress; } putchar(keypress); keypress=0x00; } } } void write_eeprom_16bits(int address, long* val){ int pLow, pHigh; printf("write_eeprom_16bits( address=%u, val=%lx)\r\n",address,val); pLow = val; pHigh = val>>8; printf("write_eeprom( address=%u, val=%x)\r\n",address,pHigh); write_eeprom(address,pHigh); delay_ms(12); ++address; printf("write_eeprom( address=%u, val=%x)\r\n",address,pLow); write_eeprom(address,plow); delay_ms(12); } long read_eeprom_16bits(int address){ int pLow, pHigh; long result; printf("read_eeprom_16bits( address=%u)\r\n",address); pHigh = read_eeprom(address); printf("read_eeprom( address=%u) = %x\r\n",address,pHigh); ++address; pLow = read_eeprom(address); printf("read_eeprom( address=%u) = %x\r\n",address,pLow); result=(pHigh<<8); result+=pLow; return result; } void main(){ disable_interrupts(global); setup_adc_ports(NO_ANALOGS); setup_adc(ADC_OFF); setup_spi(FALSE); setup_psp(PSP_DISABLED); setup_counters(RTCC_INTERNAL,RTCC_DIV_2); setup_timer_0(RTCC_OFF); setup_timer_1(T1_INTERNAL | T1_DIV_BY_1); setup_timer_2(T2_DISABLED,0,1); setup_timer_3(T3_DISABLED); setup_comparator(NC_NC_NC_NC); setup_vref(FALSE); port_b_pullups(FALSE); set_tris_e(0b00010000); set_tris_c(0b10000000); delay_ms(1000); output_High(PIN_E0); output_High(PIN_E1); output_High(PIN_E2); printf("\r\n"); printf("18F4550 in RRBOARAD2\r\n"); printf("Test EEPROM with 18 bits\r\n\n"); delay_ms(500); output_Low(PIN_E0); output_Low(PIN_E1); output_Low(PIN_E2); Command=0x00; enable_interrupts(int_rda); enable_interrupts(global); x=0x1f2f; y=0; printf("initial 16 bits x = %lx (%lu), y = %lx (%lu)\r\n",x,x,y,y); write_eeprom_16bits(0,x); printf("\r\n"); while(TRUE) { if(Command=='r'){ Command=0x00; printf("\r\n\n"); y=read_eeprom_16bits(0); printf("final 16 bits x = %lx (%lu), y = %lx (%lu)\r\n",x,x,y,y); } } } |
||
| Funciones especiales para Leer y Escribir la EEPROM interna del PIC |
|
|
|
|
|
Lib_Int_EEPROM |
||
|
//////////////////////////////////////////////////////////////////////////////// //// lib_int_eeprom.c //// //////////////////////////////////////////////////////////////////////////////// //// //// //// void write_int1_eeprom(address, int8 bitPosition, int1 data) //// //// Call to write one bit of data //// //// //// //// int1 read_int1_eeprom(address, int8 bitPosition) //// //// Call to read one bit of data //// //// //// //// void write_int16_eeprom(address, int16 data) //// //// Call to write a 16 bit integer //// //// //// //// int16 read_int16_eeprom(address) //// //// Call to read a 16 bit integer //// //// //// //// void write_int32_eeprom(address, int32 data) //// //// Call to write a 32 bit integer //// //// //// //// int32 read_int32_eeprom(address) //// //// Call to read a 32 bit integer //// //// //// //// void write_float_eeprom(address, float data) //// //// Call to write a floating point number //// //// //// //// float read_float_eeprom(address) //// //// Call to read a floating point number //// //// //// //////////////////////////////////////////////////////////////////////////////// #ifndef INTERNAL_EEPROM_UTILITIES #define INTERNAL_EEPROM_UTILITIES // Used to adjust the address range #ifndef INT_EEPROM_ADDRESS #define INT_EEPROM_ADDRESS int8 #endif //////////////////////////////////////////////////////////////////////////////// //// Internal EEPROM Functions //////////////////////////////////////////////////////////////////////////////// // Purpose: Write one bit to internal eeprom -------------------------------- // Inputs: 1) An eeprom address // 2) The bit position (LSB == 0) // 3) The bit to write // Outputs: None void write_int1_eeprom(INT_EEPROM_ADDRESS address, int8 bitPosition, int1 data){ int8 stored_data; stored_data = read_eeprom(address); if(data){ bit_set(stored_data, bitPosition); }else{ bit_clear(stored_data, bitPosition); } write_eeprom(address, stored_data); } // Purpose: Read one bit from internal eeprom ------------------------------- // Inputs: 1) An eeprom address // 2) The bit position (LSB == 0) // Outputs: The bit read from internal eeprom int1 read_int1_eeprom(INT_EEPROM_ADDRESS address, int8 bitPosition){ return bit_test(read_eeprom(address), bitPosition); } // Purpose: Write a 16 bit number to internal eeprom ------------------------ // Inputs: 1) An eeprom address // 2) The 16 bit number to write to internal eeprom // Outputs: None void write_int16_eeprom(INT_EEPROM_ADDRESS address, int16 data){ int8 i; for(i = 0; i < 2; ++i){ write_eeprom(address + i,*(&data + i)); } } // Purpose: Read a 16 bit number from internal eeprom ----------------------- // Inputs: An eeprom address // Outputs: The 16 bit number read from internal eeprom int16 read_int16_eeprom(INT_EEPROM_ADDRESS address){ int8 i; int16 data; for(i = 0; i < 2; ++i){ *(&data + i) = read_eeprom(address + i); } return(data); } // Purpose: Write a 32 bit integer to internal eeprom ----------------------- // Inputs: 1) An eeprom address // 2) The 32 bit number to write to internal eeprom // Outputs: None void write_int32_eeprom(INT_EEPROM_ADDRESS address, int32 data){ int8 i; for(i = 0; i < 4; ++i){ write_eeprom(address + i,*(&data + i)); } } // Purpose: Read a 32 bit integer from internal eeprom ---------------------- // Inputs: An eeprom address // Outputs: The 32 bit integer read from internal eeprom int32 read_int32_eeprom(INT_EEPROM_ADDRESS address){ int8 i; int32 data; for(i = 0; i < 4; ++i){ *(&data + i) = read_eeprom(address + i); } return data; } // Purpose: Write a floating point number to internal eeprom ---------------- // Inputs: 1) An eeprom address. Four eeprom locations will be used. // 2) The floating point number to write to internal eeprom // Outputs: None #separate void write_float_eeprom(INT_EEPROM_ADDRESS address, float data){ int8 i; for(i = 0; i < 4; ++i){ write_eeprom(address + i,*(&data + i)); } } // Purpose: Read a floating point number from internal eeprom --------------- // Inputs: An eeprom address // Outputs: The floating point number read from the internal eeprom #separate float read_float_eeprom(INT_EEPROM_ADDRESS address){ int8 i; float data; for(i = 0; i < 4; ++i){ *(&data + i) = read_eeprom(address + i); } return data; } #endif |
||
| Descargar lib_int_eeprom.c |
| Rutina de conversión de
Números Arábigos a Números romanos. Para que nuestro PIC hable en Latín Clásico. |
|
Cita. In illio tempor Caesare
dixit ad milites suos: ¡Milites! Si deambulandun per la via publicam
vieribus mulieribus quid dixieribus "... morenus ...". Non facendum caso,
putaverant sunt. Fin de la cita. |
| Titulo | ||
| ------ const int8 Numeros[] = { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000}; char H_in_RomanusNumericum[12]; char M_in_RomanusNumericum[12]; char S_in_RomanusNumericum[12]; ------ void dec_to_roman(int8 LI, char* ptr){ char tmp[12]; char* ptmp = (char*) tmp; strcpy(ptr,""); // transformo de la tabla Arábiga a la Románica Latinitatis // { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000}; // { 'I', 'IV', 'V', 'IX', 'X', 'XL', 'L', 'XC', 'C', 'CD', 'D', 'CM', 'M'}; for(i=12;i!=255;i--){ while(LI >= Numeros[i]){ LI = LI - Numeros[i]; Switch(i){ case 0: strcpy(ptmp,"I\0"); break; case 1: strcpy(ptmp,"IV\0"); break; case 2: strcpy(ptmp,"V\0"); break; case 3: strcpy(ptmp,"IX\0"); break; case 4: strcpy(ptmp,"X\0"); break; case 5: strcpy(ptmp,"XL\0"); break; case 6: strcpy(ptmp,"L\0"); break; case 7: strcpy(ptmp,"XC\0"); break; case 8: strcpy(ptmp,"C\0"); break; case 9: strcpy(ptmp,"CD\0"); break; case 10: strcpy(ptmp,"D\0"); break; case 11: strcpy(ptmp,"CM\0"); break; case 12: strcpy(ptmp,"M\0"); break; } ptr=strcat(ptr,ptmp); } } } ----- ds1307_get_time(hrs,min,sec); dec_to_roman(hrs, (char*) H_in_RomanusNumericum); dec_to_roman(min, (char*) M_in_RomanusNumericum); dec_to_roman(sec, (char*) S_in_RomanusNumericum); |
||
|
|
| Y para que veáis que esta rutina funciona correctamente qué mejor que mis dumps y fotos ... |
|
|
|
|
| Manejando un Array de
bits (simulado en CCS C que no lo implementa) I Para que nuestro PIC no desperdicie memoria. |
|
He montado una estructura que puede manejar
un Array de 8, 16 o 32 bits para no complicarlo demasiado. Con
igual pretensión no le he colocado tampoco el control de errores por
parámetros incongruentes (como intentar leer el bit nº 12 habiendo
definido un array de sólo 8 bits) Para empezar defino el tamaño del array a utilizar mediantes los defines (Comentando o descomentando el que necesito) #define bits_array_8 //#define bits_array_16 //#define bits_array_32 En función de estos defines creo en la RAM el tipo de variable correspondiente: #ifdef bits_array_8 int8 bits_array=0; #endif #ifdef bits_array_16 int16 bits_array=0; #endif #ifdef bits_array_32 int32 bits_array=0; #endif Al final lo que tengo es una variable llamada bits_array con el tamaño necesario. Y ahora me defino dos funciones, una para poner a un valor dado el bit que desee y otra para leerlo: int1 get_array_bit(int8 pbit){ int1 r; r=bit_test(bits_array,pbit); return r; } int1 set_array_bit(int1 vbit, int8 pbit){ int1 r; r=bit_test(bits_array,pbit); if(vbit==0) bit_clear(bits_array,pbit); else bit_set(bits_array,pbit); return r; } De forma que get_array_bit me devuelve el valor del bit en la posición pbit, que al ser un parámetro puede ser incluido en un bucle for{] por ejemplo. Y set_array_bit en la que coloco al valor vbit en la posición pbit; esta función me devuelve además el valor anterior que tenía el bit de la posición pbit, asi puedo comparar, si lo deseo, si el bit ha cambiado o no. Al igual que en la función anterior el parámetro puede ser incluido en un bucle for{]. Lo he probado y funciona perfectamente. if(isdigit(Command)){ // Bit xbit=Command-'0'; set_array_bit(1,xbit); printf("Despues de Poner : %u %x\r\n",get_array_bit(xbit),bits_array); } |
|
|
| Manejando un Array de
bits (simulado en CCS C que no lo implementa) I Para que nuestro PIC no desperdicie memoria. |
|
Tras una propuesta del amigo
Manolo
Nocturno he modificado las funciones anteriores y ya están
funcionando de forma mas rápida y elegante. El asunto está en calcular el bit a manejar mediante operaciones posicion/8 para obtener la parte entera o byte donde está alojado el bit a utilizar y posicion%8 para obtener el resto o posición del bit dentro del byte. Como estos cálculos no parecen funcionar dentro, embebidas, de las mismas instrucciones de bit_set, bit_clear o bit_test lo único que he hecho ha sido hacer estas operaciones fuera, forzándolas a devolver el resultado como int8 especificándolo así y después utilizar las funciones tal cual están. int1 get_array_bit(int8 pbit){ int1 r; int8 a,b; a = (int8) pbit/8; b = (int8) pbit%8; r=bit_test(bits_array[a],b); return r; } int1 set_array_bit(int1 vbit, int8 pbit){ int1 r; int8 a,b; a = (int8) pbit/8; b = (int8) pbit%8; r=bit_test(bits_array[a],b); bit_clear(bits_array[a],b); if(vbit==1) bit_set(bits_array[a],b); return r; } Para declarar la variable Array de bytes (los contenedores de los bits) he utilizado la declaración siguiente: #define bytes_for_bits 5 // 5 * 8 = 40 bits (0..39) int8 bits_array[bytes_for_bits]; // Array de 40 bits dividido en bytes_for_bits bytes Y para poder monitorizar todos los bits dentro de bits_array me he contruido una función que me convierte en string de bits ASCII el byte que le envíe, devolviéndome un puntero a dicho string: char* int8_to_bits_string(int8 val){ char s[]="00000000"; char* ptr; int8 i; for(i=0;i<8;i++) s[ i ]=bit_test(val,i)+'0'; s[8]='\0'; ptr=&s[0]; return ptr; } Y para comprobar que todo va como debe ir me he construido en el main() un modo de ir poniendo a 1 cada uno de los bits cada vez que le pulso algo a través del canal serie, y con cada pulsación me muestra el estado de los cuarenta bits. Y cuando llega al bit 39 se reinicializa el índice comenzando de nuevo desde el 0 pero si está ya puesto a 1 lo coloca ahora a 0. El trozo de código del main es: if(Command=='1'){ // Next Bit a 1 si 0 ó a 0 si 1 if(get_array_bit(nextbit)==0) set_array_bit(1,nextbit); else set_array_bit(0,nextbit); printf(">Set bit %2u ",nextbit); for(i=0;i<bytes_for_bits;i++){ ptr=int8_to_bits_string(bits_array[ i ]); strcpy(s,ptr); printf("%s",s); } printf("\r\n"); if(++nextbit==bytes_for_bits * 8 ) nextbit=0; } Y como todo está construido alrededor del define bytes_for_bits podemos cambiarle el valor y montar el número de bits que queramos, siempre múltiplo de 8. |
|
|
|
Nota: Esta página Web esta repleta de imágenes, textos, logotipos y demás material extraídos de los mas variados medios de los que no soy ni autor ni depositario de los correspondientes derechos de autor, uso y/o reproducción. Si Ud. es depositario de dichos derechos y desea que el material correspondiente sea eliminado de esta Web no dude en ponerse en contacto conmigo mediante e-mail y será inmediatamente retirado. Gracias. |
Esta página fue modificada el 07-02-2010 12:33:05