+ Post New Thread
Results 1 to 6 of 6
  1. #1
    Advanced Member level 5
    Points: 32,919, Level: 44
    Achievements:
    7 years registered

    Join Date
    Sep 2008
    Location
    cambridge
    Posts
    6,849
    Helped
    496 / 496
    Points
    32,919
    Level
    44

    C code for PIC16F1508 with ADC

    Hi,
    Please could you possibly check this XC8 C code for PIC16F1508?
    All it is supposed to do is read the ADC input, and if greater than 10, then get on and switch on the led driver.
    Its builds fine, but I fear the ADC registers have not all been set, and it wont work when on the hardware this week?

    Code:
    //pic16f1508  LED COLOR mixer
    
    // CONFIG
    
    // CONFIG1
    #pragma config FOSC = INTOSC    // Oscillator Selection Bits (INTOSC oscillator: I/O function on CLKIN pin)
    #pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
    #pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
    #pragma config MCLRE = OFF      // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
    #pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
    #pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
    #pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
    #pragma config IESO = OFF       // Internal/External Switchover Mode (Internal/External Switchover Mode is disabled)
    #pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)
    
    // CONFIG2
    #pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
    #pragma config STVREN = OFF     // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
    #pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
    #pragma config LPBOR = OFF      // Low-Power Brown Out Reset (Low-Power BOR is disabled)
    #pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
    
    
    // #pragma config statements should precede project file includes.
    // Use project enums instead of #define for ON and OFF.
    
    #include 
    #include 
    
    #define  _XTAL_FREQ 4000000
    
        uint16_t   count;
        uint16_t   count1;
        uint16_t   count2;
        uint16_t   vbusmeas;
    
    void main(void) {
        //SETUP PORTS
    
        TRISA = 0x38;   //ips are temp, commsbus
        TRISB = 0x00;
        TRISC = 0x04;
        
        //RA2 = PWM into RC for dimming
        //RC1 = PWM DIMMING OR TURN OFF
        
       /* PORT FUNCTIONS
        RA0 = DAT
        RA1 = CLK
        RA2 = DIM1_UC...dim the HV9910B with PWM into RC....................
        RA3 = MCLR
        RA4 = TEMP input    (MAKE OP LOW FOR NOW)
        RA5 = COMMSBUS  (MAKE IP) ***
        RA6 = NO PIN
        RA7 = NO PIN
                
        RB0 = NO PIN
        RB1 = NO PIN
        RB2 = NO PIN
        RB3 = NO PIN
        RB4 = NC OP LOW
        RB5 = NC OP LOW
        RB6 = NC OP LOW
        RB7 = NC OP LOW
                
        RC0 = CHILICOMMS OP LOW   (MAKE OP LOW FOR NOW) ..NNEDS WEAK PULLUP
        RC1 = TURN OFF HV9910B (OP)
        RC2 = VBUSMEAS
        RC3 = NC OP LOW
        RC4 = COMMSBUSDRIVE OP LOW
        RC5 = COLORMIX OP LOW..................................................
        RC6 = SC_OUT OP LOW   (MAKE OP LOW FOR NOW)
        RC7 = CURRENT MONITOR (MAKE OP LOW FOR NOW)     */
                
                
        //INITIATE PORTS
            LATAbits.LATA0 = 0; 
            LATAbits.LATA1 = 0; //
            LATAbits.LATA2 = 0; //
            //LATAbits.LATA3 = 0;   MCLR
            //LATAbits.LATA4 = 0;     //temp sensor input
            //LATAbits.LATA5 = 1;     
            //LATAbits.LATA6 = 0;     //NO INTERNAL PIN
            //LATAbits.LATA7 = 0;     //NO INTERNAL PIN
                      
            //LATBbits.LATB0 = 0;   //NO INTERNAL PIN  
            //LATBbits.LATB1 = 0;   //NO INTERNAL PIN
            //LATBbits.LATB2 = 0;   //NO INTERNAL PIN      
            //LATBbits.LATB3 = 0;   //NO INTERNAL PIN   
            LATBbits.LATB4 = 0;
            LATBbits.LATB5 = 0;           
            LATBbits.LATB6 = 0;
            LATBbits.LATB7 = 0;
                    
            LATCbits.LATC0 = 0;
            LATCbits.LATC1 = 1;     //TURN OFF LED DRIVER    
            //LATCbits.LATC2 = 0;     
            LATCbits.LATC3 = 0;      
            LATCbits.LATC4 = 0;
            LATCbits.LATC5 = 1;              
            LATCbits.LATC6 = 0;
            LATCbits.LATC7 = 0;
            
            //SETUP FUNCTION REGISTERS
            ANSELA = 0x00;
            ANSELB - 0x00;
            ANSELC = 0x04;   //VBUSMEAS
            
            ADCON0 = 0x18;  //choose AN6
            ADCON1 = 0x40;  // fosc/4, leftjust, refvdd
            ADRESH = 0x00;
        
            CM1CON0 = 0x00;
            CM1CON1 = 0x00;
            CM2CON0 = 0x00;
            CM2CON1 = 0x00;
            
            INTCON = 0x00;
            
            OPTION_REG = 0x07;  //wpu BY latch
            WPUA = 0x10;    //temperature input
            WPUB = 0x00;
            //WPUC = 0x81;    //CURRNT MO, Chilicomms //NO WPUC
        
            PWM1CON = 0x00;
            
            ADON = 1;    //ENABLE ADC
        
            
            LATAbits.LATA2 = 0; //zero light
            LATCbits.LATC1 = 1; //led driver off
            
            
            
            while(1) {
            GO = 1;    //START CONVERSION
            while(GO) {;}
            vbusmeas = ADRESH; 
            if (vbusmeas > 10) {break;}
            }
            
            LATAbits.LATA2 = 1; //max light
            LATCbits.LATC1 = 0; //led driver on
            
     
            count = 0;
            while(1){
            LATCbits.LATC5 = 1;
            __delay_us(100);
            LATCbits.LATC5 = 0;
            __delay_us(100);
            }
            
            
     
        return;
    }
    - - - Updated - - -

    Also, we have the enhanced version of the above where it reads the ADC, and then if >10, then it puts out a 50% PWM dimming signal at T=1ms on PWM1 and PWM3....we were unsure about the setting up of the PWM modules as it seemes to start off with setting the relevant TRIS bit, which seemed odd as this makes the PWM output an input. (page 253 of PIC16F1508 datasheet)

    Please could you inspect the PWM bit of thios code?...it doesnt build as it dislikes the "T2CKPS" nemonic for some reason

    PIC16F1508 datasheet
    http://ww1.microchip.com/downloads/e.../40001609E.pdf

    Code:
    //pic16f1508  LED COLOR mixer
    
    // CONFIG
    
    // CONFIG1
    #pragma config FOSC = INTOSC    // Oscillator Selection Bits (INTOSC oscillator: I/O function on CLKIN pin)
    #pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
    #pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
    #pragma config MCLRE = OFF      // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
    #pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
    #pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset disabled)
    #pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
    #pragma config IESO = OFF       // Internal/External Switchover Mode (Internal/External Switchover Mode is disabled)
    #pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is disabled)
    
    // CONFIG2
    #pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
    #pragma config STVREN = OFF     // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will not cause a Reset)
    #pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
    #pragma config LPBOR = OFF      // Low-Power Brown Out Reset (Low-Power BOR is disabled)
    #pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
    
    
    // #pragma config statements should precede project file includes.
    // Use project enums instead of #define for ON and OFF.
    
    #include 
    #include 
    
    #define  _XTAL_FREQ 4000000
    
        uint16_t   count;
        uint16_t   count1;
        uint16_t   count2;
        uint16_t   vbusmeas;
    
    void main(void) {
        //SETUP PORTS
    
        TRISA = 0x38;   //ips are temp, commsbus
        TRISB = 0x00;
        TRISC = 0x04;
        
        //RA2 = PWM into RC for dimming
        //RC1 = PWM DIMMING OR TURN OFF
        
       /* PORT FUNCTIONS
        RA0 = DAT
        RA1 = CLK
        RA2 = DIM1_UC...dim the HV9910B with PWM into RC....................
        RA3 = MCLR
        RA4 = TEMP input    (MAKE OP LOW FOR NOW)
        RA5 = COMMSBUS  (MAKE IP) ***
        RA6 = NO PIN
        RA7 = NO PIN
                
        RB0 = NO PIN
        RB1 = NO PIN
        RB2 = NO PIN
        RB3 = NO PIN
        RB4 = NC OP LOW
        RB5 = NC OP LOW
        RB6 = NC OP LOW
        RB7 = NC OP LOW
                
        RC0 = CHILICOMMS OP LOW   (MAKE OP LOW FOR NOW) ..NNEDS WEAK PULLUP
        RC1 = TURN OFF HV9910B (OP)
        RC2 = VBUSMEAS
        RC3 = NC OP LOW
        RC4 = COMMSBUSDRIVE OP LOW
        RC5 = COLORMIX OP LOW..................................................
        RC6 = SC_OUT OP LOW   (MAKE OP LOW FOR NOW)
        RC7 = CURRENT MONITOR (MAKE OP LOW FOR NOW)     */
                
                
        //INITIATE PORTS
            LATAbits.LATA0 = 0; 
            LATAbits.LATA1 = 0; //
            LATAbits.LATA2 = 0; //
            //LATAbits.LATA3 = 0;   MCLR
            //LATAbits.LATA4 = 0;     //temp sensor input
            //LATAbits.LATA5 = 1;     
            //LATAbits.LATA6 = 0;     //NO INTERNAL PIN
            //LATAbits.LATA7 = 0;     //NO INTERNAL PIN
                      
            //LATBbits.LATB0 = 0;   //NO INTERNAL PIN  
            //LATBbits.LATB1 = 0;   //NO INTERNAL PIN
            //LATBbits.LATB2 = 0;   //NO INTERNAL PIN      
            //LATBbits.LATB3 = 0;   //NO INTERNAL PIN   
            LATBbits.LATB4 = 0;
            LATBbits.LATB5 = 0;           
            LATBbits.LATB6 = 0;
            LATBbits.LATB7 = 0;
                    
            LATCbits.LATC0 = 0;
            LATCbits.LATC1 = 1;     //TURN OFF LED DRIVER    
            //LATCbits.LATC2 = 0;     
            LATCbits.LATC3 = 0;      
            LATCbits.LATC4 = 0;
            LATCbits.LATC5 = 1;              
            LATCbits.LATC6 = 0;
            LATCbits.LATC7 = 0;
            
            //SETUP FUNCTION REGISTERS
            ANSELA = 0x00;
            ANSELB - 0x00;
            ANSELC = 0x04;   //VBUSMEAS
            
            ADCON0 = 0x18;  //choose AN6
            ADCON1 = 0x40;  // fosc/4, leftjust, refvdd
            ADRESH = 0x00;
        
            CM1CON0 = 0x00;
            CM1CON1 = 0x00;
            CM2CON0 = 0x00;
            CM2CON1 = 0x00;
            
            INTCON = 0x00;
            
            OPTION_REG = 0x07;  //wpu BY latch
            WPUA = 0x10;    //temperature input
            WPUB = 0x00;
            //WPUC = 0x81;    //CURRNT MO, Chilicomms //NO WPUC
        
            T2CON = 0x00;
           
            ADON = 1;    //ENABLE ADC
            
            PWM1CON = 0x00;
            PWM3CON = 0x00;
        
            
            LATAbits.LATA2 = 0; //zero light
            LATCbits.LATC1 = 1; //led driver off
            
            
            
            while(1) {
            GO = 1;    //START CONVERSION
            while(GO) {;}
            vbusmeas = ADRESH; 
            if (vbusmeas > 10) {break;}
            }
            
            //SET UP PWM1 (RC5) FOR 50% DUTY CYCLE AT T= 1ms
            //Page 253 of PIC16F1508 DATASHEET
            TRISC5 = 1;
            PWM1CON = 0x00;
            PR2 = 0xFF;
            PWM1DCH = 0x00;
            PWM1DCL = 0x00;
            TMR2IF = 0;
            T2CKPS = 0x00;
            TMR2ON = 1;
            PWM1EN = 1;
            while (!TMR2IF){;}
            TRISC5 = 0;
            PWM1OE = 1;
            PWM1EN = 1;
            
            
            //SET UP PWM3 (RA2) FOR 50% DUTY CYCLE AT T= 1ms
            //Page 253 of PIC16F1508 DATASHEET
            TRISA2 = 1;
            PWM3CON = 0x00;
            PR2 = 0xFF;
            PWM3DCH = 0x00;
            PWM3DCL = 0x00;
            TMR2IF = 0;
            T2CKPS = 0x00;
            TMR2ON = 1;
            PWM3EN = 1;
            while (!TMR2IF){;}
            TRISC5 = 0;
            PWM3OE = 1;
            PWM3EN = 1;
            
            
            while(1){;}
     
        return;
    }

    •   AltAdvertisement

        
       

  2. #2
    Super Moderator
    Points: 81,377, Level: 69
    Achievements:
    7 years registered
    Awards:
    2nd Helpful Member
    betwixt's Avatar
    Join Date
    Jul 2009
    Location
    Aberdyfi, West Wales, UK
    Posts
    13,340
    Helped
    4454 / 4454
    Points
    81,377
    Level
    69

    Re: C code for PIC16F1508 with ADC

    Do you really want to check the ADC output is > 10? By left justifying the ADC result and using ADRESH you are ignoring the two least significant bits. If the value to check is 10, right justify it and use ADRESL.

    Brian.
    PLEASE - no friends requests or private emails, I simply don't have time to reply to them all.
    It's better to share your questions and answers on Edaboard so we can all benefit from each others experiences.


    1 members found this post helpful.

    •   AltAdvertisement

        
       

  3. #3
    Advanced Member level 5
    Points: 32,919, Level: 44
    Achievements:
    7 years registered

    Join Date
    Sep 2008
    Location
    cambridge
    Posts
    6,849
    Helped
    496 / 496
    Points
    32,919
    Level
    44

    Re: C code for PIC16F1508 with ADC

    Thanks yes, i agree, though i want to keep the same Left justification throughout as its ok and i will do other tests on the adc value later with a higher checking point.
    One thing that got me about the datasheet is how involved it is to do a PWM output.....it requires interrupts to be set, use of the TMR2 etc etc



    •   AltAdvertisement

        
       

  4. #4
    Super Moderator
    Points: 81,377, Level: 69
    Achievements:
    7 years registered
    Awards:
    2nd Helpful Member
    betwixt's Avatar
    Join Date
    Jul 2009
    Location
    Aberdyfi, West Wales, UK
    Posts
    13,340
    Helped
    4454 / 4454
    Points
    81,377
    Level
    69

    Re: C code for PIC16F1508 with ADC

    For PWM you need one timer (TMR2) to provide the start time for each pulse but you do not need any interrupts. Basically it works by clocking a counter and comparing the count value with the value that you choose for the PWM ratio. When the two are the same, it flips the PWM output bit and resets the counter again for the next shot. You can use it as a source of interrupts but they are not essential to PWM operation.

    I'm not sure why it balks at T2CKPS, on my machine it is defined in the header file PIC16F1508.h as a two-bit wide field in 'T2CONbits_t' so it should accept it. What version of compiler are you using? I have XC8 version 2.10 here.

    Brian.
    PLEASE - no friends requests or private emails, I simply don't have time to reply to them all.
    It's better to share your questions and answers on Edaboard so we can all benefit from each others experiences.



  5. #5
    Advanced Member level 5
    Points: 32,919, Level: 44
    Achievements:
    7 years registered

    Join Date
    Sep 2008
    Location
    cambridge
    Posts
    6,849
    Helped
    496 / 496
    Points
    32,919
    Level
    44

    Re: C code for PIC16F1508 with ADC

    Thanks i am using XC8 C V1.44

    Also, the modus operandi to set up the PWM module (datasheet pg 253) doesnt seem to make sense...it first tells you to set the relevant TRIS bit, it then tells you to clear it.

    PIC16F1508 datasheet:
    http://ww1.microchip.com/downloads/e.../40001609E.pdf



    •   AltAdvertisement

        
       

  6. #6
    Super Moderator
    Points: 81,377, Level: 69
    Achievements:
    7 years registered
    Awards:
    2nd Helpful Member
    betwixt's Avatar
    Join Date
    Jul 2009
    Location
    Aberdyfi, West Wales, UK
    Posts
    13,340
    Helped
    4454 / 4454
    Points
    81,377
    Level
    69

    Re: C code for PIC16F1508 with ADC

    I would update to v2.10, it may have corrections or better support for that device. As far as I know, just updating/replacing the compiler with the new one will work, I think they are backwards compatible even at command line level.

    I think the reason for the TRIS anomaly is that in some situations, the PWM may be driving circuits that need a particular condition at start up. For example, motor speed control or a bridge driver circuit. By making the PWMx pin an input it becomes incapable of driving a logic level out. Only after configuring the PWM registers would it then be safe to enable the output. Consider what might happen if the PWM output sits high for a long time in bridge driver for example. The problem could be worse if two PWM outputs were used in the same circuit and both were stuck high. So it is basically a protection feature so you are sure the PWM signals are correct before unleashing them on the outside world.

    Brian.
    PLEASE - no friends requests or private emails, I simply don't have time to reply to them all.
    It's better to share your questions and answers on Edaboard so we can all benefit from each others experiences.


    1 members found this post helpful.

--[[ ]]--