projects:electronics:tirepressuresensor:code

This is an old revision of the document!


<code asm> ;############################################################################### ;# TITLE “Pressure Sense” ;# ;# Program : Pressure sensor using an MPX5700DP sensor and LCD display ;# Version :1.0 ;# Revision Date : ;# Author : Jeff Brown ;# ;# ;# ;############################################################################### ; radix hex

	 #define	RA0_PICDEM						; If Defined, Pot on RA0, otherwise, RA8

; #define LCD_PICDEM ; If Defined, Pot on RA0, otherwise, RA8 ; #define I2C_7SEG ; If Defined, use I2C to control display

	#DEFINE		ADRC0	b''
	#DEFINE		ADRC1	b''

; #define DEBUG

	;list p=18F452
	list p=18F2220
	;include "P18F452.INC"
	include "P18F2220.INC"
	#ifdef	LCD_PICDEM
	include "XLCD.inc"                      ;This include all required files and variables.	

#endif

; * ; * Variables * ; * UDATA_ACS reg res 1 W_Temp res 1 STATUS_Temp res 1 BSR_Temp res 1 Temp res 1

Mult0 res 1 Mult1 res 1 Mult2 res 1

Mtemp0 res 1 Mtemp1 res 1 Mtemp2 res 1

TenK res 1 Thou res 1 Hund res 1 Tens res 1 Ones res 1

_Error res 1 Checksum res 1 Brightness res 1 SAA_Control res 1

global	Temp
global	Mult0
global	Mult1
global	Mult2
global	Mtemp0
global	Mtemp1
global	Mtemp2
global	TenK
global	Thou
global	Hund
global	Tens
global	Ones
global _Error
global	Checksum
global	Brightness
global	SAA_Control

; SAA1064 Constants SAA1064ADDRESS EQU B'01110000' ; Address SAA1064CONTROL EQU B'00000111' ; Control SAA1064SEGDASH EQU B'01000000' ; - SAA1064SEGDP EQU B'10000000' ; . SAA1064SEGJ EQU B'00011110' ; J

; * ; * Macros * ; *

Bin_Out macro Floc ; Output a Binary Value

	variable i

i = 0

	while i < 8
	if (i==4)
		movlw ' '
	#ifdef	LCD_PICDEM
		call	XLCDPut
	#endif
	endif
	movlw	'0'
	btfsc	Floc,(7-i),A

i+=1

	movlw	'1'
	#ifdef	LCD_PICDEM
	call	XLCDPut
	#endif
	endw
	endm

I2C_AckWait macro

	nop
	btfsc	SSPCON2,ACKSTAT
	Goto	$-2
endm

I2C_SendStart macro

	BSF		SSPCON2,SEN	; Send Start 
	call	I2C_BusyWait
endm

I2C_SendStop macro

	BSF		SSPCON2,PEN	; Send Stop 
	call	I2C_BusyWait
endm

#ifdef LCD_PICDEM ;The user can declare different definitions and make necessary commands XLCDCursorOnBlinkOn equ B'00001111' ;Display on Cursor on and Blink on XLCDCursorOnBlinKOff equ B'00001110' ;Display on Cursor on and Blink off XLCDDisplayOnCursorOff equ B'00001100' ;Display on Cursor off XLCDDisplayOff equ B'00001000' ;Display off XLCDAddrIncrOnShiftOn equ B'00000111' ;increment DDRAM address and Display shift during read and wite XLCDAddrIncrOnShiftOff equ B'00000110' ;increment DDRAM address no Display shift during read and wite XLCDAddrIncrOffShiftOff equ B'00000100' ;Do not increment DDRAM address and shift during read and wite XLCDDisplayMoveRight equ B'00011100' ;Display moves right,DDRAM Content remain unchanged XLCDDisplayMoveLeft equ B'00011000' ;Display moves left,DDRAM Content remain unchanged XLCDCursorMoveRight equ B'00010100' ;Cursor moves right,DDRAM Content remain unchanged XLCDCursorMoveLeft equ B'00010000' ;Cursor moves left,DDRAM Content remain unchanged

#endif

;** ; VECTORS

		org     0x000000		; Processor reset vector (power-up here)
		nop
		nop						; First two instructions are nop's (no operation) to allow
								; usage of break-points when using the debugger.
			goto    Start        ; Go to the beginning of the Main Program
		org		0x000008		; High Priority ISR (Interrupt Service Routine) vector
; Start of High Priority ISR
								; Write your custom High Priority ISR code here or place
		goto HiPriority_ISR		; a "goto HiPriority_ISR" here if you cannot fit the
								; required code in before the low priority ISR at 0x0018.
								; Remember, each instruction eats two lines of program
								; memory and instructions always start at even numbers.
								; i.e. The first instruction begins at memory location 0x000,
								; the next at 0x002, then 0x004, and so on.
		retfie	FAST            ; Return from High Priority ISR and re-enable Global Interrupts.
								; The "FAST" parameter tells the MCU to reload W, STATUS, and
								; BSR registers from the shadow registers which context saves
								; these registers the instant an interrupt occurs.
								; We don't use the "FAST" option for the Low Priority ISR
								; because if the High Priority interrupt is enabled and should
								; ever occur while the program is still servicing the Low
								; Priority ISR, then it will over-write the previous values
								; saved in the shadow registers.
								; Therefore, if only one ISR is required, use the High Priority
								; with the FAST option for easy context saving.
; NOTE: When a High Priority interrupt occurs, the GIE/GIEH bit is hardware disabled until
; execution of the "retfie". This prevents subsequent High Priority interrupts from
; interferring with the ISR in progress. This could mean however missing some important
; interrupt if competing interrupts occur too quickly. The High Priority interrupt can
; interrupt however a Low Priority interrupt which has its own enable/disable bit PEIE/GIEL.
; If a Low Priority ISR is in progess, it prevents another low priority from occuring until
; complete but it cannot prevent a high priority interrupt from preempting it. The High
; Priority bit GIE/GIEH acts as the overall enable/disable bit for ALL priority interrupts.
; The reason for context saving W, STATUS, and BSR is that the values in these registers
; can affect moment by moment the result of subsequent instructions.  If an interrupt
; routine alters their value(s) then when the program resumes at the point where it was
; interrupted, the results may become unpredicatable unless we first restore the values of
; W, STATUS, and BSR to their "as found" values the instant we leave the ISR (Interrupt
; Service Routine).
		org		0x000018			; Low Priority ISR (Interrupt Service Routine) vector
		nop

; movff STATUS,STATUS_Temp ; Save the Status register contents ; movwf W_Temp,A ; Save the W register contents ; movff BSR, BSR_Temp ; Save the Bank Select Register contents ; ; ; Write your custom Low Priority ISR code here. ; ; ; End of Low Priority ISR, restore the W, Status, and BSR registers. ; movff BSR_Temp,BSR ; Restore the Bank Select Register ; movf W_Temp,W,A ; Restore the Working Register ; movff STATUS_Temp, STATUS ; Restore the Status register ; ; retfie ; Return from Low Priority ISR and re-enable ; ; any Low Priority Interrupts.

PGM CODE ;Message db “LCD:”, 0 ;display of string

;Lookup Table for 7-seg ;TODO Add test to make sure number is 0x0F or below ;DP is Bit 7 SEG_LOOKUP

MOVWF	Temp,A
MOVLW	0x10
SUBWF	Temp,A
BTFSC	STATUS,C
RETLW	B'11000000'		; Return 0xC0 if over 0x0F - Light up DP and G segments
BCF		STATUS,C
RLCF	Temp,w
ADDWF	PCL,F
RETLW	B'00111111'	; 0
RETLW	B'00000110'	; 1
RETLW	B'01011011'	; 2
RETLW	B'01001111'	; 3
RETLW	B'01100110'	; 4
RETLW	B'01101101'	; 5
RETLW	B'01111101'	; 6
RETLW	B'00000111'	; 7
RETLW	B'01111111'	; 8
RETLW	B'01100111'	; 9
RETLW	B'01110111'	; A
RETLW	B'01111100'	; B
RETLW	B'01011000'	; C
RETLW	B'01011110'	; D
RETLW	B'01111001'	; E
RETLW	B'01110001'	; F

;End of Lookup

Start ; PORTA ;make PORTA digital(control signals are on PORTA)

	CLRF    LATA
	CLRF	TRISA

; #ifdef RA0_PICDEM ; BSF TRISA,RA0 ; #else

	BSF		TRISA,RA5

; #endif

	BSF		TRISA,RA4

; PORTB

	CLRF	LATB
	CLRF	TRISB

; PORTC

	CLRF	TRISC,A
	BSF		TRISC,SCL	; SDO as Input
	BSF		TRISC,SDA	; SCK as Input

; PORTD ; CLRF LATD

; ; movlw 0x06 ; movwf ADCON1

#ifdef	LCD_PICDEM
      call    XLCDInit                    ;initialize LCD module(machine cycle talken for this call
      goto    StartDisplay
      #if XLCDBLOCKING ==0                ;this part is assembled and called only in non blocking mode

PollBF: ;XLCDIsBusy is called, if LCD module is busy w return with 1 else 0

      call    XLCDIsBusy                  ;in actual practice the user can continue with his code rather that
                                          ;polling like this and he can check by calling XLCDIsBusy to see if 
      movwf reg                           ;the module is free before sending his next command to LCD.  
      btfsc   reg,0                       ;(here in the example XLCDIsBusy is in a loop and stays there untill
      goto    PollBF                      ;the busy flag is clreared)
      return        
      #endif
	#endif

StartDisplay

	;movlw	b'10000111'	; Prescaler 1:256  Enable Timer0, 16-bit, internal clock, rising edge

; movlw b'10000010' ; Prescaler 1:8 Enable Timer0, 16-bit, internal clock, rising edge

	;movlw	b'10000100'	; Prescaler 1:32  Enable Timer0, 16-bit, internal clock, rising edge
	;movlw	b'11000100'	; Prescaler 1:32  Enable Timer0, 8-bit, internal clock, rising edge
	;movlw	b'11000010'	; Prescaler 1:8   Enable Timer0, 8-bit, internal clock, rising edge
	;movlw	b'11000000'	; Prescaler 1:2   Enable Timer0, 8-bit, internal clock, rising edge

; movwf T0CON,A ; Initialize Timer

	
	BSF		TRISA,RA0
	movlw	b'00000001'
	movwf	ADCON0,A	; Initialize A/D Converter
	movlw	b'00001110'	; AN0
	movwf	ADCON1,A	; Initialize A/D Converter
	movlw	b'10011011'
	movwf	ADCON2,A

; Initialize I2C Comm

	movlw	0x09		; For 4MHz Clock
	movwf	SSPADD
	BSF		SSPSTAT,SMP	; Disable Slew Rate Control
	BCF		SSPSTAT,CKE	; Disable SMBus specific inputs
	movlw	b'00001000'	; MSSP as I2C Master
	movwf	SSPCON1

BSF SSPCON1,SSPEN ; Enable SSP Module

	#ifdef	LCD_PICDEM
		call	XLCDClear	; Clear LCD
	#endif
		movlw	0xff
		movwf	Checksum
		clrf	Brightness
		incf	Brightness,F

loop

		call	Read_AD		; Read A/D Converter
		movf	ADRESL,W,A	; Move ADRESL
		movwf	Mult0,A		; to Mult0
		movf	ADRESH,W,A	; Move ADRESL
		movwf	Mult1,A		; to Mult1
		clrf	Mult2,A		; Clear Mult2
		clrf	_Error,A	; Clear _Error
		call	_41_Sub
		call	_141_Multiply
		call	_Divide_by_128
		call	bin16_bcd
		
		movlw	0			; Skip updating if no change
		xorwf	Thou,W,A	;
		xorwf	Hund,W,A	;
		xorwf	Tens,W,A	;
		xorwf	Ones,W,A	;
		movwf	Mtemp0,A	;
		subwf	Checksum,W,A;
		btfsc	STATUS,Z	;
		goto	No_Change	;
		movf	Mtemp0,W,A	;
		movwf	Checksum,A	;							
		I2C_SendStart
		movlw	SAA1064ADDRESS	; Address, Write Mode
		movwf	SSPBUF
		call	I2C_BusyWait
		I2C_AckWait
		movlw	0x00		; Send Instruction Byte
		movwf	SSPBUF
		call	I2C_BusyWait
		I2C_AckWait
		call	Brightfunc
		movwf	SSPBUF
		call	I2C_BusyWait
		I2C_AckWait
		
		movf	_Error,F,A		; If _Error is set, change output to ---
		btfsc	STATUS,Z
		goto	noerr
		MOVLW	SAA1064SEGDASH
		call	SEG_SEND
		call	SEG_SEND
		call	SEG_SEND
		call	SEG_SEND
		I2C_SendStop
		goto	LCDpart

noerr

		movf	Ones,W
		call	SEG_LOOKUP
		call	SEG_SEND	
		
		movf	Tens,W
		call	SEG_LOOKUP
		movwf	Mult0,A		; Add Decimal Point
		BSF		Mult0,7		; to the right of
		movf	Mult0,W		; the second digit
		call	SEG_SEND
		
		movf	Thou,W
		addwf	Hund,W
		btfsc	STATUS,Z	; Blank character if 0
		goto	blnkchr
		MOVF	Hund,W
		call	SEG_LOOKUP

blnkchr call SEG_SEND

		movf	Thou,W
		btfss	STATUS,Z	; Blank character if 0
		call	SEG_LOOKUP
		call	SEG_SEND
		I2C_SendStop	; Send STOP over I2C

; call ; goto loop

		; Convert Thou:Hund:Tens:Ones to ASCII

LCDpart movlw '0'

		addwf	Thou,F,A
		addwf	Hund,F,A
		addwf	Tens,F,A
		addwf	Ones,F,A
		
		; Suppress Leading 0 for Thousands
		movlw	'0'
		subwf	Thou,W,A
		movlw	' '
		btfss	STATUS,Z	; If Thou was '0'
		goto	Skip_Blank
		movwf	Thou,A		; Change to ' '
		
		; Suppress Leading 0 for hundreds
		movlw	'0'
		subwf	Hund,W,A
		movlw	' '
		btfsc	STATUS,Z	; If Hund was '0'
		movwf	Hund,A		; Change to ' '

Skip_Blank

		movf	_Error,F,A		; If _Error is set, change output to ---
		btfsc	STATUS,Z
		goto	No_Error
		movlw	'-'
		movwf	Thou,A
		movwf	Hund,A
		movwf	Tens,A
		movwf	Ones,A

No_Error

		
	#ifdef	LCD_PICDEM
		call	XLCDClear	; Clear LCD
		movf	Thou,W,A
		call	XLCDPut
		movf	Hund,W,A
		call	XLCDPut
		movf	Tens,W,A
		call	XLCDPut
		movlw	'.'
		call	XLCDPut
		movf	Ones,W,A
		call	XLCDPut
		movlw	' '
		call	XLCDPut
		movlw	'P'
		call	XLCDPut
		movlw	's'
		call	XLCDPut
		movlw	'i'
		call	XLCDPut
		movlw	' '
		call	XLCDPut
		movlw	' '
		call	XLCDPut
		movlw	'0'
		addwf	Brightness,W
		call	XLCDPut
		movlw	'/'
		call	XLCDPut
		movlw	'7'
		call	XLCDPut
	#endif
		

No_Change

		call	Delay
		
		goto	loop

; ; Subroutines ;

Read_AD

	bsf		ADCON0,GO_DONE,A	; Take AD measurement

Check_AD btfsc ADCON0,GO_DONE,A ; Wait until done

	goto	Check_AD	; Loop until Done
	return

RA4_Button

btfsc	PORTA,RA4
return
clrf	Mult0
nop
nop
decfsz	Mult0,f
goto	$-6
btfsc	PORTA,RA4
return
btfss	PORTA,RA4
goto	$-2

; btg PORTB,RB0

incf	Brightness,f
btfsc	Brightness,3
clrf	Brightness
return

Brightfunc ; movf Brightness,f ; btfsc STATUS,Z ; incf Brightness,f

movlw	b'00000111'
andwf	Brightness,w
movwf	Temp
bcf		STATUS,C
rlncf	Temp,f
rlncf	Temp,f
rlncf	Temp,f
rlncf	Temp,f
movlw	SAA1064CONTROL
IORWF	Temp,w
movwf	SAA_Control
return

I2C_BusyWait ; Wait until I2C is free

		bsf		LATB,RB3

BW_loop btfsc SSPSTAT,NOT_W

		goto	BW_loop

BW_loop2 movf SSPCON2,W

		andlw	b'0001111'	; Check ACKEN, RCEN, PEN, RSEN, SEN
		btfss	STATUS,Z
		goto	BW_loop2
		BCF		LATB,RB3

; btfss SSPSTAT,BF

		return

SEG_SEND

	MOVWF	Mult1
	MOVWF	SSPBUF
	CALL	I2C_BusyWait
	I2C_AckWait
	MOVF	Mult1,W
	return

Delay

		movlw	b'00000010'	; Prescaler 1:8  Disable Timer0, 16-bit, internal clock, rising edge
		
		;movwf	T0CON,A		; Initialize Timer			
		;bcf		INTCON,T0IF,A	; Clear Timer0
		movwf	T0CON,A		; Initialize Timer			
		bcf		INTCON,TMR0IF,A	; Clear Timer0
		
		movlw	0xFF		; Delay
		movwf	TMR0H
		movlw	b'10000000'		; Delay
		movwf	TMR0L
		bsf		T0CON,TMR0ON	; Enable Timer0

Delay_wt ;call RA4_Button ; Check RA4 Button

		btfss	INTCON,TMR0IF,A
		goto	Delay_wt		; Wait until delay
		bcf		T0CON,TMR0ON
		return

TX_Pressure ; Display “Pressure”

	#ifdef	LCD_PICDEM
		movlw	'P'
		call	XLCDPut
		movlw	'r'
		call	XLCDPut
		movlw	'e'
		call	XLCDPut
		movlw	's'
		call	XLCDPut
		movlw	's'
		call	XLCDPut
		movlw	'u'
		call	XLCDPut
		movlw	'r'
		call	XLCDPut
		movlw	'e'
		call	XLCDPut
		movlw	':'
		call	XLCDPut
		movlw	' '
		call	XLCDPut
		movlw	'_'
		call	XLCDPut
		movlw	'_'
		call	XLCDPut
		movlw	'.'
		call	XLCDPut
		movlw	'_'
		call	XLCDPut
	#endif
		return

_Divide_by_128 ; Divide by 2^7

		rlcf	Mult0,F,A	; Rotate left 1 (Multiply by 2)
		rlcf	Mult1,F,A	;
		rlcf	Mult2,F,A	;
		
		movf	Mult1,W,A	; Rotate right 8 (Divide by 256)
		movwf	Mult0,A		;
		movf	Mult2,W,A	;
		movwf	Mult1,A		;
		movlw	0			;
		movwf	Mult2,A		;
		return

_41_Sub ; Subtract 41

		movlw	.41
		subwfb	Mult0,F,A	; Subtract 41
		btfsc	STATUS,C	; If no Carry,
		goto	_41end		; goto end
		movf	Mult1,W,A	
		btfsc	STATUS,Z	; Make sure ADH is not zero
		goto	_41Error	; Otherwise ERROR
		decf	Mult1,F,A	; Decrement ADH for carry
		goto	_41end

_41Error movlw 0xFF

		movwf	_Error,A
		movlw	0
		movwf	Mult1,A
		movwf	Mult0,A

_41end

		retlw	0

_141_Multiply ; Generated by www.piclist.com/cgi-bin/constdivmul.exe (1-May-2002 version) ; Sat Dec 29 07:01:17 2007 GMT ; Mult = Mult * 141 ; Temp = Mtemp ; Mult size = 10 bits ; Error = 0.5 % ; Bytes order = little endian ; Round = no

; ALGORITHM: ; Clear accumulator ; Add input * 128 to accumulator ; Add input * 8 to accumulator ; Add input * 4 to accumulator ; Add input * 1 to accumulator ; Move accumulator to result ; ; Approximated constant: 141, Error: 0 %

; Input: Mult0 .. Mult1, 10 bits ; Output: Mult0 .. Mult2, 18 bits ; Code size: 45 instructions

	
	;copy accumulator to temporary
		movf	Mult1,w,A
		movwf	Mtemp1,A
		movf	Mult0,w,A
		movwf	Mtemp0,A
	
	
	;shift temporary left 2 times
		bcf		STATUS,C
		rlcf	Mtemp0,f,A
		rlcf	Mtemp1,f,A
		rlcf	Mtemp0,f,A
		rlcf	Mtemp1,f,A
	
	;add temporary to accumulator
		movf	Mtemp0,w,A
		addwf	Mult0,f,A
		movf	Mtemp1,w,A
		BTFSC	STATUS,C
		incfsz	Mtemp1,w,A
		addwf	Mult1,f,A
	
	;shift temporary left 1 times
		bcf		STATUS,C
		rlcf	Mtemp0,f,A
		rlcf	Mtemp1,f,A
	
	;add temporary to accumulator
		movf	Mtemp0,w,A
		addwf	Mult0,f,A
		movf	Mtemp1,w,A
		BTFSC	STATUS,C
		incfsz	Mtemp1,w,A
		addwf	Mult1,f,A
	
	;shift temporary left 4 times
		swapf	Mtemp1,f,A
		movf	Mtemp1,w,A
		andlw	0x0F
		xorwf	Mtemp1,f,A
		movwf	Mtemp2,A
		swapf	Mtemp0,f,A
		movf	Mtemp0,w,A
		andlw	0x0F
		xorwf	Mtemp0,f,A
		iorwf	Mtemp1,f,A
	
	;add temporary to accumulator
		clrf	Mult2
		movf	Mtemp0, w
		addwf	Mult0, f
		movf	Mtemp1, w
		BTFSC	STATUS,C
		incfsz	Mtemp1, w
		addwf	Mult1, f
		movf	Mtemp2, w
		BTFSC	STATUS,C
		incfsz	Mtemp2, w
		addwf	Mult2, f
		retlw	0

;—————- Binary (16-bit) to BCD ———————– ; Microchip Code ; xxx = highest possible result bin16_bcd

                       ; Takes number in Mult1:Mult0 
                              ; Returns decimal in 
                              ; TenK:Thou:Hund:Tens:Ones 
      swapf   Mult1,W 
      andlw   0x0F
      addlw   0xF0
      movwf   Thou 
      addwf   Thou,F 
      addlw   0xE2 
      movwf   Hund 
      addlw   0x32 
      movwf   Ones 
      movf    Mult1,W 
      andlw   0x0F 
      addwf   Hund,F 
      addwf   Hund,F 
      addwf   Ones,F 
      addlw   0xE9 
      movwf   Tens 
      addwf   Tens,F 
      addwf   Tens,F 
      swapf   Mult0,W 
      andlw   0x0F 
      addwf   Tens,F 
      addwf   Ones,F 
      rlcf     Tens,F 
      rlcf     Ones,F 
      comf    Ones,F 
      rlcf     Ones,F 
      movf    Mult0,W 
      andlw   0x0F 
      addwf   Ones,F 
      rlcf     Thou,F 
      movlw   0x07 
      movwf   TenK 
      movlw   0x0A                             ; Ten 

Lb1:

      decf    Tens,F 
      addwf   Ones,F 
      btfss   STATUS,C 
       bra   Lb1 

Lb2:

      decf    Hund,F 
      addwf   Tens,F 
      btfss   STATUS,C 
       bra   Lb2 

Lb3:

      decf    Thou,F 
      addwf   Hund,F 
      btfss   STATUS,C
       bra   Lb3 

Lb4:

      decf    TenK,F 
      addwf   Thou,F 
      btfss   STATUS,C 
       bra   Lb4 
      retlw   0

HiPriority_ISR

		nop
		return
		
		end

</asm>

  • projects/electronics/tirepressuresensor/code.1231387935.txt.gz
  • Last modified: 2014/11/13 10:50
  • (external edit)