📄 csi24wc02.s
字号:
;******************************************************************************
; File:CSI24WC02.S
; 功能:使用LPC210x模拟EEPROM器件CSI24WC02。LPC210x具有硬件I2C接口,使用其从方式进行
; I2C器件模拟,本例使用了256字节的RAM作为存储单元。
; 说明:将跳线器JP12断开,然后与主机连接。
;******************************************************************************
INCLUDE LPC2106.INC
CSI24WC02 EQU 0xA1 ; 定义从要地址,忽略通用地址
EEPROM EQU 0x40003000 ; 定义EEPROM存储单元,地址为0x40003000--0x400030FF
ADRPOINT EQU 0x40003100 ; 定义EEPROM读写操作指针
SLARCV EQU 0x40003104 ; 定义子地址接收标志,为1时表示己接收从机地址
AREA EEPROMC,CODE,READONLY
ENTRY
; 异常向量
Vectors LDR PC, ResetAddr
LDR PC, UndefinedAddr
LDR PC, SWI_Addr
LDR PC, PrefetchAddr
LDR PC, DataAbortAddr
NOP
LDR PC, IRQ_Addr
LDR PC, FIQ_Addr
ResetAddr DCD Reset
UndefinedAddr DCD Undefined
SWI_Addr DCD SoftwareInterrupt
PrefetchAddr DCD PrefetchAbort
DataAbortAddr DCD DataAbort
Nouse DCD 0
IRQ_Addr DCD IRQ_Handler
FIQ_Addr DCD FIQ_Handler
; 中断服务程序
Undefined
SoftwareInterrupt
PrefetchAbort
DataAbort
FIQ_Handler
B .
; IRQ中断处理(I2C中断处理)
IRQ_Handler
STMFD SP!,{R0-R12,LR} ; 现场保护
; 读取状态码,然后进行分析及控制
LDR R0,=I2C_BASE
LDR R1,[R0,#0x04]
AND R1,R1,#0xF8
CMP R1,#0x60 ; 判断是否接收到自身SLA+W
CMPNE R1,#0x68
BEQ SLAWR ; 接收到自身SLA+W
CMP R1,#0xA8 ; 判断是否接收到自身SLA+R
CMPNE R1,#0xB0
BEQ SLARD ; 接收到自身SLA+R
CMP R1,#0x80
BEQ RCV_DAT ; 前一次寻址接收到自身SLA+W,己接收数据,并返回ACK
CMP R1,#0xB8
BEQ SEND_DAT
CMP R1,#0xC0 ; 己发送数据,并接收到非应答信号
BEQ STOP_BUS
CMP R1,#0xA0 ; 接收到停止条件或重复起动条件A0H
BEQ STOP_BUS
; 接收其它状态值,则设置SI=0,AA=1,然后退出
OTHER_STA MOV R1,#0x04
STR R1,[R0] ; 设置AA=1
B EXIT_IRQ ; 退出中断(会清除SI位)
;******************************************************************************
; 从接收状态,即接收到SLA+W。
; 将子地址接收标志置0,然后退出。
;******************************************************************************
SLAWR MOV R1,#0
LDR R2,=SLARCV
STR R1,[R2] ; 子地址接收标志置0
MOV R1,#0x04
STR R1,[R0] ; 设置AA=1
B EXIT_IRQ ; 退出中断(会清除SI位)
;******************************************************************************
; 从发送状态,即接收到SLA+R,或已发送数据并接收到ACK位。
; 发送当前读写指针的一字节数据,并将读写指针自动加1。
;******************************************************************************
SLARD
SEND_DAT LDR R1,=EEPROM ; 取得E2PROM操作实际地址
LDR R2,=ADRPOINT
LDR R2,[R2]
ADD R2,R2,R1
LDRB R1,[R2] ; 读出数据
AND R1,R1,#0xFF
STR R1,[R0,#0x08] ; 发送数据
LDR R2,=ADRPOINT ; 读写指针加1
LDR R1,[R2]
ADD R1,R1,#1
AND R1,R1,#0xFF
STR R1,[R2]
MOV R1,#0x04
STR R1,[R0] ; 设置AA=1
B EXIT_IRQ
;******************************************************************************
; 接收主要发送的数据。
; 程序先判断是否接收子地址,若没有接收,则接收并设置读写指针及该标志;
; 若程序已接收子地址,则开始接收数据,并将读写指针自动加1。
;******************************************************************************
RCV_DAT LDR R2,=SLARCV ; 判断SLARCV是否为0
LDR R1,[R2]
CMP R1,#0
BEQ RCVSLA ; 若是,则接收子地址
RCVDATA LDR R1,=EEPROM ; 取得E2PROM操作实际地址
LDR R2,=ADRPOINT
LDR R2,[R2]
ADD R2,R2,R1
LDR R1,[R0,#0x08] ; 接收数据,写入模拟E2PROM
AND R1,R1,#0xFF
STRB R1,[R2]
LDR R2,=ADRPOINT ; 读写指针加1
LDR R1,[R2]
ADD R1,R1,#1
AND R1,R1,#0xFF
STR R1,[R2]
MOV R1,#0x04
STR R1,[R0] ; 设置AA=1
B EXIT_IRQ ; 退出中断
RCVSLA LDR R1,[R0,#0x08] ; 读取接收到的数据I2DAT
LDR R2,=ADRPOINT
STR R1,[R2] ; 设置读写指针ADRPOINT
MOV R1,#1
LDR R2,=SLARCV
STR R1,[R2] ; 设置SLARCV标志为1
MOV R1,#0x04
STR R1,[R0] ; 设置AA=1
B EXIT_IRQ ; 退出中断
;******************************************************************************
; 结束总线,设置SI=0,AA=1。
;******************************************************************************
STOP_BUS MOV R1,#0x04
STR R1,[R0] ; 设置AA=1
B EXIT_IRQ ; 退出中断(会清除SI位)
EXIT_IRQ MOV R1,#0x38
STR R1,[R0,#0x18] ; 清除标I2C标志位,STA、STO、SI
LDMFD SP!,{R0-R12,LR} ; 恢复现场
SUBS PC,LR,#4
;******************************************************************************
; 主程序,进行I2C从机设置,并初始化EEPROM操作指针。
;******************************************************************************
Reset MSR CPSR_c,#0xd2 ; 切换到IRQ模式
LDR R0,=0x40003F00 ; 设置IRQ模式的堆栈,0x40003E00-0x40003EFF
MOV SP,R0
MSR CPSR_c,#0x53 ; 切换到管理模式并开放IRQ中断
LDR R0,=0x40003FFF ; 设置管理模式的堆栈,0x40003F00-0x40003FFF
MOV SP,R0
LDR R0,=MEMMAP ; REMAP操作。(若使用0地址写入到FLASH,则不要使用REMAP)
MOV R1,#0x02
STR R1,[R0]
LDR R0,=ADRPOINT
MOV R1,#0
STR R1,[R0] ; 初始化读写指针为0
LDR R0,=SLARCV
STR R1,[R0] ; 子地址接收标志置0
; 设置为从机方式
LDR R0,=PINSEL0 ; 设置I2C控制口有效
MOV R1,#0x50
STR R1,[R0]
LDR R0,=I2C_BASE
MOV R1,#CSI24WC02
STR R1,[R0,#0x0C] ; 设置从机地址,I2ADR=CSI24WC02
MOV R1,#0x44
STR R1,[R0] ; I2C配置为从机模式,I2CONSET=0x44
; 允许I2C中断(设置为非向量IRQ)
LDR R0,=VIC_BASE_ADDR
MOV R1,#0x00
STR R1,[R0,#0x0C] ; 所有中断设置为IRQ中断,VICIntSelect=0x00
MOV R1,#0x0200
STR R1,[R0,#0x10] ; 允许I2C中断,VICIntEnable=0x0200
B . ; 等待I2C中断
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -