📄 89s51-tea5767.asm
字号:
;I2C控制TEA5767,每按一次按键步进0.1M,频率(88-108MHZ)
SDA EQU P2.0
SCL EQU P2.1
SEN EQU P2.2
;*************
ORG 0100H
LJMP INIT
INIT:
CLR SEN
LCALL T4
SETB SEN
S: MOV R5,#05H
MOV R6,#29H
MOV R7,#0DBH
R: LCALL START
MOV A,#11000000B ;送芯片地址&写命令
LCALL WRBYTE
LCALL CACK
MOV A,R6 ;静音&开关搜索模式&预置搜索范围(5-0)
LCALL WRBYTE
LCALL CACK
MOV A,R7 ;预置搜索范围(7-0)
LCALL WRBYTE
LCALL CACK
MOV A,#10100000B ;上下搜索&搜索精度&高低充电电流&单声立体声&左右声道静音&设置PORT1
LCALL WRBYTE
LCALL CACK
MOV A,#00011111B ;设置PORT2&待机模式&波段制式&晶振频率&软件静音&高电平切割&噪音消除&搜寻指示
LCALL WRBYTE
LCALL CACK
MOV A,#00000000B ;6.5M选择&设置加重时间常数
LCALL WRBYTE
LCALL CACK
LCALL STOP
CLR P3.0
JB P3.7,$
LCALL T4
LCALL T4
JNB P3.7,$
LCALL T4
DJNZ R5,LOOP1
MOV R5,#05H
CJNE R7,#0FFH,LOOP
MOV R7,#0CH
INC R6
LJMP R
LOOP: INC R7
LOOP1: MOV A,R7
CLR C
ADD A,#0CH
MOV R7,A
JC TR6
CJNE R7,#6FH,R
CJNE R6,#33H,R
LJMP S
TR6: INC R6
CJNE R6,#33H,R
CJNE R7,#6FH,R
LJMP S
;启动I2C总线子程序
START: SETB SDA
NOP
SETB SCL ;起始条件建立时间大于4.7us
NOP
NOP
NOP
NOP
NOP
CLR SDA
NOP ;起始条件锁定时大于4us
NOP
NOP
NOP
NOP
CLR SCL ;钳住总线,准备发数据
NOP
RET
;结束总线子程序
STOP: CLR SDA
NOP
SETB SCL ;发送结束条件的时钟信号
NOP ;结束总线时间大于4us
NOP
NOP
NOP
NOP
SETB SDA ;结束总线
NOP ;保证一个终止信号和起始信号的空闲时间大于4.7us
NOP
NOP
NOP
RET
;发送应答信号子程序
MACK: CLR SDA ;将SDA置0
NOP
NOP
SETB SCL
NOP ;保持数据时间,即SCL为高时间大于4.7us
NOP
NOP
NOP
NOP
CLR SCL
NOP
NOP
RET
;发送非应答信号
MNACK: SETB SDA ;将SDA置1
NOP
NOP
SETB SCL
NOP
NOP ;保持数据时间,即SCL为高时间大于4.7us
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
CLR SCL
RET
; SETB ACK ;判断应答位
CEND: NOP
CLR SCL
NOP
LJMP START
;发送字节子程序
;字节数据放入ACC
;每发送一字节要调用一次CACK子程序,取应答位
WRBYTE: 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: MOV R0,#08H
RLP: SETB SDA
NOP
SETB SCL ;时钟线为高,接收数据位
NOP
NOP
MOV C,SDA ;读取数据位
MOV A,R2
CLR SCL ;将SCL拉低,时间大于4.7us
RLC A ;进行数据位的处理
MOV R2,A
NOP
NOP
NOP
DJNZ R0,RLP ;未够8位,再来一次
RET
; 无子地址器件写字节数据
; 入口参数: 数据为ACC、器件从地址SLA
; 占用: A、R0、CY
IWRBYTE: PUSH ACC
IWBLOOP: LCALL START ;起动总线
; MOV A,SLA
LCALL WRBYTE ;发送器件从地址
LCALL CACK
; JNB ACK,RETWRB ;无应答则跳转
POP ACC ;写数据
LCALL WRBYTE
LCALL CACK
LCALL STOP
RET
RETWRB: POP ACC
LCALL STOP
RET
;无子地址器件读字节数据
;入口参数: 器件从地址SLA
;出口参数: 数据为ACC
;占用 A 、R0、R2 、CY
IRDBYTE: LCALL START
; MOV A,SLA ;发送器件从地址
INC A
LCALL WRBYTE
LCALL CACK
; JNB ACK,RETRDB
LCALL RDBYTE ;进行读字节操作
LCALL MNACK ;发送非应信号
RETRDB: LCALL STOP ;结束总线
RET
;向器件指定子地址写N个数据
;入口参数: 器件从地址SLA、器件子地址SUBA 、发送数据缓冲区MTD、发送字节数NUMBYTE
; 占用: A 、R0 、R1 、R3 、CY
;IWRNBYTE: MOV A,NUMBYTE
MOV R3,A
LCALL START ;起动总线
; MOV A,SLA
LCALL WRBYTE ;发送器件从地址
LCALL CACK
; JNB ACK,RETWRN ;无应答则退出
; MOV A,SUBA ;指定子地址
LCALL WRBYTE
LCALL CACK
; MOV R1,#MTD
WRDA: MOV A,@R1
LCALL WRBYTE ;开始写入数据
LCALL CACK
; JNB ACK,IWRNBYTE
INC R1
DJNZ R3,WRDA ;判断写完没有
RETWRN: LCALL STOP
RET
;向器件指定子地址读取N个数据
;入口参数: 器件从地址SLA、器件子地址SUBA、接收字节数NUMBYTE
;出口参数: 接收数据缓冲区MTD
;占用:A、 R0、 R1、 R2、 R3、 CY
;IRDNBYTE: MOV R3,NUMBYTE
LCALL START
; MOV A,SLA
LCALL WRBYTE ;发送器件从地址
LCALL CACK
; JNB ACK,RETRDN
; MOV A,SUBA ;指定子地址
LCALL WRBYTE
LCALL CACK
LCALL START ;重新起动总线
; MOV A,SLA
INC A ;准备进行读操作
LCALL WRBYTE
LCALL CACK
; JNB ACK,IRDNBYTE
; MOV R1,#MRD
RDN1: LCALL RDBYTE ;读操作开始
MOV @R1,A
DJNZ R3,SACK
LCALL MNACK ;最后一字节发非应答位
RETRDN: LCALL STOP ;并结束总线
RET
SACK: LCALL MACK
INC R1
SJMP RDN1
T4:
MOV R4,#01H;DELAY 1.56S
T42: MOV 30H,#0FFH
T41: MOV R2,#0FFH
DJNZ R2,$
DJNZ 30H,T41
DJNZ R4,T42
RET
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -