网站首页
IC库存
IC展台
电子资讯
技术资料
PDF文档
我的博客
IC72论坛
ic72 logo
资料首页最新产品 技术参数 电路图 设计应用 解决方案 代理商查询 IC替换 IC厂商 电子辞典
关键字: 技术文章 PDF资料 IC价格 电路图 代理商查询 IC替换 IC厂商 电子辞典

pic单片机的模拟I2C通信

;                    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:
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;    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


 以下为测试程序(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.innovatus.com
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;    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

热门搜索:602-15 SBB830-QTY10 SS480806 1301380020 PS2408 2866572 2320306 PS3612 SS3612 TLP606B 8300SB2-LF 2856142 2838254 B3429D 2838283 2838319 BTA12-800TWRG B30-7100-PCB LS606M PS120406 TLM615SA PDUMH15 SUPER6OMNI D 6NX-6 01C1001JF
COPYRIGHT:(1998-2010) IC72 达普IC芯片交易网
客户服务:service@IC72.com 库存上载:IC72@IC72.com
(北京)联系方式: 在线QQ咨询:点击这里给我发消息 联系电话:010-82614113 传真:010-82614123
京ICP备06008810号-21 京公网安备 11010802032910 号 企业资质