最近用义隆单片机做东西,需要编写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
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
读写之间加延时。
以前好像也遇到过。对照时序图检查程序。
读写之间加延时。
-----------------------------------------------------------------------
谢谢朋友,刚又读了一遍手册,应该是写入完成后,器件进入内部写周期,无法响应外界输入,所以没应答信号。
正准备加入这个函数呢,呵呵。
most of the times people cannot afford to code in assembly.
so if I were you, I would think hard about moving to C, as a cheaper and more efficient way of coding for complex projects.
一周热门 更多>