PDA

View Full Version : PIC16F877 I2C programme



cooqo
- 21st April 2008, 03:08
;************************************************* ***
;* 877I2CA.asm *
;* Very simple I2C sample program without Display *
;************************************************* ***
;************************************************* *****************************************
; This source code provides a demonstration of the MSSP peripheral
; on the PIC16F877 MCU.
; The additional external subroutine are used for LCD Module
; PIC16F877 frequency : 4 Mhz
;
; The subroutines for I2C
; :I2C_BYTE_READ ; Read a Byte from Address I2C_Addr and put into I2C_Data
; :I2C_BYTE_WRITE ; Write to I2C_Addr with data @ I2C_Data
; :I2C_ACK_CHECK ; Wait until I2C device can accept further command
; :InitI2C ; Initial I2C Module
; :StartI2C ; Set START Condition !!
; :StopI2C ; Set STOP Condition
; :RstartI2C ; Set Restart Condition
; :RecI2C ; Enable I2C Receive
; :ACKI2C ; Initial ACK response
; :NACKI2C ; Initial NACK response
; :WaitI2C ; Wait until SSPIF Set
;************************************************* ********************************************

list p=16f877
#include <p16f877.inc>

CBLOCK 0x20

I2C_Data
I2C_Addr

ENDC

w_temp EQU 0x72
status_temp EQU 0x73
pclath_temp EQU 0x74


;********************************************
; Locates startup code @ the reset vector
;********************************************
Reset_Addr
org 0x00
nop
goto Prog_Main
nop
nop

;************************************************* ************
;**** The Start Address of ISR is 0x00
;************************************************* ************

PUSH
movwf w_temp ; save off current W register contents
movf STATUS,w ; move status register into W register
movwf status_temp ; save off contents of STATUS register
movf PCLATH,W
movwf pclath_temp


POP
movf pclath_temp,W
movwf PCLATH
movf status_temp,w ; retrieve copy of STATUS register
movwf STATUS ; restore pre-isr STATUS register contents
swapf w_temp,f
swapf w_temp,w ; restore pre-isr W register contents
retfie ; return from interrupt


;----------------------------------------------------------------------

Prog_Main

BANKSEL TRISB ; Select Bank 1
movlw b'11000000' ; setup PORTB
movwf TRISB

BSF OPTION_REG,NOT_RBPU ; Disable PORTB pull-ups
BCF STATUS, RP0 ; Select Bank 0

call InitI2C

Main:

BANKSEL I2C_Addr
movlw 0x18
movwf I2C_Addr

BANKSEL I2C_Data ; Bank Switching, in case its bank is differ than I2C_Addr !!
movlw 0x99
movwf I2C_Data
call I2C_BYTE_WRITE ; Write to I2C Device when Address & Data are set OK

call I2C_ACK_CHECK ; Check the ACK response, Wait until the Device Acknowledge
; Issue !! The subroutine will not return until the device send ACK !!


BANKSEL I2C_Addr
movlw 0x18
movwf I2C_Addr
call I2C_BYTE_READ

nop
nop
goto $


;************************************************* ***************************
I2C_BYTE_READ: ; Read a Byte @ I2C_Addr to Buffer I2C_Data
;************************************************* ***************************

call StartI2C ; Set SSPCON2.SEN
call WaitI2C ; Wait PIR1,SSPIF

BANKSEL SSPBUF
movlw B'10100000' ; Write Command
movwf SSPBUF
call WaitI2C

BANKSEL I2C_Addr ; The "BANKSEL" may not necessary if I2C_Addr is @ the same bank with SSPBUF
movf I2C_Addr,W ; The Address you wish to "READ" from

BANKSEL SSPBUF
movwf SSPBUF
call WaitI2C

call RstartI2C ; Restart Condition !!
call WaitI2C ; Wait Until Restart OK !!

BANKSEL SSPBUF
movlw B'10100001' ; Write Read Command
movwf SSPBUF
call WaitI2C

call RecI2C ; Enable I2C Receive
call WaitI2C ; Wait Until Buffer Received
BANKSEL SSPBUF
movf SSPBUF,W ; Save to I2C_Data First !!
BANKSEL I2C_Data
movwf I2C_Data

call NACKI2C ; Initial NACK Response !!
call WaitI2C ; Wait until NACK sent out
call StopI2C ; Initial STOP Condition
call WaitI2C ; Wait Until STOP Condition Terminated
return

;************************************************* ***************************
I2C_ACK_CHECK: ; Read a Byte @ I2C_Addr to Buffer I2C_Data
;************************************************* ***************************

call StartI2C ; Set SSPCON2.SEN
call WaitI2C ; Wait PIR1,SSPIF

BANKSEL SSPBUF
movlw B'10100001' ; Read Command
movwf SSPBUF
call WaitI2C

BANKSEL SSPCON2
btfss SSPCON2,ACKSTAT ; Check ACKSTAT bit , 0 = ACK , 1 = NACK
goto ACK_Return
call StopI2C
call WaitI2C
goto I2C_ACK_CHECK

ACK_Return:
call StopI2C ; Initial STOP Condition
call WaitI2C ; Wait Until STOP Condition Terminated
return

;************************************************* ***************************
I2C_BYTE_WRITE: ; Write a Byte to I2C_Addr with I2C_Data
;************************************************* ***************************

call StartI2C ; Set SSPCON2.SEN
call WaitI2C ; Wait PIR1,SSPIF

BANKSEL SSPBUF
movlw B'10100000' ; Write Command
movwf SSPBUF
call WaitI2C

BANKSEL I2C_Addr ; The "BANKSEL" may not necessary if I2C_Addr is @ the same bank with SSPBUF
movf I2C_Addr,W ; The Address you wish to "READ" from
BANKSEL SSPBUF
movwf SSPBUF
call WaitI2C

BANKSEL I2C_Data
movf I2C_Data,W
BANKSEL SSPBUF
movwf SSPBUF
call WaitI2C

call StopI2C ; Initial STOP Condition
call WaitI2C ; Wait Until STOP Condition Terminated
return


;************************************************* *********************
; The following subroutines perform commonly used I2C functions.
;************************************************* *********************

InitI2C: ; The subroutine of I2C Initialization
BANKSEL TRISC
movlw B'00011000' ; Initial PortC,bit 3 & 4 as Input
movwf TRISC ; RC3 = SCL , RC4 = SDA

BANKSEL PORTC
movlw 0xff
movwf PORTC

movlw 0x09 ; This gives 100KHz I2C clock @ 4MHz
banksel SSPADD
movwf SSPADD
movlw b'10000000' ; Disable slew rate control.
banksel SSPSTAT
movwf SSPSTAT
movlw b'00000000' ;
movwf SSPCON2 ; Setup MSSP for continuous reception.
movlw b'00101000' ; Enable MSSP and setup for I2C master
banksel SSPCON ; mode.
movwf SSPCON
return


StartI2C ; Initiate the I2C START condition.
banksel SSPCON2
bsf SSPCON2,SEN
return

StopI2C ; Initiate the I2C STOP condition.
banksel SSPCON2
bsf SSPCON2,PEN
return

RstartI2C ; Initiate the I2C restart condition.
banksel SSPCON2
bsf SSPCON2,RSEN
return

NACKI2C
banksel SSPCON2
bsf SSPCON2,ACKDT ; Set the ACK bit
bsf SSPCON2,ACKEN ; Initiate the NACK sequence.
return

ACKI2C
banksel SSPCON2
bcf SSPCON2,ACKDT ; Clear the ACK bit
bsf SSPCON2,ACKEN ; Initiate the NACK sequence.
return

RecI2C
banksel SSPCON2 ;
bsf SSPCON2,RCEN ; Set the receive enable bit.
return


WaitI2C ; Poll for SSPIF
banksel PIR1
FLoop btfss PIR1,SSPIF
goto FLoop
bcf PIR1,SSPIF
return


;----------------------------------------------------------------------

end ; *********** End Of Program !!!!!

precision
- 21st April 2008, 09:32
So what's the problem in this code ?

.

Acetronics2
- 21st April 2008, 09:40
May be the problem is assembler !!!

or




#include



could be a problem too ...

Alain

precision
- 21st April 2008, 10:02
Oh, forget to include




list p=16f877a
include "p16f877a.inc"



This code example is Written by: Richard Yang , Sr. Corporate Application Engineer, Microchip Technology Inc.

Read this app. note

http://www.pic16.com/tigao/041013/I2C_EE.asm


.