Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Simple ADC code in XC8 for PIC16F18856

Status
Not open for further replies.
T

treez

Guest
Hi,
The following XC8 C Code just reads the ADC input…then if above a certain value, it then outputs a PWM out on a pin.
Do you think this code is OK… it builds fine.
The ADC had loads of registers and it didnt look like you had to bother setting all of them?

It would be good if microchip had like an "LTspice simulator " for their microcontrollers with C code in them. I couldnt find it on their website....do you know if there is one?

Code:
//This checks the voltage
//then if its ok, it PWMs the light level.

//PIC16F18856
//XC8 compiler
//MPLAB X V3.61
//date 23aug2019

// PIC16F18856 Configuration Bit Settings
//
// 'C' source line config statements

// CONFIG1
#pragma config FEXTOSC = OFF    // External Oscillator mode selection bits (Oscillator not enabled)
#pragma config RSTOSC = HFINT1  // Power-up default value for COSC bits (HFINTOSC (1MHz))
#pragma config CLKOUTEN = OFF   // Clock Out Enable bit (CLKOUT function is disabled; i/o or oscillator function on OSC2)
#pragma config CSWEN = OFF      // Clock Switch Enable bit (The NOSC and NDIV bits cannot be changed by user software)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (FSCM timer disabled)

// CONFIG2
#pragma config MCLRE = OFF      // Master Clear Enable bit (MCLR pin function is port defined function)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (PWRT enabled)
#pragma config LPBOREN = OFF    // Low-Power BOR enable bit (ULPBOR disabled)
#pragma config BOREN = ON       // Brown-out reset enable bits (Brown-out Reset Enabled, SBOREN bit is ignored)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (VBOR) set to 1.9V on LF, and 2.45V on F Devices)
#pragma config ZCD = OFF        // Zero-cross detect disable (Zero-cross detect circuit is disabled at POR.)
#pragma config PPS1WAY = OFF    // Peripheral Pin Select one-way control (The PPSLOCK bit can be set and cleared repeatedly by software)
#pragma config STVREN = OFF     // Stack Overflow/Underflow Reset Enable bit (Stack Overflow or Underflow will not cause a reset)

// CONFIG3
#pragma config WDTCPS = WDTCPS_31// WDT Period Select bits (Divider ratio 1:65536; software control of WDTPS)
#pragma config WDTE = OFF       // WDT operating mode (WDT Disabled, SWDTEN is ignored)
#pragma config WDTCWS = WDTCWS_7// WDT Window Select bits (window always open (100%); software control; keyed access not required)
#pragma config WDTCCS = SC      // WDT input clock selector (Software Control)

// CONFIG4
#pragma config WRT = OFF        // UserNVM self-write protection bits (Write protection off)
#pragma config SCANE = not_available// Scanner Enable bit (Scanner module is not available for use)
#pragma config LVP = OFF        // Low Voltage Programming Enable bit (High Voltage on MCLR/Vpp must be used for programming)

// CONFIG5
#pragma config CP = OFF         // UserNVM Program memory code protection bit (Program Memory code protection disabled)
#pragma config CPD = OFF        // DataNVM code protection bit (Data EEPROM code protection disabled)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.

#include <xc.h>
#include <stdint.h>

#define  _XTAL_FREQ 4000000

    uint16_t   count;
    uint16_t   count1;
    uint16_t   vbusmeas;

void main(void) {
    
    //Setup ports
        TRISA = 0x10;    //
        TRISB = 0x19;    //
        TRISC = 0x02;    //
        
        ANSELA = 0x10;   //A4=TEMP INPUT
        ANSELB = 0x00;    //B0=VBUS; B4=CURRENT
        ANSELC = 0x00;  //C1=SHORT CIRCUIT
        
        WPUA = 0x00;
        ODCONA = 0x00;
        SLRCONA = 0x00;
        INLVLA = 0x00;      //ST?
        CCDPA = 0x00;
        CCDNA = 0x00;
        
        WPUB = 0x00;
        ODCONB = 0x00;
        SLRCONB = 0x00;
        INLVLB = 0x00;      //ST?
        CCDPB = 0x00;
        CCDNB = 0x00;
        
        WPUC = 0x00;
        ODCONC = 0x00;
        SLRCONC = 0x00;
        INLVLC = 0x00;      //ST?
        CCDPC = 0x00;
        CCDNC = 0x00; 
        
        INTCON = 0x00;
       
        CM1CON0 = 0x00;
        CM1CON1 = 0x00;
        CM2CON0 = 0x00;
        CM2CON1 = 0x00;

        PWM6CON = 0x00;
        PWM7CON = 0x00;
        
        ZCDCON = 0x00;
        
        ADCON0 = 0x00;  //fosc;leftjust;
        ADCON1 = 0x00;  //
        ADCON2 = 0x00;  //
        ADCON3 = 0x00;  //
        ADRESH = 0x00;
        ADCLK = 0x3F;   //FOSC/128
        ADREF = 0x00;    //Vref is vdd
        ADPCH = 0x08;    //adc chan B0....VBUS_MEAS
        
        ADON = 1;    //ENABLE ADC
        
        //Initialize ports
        LATAbits.LATA0 = 0;     //nc
        LATAbits.LATA1 = 0;     //nc
        LATAbits.LATA2 = 0;     //DIM_AN OUTPUT
        LATAbits.LATA3 = 0;     //NC
        //LATAbits.LATA4 = 0;     //TEMP INPUT ADC
        LATAbits.LATA5 = 0;     //NC
        LATAbits.LATA6 = 1;     //DIM_PWM OUTPUT
        LATAbits.LATA7 = 0;     //NC
                  
        //LATBbits.LATB0 = 0;      //VBUS_MEAS INPUT ADC
        LATBbits.LATB1 = 0;     //NC
        LATBbits.LATB2 = 0;    //DALI_TX     
        //LATBbits.LATB3 = 0;    //DALI_RX
        //LATBbits.LATB4 = 0;     //LED CURRENT INPUT ADC
        LATBbits.LATB5 = 0;      //NC     
        LATBbits.LATB6 = 0;     //SPCLK
        LATBbits.LATB7 = 0;     //SPDAT
                
        LATCbits.LATC0 = 0;     //NC
        //LATCbits.LATC1 = 0;     //SC_OUT INPUT ADC    
        LATCbits.LATC2 = 0;     //NC  
        LATCbits.LATC3 = 0;    //NC 
        LATCbits.LATC4 = 0;     //NC
        LATCbits.LATC5 = 1;      //NC     
        LATCbits.LATC6 = 0;     //CK_TEST PAD
        LATCbits.LATC7 = 0;     //RX TEST PAD
                
        
    //800ms delay
    for (count=1;count<=10;count++)   {
    __delay_ms(100);
    }
        
        while(1) {
        ADGO = 1;    //START CONVERSION
        while(ADGO) {;}
        vbusmeas = ADRESH; 
        if (vbusmeas > 59) {break;} //only start  if vbus>28v
        }

        
    while(1) { 
    LATAbits.LATA6 = 1;     //DIM_PWM OUTPUT
    __delay_us(750);
    LATAbits.LATA6 = 0;
    __delay_us(250);
    }

    return;
}
 

Microchip do provide simulators but only for their MCUs and not f or any surrounding components. When testing devices that interface with the outside world, they do have the ability to inject values into registers at the appropriate times (or based on other triggers). Personally, I think their simulators have very limited value (actually simulators in general have limited value - they are often just another layer of bugs) and the only real way to test out if your code works is on a real device.
Normally I'm in favour of setting register bits individually, but I think you have taken this a little too far. The vast majority of the registers that you set to zero automatically are set to zero on a reset. Therefore all you are doing is creating a series of effective 'nop's. In my opinion (and it is only that) you would have cleaner code if you only set the specific register bits that you need to change from their POR defaults. By all means add comments about what some of the other bits do, but these devices often have only small FLASH memories so why waste what there is.
One way to avoid having your program #defines for ON and OFF conflict with the config settings is to put those into a separate compilation unit. AS long as they are somewhere in the set of compiled source files then they will end up in the app. (I'm certainly NOT recommending that you do #define ON and OFF - personally I think that is as ugly as it gets but this is a way around that problem.)
Susan
 
  • Like
Reactions: treez

    T

    Points: 2
    Helpful Answer Positive Rating
Thanks,
I’ve actually been reading through the PIC16F18556 datasheet in order to be able to program two ADC inputs…one is for a 10ms sample rate, and the other is for a 1ms sample rate.
I know exactly what I want the ADC’s to do…but can’t yet decipher how to do this from the datasheet,
*…………………*…………………….*……………………*……………………….*…………………
For the 10ms sample rate ADC:
I first wish to discharge the internal ADC capacitor (C_HOLD), by switching on the internal discharge switch for 250us..
..I then wish to switch OFF the C_HOLD discharge switch and then delay for 250us.
..I then wish to switch ON the sample switch and leave it ON for 9ms..
..I then wish to delay for 1ms after switching on the sample switch
..I then wish to start a conversion (ie 1ms after switching on the sample switch)…and I want the conversion to go on for 7.5ms or less, I don’t care how long, as long as its less than 7.5ms.
..then 9ms after switching the sample switch ON, I wish to switch the sample switch OFF.
..then 500us after switching off the sample switch, I wish to switch the C_HOLD discharge switch back ON
..then repeat the above
*…………………*…………………….*……………………*……………………….*…………………
The attached LTspice sim shows how I want to manage the ADC readings

The datasheet has a lot of Jargon words, but i cannot yet work out which jargon word represents the various features that i describe above.
 

Hi,

I know exactly what I want the ADC’s to do
Do the timings really make sense?
* discharging C_Hold typicaly takes a microsecond or so, discharging it for 250us won't do anything..
* sampling time is also in the range of 1us....leaving it ON for 9ms before the conversion will cause the same result as leaving it ON just a couple of microseconds before the conversion.

Usually these timings are generated by the ADC internal logic and the user does not have to care much about it.
What's your intention?

And timings generated by "busy waits" are not very precise. Thus the ADC result has to be considered not very precise, too.
In detail it depends on analog input signal wavefirm and how you process the ADC data.

Klaus
 
  • Like
Reactions: treez

    T

    Points: 2
    Helpful Answer Positive Rating
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top