电路设计,软件开发,专业项目团队承接电子产品开发!


ISPRO下载型编程器
火爆销售中

RS232/TTL转换器
全IC串口窃电

RS232/TTL转换线
全IC串口窃电

ByteBlasterMV Cable
CPLD/FPGA并口下载线

ByteBlaster II Cable ISPRO下载型编程器
支持S51/AVR/PIC
超级51开发板套件
前卫实用超值

PC/MCU/CPLD
三合一学习套件

全新万年历方案
AVR单片机开发板
 

Min51单片机仿真机
迷你型

ARM7开发板
仅售260元!
 

RS-232/RS-485双向接口电平转换器  

51单片机升级STM32
火爆销售中
MPLAB-ICD2
火爆销售中
LED51开发板
玩具又名图文显示棒

面板模块/开发板
经济危机明智决择

       

GSM MODEM GSM猫

SMS短信模块 工业级/全自动
火爆销售中

大功率数传电台

高速数传电台

您当前位置:电子技术资料 -> PIC -> PIC汇编 ->

祝您阅读愉快!

ISPRO下载型编程器

MPLAB-ICD2 PIC仿真/烧写器
↑↑本文相关产品介绍↑↑

pic单片机的模拟I2C通信


类别:技术文章
来源:本站整理
作者:本站整理
关键字:I2C
加入日期:2002-3-29

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


您可能还会关注的相关技术资料:

中国电子网
www.EC66.com
QQ:34740080 EMAIL:iloveaoe@163.com
最佳浏览:1024*768
Copyright (C) 2001-2010 EC66.COM All Rights Reserved
Aoe/帝国 制作维护
粤ICP备18061901号