C code for PIC16F1508 with ADC  - Page 1
Forum section: electronics / general

author: ocset
author_rank: Super Contributor
timestamp: September 22, 2019, 10:50:29 am
content: 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 for ON and OFF.<xc.h><stdint.h>_XTAL_FREQ 4000000uint16_t count;uint16_t count1;uint16_t count2;uint16_t vbusmeas;void main(void) {//SETUP PORTSTRISA = 0x38; //ips are temp, commsbusTRISB = 0x00;TRISC = 0x04;//RA2 = PWM into RC for dimming//RC1 = PWM DIMMING OR TURN OFF/* PORT FUNCTIONSRA0 = DATRA1 = CLKRA2 = DIM1_UC...dim the HV9910B with PWM into RC....................RA3 = MCLRRA4 = TEMP input (MAKE OP LOW FOR NOW)RA5 = COMMSBUS (MAKE IP) ***RA6 = NO PINRA7 = NO PINRB0 = NO PINRB1 = NO PINRB2 = NO PINRB3 = NO PINRB4 = NC OP LOWRB5 = NC OP LOWRB6 = NC OP LOWRB7 = NC OP LOWRC0 = CHILICOMMS OP LOW (MAKE OP LOW FOR NOW) ..NNEDS WEAK PULLUPRC1 = TURN OFF HV9910B (OP)RC2 = VBUSMEASRC3 = NC OP LOWRC4 = COMMSBUSDRIVE OP LOWRC5 = COLORMIX OP LOW..................................................RC6 = SC_OUT OP LOW (MAKE OP LOW FOR NOW)RC7 = CURRENT MONITOR (MAKE OP LOW FOR NOW) *///INITIATE PORTSLATAbits.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 PINLATBbits.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 REGISTERSANSELA = 0x00;ANSELB - 0x00;ANSELC = 0x04; //VBUSMEASADCON0 = 0x18; //choose AN6ADCON1 = 0x40; // fosc/4, leftjust, refvddADRESH = 0x00;CM1CON0 = 0x00;CM1CON1 = 0x00;CM2CON0 = 0x00;CM2CON1 = 0x00;INTCON = 0x00;OPTION_REG = 0x07; //wpu BY latchWPUA = 0x10; //temperature inputWPUB = 0x00;//WPUC = 0x81; //CURRNT MO, Chilicomms //NO WPUCPWM1CON = 0x00;ADON = 1; //ENABLE ADCLATAbits.LATA2 = 0; //zero lightLATCbits.LATC1 = 1; //led driver offwhile(1) {GO = 1; //START CONVERSIONwhile(GO) {;}vbusmeas = ADRESH;if (vbusmeas > 10) {break;}}LATAbits.LATA2 = 1; //max lightLATCbits.LATC1 = 0; //led driver oncount = 0;while(1){LATCbits.LATC5 = 1;__delay_us(100);LATCbits.LATC5 = 0;__delay_us(100);}return;}

author: ocset
author_rank: Super Contributor
timestamp: September 22, 2019, 11:44:17 am
content: 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 this code?...it doesnt build as it dislikes the "T2CKPS" nemonic for some reason.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 datasheethttp://ww1.microchip.com/downloads/e.../40001609E.pdfCode://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 for ON and OFF.<xc.h><stdint.h>_XTAL_FREQ 4000000uint16_t count;uint16_t count1;uint16_t count2;uint16_t vbusmeas;void main(void) {//SETUP PORTSTRISA = 0x38; //ips are temp, commsbusTRISB = 0x00;TRISC = 0x04;//RA2 = PWM into RC for dimming//RC1 = PWM DIMMING OR TURN OFF/* PORT FUNCTIONSRA0 = DATRA1 = CLKRA2 = DIM1_UC...dim the HV9910B with PWM into RC....................RA3 = MCLRRA4 = TEMP input (MAKE OP LOW FOR NOW)RA5 = COMMSBUS (MAKE IP) ***RA6 = NO PINRA7 = NO PINRB0 = NO PINRB1 = NO PINRB2 = NO PINRB3 = NO PINRB4 = NC OP LOWRB5 = NC OP LOWRB6 = NC OP LOWRB7 = NC OP LOWRC0 = CHILICOMMS OP LOW (MAKE OP LOW FOR NOW) ..NNEDS WEAK PULLUPRC1 = TURN OFF HV9910B (OP)RC2 = VBUSMEASRC3 = NC OP LOWRC4 = COMMSBUSDRIVE OP LOWRC5 = COLORMIX OP LOW..................................................RC6 = SC_OUT OP LOW (MAKE OP LOW FOR NOW)RC7 = CURRENT MONITOR (MAKE OP LOW FOR NOW) *///INITIATE PORTSLATAbits.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 PINLATBbits.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 REGISTERSANSELA = 0x00;ANSELB - 0x00;ANSELC = 0x04; //VBUSMEASADCON0 = 0x18; //choose AN6ADCON1 = 0x40; // fosc/4, leftjust, refvddADRESH = 0x00;CM1CON0 = 0x00;CM1CON1 = 0x00;CM2CON0 = 0x00;CM2CON1 = 0x00;INTCON = 0x00;OPTION_REG = 0x07; //wpu BY latchWPUA = 0x10; //temperature inputWPUB = 0x00;//WPUC = 0x81; //CURRNT MO, Chilicomms //NO WPUCT2CON = 0x00;ADON = 1; //ENABLE ADCPWM1CON = 0x00;PWM3CON = 0x00;LATAbits.LATA2 = 0; //zero lightLATCbits.LATC1 = 1; //led driver offwhile(1) {GO = 1; //START CONVERSIONwhile(GO) {;}vbusmeas = ADRESH;if (vbusmeas > 10) {break;}}//SET UP PWM1 (RC5) FOR 50% DUTY CYCLE AT T= 1ms//Page 253 of PIC16F1508 DATASHEETTRISC5 = 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 DATASHEETTRISA2 = 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;}

author: rstofer
author_rank: Super Contributor
timestamp: September 26, 2019, 01:52:33 pm
content: Quote from: treez on September 22, 2019, 11:44:17 amYou set the TRIS bit high to make the pin an input and incapable of erroneously driving an output before you set up the PWM. After things are set, you clear the TRIS bit to make the pin an output. This is a very common practice. In fact, the pin probably defaults to input and setting it high is probably redundant but it's best to follow the directions.http://ww1.microchip.com/downloads/en/DeviceDoc/40001609E.pdf

author: cv007
author_rank: Frequent Contributor
timestamp: September 26, 2019, 10:09:55 pm
content: >it doesnt build as it dislikes the "T2CKPS" nemonic for some reason.Look in the header file. There is no T2CKPS because its 2 bits. T2CKPS0, T2CKPS1 are the bits, which both are of type __bit. There is no __2bit type.If you want to set/read the 2 bits, you need to use the struct access they have-T2CONbits.T2CKPS = 0;// or 1, 2, 3or you can do bit access, separately-T2CKPS0 = 0; //or 1T2CKPS1 = 0; //or 1or you can use the bitfield macros (don't)-T2CON = (T2CON & ~_T2CON_T2CKPS_MASK) | 1<<_T2CON_T2CKPS_POSITION; //or 0<<, 2<<, 3<<All is in the header file.I would use the struct access for most things, so you don't need to bit access everything and you can see the containing register name.T2CONbits.T2CKPS = 0b10; //prescale 16orT2CONbits.T2CKPS = 2; //prescale 16makes more sense than-T2CKPS0 = 0; //prescale 16T2CKPS1 = 1;as you can set the value on one line, and also see it belongs to the T2CON register.