正文

PIC单片机的模拟I2C通信2005-06-09 18:04:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/wegang/1600.html

分享到:

;                     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 以下为测试程序(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 #include "i2c_low.asm" END

阅读(8334) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册