网站首页
IC库存
IC展台
电子资讯
技术资料
PDF文档
我的博客
IC72论坛
ic72 logo
搜索关键字: 所有资讯 行业动态 市场趋势 政策法规 新品发布 技术资讯 价格快报 展会资讯
  • 达普IC芯片交易网 > 新闻中心 > 技术参数 > 正文
  • RSS
  • pic单片机的模拟I2C通信
    http://www.ic72.com 发布时间:2008/8/15 16:04:09

    ;                    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


    www.ic72.com 达普IC芯片交易网
  • 行业动态
  • 市场趋势
  • 政策法规
  • 新品发布
  • Baidu

    IC快速检索:abcdefghijklmnopqrstuvwxyz0123456789
    COPYRIGHT:(1998-2010) IC72 达普IC芯片交易网
    客户服务:service@IC72.com 库存上载:IC72@IC72.com
    (北京)联系方式: 在线QQ咨询:点击这里给我发消息 联系电话:010-82614113 传真:010-82614123
    京ICP备06008810号-21 京公网安备 11010802032910 号 企业资质