;****************************************************************************** ; Filename: APP_1169 (Absolute Code Version) ; Date: 8/22/03 ; File Version: 1.1 ; ; Author: Ted Salazar ; Company: Maxim ; ; ; Description: This program gives Maxim customers a working example ; of interfacing to the MAX1169 16-bit I2C ADC using ; the PIC18F442's internal MSSP I2C peripheral. ; ; ; History: ; 08/22/03: Upgraged UART baud rate from 2400bps to 115.2kbps ; 08/22/03: Moved UART "OK" & LF after initializing PORTC ; 05/19/03: PIC18F442 HWI2C peripheral code now working ;****************************************************************************** ; ; Files required: P18F442.INC ; ;****************************************************************************** radix hex ;Default to HEX LIST P=18F442, F=INHX32 ;Directive to define processor and file format #include ;Microchip's Include File ;****************************************************************************** ;****************************************************************************** ; Bit Definitions xmit equ 06 ; Asynchronous TX is at C6 ; ;****************************************************************************** ;Variable definitions ; These variables are only needed if low priority interrupts are used. ; More variables may be needed to store other special function registers used ; in the interrupt routines. CBLOCK 0x080 WREG_TEMP ;variable used for context saving STATUS_TEMP ;variable used for context saving BSR_TEMP ;variable used for context saving ; ENDC CBLOCK 0x000 EXAMPLE ;example of a variable in access RAM data0 data0_temp data1_temp temp xmtreg cntrb cntra bitctr tcount xcount ; ENDC ;****************************************************************************** ;Reset vector ; This code will start executing when a reset occurs. ORG 0x0000 goto Main ;go to start of main code ;****************************************************************************** ;High priority interrupt vector ; This code will start executing when a high priority interrupt occurs or ; when any interrupt occurs if interrupt priorities are not enabled. ORG 0x0008 bra HighInt ;go to high priority interrupt routine ;****************************************************************************** ;Low priority interrupt vector and routine ; This code will start executing when a low priority interrupt occurs. ; This code can be removed if low priority interrupts are not used. ORG 0x0018 movff STATUS,STATUS_TEMP ;save STATUS register movff WREG,WREG_TEMP ;save working register movff BSR,BSR_TEMP ;save BSR register ; *** low priority interrupt code goes here *** movff BSR_TEMP,BSR ;restore BSR register movff WREG_TEMP,WREG ;restore working register movff STATUS_TEMP,STATUS ;restore STATUS register retfie ;****************************************************************************** ;High priority interrupt routine ; The high priority interrupt code is placed here to avoid conflicting with ; the low priority interrupt vector. HighInt: ; *** high priority interrupt code goes here *** retfie FAST ;****************************************************************************** ;Start of main program ; The main program code is placed here. Main: ; *** main code goes here *** start movlw 0x0FF movwf PORTB clrf PORTA movlw 0x06 ;T Configure PortA as Digital movwf ADCON1 movlw 0x00FB ;T A2 OUTPUT, ALL OTHERS INPUT movwf TRISA movlw 0x0001 ;T B0 INPUT, ALL OTHERS OUTPUT movwf TRISB ;****************************************************************************** HWI2C_init ;T I2C MSSP Initialization for M2EAM schematic movlw 0x00BF ;T C6 (TX) OUTPUT, ALL OTHER C's INPUTs movwf TRISC movlw 0x0028 ;T turn MSSP ON & I2C MASTER movwf SSPCON1 ;T used to be sspcon movlw 0x0000 ;T I2C FAST Mode Slew Rate Setting movwf SSPSTAT ;T used to be sspstat movlw 0x0018 ;T SSPADD = (FOSC/(4*SCL)) -1 => 400kHz @ 40MHz movwf SSPADD ;T used to be sspadd ;****************************************************************************** ; bsf PORTC,xmit dly clrf bitctr dly0 call full decfsz bitctr,f goto dly0 ; movlw 0x4F ; 'O' = 0x4F movwf xmtreg call asyxmtc movlw 0x4B ; 'K' = 0x4B movwf xmtreg call asyxmtc movlw 0x0D ; CR = Carriage Return = 0x0D movwf xmtreg call asyxmtc movlw 0x0A ; LF = Line Feed = 0x0A movwf xmtreg call asyxmtc ;****************************************************************************** ; InitializeMAX1169 ; *** InitializeMAX1169 code goes here *** ; No code Required... ; Ensure ADD[3:0] make slave address 0x7F ; on the PCB hardware. ; Ensure REFADJ is NOT tied to AVDD so ; that internal reference mode is enabled ContinuousReadMAX1169 ; *** ContinuousReadMAX1169 code goes here *** call HWI2C_start ; I2C read movlw 0x7F ; load w with literal call HWI2C_W_slaveAddr ; Call Slave_Address Function w/ R = 1 btfsc STATUS,0 ; Bit0 = C Flag; C Flag set = error goto errorsr ; Goto the error service routine loop4ever ;1st 8-bits call delay ; Clock Stretch for tconv call HWI2C_readMore_W ; btfsc SSPCON2,ACKSTAT ; Is there an error? goto errorsr ; Goto the error service routine movf data0,w ; Move received data in data0 to w movwf data0_temp ; Move w to data0_temp ;2nd 8-bits call HWI2C_readMore_W ; btfsc SSPCON2,ACKSTAT ; Is there an error? goto errorsr ; Goto the error service routine movf data0,w ; Move received data in data0 to w movwf data1_temp ; Move w to data1_temp to make program ; easier to follow ; Perform Asynchronous comm movf data0_temp,w ; Move received data in data0_temp to w movwf xmtreg ; Move w to xmtreg call asyxmtc ; Call UART routine movf data1_temp,w ; Move received data in data0_temp to w movwf xmtreg ; Move w to xmtreg call asyxmtc ; Call UART routine goto loop4ever ; Goto the endless loop ;****************************************************************************** errorsr ; *** errorsr code goes here *** call HWI2C_readLast_W ; call HWI2C_stop ; dead movlw 0x45 ; Load w with ASCII 'E' for ERROR movwf xmtreg ; Move w to xmtreg call asyxmtc ; Call UART routine goto dead ; Transmit ASCII 'E' forever ;****************************************************************************** HWI2C_start movlw 0x00 ;T load w with literal movwf tcount ;T move w to tcount bcf PIR1,SSPIF ;T clear completed flag bsf SSPCON2,SEN ;T send start sloop1 ; call delay_100ms ;OP_T btfsc PIR1,SSPIF ;T start completed? goto sxloop ;T exit loop incf tcount,f ;T increment tcount movlw 0xFF ;T load w with literal subwf tcount,w ;T subtract 0xFF from tcount result in w btfss STATUS,Z ;T test zero flag, skip next instr if z set goto sloop1 ;T loop until timeout goto serror ;T complete timeout error sxloop call clear_cf_ok ;T clear carry flag =>Success return serror call set_cf_error ;T set carry flag =>error return ;****************************************************************************** HWI2C_stop movlw 0x00 ;T load w with literal movwf tcount ;T move w to tcount bcf PIR1,SSPIF ;T clear completed flag bsf SSPCON2,PEN ;T send stop ploop1 ; call delay_100ms ;OP_T btfsc PIR1,SSPIF ;T start completed? goto pxloop ;T exit loop incf tcount,f ;T increment tcount movlw 0xFF ;T load w with literal subwf tcount,w ;T subtract 0xFF from tcount result in w btfss STATUS,Z ;T test zero flag, skip next instr if z set goto ploop1 ;T loop until timeout goto perror ;T complete timeout error pxloop call clear_cf_ok ;T clear carry flag =>Success return perror call set_cf_error ;T set carry flag =>error return ;****************************************************************************** HWI2C_repeatedStart movlw 0x00 ;T load w with literal movwf tcount ;T move w to tcount bcf PIR1,SSPIF ;T clear completed flag bsf SSPCON2,RSEN ;T send repeated start rsloop1 ; call delay_100ms ;OP_T btfsc PIR1,SSPIF ;T repeated start completed? goto rsxloop ;T exit loop incf tcount,f ;T increment tcount movlw 0xFF ;T load w with literal subwf tcount,w ;T subtract 0xFF from tcount result in w btfss STATUS,Z ;T test zero flag, skip next instr if z set goto rsloop1 ;T loop until timeout goto rserror ;T complete timeout error rsxloop call clear_cf_ok ;T clear carry flag =>Success return rserror call set_cf_error ;T set carry flag =>error return ;******************************************************************************; HWI2C_W_slaveAddr bcf PIR1,SSPIF ;T clear completed flag movwf SSPBUF ;T send data wloop1 btfss PIR1,SSPIF ;T data sent? goto wloop1 ;T loop until completed btfsc SSPCON2,ACKSTAT ;T ACK error? if no then skip goto werror ;T set_cf_error call clear_cf_ok ;T clear carry flag =>Success return werror call set_cf_error ;T set carry flag =>error return ;****************************************************************************** set_cf_error movlw 0x00 ; 0x00 into W sublw 0x00 ; Subtract W-0x00: If W<=N C set; If W>N C clear. return ; error=> cf=set ;****************************************************************************** clear_cf_ok movlw 0x01 ; 0x00 into W sublw 0x00 ; Subtract W-0x00: If W<=N C set; If W>N C clear. return ; success=> cf=clear ;****************************************************************************** HWI2C_readMore_W movlw 0x00 ;T load w with literal movwf tcount ;T move w to tcount bcf PIR1,SSPIF ;T clear completed flag bsf SSPCON2,RCEN ;T receive data byte rloop1 ; call delay_100ms ;OP_T btfsc PIR1,SSPIF ;T data byte received? goto xloop ;T exit loop incf tcount,f ;T increment tcount movlw 0xFF ;T load w with literal subwf tcount,w ;T subtract 0xFF from tcount result in w btfss STATUS,Z ;T test zero flag, skip next instr if z set goto rloop1 ;T loop until timeout goto rerror ;T receive timeout error xloop movf SSPBUF,w ;T load data byte into w movwf data0 ;T loads data byte into data0 bcf PIR1,SSPIF ;T clear completed flag bcf SSPCON2,ACKDT ;T set ACK bsf SSPCON2,ACKEN ;T send ACK rloop2 btfss PIR1,SSPIF ;T send completed? goto rloop2 ;T loop until completed call clear_cf_ok ;T clear carry flag =>Success movf data0,w ;T move contents of data0 to w return rerror call set_cf_error ;T set carry flag =>error return ;****************************************************************************** HWI2C_readLast_W movlw 0x00 ;T load w with literal movwf tcount ;T move w to tcount bcf PIR1,SSPIF ;T clear completed flag bsf SSPCON2,RCEN ;T receive data byte rloop3 ; call delay_100ms ;OP_T btfsc PIR1,SSPIF ;T data byte received? goto xloop2 ;T exit loop incf tcount,f ;T increment tcount movlw 0xFF ;T load w with literal subwf tcount,w ;T subtract 0xFF from tcount result in w btfss STATUS,Z ;T test zero flag, skip next instr if z set goto rloop3 ;T loop until timeout goto rerror2 ;T receive timeout error xloop2 movf SSPBUF,w ;T load data byte into w movwf data0 ;T loads data byte into data0 bcf PIR1,SSPIF ;T clear completed flag bsf SSPCON2,ACKDT ;T set NOACK bsf SSPCON2,ACKEN ;T send NOACK rloop4 btfss PIR1,SSPIF ;T send completed? goto rloop4 ;T loop until completed call clear_cf_ok ;T clear carry flag =>Success movf data0,w ;T move contents of data0 to w return rerror2 call set_cf_error ;T set carry flag =>error return ;****************************************************************************** ; UART routine asyxmtc bcf PORTC,xmit ;T used to be portc,xmit call full movlw 0x08 ;TEST_T "08" movwf bitctr asyxmt1 rrcf xmtreg,f btfsc STATUS,C goto asyxmt2 bcf PORTC,xmit ;T used to be portc,xmit goto asyxmt3 asyxmt2 bsf PORTC,xmit ;T used to be portc,xmit ; asyxmt3 call full decfsz bitctr,f goto asyxmt1 ; bsf PORTC,xmit ;T used to be portc,xmit call full retlw 0 ;****************************************************************************** ; Modified for 115.2kbps (~8.6usec bit period) full movlw d'3' movwf cntrb vdly0 movlw d'6' ; was d'43' for 2400 baud movwf cntra vdly1 decfsz cntra,f goto vdly1 decfsz cntrb,f goto vdly0 retlw 0 ;****************************************************************************** ;Delay Subroutine ;This subroutine implementes a delay greater ;than or equal to the MAX1169's maximum conversion time in fast mode delay movlw 0x0F ;0x0F to w movwf xcount ;to xcount repeat decfsz xcount,f ;decrement xcount and skip if '0' goto repeat ;not '0' yet return ;****************************************************************************** ;End of program END