用汇编写的IIC通信协议,求教下各位朋友。
最近用义隆单片机做东西,需要编写IIC通信协议,不过不需要非常标准,只需要和AT24CXX之间能实现通信就可以,不需要太严格的错误检测。选用的芯片是EM78P163N+AT24C02N。
自己参考网上找的时序写了模拟IIC的 字节写入 字节读出 起始位 结束位 应答位 非应答位 子程序。然后分别写了 写入3个字节,读出3个字节的程序 进行调试,都通过了,写入程序写入后,用读取程序读出校验的结果是正确的。
但是我把2个测试程序合并到一起,先写入然后读取并校验结果,写入部分正常,读取部分却不行了,通过手动设置测试点的方式,发现就在写和读衔接的地方出问题的。
写入是正常完成的,读取时第一步先写入IC地址,就是到这一步有问题,一直没应答信号,没有写成功,很奇怪,写入程序和读取程序的这个部分用的一模一样的语句。估计是结束位的时序有问题,但是自己弄了半天没弄出来,所以来求教下各位,怎么回事?
程序如下
INCLUDE "EM78P163N.INC"
SDA == PORT6.0
SCL == PORT6.1
SDACR == P6CR
BS MACRO SDACR;释放SDA线宏
MOV A,@0X01
IOW P6CR
ENDM
BC MACRO SDACR;占用SDA线宏
MOV A,@0
IOW P6CR
ENDM
IIC_BIT_NUM == R10
IIC_DATA == R11
IIC_RDDATA0 == R13
IIC_RDDATA1 == R14
IIC_RDDATA2 == R15
IIC_WRDA == 0B10100000
IIC_RDDA == 0B10100001
IIC_SPK_SIGN== R12.0;响应应答标志位:1有应答,0无应答.
ORG 0
ADD A,@0XFF
ADD A,@0XFF
ADD A,@0XFF
ADD A,@0XFF
ADD A,@0XFF
JMP MAIN
ORG 0X20
MAIN:
;初始化部分
MOV A,@0
IOW P6CR
IOW P5CR
MOV A,@0XFF
MOV PORT6,A
MOV PORT5,A
MOV A,@0XF4
IOW PHCR
;写入部分
MOV A,@IIC_WRDA;写入3个数据
MOV IIC_DATA,A
CALL IIC_BEGIN
CALL IIC_WRITE
MOV A,@0
MOV IIC_DATA,A
CALL IIC_WRITE
MOV A,@0B01010101
MOV IIC_DATA,A
CALL IIC_WRITE
MOV A,@0B01010101
MOV IIC_DATA,A
CALL IIC_WRITE
MOV A,@0XFF
MOV IIC_DATA,A
CALL IIC_WRITE
CALL IIC_END
BC PORT5.0;写入结束
;读取部分
MOV A,@IIC_WRDA;读取写入的三个数据
MOV IIC_DATA,A
CALL IIC_BEGIN
CALL IIC_WRITE
MOV A,@0
MOV IIC_DATA,A
CALL IIC_WRITE
MOV A,@IIC_RDDA
MOV IIC_DATA,A
CALL IIC_BEGIN
CALL IIC_WRITE
BC PORT5.1;写入读操作命令结束
CALL IIC_READ
MOV IIC_RDDATA0,A
CALL IIC_AN
CALL IIC_READ
MOV IIC_RDDATA1,A
CALL IIC_AN
CALL IIC_READ
MOV IIC_RDDATA2,A
CALL IIC_UNAN
CALL IIC_END
;校验部分
MOV A,@0B01010101;比较读出的数据是否为写入的数据
SUB IIC_RDDATA0,A
JBC Z
BC PORT6.7
SUB IIC_RDDATA1,A
JBC Z
BC PORT6.6
SUB IIC_RDDATA2,A
JBC Z
BC PORT6.5
LOOP:
JMP LOOP
;*功能函数部分*
;IIC起始位
IIC_BEGIN:
BC SDACR
BS SDA
BS SCL
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP;NOP*10=5us
BC SDA
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP;NOP*9=4.5us
BC SCL
RET;起始位结束时:SCL=0,SDA=0.
;IIC结束位
IIC_END:
BC SDA
BS SCL
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP;NOP*9=4.5us
BS SDACR
JBS SDA
JMP IIC_END
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP;NOP*10=5us
RET;结束位结束时:SCL=1,SDA=1.
;IIC写入一字子程序
IIC_WRITE:
MOV A,@8
MOV IIC_BIT_NUM,A
IIC_WRITE_0:
RLC IIC_DATA
JBC R3,0
JMP SET_P60
BC SDA
JMP IIC_W1BIT_END
SET_P60:
BS SDA
IIC_W1BIT_END:
BS SCL;产生一个大于4us的正脉冲
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP;NOP*9=4.5us
BC SCL
DJZ IIC_BIT_NUM
JMP IIC_WRITE_0
IIC_SPK:;IIC响应从器件应答
BS SDACR
BS SCL
NOP
NOP
NOP
JBC SDA
JMP CLR_IIC_SPK_SIGN
BS IIC_SPK_SIGN;置1应答标志位
JMP IIC_SPK_END
CLR_IIC_SPK_SIGN:
BC IIC_SPK_SIGN
IIC_SPK_END:;应答操作为3步*0.5us
NOP
NOP
NOP
BC SCL
BC SDACR
JBS IIC_SPK_SIGN
JMP IIC_SPK;未收到应答,继续等待应答.
RET
;IIC读取一字子程序
IIC_READ:
BS SDACR
MOV A,@8
MOV IIC_BIT_NUM,A
IIC_READ_0:
BS SCL;产生一个大于4us的正脉冲,中间读取SDA.
NOP
NOP
NOP
JBC SDA
JMP SET_C
BC C
JMP ICC_R1BIT_END
SET_C:
BS C
ICC_R1BIT_END:
RLC IIC_DATA
NOP
NOP
BC SCL
DJZ IIC_BIT_NUM
JMP IIC_READ_0
BC SDACR
BC SDA
MOV A,IIC_DATA
RET
;IIC应答位
IIC_AN:
BC SDA
BS SCL
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
BC SCL
RET
;IIC非应答位
IIC_UNAN:
BS SDA
BS SCL
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
BC SCL
RET 在写之后,最小延迟5MS,再读,看看...
不知是否有帮助... 写入24CXX后要等一段时间,一般在5-10ms,不同芯片不太一样。在24cxx手册里有,好像叫write cycle time。
用FRAM就没这事。 你把SDA上拉1K电阻看看 呵呵,谢谢LS 3位朋友,这个程序发帖次日已解决,忘了来编辑下了。
原因是写操作结束后,接着进行下一操作时,需要类似LCD显示器那样查忙,不忙时,E2ROM才会接受操作指令,当然延时也行的,但是延时就没法确定数据是否被成功的写入,而且延时会使系统资源不同程度的浪费。EM78P163N的几个IO口有内部上拉电阻,使能之就不必加外部上拉电阻了,但是阻值不得而知。
为做这个小项目,专门借了编程器来,最后样品也通过了全部功能及稳定性的测试,但是“客户”最后还是不要了,样品也不退还给我,辛苦费都不给一点,还编程器时自己还给人家老师傅买了两包烟,悲惨的第一次哎。(看到此贴,突发牢骚。)
页:
[1]