View previous topic :: View next topic |
Author |
Message |
takumi
Joined: 07 Mar 2009 Posts: 14
|
PWM_help please |
Posted: Wed Mar 18, 2009 8:18 pm |
|
|
hi all,
I try to generate pwm to pulse my led, but my the pwm does not work as I want. Please help me... I have simulate it in proteus but the duty only 100us not 200us as needed.
pwm period = 1250Hz = 800us
desired duty cyles 25% = 200us
PIC16F877A, XTAL=20Mhz
Code: |
void main()
{
float duty;
long value_adc;
int adc_lsb, adc_msb;
unsigned long i;
//initialize
setup_adc_ports(ALL_ANALOG);
setup_adc(ADC_CLOCK_DIV_32);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_16, 249,1);
duty = 62;
set_pwm1_duty(duty);
do{
set_adc_channel(0);
for(i=0;i<10000;i++){
value_adc = read_adc();
adc_lsb = value_adc;
adc_msb = (value_adc<<6)>>14;
printf("%Lu,%2X%2X \r\n",i,adc_msb,adc_lsb);
// delay_ms(20);
}
}while(1);
} |
btw do I need delay after adc? and will delay disturb my PWM duty?
please help |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Mar 18, 2009 9:24 pm |
|
|
Quote: | float duty;
duty = 62;
set_pwm1_duty(duty); |
You have declared the duty cycle as a 'float'.
The CCS manual says this:
Quote: | Syntax: set_pwm1_duty (value)
Parameters: value may be an 8 or 16 bit constant or variable. |
|
|
|
takumi
Joined: 07 Mar 2009 Posts: 14
|
|
Posted: Wed Mar 18, 2009 10:10 pm |
|
|
PCM programmer wrote: | Quote: | float duty;
duty = 62;
set_pwm1_duty(duty); |
You have declared the duty cycle as a 'float'.
The CCS manual says this:
Quote: | Syntax: set_pwm1_duty (value)
Parameters: value may be an 8 or 16 bit constant or variable. |
|
thanks I have change it and it works :) ...
btw how about the delay after send adc? will it effect my pwm? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Mar 18, 2009 10:18 pm |
|
|
The pwm hardware module runs independently of any delays in your code. It's not affected. |
|
|
takumi
Joined: 07 Mar 2009 Posts: 14
|
|
Posted: Thu Mar 19, 2009 6:09 am |
|
|
how about this
pwm1 i already create the pwm 200us(on)600us(off)
is it posible to create pwm2 that 400us(off)200us(on)200us(off)?
setup_ccp1(CCP_PWM);
setup_ccp2(CCP_PWM);
setup_timer_2(T2_DIV_BY_16, 249,1);
set_pwm1_duty(64);
delay_us(400); <will this delay effect my a2d?
set_pwm2_duty(64); |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Mar 19, 2009 11:07 am |
|
|
Quote: | pwm1 i already create the pwm 200us(on)600us(off)
is it posible to create pwm2 that 400us(off)200us(on)200us(off)? |
There is no phase shift ability between PWM channels 1 and 2.
Quote: | delay_us(400); <will this delay effect my a2d? |
The A/D is a separate hardware module. It can acquire and capture
the A/D signal in a few microseconds. A delay_us(400) statement farther
along in your program after the read_adc() statement does not affect
the A/D. |
|
|
takumi
Joined: 07 Mar 2009 Posts: 14
|
|
Posted: Fri Mar 20, 2009 12:54 pm |
|
|
I have created a pwm as below:
Code: | void pwm(){
output_high(pin_d2);
output_low(pin_b4);
delay_us(70);
output_low(pin_d2);
output_low(pin_b4);
delay_us(430);
output_low(pin_d2);
output_high(pin_b4);
delay_us(70);
output_low(pin_d2);
output_low(pin_b4);
delay_us(430);
} |
and then run it along with my adc_read();
Code: |
void main(){
set_adc_channel(0);
delay_us(20);
while(1){
for(i=0;i<1000;i++){
pwm();
value_adc = read_adc();
adc_lsb = value_adc;
adc_msb = (value_adc<<6)>>14;
printf("%Lu,%2X%2X \r\n",i,adc_msb,adc_lsb);
delay_us(200);
}
}
|
I found that the delay_us(200) < affect my pwm. Is there any possible way to create a difference phase of pwm that will on while mcu on as CCP1?
Btw since I used 20MHz clock and my adc tdiv = 32,
how would be my best delay between reading the adc.
I have read from the PIC16f877A datasheet that TAD = (1/Clock)*32=1.6us
and for 10bit req 12TAD = 1.6ux12 = 19.2us
and there is TACQ = 19.72us
Would it be 12TAD + TACQ = 38.92us ~~ 40us is the best delay between my reading?
how about the the buffer of tx/rx to when i printf to it.... |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Mar 20, 2009 1:16 pm |
|
|
Of course it affects your pwm. In your original question, you were
using the hardware PWM module. Now in your latest code you are
using software PWM done by delay statements. Any delays
in your main loop will add to the delays in your software PWM. |
|
|
takumi
Joined: 07 Mar 2009 Posts: 14
|
|
Posted: Sun Mar 22, 2009 11:18 pm |
|
|
hi all,
PIC16f877A, 20MHz
Need help "please" since hardware pwm cannot be use in my application.
I used software pwm but not get the result as I want.
I want to have a pwm dual pulse at freq=40KHz and duty cycle 50%
that mean 12.5us on and 12.5us off 12.5us on and 12.5us off and then
delay 10ms before it start pulse again.
Code: |
for(;;){
//first period
output_high(pin_b1);
delay_us(12.5);
output_low(pin_b1);
delay_us(12.5);
//second period
output_high(pin_b1);
delay_us(12.5);
output_low(pin_b1);
delay_us(12.5);
delay_ms(10);
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Mar 22, 2009 11:49 pm |
|
|
Quote: | PIC16f877A, 20MHz
output_high(pin_b1);
delay_us(12.5);
output_low(pin_b1);
delay_us(12.5);
|
Download the CCS manual.
http://www.ccsinfo.com/downloads/ccs_c_manual.pdf
Look in the section on delay_us():
Quote: | delay_us( )
Syntax: delay_us (time)
Parameters: time - a variable 0-65535(int16) or a constant 0-65535 |
You can't use "12.5" for the delay time. It can be 11, 12 or 13. If you
want to use smaller time periods (less than 1 us), then add a line for
delay_cycles(). Also, the output_low() statement will take 4 cycles (if
you are using standard i/o mode). At 20 MHz, there are 5 cycles in 1 us.
Use this information to calculate the correct delay times. |
|
|
|