TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: man3s en 29 de Abril de 2012, 12:53:14
-
Hola amigos de TodoPic, pues ando en un proyectillo y se me ha presentado un inconveniente que realmente no me esperaba :D, al intentar usar dos interrupciones de timer, timer0 y timer2, y al simularlo en proteus me encuentro con que solo una interrupcion se cumple, en este caso la interrupcion por Timer0, he de suponer que es por cuestiones de prioridad, habra manera de que ambas interrupciones trabajen ligeramente desfasadas, es un pwm para un motor donde la exactitud es primordial, les dejo el codigo :-):
#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOMCLR
#use delay(clock=48000000)
int x;
int y;
#int_timer0
void interrupcion_timer0(){
set_timer0(208);
x++;
if(x <= 20)
{
if(x <= 10){
output_high(PIN_C1);
}else{
output_low(PIN_C1);
}
}else{
x = 0;
}
}
#int_timer2
void interrupcion_timer2(){
set_timer2(12);
y++;
if(y <= 20)
{
if(y <= 10){
output_high(PIN_C2);
}else{
output_low(PIN_C2);
}
}else{
y = 0;
}
}
void main()
{
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1|RTCC_8_BIT);
setup_timer_1(T1_DISABLED|T1_DIV_BY_1);
setup_timer_2(T2_DIV_BY_16,150,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(int_timer0);
enable_interrupts(int_timer2);
enable_interrupts(global);
set_timer0(208);
set_timer2(12);
for(;;){
}
}
Intente darle solucion de la siguiente manera, pero el desfasamiento es notable:
#int_timer0
void interrupcion_timer0(){
set_timer0(208);
x++;
if(x <= 20)
{
if(x <= 10){
output_high(PIN_C1);
}else{
output_low(PIN_C1);
}
}else{
x = 0;
disable_interrupts(int_timer0);
enable_interrupts(int_timer2);
}
}
#int_timer2
void interrupcion_timer2(){
set_timer2(12);
y++;
if(y <= 20)
{
if(y <= 10){
output_high(PIN_C2);
}else{
output_low(PIN_C2);
}
}else{
y = 0;
disable_interrupts(int_timer2);
enable_interrupts(int_timer0);
}
}
Espero alguien pueda ayudarme, aclaro que lo hago con timer porque los ccp no me han funcionado, no me dan el duty correcto. Saludos :-).
-
El ccp te da el ciclo de trabajo incorrecto porque lo implementas mal! Te conviene solucionar ese caso me parece... Utiliza el buscador de como calcular PWM y configurarlo en CCS ;-)
-
tu timer 2 lo configuras con un periodo de 0, entonces tu timer se esta reseteando siempre por eso no vez la interrupcion. porque no usas el pwm por software?
-
Valla que rapido contestan :shock: , eso me agrada :D, bueno he visto el error que me mencionas y efectivamente estoy cargando mal el timer 2, ahora lo tengo de la siguiente manera:
Para obtener una frecuencia de 5KHz y a un duty de 50% y aplicando la formula:
TPWM = (1/clock)*4*divisor*precarga
TPWM = (1/48MHz)*4*16*150 = me da un periodo de 200uS
f = 1/T entonces 1/200us = 5Khz que es justo lo que necesito
entonces configuro el timer de la siguiente manera:
setup_timer_2(T2_DIV_BY_16,150,1);
SETUP_CCP1(CCP_PWM);
SET_PWM1_DUTY(50);
Pero al simularlo en Proteus v7.7 el osciloscopio me da efectivamente la frecuencia pero el duty me da del 35 % solamente, y al no tener conocimientos del ccp asi que opte por hacerlo con timer, pero aun asi me surgio el problemas de las interrupciones pararelas :D.
¿Algo ando haciendo mal?, saludos
-
El ciclo de trabajo lo cambiarias dentro de tu interrupcion, cambiando tu contador, para que sea 50% tendrias que contar el mismo numero de interrupciones prendido y apagado, tambien estas precargando el timer cada que entras a la interrupcion, checa si ese valor es correcto.
De todas formas te aconsejo usar el pwm por software, es mas facil que hacerlo por interrupciones. Busca en el foro
-
SET_PWM1_DUTY(50);
Porque colocas 50? Leiste la ayuda de CCS para esa función? Que parámetro recibe?
-
SET_PWM1_DUTY(50);
Porque colocas 50? Leiste la ayuda de CCS para esa función? Que parámetro recibe?
como dice suky
el valor maximo que recibe esa funcion es 1023, no esta en porcentaje, y es para el pwm por sftware
-
aaaa okeey :lol: pense q era porcentual pero recibe una variable int16 :D que tonto he sido, pero bueno, creo ahora queda por mi cuenta establecer cual sera el parametro correcto para lograr el 50% de duty, gracias por la ayuda ruky && rivale, creo tendre que darle una leida a la ayuda, pero bueno, entonces creo puedo concluir no es posible que dos interrupciones de timer al mismo tiempo, las razones las desconozco, pero si alguien pudiese darme una respuesta se los agradeceria que al fin y al cabo el tema lo cree por la duda de las interrupciones mas no por el pwm, saludos.
-
Si se pueden tener 2 interrupciones activas al mismo tiempo, el problema era el como tenias configurado tu timer 2
-
Caso cerrado :D . Bravo ((:-)), Gracias por la ayuda amigos, suerte y exito.
-
SET_PWM1_DUTY(50);
Porque colocas 50? Leiste la ayuda de CCS para esa función? Que parámetro recibe?
como dice suky
el valor maximo que recibe esa funcion es 1023, no esta en porcentaje, y es para el pwm por sftware
Por hardware sera ;-)
-
SET_PWM1_DUTY(50);
Porque colocas 50? Leiste la ayuda de CCS para esa función? Que parámetro recibe?
como dice suky
el valor maximo que recibe esa funcion es 1023, no esta en porcentaje, y es para el pwm por sftware
Por hardware sera ;-)
:oops: :oops: :oops: cierto, es por hardware
-
Como dato ya me ha funcionado, he aplicado la formula Duty cycle = value*(1/clock)*t2div donde value es el valor que va en SET_PWM1_DUTY(value) y obteniendo un valor de 300, se ha generado el duty al 50% y una frecuencia de 5kHz :-) . Gracias a ustedes ya se usar el ccp en modo pwm :D, thnks.