Wanted to generate PWM pulses using IC16F87XA - Page 1
Forum section: electronics / beginners

author: khatus
author_rank: Regular Contributor
timestamp: April 07, 2020, 06:24:37 pm
content: Hello guys I wanted to generate 4.9kHZ Pwm using Pic micro controller with out using in build functions.I am using PIC16F87XA mcu this time .Here is my codeCode:void main(){PR2=0x65; // Frequency: 4.90 kHzCCP1CON=0b00001100; //Configure the CCP1 moduleT2CON.T2CKPS0 = 1;T2CON.T2CKPS1 = 0;TRISC.B2 = 0; // make port pin on C as outputwhile(T2CON.TMR2ON = 1) //Infinite Loop{}}Here is the steps that i have followedBUT while simulating it in proteus i did not get any result from RC2 PIN(CCP1 pin of PC microcontroller) i did not get any pulse from the pin.What is the problem??

author: MarkF
author_rank: Super Contributor
timestamp: April 07, 2020, 07:26:24 pm
content: I have setup PWM on a pic18F2550 and here is some code for a pic16F877A (I don't remember if I tested the PIC16 code):Code:// PWM token...// buffer == Prescalar (0 = Turn Off PWM Mode)// buffer == PR2// buffer == CCPR1L (Duty Cycle)case FT_PWM:T2CON=buffer; // Timer2 Control Regif (buffer==0) {CCP1CON=0; // PWM OffTRISCbits.TRISC2=1; // Pin as Input} else {PR2=buffer; // PWM PeriodCCPR1L=buffer; // Duty Cycle MSBsCCP1CON=0x0c; // PWM On & Duty Cycle LSBsTRISCbits.TRISC2=0; // Pin as Output}break;I noticed in your code your TRIS direction code is wrong.You are mixing PortB and PortC.Code:TRISC.B2 = 0; // make port pin on C as outputShould be:Code:TRISCbits.TRISC2=0; // Pin as Output

author: khatus
author_rank: Regular Contributor
timestamp: April 07, 2020, 07:54:27 pm
content: Can you show something simpler .I am newbie.

author: chayanforyou
author_rank: Newbie
timestamp: April 08, 2020, 02:17:21 am
content: Here You Go.Code:/*PWM Generation 4.88KHz********************************Compiler: mikroC Pro for PICForPIC 16F877A @ 20MHzCONFIG:$2007 : 0x2F42Copyright (c) 2020Chayan Mistry*/// --- Function for Setting PWM Duty Cycle ---void SetPWMDutyCycle(unsigned int DutyCycle) // Give a value in between 0 and 1024 for DutyCycle{CCPR1L = DutyCycle>>2; // Put MSB 8 bits in CCPR1LCCP1CON &= 0xCF; // Make bit4 and 5 zeroCCP1CON |= (0x30&(DutyCycle<<4)); // Assign Last 2 LSBs to CCP1CON}// --- Main Function ---void main(){TRISC.B2 = 0; // Make CCP1 pin as outputCCP1CON = 0x0C; // Configure CCP1 module in PWM modePR2 = 0xFF; // Configure the Timer2 periodT2CON = 0x01; // Set Prescaler to be 4, hence PWM frequency is set to 4.88KHz.SetPWMDutyCycle(512); // Intialize the PWM to 50% duty cycleT2CON |= 0x04; // Enable the Timer2, hence enable the PWM.while (1) //Infinite loop{} //end while} //end main

author: khatus
author_rank: Regular Contributor
timestamp: April 08, 2020, 05:08:06 am
content: Thanks

author: khatus
author_rank: Regular Contributor
timestamp: April 08, 2020, 07:47:29 am
content: Here is my code This time i wanted to vary pwm signal according to a potentiometer connected at pin A1.Here is my code for mikroc.But THe pwm signal did not vary according to the adc value.Code:void PWM_Init(unsigned char period){TRISC &=0xFD; // Set RC2 as output/* CCP PWM mode */CCP1CON &= 0xCF; // 5,4 bits zeroed (DC1B1:DC1B0 = 00)CCP1CON |= 0x0C; // PWM mode ( CCP1M3:CCP1M0 = 1100)/* Timer2 configuration */PR2 = period; // configure timer2 periodT2CON = 0x02; // Set prescalar 16TMR2ON_bit = 1; // timer2 on}void PWM_setDC(unsigned int dutycycle){CCPR1L = dutycycle>>2; // PWM duty cycle - first 8-bits (MSb)CCP1CON &= 0xCF; // 5,4 bits zeroed (DC1B1:DC1B0 = 00)CCP1CON |= ((dutycycle<<4)&0x30); // PWM duty cycle - last 2-bits (LSb) in CCP1CON 5,4 bits}void main(){int adc_value;TRISC = 0x00; //PORTC as outputTRISA = 0xFF; //PORTA as inputPWM_Init(0xFF);//This sets the PWM frequency of PWM1while(1); //Infinite Loop{adc_value = ADC_Read(1); //Reading Analog Channel 0PWM_setDC(adc_value);delay_ms(50);}}https://openlabpro.com/guide/pulse-width-modulation-using-pic18f4550/?fbclid=IwAR2a1g4x03pfe-nlGO5xAImaFrZUSOzNqZa5DS4t4Hts6kWZaBuF_nyQBIgI used the following link code for my code.

author: MarkF
author_rank: Super Contributor
timestamp: April 09, 2020, 03:38:56 pm
content: You need to use AN0 (not AN1 as shown in your circuit).Refer to register ADCON1 for analog channel selections.Code:/** File: main.c* Author: Mark* Compiler: Microchip XC8*/// CONFIGURATION BITS#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)#pragma config BOREN = OFF // Brown-out Reset Enable bit (BOR disabled)#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)#define _XTAL_FREQ 20000000L#include <xc.h>#include <stdio.h>#include <stdlib.h>//======================================================================void main(void){// SETUP PWMTRISCbits.TRISC2=0; // Pin as OutputPR2=0xff; // PWM Period (4.88 KHz)CCPR1L=0; // Duty Cycle MSBsCCP1CON=0x0c; // PWM OnT2CON=0x05; // Timer2 Ctrl Reg (Timer2=On, Prescale=4)// SETUP A/D CONVERSIONTRISAbits.TRISA0=1; // Pin as InputADCON0bits.CHS=0; // Channel=AN0ADCON1=0x0e; // FSOC/32 and Left Justified ResultADCON0=0x81; // FSOC/32 and A/D Onwhile (1){// Get AN0 and Update PWMADCON0bits.GO=1; // Start A/D conversionwhile (ADCON0bits.nDONE); // Wait for DoneCCP1CON=((ADRESL>>2) & 0x30) | 0x0c; // PWM Duty Cycle lower bits + PWM OnCCPR1L=ADRESH; // PWM Duty Cycle upper bits__delay_ms(100); // Delay 100ms (i.e. 10Hz update rate)}}