;**************************************************************
;程序名称:LM75+LCD1602
;主控芯片:89c51,12MHZ
;**************************************************************
RS BIT P2.0 ;定义LCD1602的RS为P2.0
RW BIT P2.1 ;定义LCD1602的RW为P2.1
E BIT P2.2 ;定义LCD1602的E为P2.2
SDA BIT P3.7 ;定义24C02数据线
SCL BIT P3.6 ;定义24C02时钟线
RD_DATA DATA 30H ;读出数据缓冲区首地
ConfReg EQU 01H
DATA1 EQU 00H
;//////主程序开始//////////////////////////////////////////////
ORG 0000H
AJMP MAIN
ORG 0000H
MAIN:MOV SP,#60H
;//////LCD1602初始化///////////////////////////////////////////
MOV P0,#01H ;清除屏幕
ACALL ENABLE ;调用ENABLE子程序 .
MOV P0,#38H ;8位点阵方式 .
ACALL ENABLE
MOV P0,#06H ;移动光标
ACALL ENABLE
MOV P0,#0CH ;开显示,有光标,光标显示 .
ACALL ENABLE
;///////从LM75读数据////////////////////////////////////////////
LOOP:LCALL WR_Byte
LCALL RD_Byte
MOV A,R5
MOV B,#10D
DIV AB
MOV 30H,A
MOV A,B
MOV B,#10D
MUL AB
MOV B,#10D
DIV AB
MOV 31H,A
MOV 32H,B
;//////LCD1602显示部分//////////////////////////////////////////
REP2:MOV P0,#83H ; 第1行位置 .
LCALL ENABLE
MOV R1,#30H ;显示缓冲区内容
LCALL WRITE
;MOV R6,#04H
MOV P0,#84H ; 第1行位置 .
LCALL ENABLE
MOV R1,#31H ;显示缓冲区内容
LCALL WRITE
MOV P0,#85H ; 第1行位置 .
LCALL ENABLE
MOV R1,#32H ;显示缓冲区内容
LCALL WRITE
AJMP LOOP
;//////启动LM75子程序//////////////////////////////////
START:SETB SCL ;时钟高电平时数据下降沿为启动信号
NOP
NOP
SETB SDA
NOP
NOP
CLR SDA
NOP
NOP
CLR SCL ;钳住IC总线准备发送或接受数据
NOP
NOP
RET
;//////停止LM75子程序///////////////////////////////////
STOP:CLR SDA ;时钟高电平时数据上升沿为停止信号
NOP
NOP
SETB SCL
NOP
NOP
SETB SDA
NOP
NOP
CLR SCL
RET
;//////写LM75操作子程序////////////////////////////////
;输入参数: R1---要写入的地址,B---要写入的数据
;///////////////////////////////////////////////////////
WR_Byte:LCALL START ;调用启动24c02子程序
REP_S1: MOV A,#90H ;写器件地址
LCALL Send_B ;调用发送一个字节到I2C总线子程序
LCALL WAITACK ;调用应答信号检测程序
JC REP_S1 ;没有应答则重发数据
REP_S2: MOV A,CONFREG ;写入地址
LCALL Send_B
LCALL WAITACK
JC REP_S2
REP_S3: MOV A,DATA1 ;写入数据
LCALL Send_B
LCALL WAITACK
JC REP_S3
LCALL STOP ;调用停止子程序
LCALL DELAY ;130MS 延时,实际这里只需5MS延时
RET
;//////向IIC总线发送一个字节数据子程序/////////////////////////////
;入口参数:A---待发送数据存放在A中
;//////////////////////////////////////////////////////////////////
Send_B: MOV R7,#08H ;发送位数
S_B: RLC A
MOV SDA,C
NOP
NOP
SETB SCL
NOP
NOP
CLR SCL
DJNZ R7,S_B ;8位发送完毕?
NOP
NOP
RET
;//////检测应答信号//////////////////////////////////////////////
;出口参数:C---是否有应答信号
;////////////////////////////////////////////////////////////////
WAITACK:SETB SDA ;释放SDA信号线
NOP
NOP
SETB SCL
NOP
NOP
REP3: MOV C,SDA
CLR SCL
NOP
NOP
RET
;//////读LM75操作子程序///////////////////////////////////////
;输入参数:R2---要读的字节地址,
;输出参数: A---结果
;//////////////////////////////////////////////////////////////
RD_Byte:
LCALL START
REP_S4:MOV A,#90H
LCALL Send_B
LCALL WAITACK
JC REP_S4
REP_S5:MOV A,DATA1
LCALL Send_B
LCALL WAITACK
JC REP_S5
REP_S6: LCALL START ;重发启动信号
MOV A,#91H
LCALL Send_B
LCALL WAITACK
JC REP_S6
LCALL Receive_B ;调用从I2C总线上接收一个字节数据子程序
MOV R5,A
LCALL Receive_B
MOV R4,A
LCALL STOP
RET
;//////从IIC总线上接收一个字节数据子程序//////////////////////////////
;出口参数:A---接收数据存放在A中
;//////////////////////////////////////////////////////////////////////
Receive_B:
SETB SDA ;释放SDA数据线
MOV R7,#08H ;一个字节共接收8位数据
CLR A
R_B: SETB SCL ;启动一个时钟周期,读总线
NOP
NOP
MOV C,SDA ;将SDA状态读入C
RLC A ;结果移入A
CLR SCL
NOP
NOP
DJNZ R7,R_B ;判断8位数据是否接收完全?
SETB SDA
NOP
NOP
RET
;//////写lcd1602指令子程序/////////////////////////////
ENABLE:
CLR RS
CLR RW
CLR E
ACALL DELAY
SETB E
RET
;//////写LCD1602数据子程序/////////////////////////////
WRITE:
MOV A,@R1
ADD A,#30H
MOV P0,A
SETB RS
CLR RW
CLR E
LCALL DELAY
; LCALL DELAY
; LCALL DELAY
SETB E
; INC R1
; DJNZ R6,WRITE ; 数据写完没有.
RET
;//////130MS延时子程序////////////////////////////
DELAY:
MOV R7,#0FFH
D1:
MOV R6,#0FFH
DJNZ R6,$
DJNZ R7,D1
RET
;//////写入数据存放处/////////////////////////////
TAB: DB "0,1,2,3,4,5,6,7,8,9"
;//////程序结束/////////////////////////////////////
END
ORG 0000H
AJMP MAIN
ORG 0000H
MAIN:MOV SP,#60H
......
地址重复了,应改成如下:
ORG 0000H
AJMP MAIN
ORG 0030H
MAIN:MOV SP,#60H
......
仅就基本的51单片机的2个外部中断、3个定时器中断、1个串口中断入口,占用了0030H以下的地址(扩展功能的如stc系列用得更多),所以一般最好别再占用。也许你现在的这一点程序用不到这一块(其实第二行已经用到),以后移植或扩展功能时说不定会用到。所以习惯上都是从0100H开始写入程序。养成一个良好的习惯会有好处的。
其余的没有细看,不知道你遇到了什么问题?
另外,如果使用的是89c51,栈底设置设置有点高了,61H~7FH不一定够用(60H用不到),一旦溢出出错,很难查找。