⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2ctoser.asm

📁 I2C to serial communication code
💻 ASM
字号:
   ;;;;;;;;MCU晶振33.177MHZ,I2C速度设定为40~100KHZ (每个周期I2C包含82个单周期指令)
ORG 0000H
AJMP MAIN
ORG 0030H
MAIN:
  MOV SP,#60H
  MOV PMR,#01011011B                   ;SETB DME0         ;设置允许访问片上SRAM
   ;;;开启定时器2为串口通讯的波特率发生器
   SETB RCLK
   SETB TCLK
   MOV TH2,#0FFH
   MOV TL2,#0F7H ;#93H          ;设置串口通讯的波特率为115200bps(baud=fosc/2*16*[65536-(RCAP2H、RCAP2L)])
   MOV RCAP2H,#0FFH
   MOV RCAP2L,#0F7H
   SETB TR2
   MOV SCON,#50H           ;置串行接口工作于方式1
   ;;;;;;;;;;;;;;;;;;;;;
  ACK EQU 01H
  SCL EQU P3.6
  SDA EQU P3.7
  I2CRTD DATA 30H
  I2CRRD DATA 31H
  I2CADDR DATA 32H
  I2CADDRH DATA 33H
  I2CADDRL DATA 34H
  I2CNUMBYTE DATA 35H
  MOV I2CRTD,#14H
  MOV I2CRRD,#0D4H
  ;MOV I2CADDR,#0A0H
  MOV I2CADDRH,#04H
  MOV I2CADDRL,#05H
  SETB RS1
  SETB RS0
  MOV R0,#19H
 RRDD:
  LCALL I2CRDPG
  MOV A,I2CRRD
  CLR TI
  MOV SBUF,A
 CTI:JNB TI,CTI
  MOV A,I2CADDRL
  INC A 
  MOV I2CADDRL,A 
  SETB RS1
  SETB RS0
  DJNZ R0,RRDD
  AJMP MAIN
  I2CRDPG:       ;根据定义的16位地址和数据发送、接收缓冲区,进行单次单字节的数据传输
      SETB RS1
      CLR RS0
      MOV I2CNUMBYTE,#01H
      MOV R3,I2CNUMBYTE
      LCALL START
      MOV A,I2CADDR
      LCALL WRBYTE                 ;发送器件从地址(器件物理地址)
      LCALL CACK
      JNB ACK,RETRDN
      MOV A,I2CADDRH               ;指定子地址高8位
      LCALL WRBYTE
      LCALL CACK
      JNB ACK,RETRDN
      MOV A,I2CADDRL                ;指定子地址低8位
      LCALL WRBYTE
      LCALL CACK
      LCALL START                   ;重新启动总线
      MOV A,I2CADDR
      INC A                         ;准备进行读操作
      LCALL WRBYTE
      LCALL CACK
      JB ACK,I2CRDPG               ;没有确认信号,则重新尝试读一次
      MOV R1,#I2CRTD
    RDN1:
      LCALL RDBYTE                 ;读操作开始
      MOV @R1,A
      DJNZ R3,SACK
      LCALL MNACK                  ;最后一字节发非应答位
    RETRDN:
      LCALL STOP
      CLR RS1
      CLR RS0                      ;寄存器还原为寄存器0
      RET
    SACK:
      LCALL MACK
      INC R1
      SJMP RDN1
  LCALL I2CSOLOWR
  AJMP MAIN
     ;;启动I2C总线
     START:
      SETB SDA
      NOP
      NOP
      NOP
      SETB SCL         ;起始条件建立时间大于××s
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
      CLR SDA           ;起始条件锁定时间大于××s
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
      NOP
      CLR SCL           ;钳住总线,准备发数据
      NOP
      NOP
      RET

    ;结束总线子程序
     STOP:
      CLR SDA
      NOP
      NOP
      NOP
      SETB SCL          ;发送结束条件的时钟信号
      NOP               ;结束总线时间大于××s
      NOP
      NOP
      NOP
      NOP
      NOP
      SETB SDA          ;结束总线
      NOP               ;保证一个中止信号和起始信号的空闲时间对于××s
      NOP
      NOP
      NOP
      RET

    ;发送应答信号子程序
    MACK:
      CLR SDA            ;将SDA置0
      NOP
      NOP
      SETB SCL
      NOP                ;保持数据时间,即SCL为高电平时间大于**us
      NOP
      NOP
      NOP
      NOP
      CLR SCL
      NOP
      NOP
      RET
    ;发送非应答信号
    MNACK:
      SETB SDA          ;将SDA置1
      NOP
      NOP
      SETB SCL
      NOP               ;保持数据时间,即SCL为高电平时间大于**us
      NOP
      NOP
      NOP
      NOP
      CLR SCL
      NOP
      NOP
      RET

   ;检查应答位子程序
   ;返回值,ACK=1时表示有应答
   CACK:
      SETB SDA
      NOP
      NOP
      SETB SCL
      CLR ACK
      NOP
      NOP
      MOV C,SDA
      JC CEND
      SETB ACK          ;判断应答位
   CEND:
      NOP
      CLR SCL
      NOP
      RET
   ;发送字节子程序
   ;字节数据放入ACC
   ;每发送一字节要调用一次CACK子程序,取应答位
   WRBYTE:
      SETB RS1
      CLR RS0
      MOV R0,#08H
   WLP:
      RLC A            ;取数据位
      JC WR1
      SJMP WR0         ;判断数据位
   WLP1:
      DJNZ R0,WLP
      NOP
      RET
   WR1:
      SETB SDA         ;发送1
      NOP
      SETB SCL
      NOP
      NOP
      NOP
      NOP
      NOP
      CLR SCL
      SJMP WLP1
   WR0:
      CLR SDA          ;发送0
      NOP
      SETB SCL
      NOP
      NOP
      NOP
      NOP
      NOP
      CLR SCL
      SJMP WLP1
   ;读取字节子程序
   ;读出的值在ACC
   ;每取一字节要发送一个应答/非应答信号
   RDBYTE:
      SETB RS1
      CLR RS0
      MOV R0,#08H
   RLP:
      SETB SDA
      NOP
      SETB SCL          ;时钟线为高,接收数据位
      NOP
      NOP
      MOV C,SDA         ;读取数据位
      MOV A,R2
      CLR SCL           ;将SCL拉低,时间大于**us
      RLC A             ;进行数据位的处理
      MOV R2,A
      NOP
      NOP
      NOP
      DJNZ R0,RLP       ;未够8位再来一次
      RET
      ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
      ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
      ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
      I2CSOLOWR:     ;根据定义的16位地址和数据发送、接收缓冲区,进行单次单字节的数据传输
     MOV I2CNUMBYTE,#01H
     MOV A,I2CNUMBYTE
     SETB RS1
     CLR RS0
     MOV R3,A
     LCALL START         ;启动总线
     MOV A,I2CADDR
     LCALL WRBYTE        ;发送器件从地址
     LCALL CACK
     JNB ACK,RETWRN       ;无应答则退出
     MOV A,I2CADDRH
     LCALL WRBYTE
     LCALL CACK
     JNB ACK,RETWRN       ;无应答则退出
     MOV A,I2CADDRL
     LCALL WRBYTE
     LCALL CACK
     JNB ACK,RETWRN       ;无应答则退出
     MOV R1,#I2CRRD
   WRDA:
     MOV A,@R1
     LCALL WRBYTE          ;开始写入数据
     LCALL CACK
     JB ACK,I2CSOLOWR       ;无应答则重新写一遍
     INC R1
     DJNZ R3,WRDA           ;判断写完没有
   RETWRN:
     LCALL STOP
     CLR RS1
     CLR RS0                ;还原为寄存器0
     RET
     END
   ;向器件指定子地址读1个数据
   ;入口参数:器件从地址I2CADDR,器件子地址I2CADDRH、I2CADDRL,发送数据缓冲区I2CTD,发送字节数I2CNUMBYTE。
   ;占用:A,R0,R1,R2,R3,CY
   I2CRDPG:       ;根据定义的16位地址和数据发送、接收缓冲区,进行单次单字节的数据传输
      SETB RS1
      CLR RS0
      MOV I2CNUMBYTE,#01H
      MOV R3,I2CNUMBYTE
      LCALL START
      MOV A,I2CADDR
      LCALL WRBYTE                 ;发送器件从地址(器件物理地址)
      LCALL CACK
      JNB ACK,RETRDN
      MOV A,I2CADDRH               ;指定子地址高8位
      LCALL WRBYTE
      LCALL CACK
      JNB ACK,RETRDN
      MOV A,I2CADDRL                ;指定子地址低8位
      LCALL WRBYTE
      LCALL CACK
      LCALL START                   ;重新启动总线
      MOV A,I2CADDR
      INC A                         ;准备进行读操作
      LCALL WRBYTE
      LCALL CACK
      JB ACK,I2CRDPG               ;没有确认信号,则重新尝试读一次
      MOV R1,#I2CRTD
    RDN1:
      LCALL RDBYTE                 ;读操作开始
      MOV @R1,A
      DJNZ R3,SACK
      LCALL MNACK                  ;最后一字节发非应答位
    RETRDN:
      LCALL STOP
      CLR RS1
      CLR RS0                      ;寄存器还原为寄存器0
      RET
    SACK:
      LCALL MACK
      INC R1
      SJMP RDN1

    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
   I2CSOLOWR:     ;根据定义的16位地址和数据发送、接收缓冲区,进行单次单字节的数据传输
     MOV I2CNUMBYTE,#01H
     MOV A,I2CNUMBYTE
     SETB RS1
     CLR RS0
     MOV R3,A
     LCALL START         ;启动总线
     MOV A,I2CADDR
     LCALL WRBYTE        ;发送器件从地址
     LCALL CACK
     JNB ACK,RETWRN       ;无应答则退出
     MOV A,I2CADDRH
     LCALL WRBYTE
     LCALL CACK
     JNB ACK,RETWRN       ;无应答则退出
     MOV A,I2CADDRL
     LCALL WRBYTE
     LCALL CACK
     JNB ACK,RETWRN       ;无应答则退出
     MOV R1,#I2CRRD
   WRDA:
     MOV A,@R1
     LCALL WRBYTE          ;开始写入数据
     LCALL CACK
     JB ACK,I2CSOLOWR       ;无应答则重新写一遍
     INC R1
     DJNZ R3,WRDA           ;判断写完没有
   RETWRN:
     LCALL STOP
     CLR RS1
     CLR RS0                ;还原为寄存器0
     RET
     END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -