PIC Microcontroller, I2C, Assembly Example, PIC16F1823

Download as pdf or txt
Download as pdf or txt
You are on page 1of 9
At a glance
Powered by AI
The key takeaways are that this code implements an I2C module to communicate with an MCP4018 digital potentiometer over I2C. A potentiometer value is read and updated periodically by a timer interrupt to control the brightness of an LED. The I2C module is configured to operate in master mode at 400kbps and uses interrupts to handle communication.

The purpose of the I2C module is to communicate with an MCP4018 digital potentiometer over the I2C bus to read the current potentiometer value and send updates to control the brightness of an LED.

The I2C module is configured by setting the SSP1CON1, SSP1ADD and SSP1STAT registers to operate in master mode at 400kbps baud rate. The SCL and SDA pins are configured as inputs. Interrupts are enabled for the SSP module. The i2c_status variable tracks the current state.

;******************************************************************************

; Filename:
I2C.asm
*
; Date:
November 6, 2012
*
; File Version:
1.0
*
;
*
; Author:
Nolan Manteufel
*
;
*
; Company:
University of Texas at San Antonio
*
; URL:
www.utsa.edu/engineering
*
;
*
;******************************************************************************
list
#include

p=16f1823
; list directive to define processor
<p16f1823.inc> ; processor specific variable definitions

;-----------------------------------------------------------------------------; CONFIGURATION WORD SETUP


;-----------------------------------------------------------------------------__CONFIG
_CONFIG1, _CP_OFF & _WDTE_ON & _FOSC_INTOSC &
_PWRTE_OFF & _MCLRE_ON & _CLKOUTEN_OFF
__CONFIG
_CONFIG2, _LVP_OFF & _BORV_HI & _STVREN_ON & _WRT_OFF
;-----------------------------------------------------------------------------; RAM
;-----------------------------------------------------------------------------CBLOCK 0x20
; Location of RAM
POT
; Used for Potentiometer
POT_VALUE
;
POT_LOCATION
;
x
; Used for pointless math
i2c_address
; Used for I2C
i2c_address_buffer
;
i2c_status
;
i2c_status_buffer
;
i2c_data_out
;
i2c_data_out_buffer
;
i2c_data_in
;
i2c_data_in_buffer
;
ENDC
;
;-----------------------------------------------------------------------------; DEFINITIONS
;-----------------------------------------------------------------------------DIR
EQU
0x03
; 1 = getting brighter, 0 = getting dimmer.

LED
EQU
;---------------------------------------setup_i2c
EQU
ready_i2c
EQU
;---------------------------------------start_i2c
EQU
stop_i2c
EQU
;---------------------------------------address_put_i2c
EQU
;---------------------------------------data_put_i2c
EQU
done_i2c
EQU

0x05

; LED location on PORTC

0x00
0x01

; I2C Status Values


;

0x02
0x04

;
;

0x05

0x0e
0x10

;
;

;-----------------------------------------------------------------------------; RESET VECTOR


;-----------------------------------------------------------------------------ORG 0x0000
; Reset vector
nop
;
goto START
;
;-----------------------------------------------------------------------------; INTERRUPT SERVICE ROUTINE
;-----------------------------------------------------------------------------ORG
0x0004
;
nop
;
banksel
INTCON
;
btfsc
INTCON, TMR0IF
; checks for TIMR0 IF
goto
timer0_isr
;
banksel
PIR1
;
btfsc
PIR1, SSP1IF
; checks for I2C IF
goto
run_I2C
;
banksel
INTCON
;
movlw
b'01100000'
;
movwf
INTCON
;
retfie
;
;------------------------------------------------------------------------------; TIMER0 Interrupt Service Routine
;------------------------------------------------------------------------------timer0_isr
;
banksel
i2c_status
;
movfw
i2c_status
;
sublw
ready_i2c
;
btfss
STATUS, Z
;

retfie
POT_VALUE
banksel
POT_VALUE
btfsc
goto
goto
brighter
banksel
incf
movfw
xorlw
btfsc
goto
movfw
movwf
movfw
movwf
movlw
movwf
call
banksel
movlw
movwf
retfie
dimm_down
banksel
bcf
retfie
dimmer
banksel
decf
movfw
xorlw
btfsc
goto
movfw
movwf
movfw
movwf
movlw
movwf
call
banksel

; clear == I2C busy, don't modify the


POT

; set == I2C ready, modify and send

POT, DIR
brighter
dimmer

;
; set == going up
; clear == going down
;
;
;
;
;
;
; set == maximum limit
; clear == still going up
;
;
;
;
;
;
;
;
;
;
;
;
; change direction
;
;
;
;
;
;
;
; set == minumum limit
; clear == still going down
;
;
;
;
;
;
;

POT_VALUE
POT_VALUE, F
POT_VALUE
0xd0
STATUS, Z
dimm_down
POT_LOCATION
i2c_address
POT_VALUE
i2c_data_out
start_i2c
i2c_status
run_I2C
INTCON
b'01100000'
INTCON

POT
POT, DIR

POT_VALUE
POT_VALUE, F
POT_VALUE
0xb0
STATUS, Z
brighten_up
POT_LOCATION
i2c_address
POT_VALUE
i2c_data_out
start_i2c
i2c_status
run_I2C
INTCON

movlw
movwf
retfie
brighten_up
banksel
bsf
retfie

b'01100000'
INTCON

POT
POT, DIR

;
;
;
;
;
; change direction
;

;-----------------------------------------------------------------------------; MAIN PROGRAM


;-----------------------------------------------------------------------------START
;
movlw
0xb0
;
banksel
POT_VALUE
;
movwf POT_VALUE
;
movlw
b'01011110'
; MCP4018 address
movwf
POT_LOCATION
;
bsf
POT, DIR
;
;------------------------------------------------------------------------------; Configuring PORTC for LED, see page 129 of PIC16F1823 datasheet
;------------------------------------------------------------------------------config_PORTC
banksel
PORTC
bcf
PORTC, LED
banksel
LATC
bcf
LATC, LED
banksel
ANSELC
clrf
ANSELC
banksel
TRISC
bcf
TRISC, LED
;-----------------------------------------------------------------------------; Initialize RAM used for I2C.
;-----------------------------------------------------------------------------banksel
i2c_status
;
clrf
i2c_address
;
clrf
i2c_address_buffer
;
clrf
i2c_status
;
clrf
i2c_status_buffer
;
clrf
i2c_data_out
;
clrf
i2c_data_out_buffer
;
clrf
i2c_data_in
;
clrf
i2c_data_in_buffer
;

call

run_I2C

; Initializes the I2C Module

;------------------------------------------------------------------------------; Configuring Timer0 and Interrupts, see page 177 of PIC16F1823 datasheet
;------------------------------------------------------------------------------banksel
TMR0
;
clrf
TMR0
;
banksel
OPTION_REG
;
movlw
b'00000011'
; Number to configure TIMER0.
movwf
OPTION_REG
;
banksel
INTCON
;
movlw
b'11100000'
;
movwf
INTCON
;
;------------------------------------------------------------------------------; Pointless math
;------------------------------------------------------------------------------math
;
incf
x,F
;
movlw 0x04
;
movfw i2c_status
;
addwf x,F
;
decf x,F
;
goto math
;
;------------------------------------------------------------------------------; I2C
;------------------------------------------------------------------------------run_I2C
; Only PUBLIC I2C function
clrwdt
;
movlw
setup_i2c
;
banksel
i2c_status
;
xorwf
i2c_status
;
banksel
STATUS
;
btfsc
STATUS, Z
;
goto
setup_I2C
;
banksel
movfw
sublw
btfsc
return

i2c_status
i2c_status
ready_i2c
STATUS, Z

;
;
;
;

movfw

i2c_status

sublw
btfsc
goto

start_i2c
STATUS, Z
start_I2C

;
;
;

movfw
sublw
btfsc
goto

i2c_status
stop_i2c
STATUS, Z
stop_I2C

;
;
;
;

movfw
sublw
btfsc
goto

i2c_status
address_put_i2c
STATUS, Z
addressPut_I2C

;
;
;
;

movfw
sublw
btfsc
goto

i2c_status
data_put_i2c
STATUS, Z
dataPut_I2C

;
;
;
;

movfw
sublw
btfsc
goto
goto

i2c_status
done_i2c
STATUS, Z
done_I2C
setup_I2C

;
;
;
;
;

setup_I2C
;------------------------------------------------------------------------------; Configuring I2C, see page 277 of PIC16F1823 datasheet
;------------------------------------------------------------------------------banksel
SSP1CON1
; Mode: Master I2C
movlw
b'00101000'
;
movwf SSP1CON1
;
banksel
SSP1ADD
; Baud Rate == 400KHz @ 16MHz
movlw
b'00001001'
;
movwf SSP1ADD
;
banksel
SSP1STAT
; Slew Rate == enabled
movlw
b'00000000'
;
movwf SSP1STAT
;
banksel
TRISC
; Pins == inputs
bsf
TRISC, SCL
;
bsf
TRISC, SDA
;
banksel
PIR1
; Interrupts
bcf
PIR1, SSP1IF
;
banksel
INTCON
;

bsf
banksel
bsf
banksel
bcf
movlw
banksel
movwf
return
start_I2C
banksel
bsf
movlw
banksel
movwf
return

INTCON, PEIE
PIE1
PIE1, SSP1IE
PIE2
PIE2, BCL1IE
ready_i2c
i2c_status
i2c_status

SSP1CON2
SSP1CON2, SEN
address_put_i2c
i2c_status
i2c_status

addressPut_I2C
banksel
PIR1
bcf
PIR1, SSP1IF
banksel
i2c_address
movfw
i2c_address
banksel
SSP1BUF
movwf SSP1BUF
movlw
data_put_i2c
banksel
i2c_status
movwf
i2c_status
retfie

;
;
; SSP Event IF == enable
;
; SSP Collision IF == disable
;
;
; Set i2c_status = ready_i2c
;
;
;
; Sends start signal,
; Sets status to "address_put_i2c",
;
;
; Returns to wait for interrupt.
;
;
; Clears interrupt flag.
;
; MCP4018 address == b'01011110'
;
; Sends the address,
;
;
; Sets the status to "data_put_i2c",
; Returns from Interrupt.

dataPut_I2C
;
banksel
PIR1
;
bcf
PIR1, SSP1IF
; Clears interrupt flag.
banksel
SSP1CON2
;
btfsc
SSP1CON2, ACKSTAT
;
goto
test_NACK
; set = NACK
banksel
i2c_data_out
; clear = ACK, chip ready
movfw
i2c_data_out
;
banksel
SSP1BUF
;
movwf SSP1BUF
; Sends the data, Sets status to "stop_i2c",
movlw
stop_i2c
;
banksel
i2c_status
;
movwf
i2c_status
;
banksel
PORTC
;

bcf
retfie
stop_I2C
banksel
bcf
banksel
btfsc
goto
bsf
movlw
banksel
movwf
retfie
test_NACK
banksel
bsf
goto
done_I2C
banksel
bcf
movlw
banksel
movwf
movfw
btfsc
retfie
movwf
clrf
movfw
movwf
clrf
movfw
movfw
clrf
movfw
movwf
mode.
clrf
call
retfie

PORTC, LED

; Sets status to "stop_i2c".


; Returns from interrupt.

PIR1
PIR1, SSP1IF
;
SSP1CON2
SSP1CON2, ACKSTAT
test_NACK
SSP1CON2, PEN
done_i2c
i2c_status
i2c_status

i2c_status
i2c_status_buffer
i2c_address_buffer
i2c_address
i2c_address_buffer
i2c_data_out_buffer
i2c_data_out
i2c_data_out_buffer
i2c_data_in_buffer
i2c_data_in
i2c_data_in_buffer
run_I2C

;
;
; set = NACK
; clear = ACK, data sent
;
;
; Sets status to "done_i2c".
; Returns from interrupt.
;
;
;
;

PORTC
PORTC, LED
done_I2C

PIR1
PIR1, SSP1IF
ready_i2c
i2c_status
i2c_status
i2c_status_buffer
STATUS, Z

;
;

;
;
;
;
;
; Sets status to "ready_i2c".
; Checks i2c_status_buffer,
;
; clear = buffer empty.
; set = buffer full.
;
;
;
;
;
;
;
; In/Out data registers is pointless for I2C.
; In/Out distinction may be helpful for SPI
;
;
;

END

You might also like