TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: Agustina en 31 de Marzo de 2008, 20:52:19

Título: PWM! me tiene LOCA!
Publicado por: Agustina en 31 de Marzo de 2008, 20:52:19
HOLA A TODOS!!

estoy intentando hacer andar el PWM de un 16F88 pero no hay caso... he probado de mil formas. Necesito generar una onda cuadrada de 40khz, simplemente eso! y nada.... se que lo he hecho antes pero no recuerdo como, alguien me podria ayudar?

asi es como tengo configurado al micro:

set_tris_a (0b00111001);   //Ra7-Ra6-Ra5-Ra4-Ra3-Ra2-Ra1-Ra0
set_tris_b (0b00000100);   //Rb7-Rb6-Rb5-Rb4-Rb3-Rb2-Rb1-Rb0
SETUP_CCP1(CCP_OFF);
setup_adc_ports(sAN0);
setup_adc(ADC_CLOCK_INTERNAL);

OUTPUT_B(1);
OUTPUT_A(1);

setup_counters( RTCC_INTERNAL, RTCC_DIV_4 | RTCC_8_BIT);

SETUP_CCP1(CCP_PWM); //Modo PWM para el CCP1
setup_timer_2(T2_DIV_BY_1,114,1);     
SET_PWM1_DUTY(40);


enable_interrupts(global);
enable_interrupts(int_rtcc);
enable_interrupts(int_rda);
set_rtcc(0);

muchas gracias!  :g)
Título: Re: PWM! me tiene LOCA!
Publicado por: micro_cadaver en 01 de Abril de 2008, 02:08:54
tienes que leer el datasheet amiga. saludos. si tienes mas dudas no dudes en postear (que ?)

Código: C
  1. #include <16f88.h>
  2. #use delay(clock=4000000)
  3.  
  4.  
  5. void main()
  6. {
  7.    set_tris_a (0b00111001);   //Ra7-Ra6-Ra5-Ra4-Ra3-Ra2-Ra1-Ra0
  8.    set_tris_b (0b00000100);   //Rb7-Rb6-Rb5-Rb4-Rb3-Rb2-Rb1-Rb0
  9.    SETUP_CCP1(CCP_OFF);
  10.    setup_adc_ports(sAN0);
  11.    setup_adc(ADC_CLOCK_INTERNAL);
  12.    
  13.    OUTPUT_B(1);
  14.    OUTPUT_A(1);
  15.    
  16.    setup_counters( RTCC_INTERNAL, RTCC_DIV_4 | RTCC_8_BIT);
  17.    
  18.    SETUP_CCP1(CCP_PWM); //Modo PWM para el CCP1
  19.  
  20.    //para obtener 40khz con 4Mhz, 50% desde el timer 2 con pwm
  21.    //
  22.    //formula:  periodo = (PR2+1)* 4 * Tosc * (prescaler tmr2)
  23.    //          0.000025 = (PR2+1) * 1/1000 000 * 1
  24.    //PR2 = 24
  25.    //
  26.    setup_timer_2(T2_DIV_BY_1,24,1);    
  27.    //el timer2 tendra un multiplicador por 1 de preeescaler,
  28.    //su periodo de reseteo (PR2) sera en el valor 24,
  29.    //el postcale no se usa en pwm lo dejamos en 1 .
  30.    
  31.    SET_PWM1_DUTY(12);
  32.    // 50% del periodo  =  duty * 4 * tosc * tmr2 preescaler
  33.    // 0.0000125 = duty * 1/1000000 * 1
  34.    // duty = 12.5
  35.    
  36.    
  37. //   enable_interrupts(global);
  38. //   enable_interrupts(int_rtcc);
  39. //   enable_interrupts(int_rda);
  40.    set_rtcc(0);
  41.    
  42.    while(1);
  43. }

(http://img507.imageshack.us/img507/5733/38944230mq4.jpg)
Título: Re: PWM! me tiene LOCA!
Publicado por: Agustina en 01 de Abril de 2008, 02:58:38
Gracias por la respuesta, pero no esoty usando un clock de 4mhz. La frecuencia y el duty cicle en mi ejemplo son valores diferentes ya que queria probar si andaba primero con cualquier frecuenta.

Probe tu codigo en el pic pero tampoco genera una onda...

de hecho, probe con un 16f628A y anda perfectamente, pero con el F88 no...  :?
Título: Re: PWM! me tiene LOCA!
Publicado por: Agustina en 01 de Abril de 2008, 04:29:46
LISTO! :-/

agregue en los fuses "CCPB3"....

porque? no lo se... pero comenzo a funcionar luego de hacer eso. alguien sabe que funcion cumple el fuse CCPB3?

gracias
Título: Re: PWM! me tiene LOCA!
Publicado por: Nocturno en 01 de Abril de 2008, 05:28:52
Lo explica en la página 130 de la datasheet:
bit 12 CCPMX: CCP1 Pin Selection bit
1 = CCP1 function on RB0
0 = CCP1 function on RB3
Título: Re: PWM! me tiene LOCA!
Publicado por: micro_cadaver en 01 de Abril de 2008, 12:48:15
por eso a leer bien el datasheet  :mrgreen:
Título: Re: PWM! me tiene LOCA!
Publicado por: Agustina en 09 de Abril de 2008, 19:58:58
A veces a una se le escapan cosas  :mrgreen:

Título: Re: PWM! me tiene LOCA!
Publicado por: scientist en 10 de Abril de 2008, 01:16:42
aprovecho este hilo para hacer una pregunta, y es que no logro entender la formula que da el datasheet para calcular el duty cycle,este es:
PWM Duty Cycle =(CCPR1L:CCP1CON<5:4>) •TOSC • (TMR2 Prescale Value)
 y no logro entenderlo por los registros ccpr1L y ccp1con y que quiere decir <5:4>,ya he hecho varios programas de pwm,pero nunca lo hago calculando un duty cycle en concreto, por favor despejen esta duda
Título: Re: PWM! me tiene LOCA!
Publicado por: LuNaTk en 10 de Abril de 2008, 01:39:53
Significa que para calcularlo se toma en cuenta los bits 5 y 4 del registro CCP1CON como los menos significativos (en ese orden) y el registro CCPR1L como el mas significativo       

     
CCPR1L                                   | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |                 
CCP1CON                                                                            | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |
                                                \/     \/     \/     \/     \/     \/     \/     \/    \/    \/                 
( CCPR1L:CCP1CON<5:4>)      | B9 | B8 | B7 | B6 | B5 | B4 | B3 | B2 | B1 | B0 |   
Título: Re: PWM! me tiene LOCA!
Publicado por: Nocturno en 10 de Abril de 2008, 01:46:23
(Cuando lo tenía escrito se ha colado delante la respuesta de LuNaTk)

El duty cicle es un valor que se calcula con una resolución de 10 bits. Como los registros no tienen más de 8 bits, el PIC utiliza 8 bits de un registro + 2 bits de otro registro como un único operador.
De esta manera, los 8 bits más significativos serán los que hayas puesto en CCPR1L y los 2 bits menos significativos serán el bit nº 5 y el bit nº 4 de CCP1CON.

Si estás hablando de un 16F esos registros están en:
CCPR1L 0x15
CCP1CON 0x17

Suerte

Título: Re: PWM! me tiene LOCA!
Publicado por: scientist en 10 de Abril de 2008, 02:01:56
gracias LuNaTk paisano, jejeje, y como siempre al profe Nocturno, al que considero un amigo lejano(por distancia), ya despeje mis dudas gracias al buen micro_cadaver,  la formula para el que la quiera, asi es

registro de 10 bits=(xtal*Tdepwm(el que se necesite))/4
Título: Re: PWM! me tiene LOCA!
Publicado por: pocher en 10 de Abril de 2008, 09:53:49
Solo una cosa más que todavía no ha salido y es importante.

Si se va a usar una resolución de 8 bits, la variable para el Duty hay que declararla como int y la fórmula para el cálculo de CCPR1L es:

CCPR1L=Duty/(4·Tosc·TMR2prees) ---> con el 4

Si se va a usar una resolución de 10 bits, la variable para el Duty hay que declararla como long y la fórmula para el cálculo de CCPR1L es:

CCPR1L=Duty/(Tosc·TMR2prees) ---> sin el 4

La fórmula para el cálculo de PR2 es la misma en los 2 casos:

PR2=(T/(4·Tosc·TMR2prees))-1

Un saludo

Título: Re: PWM! me tiene LOCA!
Publicado por: Nocturno en 10 de Abril de 2008, 12:13:49
Curiosa forma de verlo  :-/ , yo siempre lo habría convertido a 10 bits añadiéndole dos bit '0' por la derecha.
Título: Re: PWM! me tiene LOCA!
Publicado por: Tho0oR en 07 de Junio de 2008, 07:17:07
Holaa!!

Soy nuevo en esto de programar en C para pics.

ya tengo hechos algunos ejercios muy basicos y me empieza a gustar esto. Ahora me quiero meter con el PWM. Si os soy sincero, he querido ponerme a ello pero no he sabido ni empezar.

Alguien me podria dar un enlace, o explicar, cuales son los pasos para hacer un ejercicio, la configuracion, como se calcula, porque leo las formulas... pero nose como ponerlas en el lenguaje C... soy un ignorante, espero que me perdoneis.

Por ejemplo, como puedo hacer para que pueda variar el "duty cycle" entre 0ms y 3ms?... pongamos de una señal de 3ms de periodo?

Gracias de antemano!!
Título: Re: PWM! me tiene LOCA!
Publicado por: scientist en 08 de Junio de 2008, 20:00:13
pues la frecuencia que quieres la calculas desde el timer 2 , en el data esta, por suerte y sino mal me acuerdo, la frecuencia que deseas si alcanza a llegar para el mudulo de pwm, esto lo digo, sacando el pwm por hardware, aqui esta el ejemplo

setup_timer_2(T2_DIV_BY_8,0x4F,1);

en donde le dices que tu preescaler es divisible entre 8, y el conteo empezara de 0x00 hasta 0x4F, y solo un desbordamiento necesitara para hacer una interrupcion, aqui puedes hacer los calculos, aunque te recomiendo un programita que hice el maestro Redpic que te evita hacer todo esos calculos, visita su pagina y descargalo, ahora para hacer variar el ancho de pulso se hace con la funcion pwm duty, aqui pongo un ejemplito para hacerlo variar por el valor analogico, aunque puedes usar las formulas arriba mencionadas

Código: [Seleccionar]
long duty;

int grados_temperatura;


void toma_adc(void){
set_adc_channel(0);
delay_ms(1);
duty= read_adc();
delay_ms(1);
grados_temperatura = (int) ((duty * 391) / 1000);
printf("L = %u T = %u \n",duty,grados_temperatura);
}

void main()
{

   setup_adc_ports(RA0_RA1_ANALOG_RA3_REF);
   setup_adc(ADC_CLOCK_INTERNAL);
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DIV_BY_8,0x4F,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(TRUE);
   setup_ccp1(CCP_PWM);
   set_tris_a(0xFF);
   
   // TODO: USER CODE!!

   do{
   toma_adc();
   output_b(duty);
   set_pwm1_duty(duty);
   
   }while(true);

}

puedes usar long o int, depende, como ya explico previamente el el amigo pocher. saludos