Home > pic18f, Uncategorized > pic18f assembly example 5 – Sample ADC and pass through to DAC

pic18f assembly example 5 – Sample ADC and pass through to DAC

;-----------------------------------------------------------------------------------------------------------------------------
; This assembly code sets up a timer interrupt to be triggered every millisecond on the pic18f4620.
; When the interrupt service routine is called an ADC on channel 0 is performed and this value is sent a DAC (MCP4921) via a SPI protocol.
;
; Test cicruit used is same as at http://eleceng.dit.ie/daq_lite/build.html
;
; In the main part of the code the value associated with analog channel 0 is monitored in a continuous loop. If the value
;   is high then LATD2 is set high otherwise LATD2 is set low
;
; by David Dorran (https://dadorran.wordpress.com) May 2014
;-----------------------------------------------------------------------------------------------------------------------------
 
;configure the  assembler directive 'list' so as to set processor to 18f4620 and set the radix used for data expressions to decimal (can be HEX|DEC|OCT)

;configure the  assembler directive 'list' so as to set processor to 18f4620 and set the radix used for data expressions to decimal (can be HEX|DEC|OCT)
    list p=18f4620, r=DEC
    #include <p18f4620.inc>
; configure the micro so that the watchdog timer is off, low-voltage programming is off, master clear is off and the clock works off the internal oscillator
    config WDT=OFF, LVP=OFF, MCLRE=OFF, OSC=INTIO67
;The org directive tells the compiler where to position the code in memory
    org 0x0000 ;The following code will be programmed in reset address location i.e. This is where the micro jumps to on reset
    goto Main ;Jump to Main immediately after a reset

 ;NOTE: When an interrupt is triggered the micro jumps to 0x0008 for high priority and 0x0018 for low priority.
    org 0x0008
    goto hi_isr ;once a high priority interrupt is triggered jump to hi_isr
    org 0x0018
    goto low_isr ;once a low priority interrupt is triggered jump to low_isr

;--------------------------------------------------------------------------
; Main Program -------------------------------------------------------------
;--------------------------------------------------------------------------
    org 0x0100 ; the following code is placed at address 0x0100 in program memory (Flash memory)
Main

y  equ  0x20 ; y refers to a register at address 0x20
    call micro_config ; configure pins,timers, ADC etc.

main_loop
    nop ; Just wait for a timer interrupt to be triggered
    goto main_loop

    ;----------------------------------------------------------------------------------------------------------
    ;-----High Priority Interrupt Service Routine -------------------------------------------------------------
    ;----------------------------------------------------------------------------------------------------------
    org 0x0200
hi_isr
    btfss INTCON, TMR0IF
    goto end_int
    bcf INTCON, TMR0IF; reset interrupt
     ;An interrupt has been set up to be generated whenever TMR0 goes from FFFFh to 0000h i.e. on overflow.
    ;Would like the timer overflow flag triggered every 1ms so will set timer to 0xffff - 1000 = 0xFC17
    movlw 0x17
    movwf TMR0L
    movlw 0xFC
    movwf TMR0H

	bsf ADCON0,GO; start ADC conversion

    ; wait for hardware to reset GO bit - indicating ADRES SFR is ready to read
adc_not_ready
	btfsc ADCON0, GO
    goto adc_not_ready

    movff ADRESH, y
    goto spi_write ;write contents of y to SPI device
end_int
    retfie ;return and reset interrupts

    
    
    ;----------------------------------------------------------------------------------------------------------
    ;-------configure pins, ADC,timers and interrupts on the pic18f4620    -----------------------------------
    ;----------------------------------------------------------------------------------------------------------
micro_config
     ; configure LATD0-LATD3 as outputs and RD4-RD7 as inputs
    movlw 0xf0
    movwf TRISD
    clrf LATD ; turn off all LATD output pins

    ; SPI configuration ------------------------------------------------------------
    clrf TRISC
    ;bcf TRISC,3 ; pin 3 on PORTC used as SPI clock and should be configured as an output to operate in master mode
    ;bcf TRISC,5 ; pin 5 on PORTC used for SPI serial data out (SDO) and should be configured as an output
    movlw B'10110000' ; set up SPI control register see pg 163 for details
    movwf SSPCON1;
    bsf SSPSTAT,CKE; data transmitted on rising edge
    ; END SPI config ----------------------------------------------------------


    ; Set clock frequency (section 2 of the PIC18F4620 Data Sheet)
    ; Set Fosc = 8MHz, which gives Tcy = 0.5us
    movlw B'01110000'
    movwf OSCCON

    ; all channels set up for ADC - no particular reason why
    movlw B'00000001'
 	movwf ADCON1

    ; set tad so that capacitor on ADC can fully charge - see pg129
    movlw B'00100010'
 	movwf ADCON2

    clrf ADCON0; select analog channel 0;
    bsf ADCON0,ADON; //enable ADC

    bcf INTCON, GIE ;Disable global interrupts
    bcf T0CON, TMR0ON; turn off timer 0
    bsf INTCON, TMR0IE; Enable TIMER0 interupt

    ;set up 1:2 prescaler so that TMR0 SFR is incremented every 2 Tcy  i.e. 1us
    bcf T0CON,0
    bcf T0CON,1
    bcf T0CON,2

    bcf T0CON, T0CS; use internal instruction cycle clock
    bcf T0CON, T08BIT; use 16 bit mode
    bcf T0CON, PSA; turn on prescaler

    ; setup so that timer0 overflow is triggered quickly initially
    ; after the first trigger then set it up so that it is triggered at the rate you want in the high_isr routine
    movlw 0xFF
    movwf TMR0L
    movlw 0xFF
    movwf TMR0H

    bsf INTCON2, TMR0IP; ; Set the timer0 interrupt up as high priority
    bsf INTCON, GIE ;Enable global interrupts
    bsf T0CON, TMR0ON; turn on timer 0
    return

    ;----------------------------------------------------------------------------------------------------------
    ;-----WRITE contents in y to DAC (MCP4921) using SPI ------------------------------------------------------
    ;----------------------------------------------------------------------------------------------------------
spi_write
    ;two bytes of data sent to spi daq (a 12-bit dac). First nibble of first byte is dac config settings; second nibble is
    ; the most significant 4 bits of 12bit numerical value. The second byte contains the 8 least signifcant bits of the 12-bit value

	bcf LATD, LATD1; // Select SPI DAC chip

    movf SSPBUF, W ;WREG reg = contents of SSPBUF (this clears BF) which will be set again after the data is transmitted
    ; load SSPBUFF with spi dac config data to be sent to SPI device
    ; First nibble of first byte sent to dac is dac config settings; second nibble is
    ; the most significant 4 bits of 12bit numerical value
    swapf y, f
    movlw 0x0f
    andwf y, W ; W no holds 4 most signicant bits in lower nibble

    iorlw 0x70 ; these are configuration bits for spi dac
    movwf SSPBUF

spi_wait1
    btfss SSPSTAT, BF ;Has data been received (transmit complete)?
    goto spi_wait1 ;No

    movf SSPBUF, W ;WREG reg = contents of SSPBUF (this clears BF) which will be set again after the data is transmitted
    ; load SSPBUFF with y data to be sent to SPI device

    movlw 0xf0
    andwf y, W ;
    movwf SSPBUF

spi_wait2
    btfss SSPSTAT, BF ;Has data been received (transmit complete)?
    goto spi_wait2 ;No

	bsf LATD, LATD1; // Select SPI DAC chip
    goto end_int


    ;----------------------------------------------------------------------------------------------------------
    ;-----Low Priority Interrupt Service Routine -------------------------------------------------------------
    ;----------------------------------------------------------------------------------------------------------
    org 0x0300
low_isr
    nop ; put whatever you would like to do on low priority interrupt here
    retfie ;return and reset interrupts

    end ; End of ASM code
Categories: pic18f, Uncategorized
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: