Download - 6- 3 8051 的串行通讯端口的应用
6-3 8051 的串行通讯端口的应用 例 1. 利用串口方式 0 扩展并行I/O 75495 、 75497是常用的串 / 并、并 / 串转换移位寄存器,利用这些芯片及 8051的串行端口工作方式 0 ,可方便地扩展并行 I/O接口
75495的原理图
75497的原理图
8051串行口扩展原理图
波形图
编程分析:
对于高速 I/O (如机床位置反馈信号、运动脉冲控制信号等),使用中断处理比较合适,但对于普通 I/O (如按钮开关、急停开关、限位开关、继电器、电磁阀等) , 并不需要很快的响应速度,反而需要进行滤波处理,对这些信号的处理,一般在主程序中定时扫描即可,扫描周期应≥ 5ms ,一般不要超过 100ms 。 对于本例,对输入输出的读写,用串口中断程序来实现,对这些 I/O 的逻辑运算和处理,则放在主程序中进行。在 I/O 处理完成后,通过写 SBUF 来启动 I/O 的读写(仅写一次), I/O 的刷新由串口不断产生中断来完成。 由于同步串行传输速度快 , 也可以采用查询的方式来实现串行端口的读写。
T2 中断
标志定时 1
返回
开始
初始化
标志定时 0
标志定时 =1?Y
N
高速处理程序
I/O处理程序
启动 I/O刷新
方案 1 :
利用定时器将主程序分为高速和低速处理 2个节拍,利用中断实现 I/O的读写,输入输出的刷新在同一节拍完成。程序简单,但响应有延时。
TI 中断
P1.0
TI 0
发送完? Y
N
发送数据
修改发送地址
返回
P1.10
REN1
返回
P1.0
RI 中断
RAMA
输入完?Y
N
ASBUF
修改接收地址
返回
REN0
返回
RI0RI0
方案 2:
利用定时器将主程序分为高速和低速处理 2个节拍,利用中断实现I/O的读写,输入、输出的刷新分节拍完成。
开始
初始化
REN=0 ?Y
N
高速处理程序
I/O处理程序
启动刷新 OUT
定时标志 =1?Y
N
标志定时 0
T2中断
设置地址 REN1
返回
标志定时 1
P1.10 P1.0
TI 中断
P1.0
TI 0
发送完? Y
N
发送数据
修改发送地址
返回
P1.10
返回
RI 中断
RAMA
输入完?Y
N
ASBUF
修改接收地址
返回
REN0
返回
RI0RI0
T2 中断
标志定时 1
返回
方案 3:
利用定时器将主程序分为高速和低速处理 2个节拍,用查询实现 I/O的读写
开始
初始化
标志定时 0
标志定时 =1?Y
N
高速处理程序
I/O处理程序
刷新 OUT
刷新 INPUT
发送
P1.0
发送完? Y
N
发送数据
修改发送地址
TI=1 ?
Y
返回
P1.11 P1.10 P1.0
REN1
输入完?Y
N
RAMASBUF
修改接收地址
REN0
接收
RI0
RI0
RI=1 ?
返回
编程:
设单片机晶振频率为 12MHz ,定时器 T2 定时时间为 5ms ,输入缓冲器地址为: 20H~21H (X_byte0~1) ,接收地址寄存器 addr_X (30h) , 接收计数器 cnt_X(31h); 输出缓冲器地址为:22H~24H(y_byte0~2) , 发送地址寄存器 addr_X (32h) ,发送计数器cnt_Y(33h);
中断向量:
org 0000hjmp mainorg 0023hjbc ti, TxD_Ijb ri, RxD_I ; 不能用 jbcretiorg 002bh; jmp int_T0 ; 方案 2clr tf2setb T_5msreti
T2 中断程序(方案 2 ):
Int_T2: clr tf2setb T_5msmov addr_X, #X_byte1mov cnt_X, #02Hclr P1.1clr p1.0setb p1.0reti
写输出子程序:
TxD_P: CLR TI ;用 jbc 指令时可省略SETB P1.1 ;选择输出MOV R1, #02HMOV R0, # Y_byte2 ;送输出初始地址
TxD_P1: MOV A, @R0 ;读输出缓冲器 MOV SBUF , A ;发送TxD_P2: JNB TI, TxD_P2 ;发送完 1 个字节? DEC R0 ;修改地址
DJNZ R1, TxD_P1CLR P1.0 ;锁存输出SETB P1.0 ;锁存输出CLR P1.1 ;切换到输入RET
读输入子程序:
RxD_P: MOV R0, #X_byte1 ;送输入首地址MOV R1, #02H ;设置输入个数CLR P1.1 ;选择输入CLR P1.0 ;锁存输入端口状态SETB P1.0SETB REN ;启动串口接收
RxD_P1: CLR RIRxD_P2: JNB RI, RxD_P2 ;接收完 1 个字节?
MOV A, SBUF ;读输入端口 MOV @R0, A ;缓冲器输入端口状态 DEC R0 ;修改地址
DJNZ R1, RxD_P1CLR REN ;停止读输入
CLR RIRET
写输出中断程序:
TxD_I: CLR TIPUSH ACC ; PSW 00HMOV R0, addr_Y ;送输出地址DJNZ cnt_Y, END_TICLR P1.0SETB P1.0CLR P1.1 ;方案 2 无CLR P1.0 ;方案 2 无SETB REN ; 方案 2 无POP 00H ; PSW ACCRETI
END_TI: MOV A, @R0 ;读输出缓冲器 MOV SBUF , A ;发送
DEC addr_Y ;修改地址POP 00H ; PSW ACCRETI
读输入中断程序:
RxD_I: PUSH ACC ; PSW 00HMOV A, SBUF ;读输入端口MOV R0, addr_X ;送输入地址
MOV @R0, A ; RAM 输入端口状态DEC addr_X ;修改地址DJNZ cnt_X, END_RICLR REN ;停止读输入CLR RI
END_RI: POP 00H ; PSW ACC CLR RI
RET
主程序公共部分:
main: mov rcap2h, #0echmov rcap2l, #78hmov th2,#0ech
mov tl2, #78hmov t2mod, #00hmov t2con, #04h ; 自动装载方式并启动mov addr_X, #X_byte1mov cnt_X, #02hmov addr_Y, #Y_byte2mov cnt_Y, #03hmov Y_byte0, #00h ; 当输出低电平有效时为 0ffhmov Y_byte1, #00h ; 当输出低电平有效时为 0ffhmov Y_byte2, #00h ; 当输出低电平有效时为 0ffhcall TxD_Pcall RxD_P
mov ie, #1011xxxxb ; 开中断Start: call fastP ; 处理高速要求程序
方案 1 主程序:jnb T_5ms, Startclr T_5mscall PLC_Pmov addr_X, #X_byte1mov cnt_X, #02hmov addr_Y, #Y_byte1mov cnt_Y, #02hmov a, Y_byte2mov sbuf, ajmp start
方案 2 主程序:jnb T_5ms, Startjb REN, startclr T_5mscall PLC_Pmov addr_Y, #Y_byte1mov cnt_Y, #02hmov a, Y_byte2mov sbuf, ajmp start
方案 3 主程序:jnb T_5ms,Startclr T_5mscall RxD_Pcall PLC_Pcall TxD_Pjmp start
T2 中断程序(方案 2 ):Int_T2: clr tf2
setb T_5msmov addr_X, #X_byte1mov cnt_X, #02Hclr P1.1clr p1.0setb p1.0reti
8051 系列单片机仅有一个串行通信接口 , 若用于异步通信 , 本例也可以用普通 I/O 口 , 用软件来实现 , 主程序用方案 3
读输入子程序:
RxD_P: MOV R0, #X_byte1 ;送输入首地址MOV R1, #02H ;设置输入个数CLR P1.1 ;选择输入CLR P1.0 ;锁存输入端口状态SETB P1.0setb p1.2 ;准备接收
RxD_P1: mov r2, #08hRxD_P2: mov c, p1.2 ;读入一位
rlc aclr p1.3 ;产生移位时钟setb p1.3 ;产生移位时钟djnz r2,RxD_P2 ;接收完一个字节?MOV @R0, A ;缓冲器输入端口状态
DEC R0 ;修改地址DJNZ R1, RxD_P1RET ; 132us (12MHz)
写输出子程序:
TxD_P: SETB P1.1 ;选择输出MOV R1, #02HMOV R0, # Y_byte2 ;送输出初始地址
TxD_P1: MOV A, @R0 ;读输出缓冲器 mov r2,#08hTxD_P2: rlc a
mov p1.2, cclr p1.3 ;产生移位时钟setb p1.3 ;产生移位时钟djnz r2, TxD_P2 ;发送完 1 个字节?
DEC R0 ;修改地址DJNZ R1, TxD_P1CLR P1.0 ;锁存输出SETB P1.0 ;锁存输出CLR P1.1 ;切换到输入 , 安全RET ; 116us(12MHz)
例 2 利用串口方式扩展数据存储器 由于串行通信(如 I2C SPI )方式连线少 , 需要的芯片引脚少 , 可大大减小 PCB 板的面积 , 且芯片价格便宜 , 采用串行接口的芯片也越来越多(如串行 EEPROM 、 D/A 、 A/D 、温度传感芯片、实时日历时钟等),在单片机系统设计中的应用越来越广泛。 在一些 8051 系列单片机中,集成了串行接口,但也有一些单片机没有这些接口。由于单片机的 I/O 口可进行位操作,通过软件用普通I/O端口,很容易就可实现这些串行扩展,本例就以 8051 的 P1口,和串行 EEPROM 24C256 为例,来说明这种扩展的设计方法。
SDA SCL24C256
A2 A1 A0
P1.0P1.1
8051 SDA SCL
24C256A2 A1 A0
[ 0 0 0 ] [ 1 1 1 ]
… …
24C256 是一片 32Kx8bit 。具有 3 根地址选择线,最多可扩展 8 片。 24Cxx 的内部有 16~64byte 的页面写缓冲器,每次写数据的个数不能超过页面的大小。也不能跨页面写。
从24C256 的读写时序可以看出,写一个字节用的次数很频繁,用子程序来实现较好。
I2wr: clr scl mov r3,#08hI2wr1: rlc a mov sda,c setb scl clr scl djnz r3,I2wr1 setb sdaI2wlp0: mov c,sda ; 应答 jc I2wlp0 ; 应答?
ret
对 EEPROM 的读写,数据源应能覆盖所有内部 RAM 单元,用 addr_D 来存放数据源的起始地址,用 num 来存放需要写数据的个数,用 addrL addrH 来存放写入 EEPROM 的内部起始地址。
; 数据源起始地址存放在 addr_D 单元,数据个数存放在=num
; adrH adrL 存放目标起始地址。
w_rom: setb scl setb sda ; 停止 clr sda ; 起始
mov a,#0a0h ; 写命令字 call I2wr mov a,addrH call I2wr mov a,addrL call I2wr
mov r0,addr_Dmov r2,num
wdl31: mov r2,numwdl3: mov r3,#08h mov a,@r0wdl4: call I2wr inc r0 djnz r2,wdl3 clr sda setb scl ; 停止 setb sda ; 停止
ret
R_rom: setb scl setb sda ;停止 clr sda ;起始
mov a,#0a0h call I2wr mov a,adrH call I2wr mov a,adrL call I2wr setb sda setb scl clr sda ; 起始
mov a,#0a1h ; 写读命令 call I2wr
mov r0,addr_Dmov r2,num
rdl1: mov r3,#08h setb sdardl2: setb scl mov c,sda rlc a clr scl djnz r3,rdl2 mov @r0,a inc r0 djnz r2,rdl3 clr sda setb scl ; 停止 setb sda ; 停止 retrdl3: clr sda ; byte end setb scl ; byte end clr scl ; byte end jmp rdl1