新闻  |   论坛  |   博客  |   在线研讨会
IIC总线程序
lcpeng | 2007-09-27 11:34:17    阅读:8743   发布文章

;*********************
;******IIC程序********
;*********************
       ORG 0000H
       SJMP MAIN
MAIN:  SDA BIT P2.4;IIC的数据端
       SCL BIT P2.5;IIC的时钟端
       KV EQU 7FH;键值存储区
        SV EQU 7EH;行扫描字暂存
        IICSV EQU 7DH;IIC存储单元首址
        DTSV EQU 77H;数据存储单元首址
        KEYNUM EQU 71H;按键次数存储位
        SLA EQU 70H;IIC器件的寻址字节
        NUM EQU 6FH
        BUZZER BIT P2.1;蜂鸣器位
;********初始化及调显示*************
        MOV R2,#17
        MOV R1,#7FH
CLRR:   CLR A
        MOV @R1,A
        DEC R1
        DJNZ R2,CLRR;初始化各存储单元
        MOV R3,#6
        MOV R1,#DTSV
CCLR00: MOV @R1,#15
        DEC R1
        DJNZ R3,CCLR00;DTSV初值附为15          
        MOV R2,#6
SCAN:   MOV A,#11H
        MOV SBUF,A
        JNB TI,$
        CLR TI
        DJNZ R2,SCAN;调显示
;*******键扫主程序**********
KEY:    MOV P1,#0F0H;令所有行为低电平
        MOV R7,#0FFH;设置计数常数
        DJNZ R7,$;延时
        MOV A,P1;读取P1口列值
        CJNE A,#0F0H,EKEY
        SJMP KEY;无键按下返回
EKEY:   LCALL D20MS
        CLR BUZZER
SKEY:   MOV A,#0;下面进行行扫描
        MOV R4,A
        MOV R5,A;行,列计数器清零
        MOV R3,#0FEH;R3为行扫描字暂存
SKEY1:  MOV A,R3
        MOV SV,R3;行扫描字送SV暂存
        MOV P1,A;扫描字送P1口
        NOP
        NOP
        NOP
        NOP
        NOP;稳定P1口输出
        MOV A,P1;读列值
        CJNE A,SV,SKEY3;有键按下跳转
        INC R4
        SETB C;准备将行扫描左移一位
        MOV A,R3
        RLC A
        MOV R3,A
        MOV A,R4
        CJNE A,#4,SKEY1
        SJMP KEY
SKEY3:  JNB ACC.4,SKEY5
        JNB ACC.5,SKEY6
        JNB ACC.6,SKEY7
        JNB ACC.7,SKEY8
        SJMP KEY
SKEY5:  MOV A,#0
        MOV R2,A
        AJMP DKEY
SKEY6:  MOV A,#1
        MOV R2,A
        AJMP DKEY
SKEY7:  MOV A,#2
        MOV R2,A
        AJMP DKEY
SKEY8:  MOV A,#3
        MOV R2,A
DKEY:   MOV A,R4
        LCALL DECODE
;********判断功能键************
        CJNE A,#15,ENT;是否是修改IIC键
        LCALL DKEY1;关提示音.
        ;MOV R3,KEYNUM;按键次数送R3********************************
        ;MOV R0,#DTSV;数据存储首址送R0
IICLP:  ;MOV A,@R0
        LCALL WRBYTE
        ;DEC R0
        ;DJNZ R3,IICLP
        MOV R2,#6
        MOV R0,#DTSV
SCAN1:  MOV DPTR,#TAB
        MOV A,@R0
        MOVC A,@A+DPTR
        MOV SBUF,A
        JNB TI,$
        CLR TI
        DEC R0
        DJNZ R2,SCAN1;调显示
        ;LCALL DKEY1
        MOV R3,#6
        MOV KEYNUM,#0
        MOV R1,#DTSV
CCLR0:  MOV @R1,#15
        DEC R1
        DJNZ R3,CCLR0
        AJMP KEY
SCAN2:  MOV R2,#6
SCAN21: MOV A,#11H
        MOV SBUF,A
        JNB TI,$
        CLR TI
        DJNZ R2,SCAN21;调显示
        LCALL DKEY1
        MOV KEYNUM,#0
        AJMP KEY
ENT:    CJNE A,#14,RESV1
        LCALL DKEY1
        ;MOV R3,KEYNUM;按键次数送R3
        ;MOV R0,#IICSV;数据存储首址送R0
RDIIC:  LCALL RDBYTE
        ;MOV @R0,A
        ;DEC R0
        ;DJNZ R3,RDIIC
        MOV R3,KEYNUM;按键次数送R3
        MOV R4,IICSV;IIC存储首址
        MOV R5,DTSV;输入数据存储首址
COMP:   MOV A,R4
        MOV SLA,R5;SLA中暂存数据地址
        CJNE A,SLA,CCLR1
        DEC R4
        DEC R5
        DJNZ R3,COMP
        ;MOV R3,KEYNUM
        ;MOV R1,#DTSV
;RESV2:  MOV A,@R1
        ;LCALL RESV
        ;DEC R1
        ;DJNZ R3,RESV2
        CLR BUZZER
        LCALL D1M
        SETB BUZZER
        MOV R3,KEYNUM
CCLR1:  MOV R1,#DTSV
CCLR:   MOV @R1,#15
        DEC R1
        DJNZ R3,CCLR
        ;MOV KEYNUM,#0
        SJMP SCAN2
RESV1:  INC KEYNUM;按键次数存储位加1
        LCALL RESV
        MOV R3,A
        MOV A,NUM
        ;INC A
        ;MOV NUM,A
        MOV R0,#DTSV
        ADD A,R0
        MOV R0,A
        MOV A,R3
        MOV @R0,A
        MOV A,NUM
        INC A
        MOV NUM,A
        LCALL DKEY1
        AJMP KEY
DKEY1:  MOV A,#0F0H
        MOV P1,A
        NOP
        NOP
        NOP
        MOV A,P1
        CJNE A,#0F0H,DKEY1
        SETB BUZZER ;判断键是否弹起
        RET
;********调整键值************
DECODE: MOV A,R4
        MOV B,#4
        MUL AB
        ADD A,R2
        RET
RESV:   MOV DPTR,#TAB;数字表头始址送DPTR
        MOVC A,@A+DPTR
        MOV SBUF,A
        JNB TI,$
        CLR TI
        RET
;*********IIC子程序*******************
;********一字节数据发送***************
WRBYTE: PUSH PSW;保护现场
WRBYTE1:MOV PSW,#18H;改用第三组工作寄存器
        MOV A,KEYNUM   
        CJNE A,#0,WRB1
        RET
        ;MOV R3,A;将欲发送数据送R3
WRB1:   MOV SLA,#0A0H;送总线寻址字节
        LCALL STA ;发送起始条件
        MOV A,SLA;读取写控制字
        LCALL WRB;发送一个字节
        LCALL CACK;检查应答位
        JB F0,WRBYTE1;无应答,重发
        MOV R0,#DTSV ;欲发送数据首址
        MOV R5,KEYNUM;R5保存欲发送数据的字节数       
WRDA:   MOV A,@R0;读一个字节数据
        LCALL WRB;发送写控制字节
        LCALL CACK;检查应答位
        JB F0,WRBYTE1;无应答,重发
        DEC R0
        DJNZ R5,WRDA;未发送完N个字节继续
        LCALL STOP ;数据发送完毕,停止
        POP PSW ;恢复现场
        RET
;**********读存数据程序****************
RDBYTE: PUSH PSW;保护现场
RDBYTE1:MOV PSW,#18H;改用第三组工作寄存器
        ;MOV R3,A    ;将欲发送数据送R3
        MOV SLA,#0A1H;送总线寻址字节
        LCALL STA ;发送起始条件
        MOV A,SLA;读入读控制字
        LCALL WRB;发送读控制字节
        LCALL CACK;检查应答位
        JB F0,RDBYTE1;无应答,重发
        MOV R1,#IICSV
       
        MOV R3,KEYNUM;欲传送字节数送R3
GO:     LCALL RDB;读一个字节
        MOV @R1,A
        DJNZ R3,ACK
        LCALL MNACK;已读完字节,发ACK非
        ;JB F0,RDBYTE1;无应答,重发
        LCALL STOP ;数据发送完毕,停止
        POP PSW ;恢复现场
        RET
ACK:    LCALL MACK;发ACK
        DEC R1
        SJMP GO;继续接收       
;**********STA子程序*******************
STA:    SETB SDA
        SETB SCL
        NOP
        NOP
        NOP
        NOP
        NOP
        CLR SDA
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        CLR SCL
        RET
;***********WRB发送子程序***************
WRB:    MOV R7,#8;位计数器初值
WLP:    RLC A;欲发送位送C
        JC WR1 ;此位为1,转至WR1
        CLR SDA ;此位为零,发送0
        SETB SCL;时钟脉冲变为高电平
        NOP
        NOP
        NOP
        NOP
        NOP;延时4微妙
        CLR SCL;时钟脉冲变为低电平
        DJNZ R7,WLP;未发送完8位,转至WLP
        RET
WR1:    SETB SDA ;此位为1,发送1
        SETB SCL;时钟脉冲变为高电平
        NOP
        NOP
        NOP
        NOP
        NOP;延时4微妙
        CLR SCL;时钟脉冲变为低电平
        DJNZ R7,WLP;未发送完8位,转至WLP
        RET
;*********RDB主机接收子程序**************
RDB:    MOV R7,#8;R7存放位计数器初值
RLP:    SETB SDA;SDA输入
        SETB SCL;SCL脉冲开始
        MOV C,SDA; 读SDA值
        MOV A,R6;取回暂存结果
        RLC A;移入新接收位
        MOV R6,A;暂存入R6
        CLR SCL;SCL脉冲结束
        DJNZ R7,RLP;未读完8位,转至RLP
        RET
;**********CACK子程序************
CACK:   SETB SDA;SDA作为输入
        SETB SCL;第九个时钟脉冲开始
        NOP
        NOP
        NOP
        MOV C,SDA;读SDA线
        MOV F0,C;转存入F0中
        CLR SCL ;时钟脉冲结束
        NOP
        NOP
        NOP
        RET
;*********发送应答位和非应答位MACK,MNACK子程序*************
MACK:   CLR SDA
        SETB SCL
        NOP
        NOP
        NOP
        NOP
        NOP
        CLR SCL
        SETB SDA;保持数据时间,大于4微秒
        RET
MNACK:  SETB SDA
        SETB SCL
        NOP
        NOP
        NOP
        NOP
        NOP
        CLR SCL
        CLR SDA;保持数据时间,大于4微秒
        RET
;*******STOP子程序**************
STOP:   CLR SDA
        SETB SCL
        NOP
        NOP
        NOP
        NOP
        NOP
        SETB SDA
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        CLR SCL
        RET
KTAB: DB 11H,12H,14H,18H,21H,22H,24H,28H
 DB 31H,32H,34H,38H,41H,42H,44H,48H
TAB:    DB 11H,0D7H,32H,92H,0D4H,98H,18H,0D1H,10H,90H;0-9
        DB 50H,1CH,39H,16H,38H,78H,70H,0FEH,0EFH,0FFH;A  B, C,    D,  E, ,F   ,P, -,  ,.  ,COLSE
        DB 01H,0C7H,22H,82H,0C4H,88H,08H,0C3H,00H,80H;带小数点的字形码0.,1.,-----9.
D200MS: MOV R1,#10
D20MS1: MOV R7,#10H
DL201:  MOV R6,#0FFH
        DJNZ R6,$
        DJNZ R7,DL201
        DJNZ R1,D20MS1
        RET
D20MS:  MOV R7,#10H
DL20:   MOV R6,#0FFH
        DJNZ R6,$
        DJNZ R7,DL20
        RET
D1M:    MOV R6,#13
D600MS1:MOV R3,#30
D10MS1: MOV R5,#10H
DL2011:  MOV R4,#0FFH
        DJNZ R4,$
        DJNZ R5,DL2011
        DJNZ R3,D10MS1
        DJNZ R6,D600MS1
        RET
        END

 

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
19861209
最近文章
IIC总线程序
2007-09-27 11:34:17
温度传感器Ds18b20程序
2007-09-27 11:14:20
打零器程序
2007-09-27 11:11:52
推荐文章
最近访客