; *******************************************************************************
; comparator-16F1827.asm
;
; NOTES
; RA3 input = Junction of resistive divider 10k in series with 5k trimpot.
; free end of 10k to +V, connect wiper to one end of 5k trimpot
; and connect to GND, other end to of trimpot to 10k.
; Set trimpot
; with wiper to GND end.
;
; Reference voltage for Comparator is Fixed Voltage Reference set to 4.096V.
;
; LED with 470 ohm series resistor conected between RA1 and GND.
;
; Turning trimpot up will trigger interrrupt routine and turn on LED.
; Power off to reset.
;********************************************************************************
;
; Target Controller PIC16F1827
; __________
; SPARE------RA2 |1 18| RA1---LED
; COMP-NEG---RA3 |2 17| RA0---SPARE
; SPARE------RA4 |3 16| RA7---SPARE
; SPARE------RA5 |4 15| RA6---SPARE
; Ground-----Vss |5 14| VDD---+5 V
; SPARE------RB0 |6 13| RB7---SPARE
; SPARE------RB1 |7 12| RB6---SPARE
; SPARE------RB2 |8 11| RB5---SPARE
; SPARE------RB3 |9 10| RB4---SPARE
; ----------
;
; *******************************************************************************
; * Device type and options *
; *******************************************************************************
;
processor 16F1827
radix dec
errorlevel -207 ; Skip found label after column 1
errorlevel -302 ; Skip out of bank nuisance messages
errorlevel -303 ; Skip program word too large. Truncated to core size
;
; *******************************************************************************
; * Configuration fuse information for 16F1827: *
; *******************************************************************************
;
include <P16F1827.INC>
__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__CONFIG _CONFIG2, _WRT_OFF & _PLLEN_OFF & _STVREN_OFF & _BORV_LO & _LVP_OFF
;
; *******************************************************************************
;
; 16F1827 Oscillator setup
; OSCCON - Oscillator control reg.
; ---------------------------------
; SPLLEN b7 enable PLL x4
; 1 = enabled 0 = disabled
; IRCF | b6-3 frequency selection
; 1111 = 16MHz HF
; 1110 = 8 or 32MHz HF
; 1101 = 4MHz HF
; 1100 = 2MHz HF
; 1011 = 1MHz HF
; 1010 = 500kHz HF
; 1001 = 250kHz HF
; 1000 = 125kHz HF
; 0111 = 500kHz MF (default)
; 0110 = 250kHz MF
; 0101 = 125kHz MF
; 0100 = 62.5kHz MF
; 0011 = 31.25kHz HF
; 0010 = 31.25kHz MF
; 000x = 31.25kHz LF
; Reserved B2 reserved, 0
; SCS B1 0-: 1x = int. OSC.
; 01 = Timer1 oscillator
; 00 = determined by FOSC <2:0> in Configuration
; POR default 00111-00 500 kHz (POR = Power On Reset)
OSCCONVAL EQU b'01101000' ; 4MhZ CLOCK
;
; *******************************************************************************
; * Allocate variables in general purpose register space *
; *******************************************************************************
;
CBLOCK 0x20 ; Start Data Block
temp
ENDC ; End of Data Block
;
; *******************************************************************************
; * Macro's *
; *******************************************************************************
;
LED_on macro
bsf PORTA,1
endm
LED_off macro
bcf PORTA,1
endm
;
; *******************************************************************************
; * Purpose: This is the start of the program. *
; *******************************************************************************
;
;
ORG 0x0000
goto start ; Jump to main program
ORG 0x0004 ; interrupt routine data save
bcf INTCON,GIE ; Clear Global Interrupt Enable bit
BANKSEL PIR2
bcf PIR2,C2IF ; Clear comparator flag
movlb 0
clrf PORTA
clrf PORTB
LED_on
goto $
retfie ; Enable general interrupts and return
;
;--------------------------------------------------------------------------------
;
start
clrf INTCON ; clear INTCON
clrf PORTA
clrf PORTB
; Set PIC oscillator frequency
banksel OSCCON ; Select OSCCON
movlw OSCCONVAL ; Oscillator frequency
movwf OSCCON ; Loads the wanted value
; Configures I/O analog/digital function
Banksel ANSELA
movlw b'00001000' ; RA3 analog all others digital
movwf ANSELA
clrf ANSELB ; PORTB all digital
; Disable all wakeup pull-ups
Banksel WPUA
clrf WPUA
clrf WPUB
banksel OPTION_REG
movlw b'10000000' ; Pull-ups disabled
;
movwf OPTION_REG ;
;
movlw b'00111100' ; PORTA (RA2:5 inputs RA0:1 & 6:7 outputs)
movwf TRISA ;
movlw b'10001111' ; PORTB 0:3 & 7 inputs 4:6 outputs
movwf TRISB ; NOTE: Pull-up via 10k resistor all unused pins
;
BANKSEL FVRCON
movlw b'10001100' ; FVR on, Comparator ref 4.096V
movwf FVRCON
;
movlb 0
movlw 40 ; Delay for FVR to stabilise
movwf temp
decfsz temp
goto $-1
BANKSEL CM1CON0
clrf CM1CON0
clrf CM1CON1
movlw b'10100011'
movwf CM2CON1 ; Positive interrupt on
; Negative interrupt off
; C2VP connects to FVR
; C2VP connects to FVR
; Unimplemented
; Unimplemented
; C2VN connects to C12IN3- pin - RA3
; C2VN connects to C12IN3- pin - RA3
movlw b'10000110'
movwf CM2CON0 ; Comparator enabled
; Comparator Output bit polarity
; Comparator Output internal
; Comparator output is not inverted
; Unimplemented
; Comparator operates in normal power, higher speed mode
; Comparator hysteresis enabled
; Comparator output to Timer1 and I/O pin is asynchronous
BANKSEL PIE2
bsf PIE2,C2IE ; Turn on Comparator 2 interrupt
bsf INTCON,PEIE ; Turn on Periperal interrupts
movlb 0
main
bsf INTCON,GIE ; Turn on Global interrupts
nop
goto $-1 ; Endless loop as comparator is independent of
; anything happening here.
;
END
;--------------------------------------------------------------------------------
#include <xc.h>
#include <stdint.h>
// CONFIG1
#pragma config FEXTOSC = OFF // External Oscillator mode selection bits->Oscillator not enabled
#pragma config RSTOSC = HFINTPLL // Power-up default value for COSC bits->HFINTOSC with 2x PLL, with OSCFRQ = 16 MHz and CDIV = 1:1 (FOSC = 32 MHz)
#pragma config CLKOUTEN = OFF // Clock Out Enable bit->CLKOUT function is disabled; i/o or oscillator function on OSC2
#pragma config CSWEN = ON // Clock Switch Enable bit->Writing to NOSC and NDIV is allowed
#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable bit->FSCM timer enabled
// CONFIG2
#pragma config MCLRE = ON // Master Clear Enable bit->MCLR pin is Master Clear function
#pragma config PWRTE = OFF // Power-up Timer Enable bit->PWRT disabled
#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 = ON // Peripheral Pin Select one-way control->The PPSLOCK bit can be cleared and set only once in software
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable bit->Stack Overflow or Underflow will cause a reset
#pragma config DEBUG = OFF // Background Debugger->Background Debugger disabled
// CONFIG3
#pragma config WDTCPS = WDTCPS_31 // WDT Period Select bits->Divider ratio 1:65536; software control of WDTPS
#pragma config WDTE = SWDTEN // WDT operating mode->WDT enabled/disabled by SWDTEN bit in WDTCON0
#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 = available // Scanner Enable bit->Scanner module is available for use
#pragma config LVP = ON // Low Voltage Programming Enable bit->Low Voltage programming enabled. MCLR/Vpp pin function is MCLR.
// 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
uint16_t value;
void main(void){
T2CLKCON=0b0011; //HFIOSC(16MHz))
T2CON=0b11000000; //pre=16=1MHz,PR4=100=10KHz, post=1 = 10kHz, timer on
PR2=99; //counts 0-99 = 100 counts
TMR2IE=1; //enable timer 2 interrupts
FVRCON=0b10001010; //enable FVR at 2.048V
ADCON0=0b10000100; //ADC on, Fosc and right justify
ADCLK=0x0f; //Fosc/32 = 1uS
ADACQ=0x05; //5uS acquisition time
ADPCH=0b00111111; //select FVR as ADC input
PIE1bits.ADIE=1; //enable ADC complete interrupt
while(!FVRRDY); //wait for FVR to be ready
PEIE=1; //enable peripheral interrupts
GIE=1; //enable global interrupts
while(1){
}
}
void __interrupt() inter(void){
if(TMR2IE && TMR2IF){
TMR2IF=0;
ADGO=1;
}
if(ADIF && ADIE){
ADIF=0;
value=ADRES;
}
}
Nice one Mike, but presumably only useful if you're not using a voltage regulator, otherwise you want to read the incoming voltage, not that out of the regulator (Vdd).This thread got me thinking about calculating Vdd from the ADC reading. On the newer chip (your included) you can use Vdd as the ADC reference and feed the ADC the fixed voltage reference. This gives a reading that increases as Vdd decreases as the 2.048V stays the same.
I played around with some code. It generates a 100uS interrupt and starts the ADC on each interrupt, on completion of the ADC reading it places the value in a variable (called value). It's in C but the general idea will work in any language. It's written for a 16F18854 as I happen to have some boards laying around with those on. Some of the registers are different to the 1827.
Note, the config data is over half the code. The interrupt that does all the work is just 7 instruction lines.Code:#include <xc.h> #include <stdint.h> // CONFIG1 #pragma config FEXTOSC = OFF // External Oscillator mode selection bits->Oscillator not enabled #pragma config RSTOSC = HFINTPLL // Power-up default value for COSC bits->HFINTOSC with 2x PLL, with OSCFRQ = 16 MHz and CDIV = 1:1 (FOSC = 32 MHz) #pragma config CLKOUTEN = OFF // Clock Out Enable bit->CLKOUT function is disabled; i/o or oscillator function on OSC2 #pragma config CSWEN = ON // Clock Switch Enable bit->Writing to NOSC and NDIV is allowed #pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable bit->FSCM timer enabled // CONFIG2 #pragma config MCLRE = ON // Master Clear Enable bit->MCLR pin is Master Clear function #pragma config PWRTE = OFF // Power-up Timer Enable bit->PWRT disabled #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 = ON // Peripheral Pin Select one-way control->The PPSLOCK bit can be cleared and set only once in software #pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable bit->Stack Overflow or Underflow will cause a reset #pragma config DEBUG = OFF // Background Debugger->Background Debugger disabled // CONFIG3 #pragma config WDTCPS = WDTCPS_31 // WDT Period Select bits->Divider ratio 1:65536; software control of WDTPS #pragma config WDTE = SWDTEN // WDT operating mode->WDT enabled/disabled by SWDTEN bit in WDTCON0 #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 = available // Scanner Enable bit->Scanner module is available for use #pragma config LVP = ON // Low Voltage Programming Enable bit->Low Voltage programming enabled. MCLR/Vpp pin function is MCLR. // 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 uint16_t value; void main(void){ T2CLKCON=0b0011; //HFIOSC(16MHz)) T2CON=0b11000000; //pre=16=1MHz,PR4=100=10KHz, post=1 = 10kHz, timer on PR2=99; //counts 0-99 = 100 counts TMR2IE=1; //enable timer 2 interrupts FVRCON=0b10001010; //enable FVR at 2.048V ADCON0=0b10000100; //ADC on, Fosc and right justify ADCLK=0x0f; //Fosc/32 = 1uS ADACQ=0x05; //5uS acquisition time ADPCH=0b00111111; //select FVR as ADC input PIE1bits.ADIE=1; //enable ADC complete interrupt while(!FVRRDY); //wait for FVR to be ready PEIE=1; //enable peripheral interrupts GIE=1; //enable global interrupts while(1){ } } void __interrupt() inter(void){ if(TMR2IE && TMR2IF){ TMR2IF=0; ADGO=1; } if(ADIF && ADIE){ ADIF=0; value=ADRES; } }
Mike.
A very simple form of wear leveling would be to reserve 1k of flash and write to 32 word locations sequentially therefore giving you 320,000 writes.There's also the fact that EEprom read/writes are more durable than flash writes in how many times it can be done - 100,000 as opposed to 10,000 times for the 16F1827.
I'd just copied it from another project which shouldn't have had it ON either!!! Didn't the pickit2/3 warn you if this was the case? Obviously PK4 doesn't - another step forward - not.BTW, did you mean to have LVP=ON?, or did you forget to untick it
A very simple form of wear leveling would be to reserve 1k of flash and write to 32 word locations sequentially therefore giving you 320,000 writes.
Out of curiosity, how many bytes can you write to EEPROM?
I'd just copied it from another project which shouldn't have had it ON either!!! Didn't the pickit2/3 warn you if this was the case? Obviously PK4 doesn't - another step forward - not.
I'm sure I used to get a warning if LVP was on. Yes, using MCC as far too complicated any other way.It's nothing to do with the PK2/3/4 - the default from MCC is for LVP, and you need to untick it when you run MCC. I presume you're setting the config bits via MCC, as I do - there's too many do do it manually.
I've never seen (or at least noticed) any warning, and to be fair it's not that un-complicated even using MCCI'm sure I used to get a warning if LVP was on. Yes, using MCC as far too complicated any other way.
Mike.
Assuming you're referring to the very recent posts?, then no - we're discussing possible warnings from MPLABX if you don't turn off the default LVP setting.I assume when you state "warning" you mean the typical interrupt, in most processors these
days, produced by the low voltage, brownout condition ?
Assuming you're referring to the very recent posts?, then no - we're discussing possible warnings from MPLABX if you don't turn off the default LVP setting.
Yes, I dislike having code spread over a huge number of files unless the project requires it and then I split them into functional routines rather than peripherals. I like to have connected code in the same file so I can see it all at once and not have to keep switching between files to check things.I also noticed you seem to cut & paste the code from MCC into your own source code, much as I do.
I'm curious... why would having LVP ON require a warning?I'm sure I used to get a warning if LVP was on.
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?