;软件模拟SPI读写24CXXX程序
;已通过实验。
;2005年5月24日
;RC3-COLCK RC4-DATA
;在24C04的00H-255H写入255--0的值。
;读出的数从RB0-RB7 的LED轮流显示。
;宁波歌林电子实验室
;网址: www.nbglin.com
;电话: 0574-88464538
;EMAIL: PICWORLD@126.COM
;========================================
include
;该程序改变头文件可直接用于16FXXXX 等28脚以上芯片.
;------------------
EEPROM EQU 20H
ADDR EQU 21H ;24C02 的数据地址。
BUFIN EQU 22H
BUFOUT EQU 23H ;待输出的数据。
SLAVE EQU 24H ;从机地址。
TXBUF EQU 25H ;发送缓冲器
BIT EQU 26H
DLY1 EQU 27H
DLY2 EQU 28H
;
#define SCL PORTB,1
#define SDA PORTB,2
#define DO EEPROM,6
#define DI EEPROM,7
;=======================
start
org 0x000
bsf STATUS,RP0
movlw b'11111111' ;RA4 键(常为高电平)
movwf TRISA
movlw b'11111111' ;RB1=SCL RB2=SDA
movwf TRISB
movlw b'00000000' ;LED
movwf TRISC
bcf STATUS,RP0
clrf PORTC
;========================================
MAIN
BTFSC PORTA,1 ;RA1 键(常为高电平)
GOTO MAIN
CALL DELAY10MS
BTFSC PORTA,1
GOTO MAIN
LOOPT BTFSS PORTA,1
GOTO LOOPT
;当键按下就进行写读操作!
;--------
BSF PORTC,1 ;代表进入写
;
MOVLW B'10100000' ;24C02地址位高4位“1010”都一样!
MOVWF SLAVE ;D1-D3位是A0,A1,A2
;D0=0是激发写操作;D0=1是激发读操作。
MOVLW B'11111111' ;待输出的数据。
MOVWF BUFOUT
CLRF ADDR ;起始写地址0。
WRITE
CALL DELAY10MS ;每写一字节的延时。
;发送1字节。
CALL BSTART ;起始位
MOVF SLAVE,0
MOVWF TXBUF ;发送从机地址
CALL TX
MOVF ADDR,0
MOVWF TXBUF ;发送字节地址
CALL TX
MOVF BUFOUT,0
MOVWF TXBUF ;发送数据字节
CALL TX
CALL BSTOP ;停止位
;--------
INCF ADDR,1 ;地址增1,
DECF BUFOUT ;数据减1。
MOVF ADDR,0
BTFSS STATUS,Z
GOTO WRITE ;地址达到256时,说明已写满EEPROM。进入读!
;
BCF PORTC,1 ;代表完成写
;========================================
GOTO READ
;========================================
;****字节读操作程序**************
;随机读出串行EEPROM中8个地址的数据
;起始地址为00
;在写操作模式下通过送控制字节和需要读出单元的地址实现
READ
CLRF ADDR ;设置起始地址为00
READ_LOOP
MOVLW B'10100000' ;24C02地址位高4位“1010”都一样!
MOVWF SLAVE ;D1-D3位是A0,A1,A2
;D0=0是激发写操作;D0=1是激发读操作。
CALL BSTART ;起始位
MOVF SLAVE,0
MOVWF TXBUF ;芯片地址写入发送缓冲器
CALL TX
MOVF ADDR,0
MOVWF TXBUF ;数据地址写入发送缓冲器
CALL TX
CALL BSTART ;起始位
MOVLW B'10100001' ;设置从地址和读操作
MOVWF TXBUF ;写入发送缓冲器
CALL TX
CALL RX ;从器件读一个字节数据
CALL BSTOP ;停止位
GOTO $+1
GOTO $+1
GOTO $+1
MOVF BUFIN,0 ;读出值在RC口显示。
MOVWF PORTC
INCF ADDR,1 ;读数据地址增1。
;
MOVLW 0XFF ;每读出一个值之间的延时。
CALL QQQ ;用于观察读出情况!
GOTO READ_LOOP
;********起始位*************
BSTART
BSF STATUS,RP0 ;设为输出
BCF TRISC,3
BCF TRISC,4
BCF STATUS,RP0
BSF SDA ;设置数据线为高电平
BSF SCL ;设置时钟线为高电平
GOTO $+1
GOTO $+1
BCF SDA ;在时钟为高电平期间数据为低电平作为起始位
GOTO $+1
GOTO $+1
BCF SCL ;定时时间调整,启动时钟序列
GOTO $+1
RETURN
;************停止位**********
BSTOP
BCF SDA ;确认数据线上为低电平
BSF STATUS,RP0 ;设置数据和时钟线为输出状态
BCF TRISB,1
BCF TRISB,2
BCF STATUS,RP0
BCF SDA ;确认数据线上为低电平
BSF SCL ;设置时钟线为高电平
GOTO $+1
BSF SDA ;当时钟为高电平数据线变为高电平作为停止位
GOTO $+1
BCF SCL ;重新设置时钟为低电平
RETURN
;********发送子程序****************************
;该程序把放在BUFOUT寄存器中数据字把其发送到串行
;EEPROM器件,然后应答位再发送1个以上的时钟到EEPROM.
;**********************************************
TX
MOVLW D'8'
MOVWF BIT ;一次完成8位数据的发送
TXLP BCF DO
BTFSC TXBUF,7 ;判位输出是否确是0
BSF DO
CALL BITOUT ;若为0,把该位送串行EEPROM
RLF TXBUF
DECFSZ BIT ;8位完成否?
GOTO TXLP
CALL BITIN ;完成,读应答位
BTFSC DI ;检查应答位
NOP
RETURN ;接通应答失失败LED发光
;****接收数据子程度*****************
;该程度从器件中读取1个字节的数据送到BUFIN寄存器
;然后送一个高电平答应,以指示不再有数据被读出.
RX
CLRF BUFIN ;清输入缓冲器
MOVLW D'8'
MOVWF BIT ;把数据数设8位
BCF STATUS,C ;确认进位位是0
RXLP RLF BUFIN ;对BUFIN左移一位
BCF BUFIN,0 ;
CALL BITIN ;读1位
BTFSC DI
BSF BUFIN,0 ;若有必要,把D0置1
DECFSZ BIT ;8位完成否
GOTO RXLP ;未完成,继续
BSF DO ;完成,置应答位1
CALL BITOUT ;去完成发送
RETURN
;************************************************
;****读取D0中的数据位,并把其发到串行该程序******
BITOUT
BSF STATUS,RP0 ;设为输出。
BCF TRISB,1
BCF TRISB,2
BCF STATUS,RP0
BTFSS DO ;检查发送数据位的状态
GOTO BITLOW ;为0,转设置数据线为低电平
BSF SDA ;为1,设置数据线为高电平
GOTO CLKOUT ;反转时钟线电平
BITLOW BCF SDA ;输出低电平
CLKOUT BSF SCL ;设置时钟线为高电平
GOTO $+1
GOTO $+1
BCF SCL ;回到时钟线为低电平
RETURN
;************************************************
;**从串行EEPROM器件中读出一位据,并存放在DI中****
BITIN
BSF DI ;假设输入为是1
BSF STATUS,RP0 ;使数据线为输入线
BCF TRISB,1
BSF TRISB,2
BCF STATUS,RP0
BSF SCL ;设时钟线为高电平
GOTO $+1
GOTO $+1
BTFSS SDA ;读数据位
BCF DI ;输入为是0,设置相应的DI
BCF SCL ;设置时钟线为低电平
RETURN
;**********延时子程序*********
DELAY10MS
MOVLW D'13'
QQQ MOVWF DLY1 ;QQQ用于长延时。
LP1 MOVLW 0FFH
MOVWF DLY2
LP0 DECFSZ DLY2
GOTO LP0
DECFSZ DLY1
GOTO LP1
RETURN
;************************
END