matsuo
Joined: 17 Feb 2012 Posts: 11
|
Control pulse (PWM) by PIC16F877 |
Posted: Fri Feb 17, 2012 8:21 pm |
|
|
Hello Sir.
I have been a problem about control pulse in PIC16F877 (CCS)
My problem
I need create PWM by CCP2 connect to CCP1 as your code (below code) and i need counter pulse (PWM) by CCP1.
Ex.
My condition that I need
When push down button switch and I need 250 Hz (clock) when it's 250 Hz(clock) after that PWM will stop (CCP2) unit i push down button next time
Can you help me, please. I'm sorry about my english is not well.
This code is Mr. PCM programmer (can i modify to my need ).
http://www.ccsinfo.com/forum/viewtopic.php?t=29963
Code: |
#include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
// This global variable holds the time interval
// between two consecutive rising edges of the
// input signal.
int16 isr_ccp_delta;
// When a rising edge occurs on the input signal,
// the CCP1 will 'capture' the value of Timer1
// at that moment. Shortly after that, a CCP1
// interrupt is generated and the following isr
// is called. In the isr, we read the 'captured'
// value of Timer1. We then subtract from it the
// Timer1 value that we 'captured' in the previous
// interrupt. The result is the time interval
// between two rising edges of the input signal.
// This time interval is then converted to a frequency
// value by code in main().
#int_ccp1
void ccp1_isr(void)
{
int16 current_ccp;
static int16 old_ccp = 0;
// Read the 16-bit hardware CCP1 register
current_ccp = CCP_1; // From 16F877.H file
// Calculate the time interval between the
// previous rising edge of the input waveform
// and the current rising edge. Put the result
// in a global variable, which can be read by
// code in main().
isr_ccp_delta = current_ccp - old_ccp;
// Save the current ccp value for the next pass.
old_ccp = current_ccp;
}
//=======================
void main()
{
int8 duty;
int8 pr2_value;
int16 current_ccp_delta;
int16 frequency;
// Setup the ADC so we can read a value from 0 to 255
// as we turn a trimpot which is connected to pin A0.
setup_adc_ports(AN0);
setup_adc(ADC_CLOCK_DIV_8); // Divisor for 4 MHz crystal
set_adc_channel(0);
delay_us(20);
// The CCP2 will be used in PWM mode to output a test
// signal that will be connected to the CCP1 pin.
// The test signal can be varied from 244 Hz to 2016 Hz
// by turning the trimpot on pin A0.
setup_ccp2(CCP_PWM);
// Setup Timer1 and CCP1 for Capture mode so that
// we can measure the input signal's frequency.
// The input signal comes from the CCP2 pin, which
// is connected to the CCP1 pin with a wire.
set_timer1(0);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
setup_ccp1(CCP_CAPTURE_RE);
// Clear the CCP1 interrupt flag before we enable
// CCP1 interrupts, so that we don't get an unwanted
// immediate interrupt (which might happen).
clear_interrupt(INT_CCP1);
enable_interrupts(INT_CCP1);
enable_interrupts(GLOBAL);
while(1)
{
// Read the A/D value from the trimpot.
// This is a value from 0 to 255. We limit
// it to a minimum of 30 for the purposes
// of this test program. This will limit the
// test signal to 2016 Hz maximum frequency.
pr2_value = read_adc();
if(pr2_value < 30)
pr2_value = 30;
// Configure CCP2 to put out a rectangular
// waveform with approximately a 50% duty
// cycle. The setting of the trimpot controls
// the frequency of this waveform.
setup_timer_2(T2_DIV_BY_16, pr2_value, 1);
duty = pr2_value / 2;
set_pwm2_duty(duty);
// Now calculate the frequency.
// Get a local copy of the latest ccp delta from the isr.
// We have to disable interrupts when we read a global
// isr variable that is larger than a single byte.
disable_interrupts(GLOBAL);
current_ccp_delta = isr_ccp_delta;
enable_interrupts(GLOBAL);
// To calculate the frequency of the input signal,
// we take the number of clocks that occurred
// between two consecutive edges of the input signal,
// and divide that value into the number of Timer1
// clocks per second. Since we're using a 4 MHz
// crystal, the Timer1 clock is 1 MHz (Timer1 runs
// at the instruction cycle rate, which is 1/4 of the
// crystal frequency). For example, suppose the
// the input waveform has a frequency of 244 Hz.
// 244 Hz has a period of about 4098 usec.
// Timer1 is clocked at 1 MHz, so between two
// consecutive rising edges of the input signal,
// it will count up by 4098 clocks. To find the
// frequency, we divide 4098 into the number of
// clocks that occur in 1 second, which is 1000000.
// This gives 1000000 / 4098 = 244 Hz.
frequency = (int16)(1000000L / current_ccp_delta);
// Display the calculated frequency.
printf("%lu Hz\n\r", frequency);
delay_ms(500);
}
}
|
Thanks you |
|