;????????????????????? Copyright (C) 1997 by Innovatus
; This code may be distributed and used freely provided that this
; copyright notice stays intact and that any modifications are noted.
; For more information about Innovatus: http://www.innovatus.com
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;??? File Name: i2c_low.asm
;?????? Author: Alan G. Smith
;????? Purpose: This code is borrowed from Microchip with all of the fancy
;?????????????? stuff taken out.
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
InitI2CBusMaster
;************************************************************
TxmtStartBit
?? bsf??? Bus_Busy?????????????????????? ; on a start condition bus is busy
?? bsf??? STATUS, RP0??????????????????? ; Select page 1
?? bsf??? _SDA?????????????????????????? ; set SDA high
?? bsf??? _SCL?????????????????????????? ; clock is high
?? call?? Delay40uSec??????????????????? ; This is necessary for setup time
?? bcf??? _SDA?????????????????????????? ; This gives a falling edge on SDA while clock is high
?? call?? Delay47uSec??????????????????? ; Necessary for START HOLD time
?? return
;************************************************************
TxmtStopBit
?? bsf??? STATUS, RP0??????????????????? ; Select page 1
?? bcf??? _SCL?????????????????????????? ; clock is low
?? bcf??? _SDA?????????????????????????? ; set SDA low
?? bsf??? _SCL?????????????????????????? ; clock is pulled up
?? call?? Delay40uSec??????????????????? ; Setup time for STOP condition
?? bsf??? _SDA?????????????????????????? ; rising edge on SDA while CLOCK is high
?? call?? Delay47uSec??????????????????? ; makes sure a START isn‘t sent immediately after a STOP
?? bcf??? Bus_Busy?????????????????????? ; The bus isn‘t busy anymore
?? return
;************************************************************
AbortI2C
?? call?? TxmtStopBit??????????????????? ; Send a stop bit
?? bsf??? Abort????????????????????????? ; set the abort bit
?? return
;************************************************************
TxmtSlaveAddr
?? movf?? SlaveAddr, w?????????????????? ; Move slave address to W
?? bcf??? ACK_Error????????????????????? ; reset Acknowledge error bit
?? movwf? I2CData??????????????????????? ; move W to I2C Data
?? bcf??? I2CData, LSB?????????????????? ; Set for write
?? btfsc? Slave_RW?????????????????????? ; If skip then write operation
?? bsf??? I2CData, LSB?????????????????? ; Clear for read
?? call?? SendData?????????????????????? ; send the address
?? btfss? Txmt_Success?????????????????? ; skip if successful
?? goto?? AddrSendFail?????????????????? ; Oops, we failed
?? retlw? TRUE?????????????????????????? ; return true
AddrSendFail
?? btfss? ACK_Error????????????????????? ; was there an error acknowledging
?? retlw? FALSE????????????????????????? ; No, so return 0
?? call?? TxmtStopBit??????????????????? ; Address not acknowleged, so send STOP bit
?? retlw? FALSE????????????????????????? ; Unsuccessful, so return 0
;************************************************************
SendData
; We might should make a copy of the data here, the example does but I don‘t see why!!!
?? bsf??? Txmt_Progress????????????????? ; We are in the middle of transmitting
?? bcf??? Txmt_Success?????????????????? ; reset success bit
?? movlw? 0x08
?? movwf? I2CBitCount??????????????????? ; Set I2C Bit Count to 8
?? bsf??? STATUS, RP0??????????????????? ; Select page 1
TxmtNextBit:
?? bcf??? _SCL?????????????????????????? ; Set clock Low
?? rlf??? I2CData, F???????????????????? ; MSB First, Note that I2CData is Destroyed
?? bcf??? _SDA?????????????????????????? ; Set clock based on what the MSB is
?? btfsc? STATUS,C?????????????????????? ; Was the MSB a 1
?? bsf??? _SDA?????????????????????????? ; Nope set it high
?? call?? Delay47uSec??????????????????? ; guarantee min LOW TIME tLOW & Setup time
?? bsf??? _SCL?????????????????????????? ; set clock high
?? call?? Delay40uSec??????????????????? ; guarantee min HIGH TIME tHIGH
?? decfsz I2CBitCount, F???????????????? ; are we done yet
?? goto?? TxmtNextBit??????????????????? ; nope, send the next bit
;
; Check For Acknowledge
;
?? bcf??? _SCL?????????????????????????? ; reset clock
?? bsf??? _SDA?????????????????????????? ; Release SDA line for Slave to pull down
?? call?? Delay47uSec??????????????????? ; guarantee min LOW TIME tLOW & Setup time
?? bsf??? _SCL?????????????????????????? ; clock for slave to ACK
?? call?? Delay40uSec??????????????????? ; guarantee min HIGH TIME tHIGH
?? bcf??? STATUS, RP0??????????????????? ; Select PAGE 0 to test SDA pin
?? btfsc? SdaPin???????????????????????? ; SDA should be pulled low by slave if OK
?? goto?? TxmtErrorAck?????????????????? ; Uh oh, slave isn‘t behaving (or isn‘t there)
?? bsf??? STATUS, RP0??????????????????? ; Select PAGE 1
?? bcf??? _SCL?????????????????????????? ; reset clock
?? bcf??? Txmt_Progress????????????????? ; reset progress bit in Bus Status
?? bsf??? Txmt_Success?????????????????? ; Transmission successful
?? bcf??? ACK_Error????????????????????? ; ACK OK
?? return
TxmtErrorAck
?? bsf??? STATUS,RP0???????????????????? ; select page 1
?? bsf??? _SDA?????????????????????????? ; tristate SDA
?? bsf??? _SCL?????????????????????????? ; tristate SCL
?? bcf??? Txmt_Progress????????????????? ; reset progress bit in Bus Status
?? bcf??? Txmt_Success?????????????????? ; Transmission NOT successful
?? bsf??? ACK_Error????????????????????? ; No ACK From Slave
?? return
;************************************************************
GetData
?? bsf??? Rcv_Progress?????????????????? ; set Bus status for txmt progress
?? bcf??? Rcv_Success??????????????????? ; reset status bit
?? movlw? 0x08
?? movwf? I2CBitCount
RcvNextBit
?? bsf??? STATUS, RP0??????????????????? ; page 1 for TRIS manipulation
?? bcf??? _SCL?????????????????????????? ; lower clock
?? bcf??? _SDA?????????????????????????? ; lower data line
?? call?? Delay47uSec??????????????????? ; guarantee min LOW TIME tLOW & setup time
?? bsf??? _SCL?????????????????????????? ; clock high, data sent by slave
?? call?? Delay40uSec??????????????????? ; guarantee min HIGH TIME tHIGH
?? bcf??? STATUS, RP0??????????????????? ; select page 0 to read Ports
?? bcf??? STATUS, C????????????????????? ; 0 out Status
?? btfsc? SdaPin???????????????????????? ; Check state of pin
?? bsf??? STATUS, C????????????????????? ; Pin was high, set status
?? rlf??? I2CData, F???????????????????? ; left Shift data (MSB first)
?? decfsz I2CBitCount, F???????????????? ; Are we done yet
?? goto?? RcvNextBit???????????????????? ; Nope, go get the next one
;
; Generate ACK bit if not last byte to be read,
; if last byte Gennerate NACK ; do not send ACK on last byte, main routine will send a STOP bit
;
?? bsf??? STATUS, RP0??????????????????? ; Page 1 for TRIS manipulation
?? bcf??? _SCL?????????????????????????? ; pull SCL low
?? bcf??? _SDA?????????????????????????? ; ACK by pulling SDA low
?? btfsc? Last_Byte_Rcv????????????????? ; Is it the last byte to receive
?? bsf??? _SDA?????????????????????????? ; If so, send NACK by setting SDA high
?? call?? Delay47uSec??????????????????? ; guarantee min LOW TIME tLOW & Setup time
?? bsf??? _SCL?????????????????????????? ; Raise Clock back up
?? call?? Delay40uSec??????????????????? ; guarantee min HIGH TIME tHIGH
RcvEnd:
?? bcf??? _SCL?????????????????????????? ; reset clock
?? bcf??? Rcv_Progress?????????????????? ; reset bit in Bus Status
?? bsf??? Rcv_Success??????????????????? ; transmission successful
?? bcf??? ACK_Error????????????????????? ; ACK OK
?? return
Delay47uSec:
?? movlw ((_47uS_Delay-5)/3 + 1)???????? ; move delay into W
DlyK
?? movwf DelayCount????????????????????? ; move what is in W to DelayCount
?? decfsz?? DelayCount, F??????????????? ; Decrement DelayCount
?? goto? $-1???????????????????????????? ; Loop until 0
?? return??????????????????????????????? ; return
Delay40uSec:
?? movlw ((_40uS_Delay-8)/3 + 1)???????? ; move delay into W
?? goto? DlyK??????????????????????????? ; goto DlyK loop
以下為測(cè)試程序(pic16f84)
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;?????????????????? Copyright (C) 1997 by Innovatus
;??????????????????????? All Rights Reserved.
; This code may be distributed and used freely provided that this
; copyright notice stays intact and that any modifications are noted.
; For more information about Innovatus: http://www.innovatu.com
s;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;??? File Name: testI2C.asm
;?????? Author: Alan G. Smith
;????? Purpose: This is testing out the I2C code.
;
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
??? LIST P=16f84, F=INHX8M, C=100, N=59
#include "p16f84.inc"
XTAL_FREQ?????? equ???? 10000000??????? ; the crystal frequency we are using
ClkOut????????? equ???? XTAL_FREQ / 4?? ; the number of cycles per second
_40uS_Delay set?? (ClkOut/250000)
_47uS_Delay set?? (ClkOut/212766)
_50uS_Delay set?? (ClkOut/200000)
#define SclPin? PORTA, 0??????????????? ; Pin for SCL (I2C)
#define SdaPin? PORTA, 1??????????????? ; Pin for SDA (I2C)
#define _SCL??? TRISA, 0??????????????? ; How do we toggle SCL
#define _SDA??? TRISA, 1??????????????? ; How do we toggle SDA
#define MSB?? 7
#define LSB?? 0
#define TRUE? 1
#define FALSE 0
InitTrisA?????? equ???? 0x07??????????? ; The Initial state to TRIS port A.
#define? Bus_Busy????? BusStatus,0
#define? Abort???????? BusStatus,1
#define? Txmt_Progress BusStatus,2
#define? Rcv_Progress? BusStatus,3
#define? Txmt_Success? BusStatus,4
#define? Rcv_Success?? BusStatus,5
#define? Fatal_Error?? BusStatus,6
#define? ACK_Error???? BusStatus,7
#define? Slave_RW????? BusControl,0
#define? Last_Byte_Rcv BusControl,1
#define? SlaveActive?? BusControl,2
CBLOCK???? 0x0C??????????????????????? ; I2C Ram needed
?? BusStatus??????????????????????????? ; The I2C Status register
?? BusControl?????????????????????????? ; The I2C Control register
?? I2CBitCount????????????????????????? ; Number of bits left to send (or receive)
?? I2CData????????????????????????????? ; Data (note: This is DESTROYED when sending)
?? SlaveAddr??????????????????????????? ; Slave Address
ENDC
CBLOCK
?? DelayCount?????????????????????????? ; used to figure out precise time delays
ENDC
?? org 0???????????????????????????????? ; Reset Vector
?? goto?? start????????????????????????? ; Goto Start
start
?? bcf??? INTCON, GIE??????????????????? ; Turn off interrupts in this critical part of code!
?? bcf??? STATUS, RP0??????????????????? ; Select Page 0 of registers
?? movlw? 0x0C?????????????????????????? ; Make sure there are 0‘s on SCL and SDA
?? movwf? PORTA????????????????????????? ; We write 1‘s to TX since 0 is a start bit
?? bsf??? STATUS, RP0??????????????????? ; Select Page 1 of registers
?? movlw? InitTrisA????????????????????? ; Load W with the value for TRIS A
?? movwf? TRISA????????????????????????? ; movw the value from W into TRIS A
;*************** DEBUG CODE (let us use LEDs) *******************
?? clrf?? TRISB
;****************************************************************
?? clrf?? BusStatus????????????????????? ; Let‘s clear out busStatus before we start
?? clrf?? BusControl???????????????????? ; Let‘s clear out busControl before we start
;*************** TEST CODE *******************
?? clrf?? PORTB
main
?? movlw? 0xB0?????????????????????????? ; address of EEPROM
?? movwf? SlaveAddr????????????????????? ; move into SlaveAddress register
?? call?? IsSlaveActive????????????????? ; Check and see if the slave is active
?? movlw? 0xFF?????????????????????????? ; move FF into w (turn all LED‘s on)
?? btfss? SlaveActive??????????????????? ; If the slave is active, leave it
?? movlw? 0xAA?????????????????????????? ; We didn‘t find it, turn off half.
?? bcf??? STATUS, RP0??????????????????? ; Select page 0 of registers
?? movwf? PORTB????????????????????????? ; move W to PortB
done???????????????????????????????????? ; Game over man!
?? goto?? done?????????????????????????? ; endless loop
IsSlaveActive
?? bcf??? Slave_RW?????????????????????? ; set for write operation
?? call?? TxmtStartBit?????????????????? ; Transmit Start Bit
?? call?? TxmtSlaveAddr????????????????? ; Transmit Slave Address
?? bcf??? SlaveActive??????????????????? ; Assume not present
?? btfss? ACK_Error????????????????????? ; skip if NACK, device is not present or not responding
?? bsf??? SlaveActive??????????????????? ; ACK received, device present & listening
?? call?? TxmtStopBit
?? return
#include "i2c_low.asm"
評(píng)論
查看更多