| 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: |
|
|
|
Controlando un SERVO con el PIC desde
nuestro PC (O todo lo que siempre quiso saber sobre los Servomotores y nunca se atrevió a preguntar) |
|
|
|
|
|
Ahora lo que
tenemos que hacer es saber cómo podemos controlar estos tiempos en nuestro
PIC para poner en alto (disparar el pulso) y en bajo (apagarlo)
siguiendo la tabla de tiempos descrita mas arriba. |
|
|
|
Como vemos
en el cronograma superior: cada vez que se produce un super RTCC,
de 4 RTC's y pico a la que llamamos flagRTCC, ponemos en alto el
PIN de la señal del Servo, debemos recordar que esto siempre va a
ocurrir en el tránsito del contador TIMER0 entre los valores de 255 y 0,
por lo que flagRTCC siempre va a coincidir con TIMER0=0. |
|
| Cada 20 milisegundos
activamos el pulso, y transcurridos 1.5 milisegundos lo desactivamos, que
es exactamente lo que queríamos hacer. El valor de TIMER0 con el comparamos para controlar la duración de cada pulso la tenemos guardada en tSERVO1, que inicialmente cargamos con el número de ticks necesarios para colocar el Servo en su punto medio, ticks_PULSO_MEDIO, y que podemos cambiar dinámicamente mediante la recepción de comandos a través de la RS232. De esta forma con los comandos "1", "2" y "3" podemos cambiar el valor de tSERVO1 a ticks_PULSO_MINIMO, ticks_PULSO_MEDIO y ticks_PULSO_MAXIMO respectivamente; y con los comandos "+" y "-" vamos incrementando o decrementando su valor. Con "r" le pedimos al PIC que nos envíe su valor actual. Ahora solo nos quedaría implementar todo esto en un programa en C que queda de la siguiente forma: |
| Titulo | ||
| // servo_pwm_232 // Ejemplo con un servo FUTABA S3003 // Alimentación y pulsos a 5V // Cuadro de Tiempos : // Periodo 20 ms (Frecuencia 50 Hz) // Ancho Pulso minimo 0.5 ms // Ancho pulso medio 1.5 ms // Ancho pulso maximo 2.5 ms // TMR0 a 1:16 -> 1 RTCC cada 4.096 ms // -> 1 Tick cada 0.096 / 256 = 0.016 ms // -> 20 ms = (4 x RTCC completas) + (1 * RTCC - 30 ticks) // Ancho Pulso minimo 0.5 ms -> 31 ticks de TMR0 // Ancho pulso medio 1.5 ms -> 93 ticks de TMR0 // Ancho pulso maximo 2.5 ms -> 155 ticks de TMR0 #include <16f876a.h> #fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT #use delay(clock=4000000) #use standard_io(b) #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) #define PIN_SERVO1 PIN_B0 const int AJUSTE_FINO_DE_RTCC = 30; const int ticks_PULSO_MINIMO = 31; const int ticks_PULSO_MEDIO = 93; const int ticks_PULSO_MAXIMO = 155; int1 flagRTCC = 0; int contRTCC = 0; int1 flagSERVO1 = 0; int tSERVO1 = ticks_PULSO_MEDIO; char Keypress =0x00; void eco_servos(void); void ajusta_servo(void); #int_rda void rda_isr() { Keypress=0x00; if(kbhit()){ Keypress=getc(); } } #int_RTCC RTCC_isr(){ ++contRTCC; if(contRTCC==4){ set_TIMER0(AJUSTE_FINO_DE_RTCC); } if(contRTCC==5){ flagRTCC=1; contRTCC=0x00; } } void main() { int ValTIMER0; setup_counters(RTCC_INTERNAL,RTCC_DIV_16); enable_interrupts(int_rda); enable_interrupts(global); printf("\r\n\SERVO Commander\r\n\r\n" ); eco_servos(); set_TIMER0(0); enable_interrupts(INT_RTCC); do { // DISPARO DEL PULSO PWM if(flagRTCC==1){ flagRTCC=0; output_high(PIN_SERVO1); flagSERVO1=1; } // CONTROL DE ANCHO DEL PULSO PWM if(flagSERVO1==1){ valTIMER0 = get_TIMER0(); if(valTIMER0>tSERVO1){ flagSERVO1=0; output_low(PIN_SERVO1); } } // CONTROL DESDE LA RS-232 if(Keypress!=0x00){ ajusta_servo(); Keypress=0x00; } } while (TRUE); } void ajusta_servo(void){ switch(Keypress){ // Periodos Prefijados case '1': tSERVO1=ticks_PULSO_MINIMO; break; case '2': tSERVO1=ticks_PULSO_MEDIO; break; case '3': tSERVO1=ticks_PULSO_MAXIMO; break; // Inc Dec Periodo case '+': if(++tSERVO1>ticks_PULSO_MAXIMO){ tSERVO1=ticks_PULSO_MAXIMO; } break; case '-': if(--tSERVO1<ticks_PULSO_MINIMO){ tSERVO1=ticks_PULSO_MINIMO; } break; // Dame Periodo actual case 'r': eco_servos(); break; } } void eco_servos(void){ printf("S=%u\r\n",tSERVO1); } |
||
|
|
|
Haz Click sobre la imagen
para verla a tamaño grande |
|
Strings Demo o como se pueden manejar las
cadenas en nuestro PIC |
||
|
Con mi insufrible manía de hacer
la cosas lo mas difícil posible he montado una demo de este asunto de los
strings mediante un "monitor rs232". Quiero decir que he hecho un programa que se comunica con el PC mediante la RS232 y que acepta comandos y argumentos de estos comandos para los ejemplos de algunas funciones ... Pero para poder hacer esto de los comandos, que en el fondo no es mas que procesar strings, he necesitado hacer uso de la mayoría de las funciones que estamos tratando de ejemplificar. El resultado ha sido plenamente satisfactorio ya que funciona perfectamente y a la vez ha salido, perdonen la inmodestia, muy pedagógico. Aparecen la mayoría de las funciones de tratamiento de strings y las que no lo hacen se manejan de forma absolutamente análogas a las que sí. |
||
|
|
||
|
||
|
Recomiendo encarecidamente, para
los interesados en el manejo de strings, el estudio detallado de la funcion
int extrae_argumentos(int cuantos) ya que implementa las esencias
fundamentales de su tratamiento. Tened en cuenta al recibir vía RS232 el carácter 0x0D (Enter) disparo el procesado de lo recibido hasta entonces en buffrec[] Así el comando strcat asdfg qwerty[0x0D] hace buffrec[] = "strcat asdfg qwerty \0" por lo que entonces debo: 1º detectar que se trata del comando strcat cosa que hago con : strcpy(xcommand,"strcat" ); if(!strncmp(buffrec,xcommand,strlen(xcommand))){ dentro de procesa_comando() 2º extraer sobre s1[] y/o s2[] los argumentos asdfg y qwerty que es lo que realiza : error=extrae_argumentos(2); y ... 3º realizar la función real strcat para presentar el resultado en : strcpy(sr,s1); strcat(sr,s2); printf("\r\n\n%s + %s = %s\r\n",s1,s2,sr); Lo demás solo sirve para que todo esto funcione. Si llegáis a comprender su funcionamiento todo lo demás es obvio y sencillo. |
||
|
strings_demo.c |
||
|
///////////////////////////////////////////////////////////////////////////////////////// // // Strings_Demo v.1.0 // // © 28.02.2006 By RedRaven (RedPic) // // Para Foro Todo Pic // // Idioma: CCS PICC v.3.242 // ///////////////////////////////////////////////////////////////////////////////////////// #include <16f876a.h> #fuses XT,NOWDT,NOPROTECT,NOLVP,PUT,BROWNOUT #use delay(clock=4000000) #use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) #include <stdlib.h> // Constantes y definiciones //////////////////////////////////////////////////////////// int const MAXLENBUFF=42; // Máxima longitud del buffer de recepción RS232 int const MAXLENCOMMAND=10; // Máxima longitud de un comando (sin argumentos) int const MAXLENARG=8; // Máxima longitud de cada uno de los argumentos s1 y s2 // Variables Globales /////////////////////////////////////////////////////////////////// char buffrec[MAXLENBUFF]; // Buffer de Recepción int xbuffrec=0x00; // índice del Buffer de Recepción int1 new_command=0; // Flag para indicar comando disponible int1 pdte_send_prompt=0; // Flags para enviar echos fuera de la int_rda int1 pdte_send_tmp_prompt=0; char s1[MAXLENARG]; // Argumento 1 char s2[MAXLENARG]; // Argumento 2 char sr[MAXLENBUFF]; // Resultado de nuestras manipulaciones de Strings // Declaracion de Funciones ///////////////////////////////////////////////////////////// void On_reset(void); // Tras RESET del Micro void Send_listen(void); // Monitoriza RS232 : Comienzo void Send_opts(void); // Monitoriza RS232 : Presenta opciones void Send_prompt(void); // Monitoriza RS232 : Presenta el Cursor void Send_tmp_prompt(void); // Monitoriza RS232 : Presenta el Cursor y el comando actual void Ini_buffrec(void); // Borra el buffer de recepción void Add_buffrec(char c); // Añade un carácter al buffer de recepción void Procesa_comando(void); // Procesado de comandos // INTERRUPCIONES /////////////////////////////////////////////////////////////////////// // INTERRUPCION RDA - Recepción USART - #int_rda void serial_isr() { if(kbhit()){ // Si hay algo pendiente de recibir ... Add_buffrec(getc()); // lo recibo y lo añado al Buffer de Recepción } } // Control del Buffer de recepción --------------------------------------- void Ini_buff_rec(void){ // Inicia a "\0" el Buffer de Recepción int i; for(i=0;i<MAXLENBUFF;i++){ // Bucle que pone a 0 todos los buffrec[i]=0x00; // caracteres en el Buffer de Recepción } xbuffrec=0x00; // Inicializo el índice de siguiente carácter recibido } void Add_buffrec(char c){ // Añade carácter al Buffer de Recepción switch(c){ case 0x0D: // [Enter] -> Habilita Flag para procesar comando en Main buffrec[xbuffrec++]=' '; // Añade un espacio en blanco al final y ... new_command=1; // Habilita Flag para procesar comando en Main break; case 0x08: // [Del] -> Borra último carácter del Buffer if(xbuffrec>0){ // Si hay algo en el buffer buffrec[--xbuffrec]=0x00; // decremento el índice, escribo un cero y ... pdte_send_tmp_prompt=1; // habilito flag para refrescar el prompt } break; case 0x01B: // [Esc] -> Borra el Buffer completamente y ... Ini_buff_rec(); // habilito flag para refrescar el prompt pdte_send_prompt=1; break; case 0x009: // [Tab] -> Refresca el prompt y el comando tal como esté pdte_send_tmp_prompt=1; break; default: buffrec[xbuffrec++]=c; // Añade carácter recibido al Buffer putc(c); // y lo monitorizo } } // Rutinas y Funciones de RROS /////////////////////////////////////////// void On_reset(void){ // Inicialización del Micro tras RESET disable_interrupts(GLOBAL); // todas las interrupciones desactivadas delay_ms(100); Ini_buff_rec(); // Inicializo Buffer de recepción new_command=0; // Desactivo flag de comando pendiente. pdte_send_prompt=0; // Desactivo Flags para enviar echo fuera de la int_rda pdte_send_tmp_prompt=0; enable_interrupts(int_rda); // interrupción RDA habilitada enable_interrupts(global); // todas las interrupciones activadas Send_listen(); // Presenta Comienzo Send_prompt(); // Presenta el Cursor } void Send_listen(void){ // Presenta Comienzo printf("\r\nStrings Demo v1.0"); Send_opts(); } void Send_opts(void){ // Relación de comandos válidos printf("\r\n\n"); printf("[?] ver comandos válidos\r\n"); printf("[strcat ABC abc] añade s2=abc a s1=ABC\r\n"); printf("[strlwr ABC] convierte ABC a minúsculas\r\n"); printf("[strstr ABC abc] busca s2=abc dentro de s1=ABC\r\n"); } void Send_prompt(void){ // Presenta el cursor printf("\r\n>"); } void Send_tmp_prompt(void){ // Presenta el cursor con el comando actual printf("\r>%s",buffrec); } // MAIN Programa Principal /////////////////////////////////////////////// void main(void) { On_reset(); do { // Deteccion de la necesidad de procesar comandos pendientes /////// if(new_command==1){ // Si hay un nuevo comando ... new_command=0; // deshabilito el aviso y ... Procesa_comando(); // Procesado de comandos Ini_buff_rec(); // inicializo todo para nuevo comando y ... pdte_send_prompt=1; // mando prompt. } // Deteccion de la necesidad de enviar echos /////////////////////// if(pdte_send_prompt==1){ // Si esta pendiente de enviar prompt ... pdte_send_prompt=0; // marco que ya no lo está y ... Send_prompt(); // lo envío. } if(pdte_send_tmp_prompt==1){ // Si esta pendiente de enviar prompt temporal ... pdte_send_tmp_prompt=0; // marco que ya no lo está y ... Send_tmp_prompt(); // lo envío. } } while(TRUE); } // Funciones necesarias ... ////////////////////////////////////////////// int extrae_argumentos(int cuantos){ int i,c; int error=0; // Para devolver código de error si se da el caso char *ptri; char *ptrf; for(i=0;i<MAXLENARG;i++){ // Bucle que pone a 0 todos los s1[i]='\0'; // caracteres en s1 y s2 antes de extraer s2[i]='\0'; } c=1; for(i=0;i<MAXLENBUFF;i++){ // Bucle que marca los separadores " " (espacios) if(buffrec[i]==' '){ // en el buffer de recepción buffrec[i]=c++; // escribiendo 0x01 en el primero, 0x02 en el segundo ... etc. } // con lo que s1 estará entre 0x01 y 0x02 y ... } // s2 estará entre 0x02 y 0x03. if(cuantos==1){ // Si necesito dos argumentos y ... if(c!=3){ // Error: tengo menos o mas de un argumento error=1; // ya que hemos puesto un numero distinto a 2 de marcas goto retorno; // observa que para 2 marcas c vale 3 } } if(cuantos==2){ // Si necesito dos argumentos y ... if(c!=4){ // Error: tengo menos o mas de dos argumentos error=1; // ya que hemos puesto un numero distinto a 3 de marcas goto retorno; // observa que para 3 marcas c vale 4 } } ptri=strchr(buffrec,0x01); // obtengo el puntero donde aparece 0x01 ptrf=strchr(buffrec,0x02); // obtengo el puntero donde aparece 0x02 if(ptri!=0 && ptrf!=0){ // Si he encontrado 0x01 y 0x02 ptri+=1; // avanzo 1 ptri para saltarme 0x01 strncpy(s1,ptri,ptrf-ptri); // Luego s1 lo extraigo entre ptri y ptrf } if(cuantos==1){ // Si solo necesito un argumento he terminado goto retorno; } ptri=strchr(buffrec,0x02); // obtengo el puntero donde aparece 0x02 ptrf=strchr(buffrec,0x03); // obtengo el puntero donde aparece 0x03 if(ptri!=0 && ptrf!=0){ // Si he encontrado 0x01 y 0x02 ptri+=1; // avanzo 1 ptri para saltarme 0x02 strncpy(s2,ptri,ptrf-ptri); // Luego s2 lo extraigo entre ptri y ptrf } retorno: return(error); } // Procesa_comando: Hace cosas o manda hacerlas ... ////////////////////// void Procesa_comando(void){ int1 procesado_ok=0; // Flag para comprobar si he procesado algo válido char xcommand[MAXLENCOMMAND]; // Comprobador de comando recibido int error; char *ptrx; // COMANDO = "" intro en blanco --------------------------------------- strcpy(xcommand,""); if(!strcmp(buffrec,xcommand)){ procesado_ok=1; goto fin_procesa; } // COMANDO = "?" ------------------------------------------------------ strcpy(xcommand,"?"); if(!strncmp(buffrec,xcommand,strlen(xcommand))){ Send_opts(); procesado_ok=1; goto fin_procesa; } // COMANDO = "strcat" ------------------------------------------------- strcpy(xcommand,"strcat"); if(!strncmp(buffrec,xcommand,strlen(xcommand))){ error=extrae_argumentos(2); if(error!=0){ printf("\r\nError: numero erróneo de argumentos"); } else{ strcpy(sr,s1); strcat(sr,s2); printf("\r\n\n%s + %s = %s\r\n",s1,s2,sr); } procesado_ok=1; goto fin_procesa; } // COMANDO = "strlwr" ------------------------------------------------- strcpy(xcommand,"strlwr"); if(!strncmp(buffrec,xcommand,strlen(xcommand))){ error=extrae_argumentos(1); if(error!=0){ printf("\r\nError: numero erróneo de argumentos"); } else{ strcpy(sr,s1); strlwr(sr); printf("\r\n\n%s -> %s\r\n",s1,sr); } procesado_ok=1; goto fin_procesa; } // COMANDO = "strstr" ------------------------------------------------- strcpy(xcommand,"strstr"); if(!strncmp(buffrec,xcommand,strlen(xcommand))){ error=extrae_argumentos(2); if(error!=0){ printf("\r\nError: numero erróneo de argumentos"); } else{ strcpy(sr,s1); ptrx=strstr(sr,s2); if(ptrx==0){ printf("\r\n\n%s no está en %s\r\n",s2,s1); } else{ printf("\r\n\n%s empieza en el caracter %uº de %s\r\n",s2,(ptrx-&sr[0])+1,s1); } } procesado_ok=1; goto fin_procesa; } fin_procesa: // COMANDO ERRÓNEO - ¿ezo qué é lo que é ?----------------------------- if(procesado_ok==0){ printf("\r\n?%s",buffrec); } } |
||
|
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-08-2010 22:42:21