// PIC18 in C - Versione 0.85 - Ottobre 2015 // Copyright (c) 2015, Vincenzo Villa // Creative Commons | Attribuzione - Condividi allo stesso modo 4.0 Internazionale (CC BY-SA 4.0) // Creative Commons | Attribution-Share Alike 4.0 Unported // https://www.vincenzov.net/tutorial/PIC18/adc.htm // PIC18F25K50 / MPLABX 3.10 / XC8 1.35 // ADC - 10 bit - See data sheet! // PIC18F25K50 Configuration Bit Settings // 'C' source line config statements #include // #pragma config statements should precede project file includes. // Use project enums instead of #define for ON and OFF. // CONFIG1L #pragma config PLLSEL = PLL4X // PLL Selection (4x clock multiplier) #pragma config CFGPLLEN = ON // PLL Enable Configuration bit (PLL Enabled) #pragma config CPUDIV = NOCLKDIV// CPU System Clock Postscaler (CPU uses system clock (no divide)) #pragma config LS48MHZ = SYS48X8// Low Speed USB mode with 48 MHz system clock (System clock at 48 MHz, USB clock divider is set to 8) // CONFIG1H #pragma config FOSC = HSH // Oscillator Selection (HS oscillator, high power 16MHz to 25MHz) #pragma config PCLKEN = OFF // Primary Oscillator Shutdown (Primary oscillator shutdown firmware controlled) #pragma config FCMEN = OFF // Fail-Safe Clock Monitor (Fail-Safe Clock Monitor disabled) #pragma config IESO = OFF // Internal/External Oscillator Switchover (Oscillator Switchover mode disabled) // CONFIG2L #pragma config nPWRTEN = OFF // Power-up Timer Enable (Power up timer disabled) #pragma config BOREN = SBORDIS // Brown-out Reset Enable (BOR enabled in hardware (SBOREN is ignored)) #pragma config BORV = 190 // Brown-out Reset Voltage (BOR set to 1.9V nominal) #pragma config nLPBOR = ON // Low-Power Brown-out Reset (Low-Power Brown-out Reset enabled) // CONFIG2H #pragma config WDTEN = OFF // Watchdog Timer Enable bits (WDT disabled in hardware (SWDTEN ignored)) #pragma config WDTPS = 32768 // Watchdog Timer Postscaler (1:32768) // CONFIG3H #pragma config CCP2MX = RC1 // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1) #pragma config PBADEN = OFF // PORTB A/D Enable bit (PORTB<5:0> pins are configured as digital I/O on Reset) #pragma config T3CMX = RC0 // Timer3 Clock Input MUX bit (T3CKI function is on RC0) #pragma config SDOMX = RC7 // SDO Output MUX bit (SDO function is on RC7) #pragma config MCLRE = ON // Master Clear Reset Pin Enable (MCLR pin enabled; RE3 input disabled) // CONFIG4L #pragma config STVREN = ON // Stack Full/Underflow Reset (Stack full/underflow will cause Reset) #pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled) #pragma config ICPRT = OFF // Dedicated In-Circuit Debug/Programming Port Enable (ICPORT disabled) #pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled) // CONFIG5L #pragma config CP0 = OFF // Block 0 Code Protect (Block 0 is not code-protected) #pragma config CP1 = OFF // Block 1 Code Protect (Block 1 is not code-protected) #pragma config CP2 = OFF // Block 2 Code Protect (Block 2 is not code-protected) #pragma config CP3 = OFF // Block 3 Code Protect (Block 3 is not code-protected) // CONFIG5H #pragma config CPB = OFF // Boot Block Code Protect (Boot block is not code-protected) #pragma config CPD = OFF // Data EEPROM Code Protect (Data EEPROM is not code-protected) // CONFIG6L #pragma config WRT0 = OFF // Block 0 Write Protect (Block 0 (0800-1FFFh) is not write-protected) #pragma config WRT1 = OFF // Block 1 Write Protect (Block 1 (2000-3FFFh) is not write-protected) #pragma config WRT2 = OFF // Block 2 Write Protect (Block 2 (04000-5FFFh) is not write-protected) #pragma config WRT3 = OFF // Block 3 Write Protect (Block 3 (06000-7FFFh) is not write-protected) // CONFIG6H #pragma config WRTC = OFF // Configuration Registers Write Protect (Configuration registers (300000-3000FFh) are not write-protected) #pragma config WRTB = OFF // Boot Block Write Protect (Boot block (0000-7FFh) is not write-protected) #pragma config WRTD = OFF // Data EEPROM Write Protect (Data EEPROM is not write-protected) // CONFIG7L #pragma config EBTR0 = OFF // Block 0 Table Read Protect (Block 0 is not protected from table reads executed in other blocks) #pragma config EBTR1 = OFF // Block 1 Table Read Protect (Block 1 is not protected from table reads executed in other blocks) #pragma config EBTR2 = OFF // Block 2 Table Read Protect (Block 2 is not protected from table reads executed in other blocks) #pragma config EBTR3 = OFF // Block 3 Table Read Protect (Block 3 is not protected from table reads executed in other blocks) // CONFIG7H #pragma config EBTRB = OFF // Boot Block Table Read Protect (Boot block is not protected from table reads executed in other blocks) #define _XTAL_FREQ 48000000 // 48 MHz CPU clock void main(void) { unsigned int voltage; // Voltage as 10 bits integer (0 -> 1023) unsigned char voltageLSB, voltageMSB; // Voltage ad 8 + 8 bits // Set RC7 as analog input (needless: default status) TRISCbits.RC7 = 1; // PORTC pin RC7 configured as an input - REGISTER 11-8: TRISx: PORTx TRI-STATE REGISTER ANSELCbits.ANSC7 = 1; // Digital input buffer disabled - REGISTER 11-5: ANSELC: PORTC ANALOG SELECT REGISTER // Set PORT_A as digital out (4 LSB - LEDS) TRISA = 0xF0; // REGISTER 11-8: TRISx: PORTx TRI-STATE REGISTER // Configure ADC ADCON2bits.ADFM = 0; // Left justified - FIGURE 18-2: 10-BIT A/D CONVERSION RESULT FORMAT ADCON2bits.ADCS = 0b110; // A/D Conversion Clock = FOSC/64 (TAD = 1.3 us @ 48 MHz) - TABLE 18-1: ADC CLOCK PERIOD (T AD ) vs. DEVICE OPERATING FREQUENCIES ADCON2bits.ACQT = 0b001; // A/D Acquisition time select bits (2 TAD - Typical) - See also 18.4 A/D Acquisition Requirements ADCON1bits.PVCFG = 0b00; // Set VDD as voltage reference // REGISTER 18-2: ADCON1: A/D CONTROL REGISTER 1 ADCON1bits.NVCFG = 0b00; // Set VSS as voltage reference // REGISTER 18-2: ADCON1: A/D CONTROL REGISTER 1 ADCON0bits.ADON = 1; // ADC is Powered On - REGISTER 18-1: ADCON0: A/D CONTROL REGISTER 0 // Super Loop while (1) { // Read voltage ADCON0bits.CHS = 0b10011; // Analog Channel Select AN19 - REGISTER 18-1: ADCON0: A/D CONTROL REGISTER 0 ADCON0bits.GO = 1; // Start conversion - REGISTER 18-1: ADCON0: A/D CONTROL REGISTER 0 while (ADCON0bits.nDONE); // Wait End Of Conversion REGISTER 18-1: ADCON0: A/D CONTROL REGISTER 0 voltageMSB = ADRESH; // Read MSB (8 bits) - REGISTER 18-4: ADRESH: ADC RESULT REGISTER HIGH (ADRESH) ADFM = 0 voltageLSB = ADRESL & 0b11; // Read LSB (2 bits) - REGISTER 18-5: ADRESL: ADC RESULT REGISTER LOW (ADRESL) ADFM = 0 voltage = (voltageMSB << 2) | voltageLSB; // Assemble MSB and LSB LATA = voltage >> 6; // Dispaly MSB on LEDs (4 bits) - REGISTER 11-10: LATx: PORTx OUTPUT LATCH REGISTER } }