I am trying to program with the PIC18F4550 a PWM with which I can regulate the duty-cycle with a variable resistance.
I attach my code to explain the problem I have.
#pragma config CPUDIV = OSC1_PLL2
#pragma config USBDIV = 1
#pragma config FOSC = HS
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config PWRT = OFF
#pragma config BOR = OFF
#pragma config BORV = 3
#pragma config VREGEN = OFF
#pragma config WDT = OFF
#pragma config WDTPS = 32768
#pragma config CCP2MX = ON
#pragma config PBADEN = ON
#pragma config LPT1OSC = OFF
#pragma config MCLRE = ON
#pragma config STVREN = ON
#pragma config LVP = ON
#pragma config ICPRT = OFF
#pragma config XINST = OFF
#pragma config CP0 = OFF
#pragma config CP1 = OFF
#pragma config CP2 = OFF
#pragma config CP3 = OFF
#pragma config CPB = OFF
#pragma config CPD = OFF
#pragma config WRT0 = OFF
#pragma config WRT1 = OFF
#pragma config WRT2 = OFF
#pragma config WRT3 = OFF
#pragma config WRTC = OFF
#pragma config WRTB = OFF
#pragma config WRTD = OFF
#pragma config EBTR0 = OFF
#pragma config EBTR1 = OFF
#pragma config EBTR2 = OFF
#pragma config EBTR3 = OFF
#pragma config EBTRB = OFF
#include <xc.h>
#define _XTAL_FREQ 20000000L
void ADC_Initialize()
{
ADCON1bits.PCFG = 0;
ADCON1bits.VCFG = 0;
ADCON0 = 0;
ADCON2bits.ACQT = 3;
ADCON2bits.ADCS = 5;
ADCON2bits.ADFM = 1;
ADCON0bits.ADON = 1;
}
unsigned int ADC_Read(unsigned char channel)
{
ADCON0 &= 0x11000101;
ADCON0 |= channel<<3;
__delay_ms(2);
GO_nDONE = 1;
while(GO_nDONE);
return ((ADRESH<<8)+ADRESL);
}
#define TMR2PRESCALE 16
long PWM_freq = 8000;
void PWM_Initialize()
{
PR2 = 0x26;
CCPR1L = 1;
TRISCbits.RC1 = 0;
TRISCbits.RC2 = 0;
T2CON = 0x03;
CCP1CON = 0x0C;
TMR2 = 0;
T2CONbits.TMR2ON = 1;
}
void PWM_Duty(unsigned int duty)
{
if(duty<1023)
{
duty = ((float)duty/1023)*(_XTAL_FREQ/(PWM_freq*TMR2PRESCALE));
CCPR1L = duty>>2;
}
}
void main()
{
int adc_value;
TRISC = 0;
TRISA = 1;
TRISD = 0;
ADC_Initialize();
PWM_Initialize();
do
{
adc_value = ADC_Read(4);
PWM_Duty(adc_value);
__delay_ms(50);
}while(1);
}
If I execute the above code, what I have at the output of the PWM are 0v and a frequency 0. As shown in the following image
If in the fixed code the value of the PWM Duty (580), for example.
Then I stop running the analog input.
So it seems that the PWM signal is regulated and I have a voltage at the output.
As I show in the following image.
What I do not understand is that in neither of the 2 cases the frequency is 0, when it should be approximately 8000Hz.
On the other hand I see that if I set the duty_cycle it seems that it regulates and gives voltage to the output.
So there must be a fault in the part of the analog input that I have not been able to find.
Finally, I leave a picture of the circuit.
1 Answer 1
With the following code I could make it work
#define TMR2PRESCALE 16
long PWM_freq = 8000;
void PWM_Initialize()
{
PR2 = ("%#x", (_XTAL_FREQ/(PWM_freq*4*TMR2PRESCALE)) - 1); //Setting the PR2 formulae using Datasheet
CCPR1L = 0x1F;
TRISCbits.RC1 = 0;
TRISCbits.RC2 = 0;
T2CON = 0x03;
CCP1CON = 0x0C;
TMR2 = 0;
T2CONbits.TMR2ON = 1;
}
void PWM_Duty(unsigned int duty)
{
if(duty < 1023)
{
duty = ((float)duty/1023)*(_XTAL_FREQ/(PWM_freq*TMR2PRESCALE));
CCPR1L = duty>>2;
}
}
void ADC_Initialize()
{
ADCON1bits.PCFG = 0;
ADCON1bits.VCFG = 0;
ADCON0 = 0;
ADCON2bits.ACQT = 3;
ADCON2bits.ADCS = 5;
ADCON2bits.ADFM = 1;
ADCON0bits.ADON = 1;
}
unsigned int ADC_Read(unsigned char ch)
{
if(ch > 13)return 0;
ADCON0 = 0;
ADCON0 = (ch<<2);
ADCON0bits.ADON = 1;
ADCON0bits.GO_DONE = 1;
while(ADCON0bits.GO_DONE == 1);
ADCON0bits.ADON = 0;
return ADRES;
}
void main()
{
int adc_value;
TRISC = 0;
TRISA = 1;
TRISD = 0;
ADC_Initialize();
PWM_Initialize();
do
{
adc_value = ADC_Read(0);
PWM_Duty(adc_value);
__delay_ms(50);
}
while(1); //Infinite Loop
}
Explore related questions
See similar questions with these tags.
PR = 0x26
that don't make any sense for me. Another case: Why the cast tofloat
? \$\endgroup\$duty = ((float)duty/1023)*(_XTAL_FREQ/(PWM_freq*TMR2PRESCALE));
This part is also wrong. JustCCPR1L = duty>>2;
.Have a look into the datasheet. \$\endgroup\$