/*
* File: Half_Bridge_16F1825_Main.c
* Author: Paul2010
*
* Created on Dec 11, 2013
*/
#ifdef __XC8
#include <xc.h>
#else
#include <htc.h>
#endif
//#include <stdio.h>
//#include <stdlib.h>
//#include <pic12f1822.h>
// __CONFIG _CONFIG1, 0x3FFF & ( _FOSC_INTOSC & _WDTE_OFF & _PWRTE_OFF & _MCLRE_ON & _CP_OFF & _CPD_OFF & _BOREN_OFF & _CLKOUTEN_ON & _IESO_OFF & _FCMEN_OFF )
// __CONFIG _CONFIG2, 0x3FFF & ( _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_19 & _LVP_OFF )
#ifdef __XC8
#pragma config PWRTE=ON, IESO=OFF, MCLRE=OFF, FOSC=INTOSC, WDTE=OFF, BOREN=OFF, CLKOUTEN=OFF, BORV=LO
#pragma config LVP = OFF, PLLEN = OFF, WRT=OFF, STVREN=OFF
#else
__CONFIG( FOSC_INTOSC & MCLRE_OFF & WDTE_OFF & PWRTE_ON & IESO_OFF);
__CONFIG(LVP_OFF & PLLEN_OFF);
#endif
#define OFFSET 1
#define USE_OR_MASKS
#define ADCON0SET 0b00001101 //<6:2>CHSEL: 00011=AN3, <1>GO/DONE, <0>ADON
#define ADCON1SET 0b01010011 //<7>ADFM 0=left, <6:4>ADCS 101=Fosc/16, <3:2>N/A, <1:0>ADPREF 11=FVR
#define ANSELASET 0b00010000 //<0,1,2,4>=ANSA0, ANSA1, ANSA2, ANSA4
//RA4=AN3, RA2=AN2, RA1=AN1, RA0=AN0
#define APF1SET 0b00000000 //<7:4>N/A, <3>P1DSEL, <2>P1CSEL, <1>P2BSEL, <0>CCP2SEL
#define CCP1SET 0b10001100 //<7:6>P1M 10=HalfBridgeFwd, <5,4>LSB, <3:0>CCP1M 1100=All Active High
#define FVRCONSET 0b10000010 //<7>FVREN, <6>FVRRDY, <5>TSEN, <4>TSRNG, <3:2>CDAFVR, <1:0>10=2.048VREF
#define OPTIONSET 0b10000111 //<7>WPU, <6>INTEDG, <5>TMR0CS 0=Fosc/4, <3>PSA 0=TMR0,
//<2:0>PS 000=1:2, 011=1:16, 111=1:256
#define OSCCONSET 0b01111011 //<7>SPLLEN, <6:3>IRCF 1111=16MHz, <2>N/A, <1:0>11=IntOsc
// 500 kHz => 200uA, 4 MHz => 700uA, 8 mHz => 1000uA
#define PWM1SET 0b10000011 // <7> P1RSTen 1=Auto Restart, <6:0> P1DC Delay Counts
// PSTR1CON: <7:5> N/A, <4> 1=Sync on PWM, <3:0> Str1xEn<D:A>
#define PSTR1SET 0b00010011
#define T1CONSET 0b00001000 // <7:6>CS: 00-fOsc/4, 01=fOsc
// <5:4>Prescale: 00=1, <3>1=enable, <2:1>N/A, <0>1=ON
// fOsc /T1CKPS /65536
// 16 MHz clock: 16000000 /65536 = 244.14 Hz = 4.096 mSec
#define T2CONSET 0b00000000 // <6:3>Postscale 00=1, <0:1>PS 00=1 01=4 10=16 11=64
#define TRISASET 0b00011011 // Set <0:1,3:4> as input, <2,5> as output
#define TRISCSET 0b11001111 // Set <0:3> as input, <4,5> as output
#define INTCONSET 0b11100000 // Setup INTCON 7:GEIE, 6:PEIE, 5:TMR0IE, 4:INTE, 3:IOCIE, 2:TMR0IF, 1:INTF, 0:IOCIF
#define PIE1SET 0b01000000 // <7>TMR1GIE, <6>ADIE, <5>RCIE, <4>TXIE, <3>SSP1IE, <2>CCP1IE, <1>TMR2IE, <0>TMR1IE
#define PIR1SET 0b00000000 // <7>TMR1GIF, <6>ADIF, <5>RCIF, <4>TXIF, <3>SSP1IF, <2>CCP1IF, <1>TMR2IF, <0>TMR1IF
/* Pin definitions for PIC16F1825
Pin 1 Vdd +5VDC
Pin 2 RA5/P2A
Pin 3 RA4/AN3/P2B/SDO1
Pin 4 RA3/MCLR-,VPP
Pin 5 RC5/P1A/RX PWMA
Pin 6 RC4/P1B/TX/SRNQ PWMB
Pin 7 RC3/AN7/P1C/P2A/SSI-
Pin 8 RC2/AN6/P1D/P2B/SDO1
Pin 9 RC1/AN5/SDA/SDI
Pin 10 RC0/AN4/SCL/SCK
Pin 11 RA2/AN2/INT/SRQ LED
Pin 12 RA1/AN1/RX/PC/SRI/Vref+
Pin 13 RA0/AN0/TX/PD/Vref-/DAC
Pin 14 Vss GND
*/
#define ConvertADC ADCON0bits.ADGO = 1
#define ReadADC 256*(int)ADRESH + (int)ADRESL
#define BusyADC ADCON0bits.GO_nDONE
#define CLKFREQ 16 //Clock Frequency (MHz)
#define CLKPER 1000/CLKFREQ //Clock period (nSec)
#define PS 16 //Prescaler
#define ADCMIN 164 // 10.5V / 8 = 1.312 * 256 / 2.048 = 164
#define ADCMAX 216 // 13.8V / 8 = 1.725 * 256 / 2.048 = 216
unsigned char timer1=0; // running time in 800 uSec steps
int ADCresult; // was unsigned
unsigned long Period, PulseWidth; // PWM period, pulse width in nSec
unsigned Numerator;
void SetupADC(void);
void SetupPWM(void);
void SetPWM(int DC);
void Initialize(void);
void interrupt HighIntCode() // for XC8 compiler
{
if( INTCONbits.TMR0IF ) { // 4 uSec update of TMR1, 250 = 1 mSec (FF08), 2500 = 10 mSec => F63C+0x0A = F646
if( ADCresult < ADCMIN )
LATAbits.LATA2 = 0; // Green LED ON
else if( ADCresult > ADCMAX )
LATAbits.LATA2 = 1; // Red LED ON
else
LATAbits.LATA2 ^= 1; // Red/Green LEDs flash
ConvertADC; // 1000/sec
INTCONbits.TMR0IF = 0;
}
else if(PIR1bits.ADIF && !BusyADC ) {
ADCresult = ADRESH;
PIR1bits.ADIF = 0;
}
else if(PIR1bits.CCP1IF) {
PIR1bits.CCP1IF = 0;
}
}
int main(int argc, char** argv) {
Initialize();
SetupADC();
SetupPWM();
SetPWM(50);
while(1) {
asm("clrwdt");
};
}
void Initialize(void) {
OSCCON = OSCCONSET;
OPTION_REG = OPTIONSET;
INTCON = INTCONSET;
TRISA = TRISASET;
TRISC = TRISCSET;
// T1CON = T1CONSET;
// PR2 = 49; // 1 MHz/4/5 = 50 KHz, / 500 = 1 kHz
// PIE1bits.TMR1IE = 1;
// T1CONbits.TMR1ON = 1;
INTCONbits.PEIE = 1; //Turn on Peripheral Interrupts
INTCONbits.GIE = 1; //Turn on Global Interrupts
}
void SetupADC(void) {
ADCON0 = ADCON0SET;
ADCON1 = ADCON1SET;
ANSELA = ANSELASET;
FVRCON = FVRCONSET;
PIE1bits.ADIE = 1; //Use ADC Interrupt
PIR1bits.ADIF = 0;
}
/****************************** Setup PWM - Uses TMR2, T2CON **************************/
void SetupPWM(void) {
PWM1CON = PWM1SET;
TRISC |= 0b00110000; // disable output
// Period should be (14+1)*4*1*16 = 960 uSec = 240 cycles
// Pulse width should be 40*16 = 640 uSec = 160 Cycles
// Duty cycle should be 40/60 = 67%
PR2 = 199; // 16*4*15=960 uSec, 16*4*16=1024 uSec
CCP1CON = CCP1SET;
CCPR1L = 10; // Pulse width = 40*16=640/960 = 67%
// Duty cycle = (CCPR2L + CCP2CON<4:5>) / 4*(PR4+1)
// Duty cycle = 10*4 /4*15 = 40/60
// Period = (PRx+1)*4*Tosc*TMRxPS
// 16 MHz clock 20 kHz PWM
// 20000 = (PR+1)*4*PS/fOsc;
// PS = 1
// PR+1 = fOsc/4*PS*fPWM = 16000/80 = 200; PR = 199
T2CON = T2CONSET; // <6:3> Postscale 1, <0:1> Prescale 1
T2CONbits.TMR2ON = 1;
// PIE1bits.CCP1IE = 1;
// PIR1bits.CCP1IF = 0;
PSTR1CON = PSTR1SET;
// APFCONbits.CCP1SEL = 1; // CCP1SEL 0=RA2, 1=RA5
TRISC &= 0b11001111; // enable output
}
void SetPWM(int DC) { // Duty Cycle DC 0 to 100%
// unsigned long Period, PulseWidth; // PWM period, pulse width in nSec
// unsigned Numerator;
Period = (PR2+1)*4*PS;
Period *= CLKPER; //nSec
PulseWidth = DC * Period / 100;
Numerator = 4*(PR2+1)*DC; //4*PulseWidth / (4*(PR2+1));
Numerator /= 100;
CCP1CONbits.DC1B = Numerator & 0b00000011;
CCPR1L = Numerator >> 2;
}