用汇编写的简易IIC通信协议,求教下各位朋友。

2020-02-08 09:14发布

最近用义隆单片机做东西,需要编写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
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
5条回答
chill520
1楼-- · 2020-02-08 10:31
以前好像也遇到过。对照时序图检查程序。
读写之间加延时。
zyp568
2楼-- · 2020-02-08 12:42
回复【1楼】chill520
以前好像也遇到过。对照时序图检查程序。
读写之间加延时。
-----------------------------------------------------------------------

谢谢朋友,刚又读了一遍手册,应该是写入完成后,器件进入内部写周期,无法响应外界输入,所以没应答信号。
正准备加入这个函数呢,呵呵。
fly_pig
3楼-- · 2020-02-08 12:54
 精彩回答 2  元偷偷看……
wangkangming
4楼-- · 2020-02-08 18:48
是的。连续写之间要加延时的
millwood0
5楼-- · 2020-02-08 23:41
怎么回事?


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.

一周热门 更多>