|
|
View previous topic :: View next topic |
Author |
Message |
timm02
Joined: 16 Jan 2008 Posts: 4 Location: Kuala Lumpur, Malaysia
|
16f877a with pwm |
Posted: Tue Feb 05, 2008 1:11 am |
|
|
hi..
i need a help to recheck my programming. i need to produce output frequency at 5kHz. the problem is when i build the pic 16f877a into circuit, the led is not blinking.
Here the code:
#include <16f877a.h> // load the header file for PIC16F877A
#include <stdlib.h>
#include <math.h>
#use delay (clock=20000000) // The oscillator frequency = 20MHz,
// System clock = Fosc/4 = 5MHz, the clock time is 0.2us
#fuses HS, NOPROTECT, NOWDT, NOLVP
#byte PORTA = 5
#byte PORTB = 6
int8 A1_pressed = FALSE;
void main()
{
set_tris_a(0xff); // Set PORT A as inputs
set_tris_b(0x00); // Set PORT B as outputs
PORTB=0; // Initialize all PORT B output to 0 volt
output_low(PIN_B1); // Set CCP1 output low
setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM
while(TRUE) // sama dgn while ( 1== 1) - loop forever
{
if(A1_pressed == TRUE) // sama dgn while (0 == A4_pressed)
{
output_high(PIN_B5); // LED turn ON
setup_timer_2(T2_DIV_BY_4, 249, 1); ///////////////////////////////////////////////////
// 5 kHz //
// period = Fosc/(Fpwm*4*T2DIV)-1 //
// >> setup_timer_2(T2_DIV_BY_X,period,1); //
// //
// value = (duty_cycle% * Fosc)/(Fpwm*4*T2DIV) //
// >> set_pwm1_duty(value); //
// //
///////////////////////////////////////////////////
set_pwm1_duty(50); // 50% duty cycle on pin B1
delay_ms(2000); // delay 2 second
}
else
{
output_low(PIN_B5); // LED turns OFF
delay_ms(1500); // delay for 1.5 seconds
}
}
} |
|
|
Ttelmah Guest
|
|
Posted: Tue Feb 05, 2008 3:26 am |
|
|
First, edit your post, use the 'code' buttons, and disable HTML. As it stands, large amounts of the code are 'lost', because they are seen as HTML, and scrambled on the display.....
Second minor comment. Your duty cycle calculation is 'wrong'. With a maximum count on the timer of 249, the 50% duty cycle 'value', will be half this. 50, will only give a 20% duty cycle.
Your TRIS statements are basically 'pointless'. Because you are not specifying 'fast_io', the compiler will be automatically controlling the TRIS, so as soon as you output a byte to port B, the tris will be set to 'output'. The extra lines won't cause any problems, but aren't really doing anything...
With the code as shown, how can 'A1_pressed', _ever_ become true?. You have declared a variable, set it to false, and nowhere is it ever set true...
As such the PWM, will never turn on.
Best Wishes |
|
|
timm02
Joined: 16 Jan 2008 Posts: 4 Location: Kuala Lumpur, Malaysia
|
fast_io |
Posted: Tue Feb 05, 2008 9:29 am |
|
|
i do make mistake as i put 50 for pwm value, i've corrected the code by replacing it to 125 as 50% from duty cycle.
but i'm a bit confusing about fast_io. do you mean that i need not to set tris in my code?
Code: |
#include <16f877a.h>
#include <stdlib.h>
#include <math.h>
#use delay (clock=20000000)
#fuses HS, NOPROTECT, NOWDT, NOLVP
#byte PORTA = 5
#byte PORTB = 6
int8 A1_pressed = TRUE;
void main()
{
set_tris_a(0xff);
set_tris_b(0x00);
PORTB=0;
output_low(PIN_B1);
setup_ccp1(CCP_PWM);
while(TRUE)
{
if(A1_pressed == TRUE)
{
output_high(PIN_B5); // LED turn ON
setup_timer_2(T2_DIV_BY_4, 249, 1); // 5 kHz
set_pwm1_duty(125); // 50% duty cycle on pin B1
delay_ms(2000); // delay 2 second
}
else
{
output_low(PIN_B5); // LED turns OFF
delay_ms(1500); // delay for 1.5 seconds
}
}
}
|
|
|
|
Wayne_
Joined: 10 Oct 2007 Posts: 681
|
|
Posted: Wed Feb 06, 2008 2:32 am |
|
|
With regards to the set_tris. At the moment you do need to put this for port B because you have the line PORTB=0;
If you used the function output_b(0); instead then you do NOT need the set_tris instructions. The reason is, if you do NOT specify fast_io on your ports then when you call a CCS function to output/input to/from a port then the compiler will automatically insert set_tris instructions to set the ports acordingly. So if you had output_low(PIN_B1); the compiler will put a set_tris instruction just before this to set B1 as an output.
But if you access the ports directly then the compiler is not clever enough to work out which direction the port pin should be set to so leaves that up to you. Also, if you specify #use fast_io(B) then the compiler will NOT insert the set_tris instructions.
You would use this if you wanted to increase the speed slightly by not having the extra code before every port access, if your port directions never changed or you just needed to know exactly what was happening.
You still have not shown how the variable A1_pressed can change to be TRUE and then back to FALSE ?
Is this via an interrupt ? If so where is your interrupt handler/code. |
|
|
timm02
Joined: 16 Jan 2008 Posts: 4 Location: Kuala Lumpur, Malaysia
|
|
Posted: Mon Feb 11, 2008 2:54 am |
|
|
I've do changes to my code, and hopefully it is right.
I've put the #use fast_io and change the variable A1_pressed to be TRUE, actually the pin A1 is on-off button.
Here is the new code:
Code: | #use fast_io(A)
#use fast_io(B)
int8 A1_pressed = TRUE;
void main()
{
set_tris_A(0xFF);
set_tris_B(0x00);
PORTB=0;
output_low(PIN_B1); // Set CCP1 output low
setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM
while(TRUE)
{
if(A1_pressed == TRUE)
{
output_high(PIN_B5); // LED turn ON
setup_timer_2(T2_DIV_BY_4, 249, 1);
set_pwm1_duty(125); // 50% duty cycle on pin B1
delay_ms(2000); // delay 2 second
}
else
{
output_low(PIN_B5); // LED turns OFF
delay_ms(1500); // delay for 1.5 seconds
}
}
} |
|
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|