📄 ex8-8.asm
字号:
$INCLUDE (STC12C5A.inc) ;包含STC12C5A60S2寄存器定义文件
SS EQU P1.4 ;定义SPI的 脚
;----------------- 定义 SPI 模式常量 ----------------------
CONFIG_MASTER EQU 11010000B ;0D4H, 忽略 SS 脚的主模式
CONFIG_SLAVE EQU 01000000B ;40H, SS脚用于确定器件为主机还是从机。
;SS=1 时为未选从模式,没有总线冲突,MISO,MOSI,SPICLK=输入,输入,输入
;SS=0 时为从模式,MISO,MOSI,SPICLK=输出,输入,输入
;------------------ 定义变量 -----------------------------
Flags EQU 20H
SPI_Receive EQU Flags.0 ;收到数据标志
TimeOver EQU Flags.1 ;RS232 接收下一个字节超时
Rec_buffer EQU 21H ;缓冲区指针
Rec_Number EQU 22H ;已接收数据长度
SPI_buffer EQU 23H ;保存 SPI 接口收到的数据
Time_Over EQU 24H ;超时计数
ORG 0000H
LJMP MAIN
ORG 000BH ;定时器0中断服务程序入口
LJMP T0_ISR
ORG 004BH ;SPI中断服务程序入口
LJMP SPI_ISR
ORG 0080H
MAIN:
MOV SP, #70H
;-----------初始化串口----------------
MOV SCON, #50H ;8位可变波特率, 无奇偶校验
MOV TMOD, #21H ;T1 为自动重装模式
MOV TH1, #0F6H
MOV TL1, #0F6H
ORL AUXR, #40H ;T1以1T的速度计数,波特率=4800*12=57600
SETB TR1
;-----------初始化 SPI------------------
MOV SPCTL,#CONFIG_SLAVE
MOV SPSTAT,#11000000B ;清零标志位SPIF和WCOL
ORL IE2,#02H ;令ESPI(IE2.1)=1,允许SPIF产生中断
;--------------------------
MOV Flags, #0 ;清标志字
SETB ET0 ;开 T0 中断
SETB EA ;开总中断
;-------------------------------------------------
Check_Receive:
JB RI, RS232_GetFirstByte ;RS232 收到第一个字节
JB SPI_Receive, SPI_GetFirstByte ;SPI 收到第一个字节
LJMP Check_Receive ;循环
RS232_GetFirstByte: ;RS232 收到第一个字节
MOV Rec_buffer, #30H
MOV Rec_Number, #0B0H ;最多接收176个字节,否则会破坏栈的内容
RS232_Received: ;RS232 收到一个字节
MOV R0, Rec_buffer ;保存收到的字节
MOV @R0, SBUF
CLR RI
DJNZ Rec_Number, RS232_Rec_Next ;判断接收缓冲区是否已满
LJMP SPI_Send ;接收缓冲区满,跳转
RS232_Rec_Next: ;准备接收下一个字节
INC Rec_buffer
MOV TH0, #0
SETB TR0 ;启动 T0
CLR TimeOver
RS232_GetNextByteWait: ;等待 RS232 传来的下一个字节
JB TimeOver, SPI_Send ;超时, 用SPI口发送RS232收到的字节
JB RI, RS232_Received
LJMP RS232_GetNextByteWait
;-----------------
SPI_Send: ;用SPI口发送RS232收到的字节
MOV A, #0B0H ;计算收到的字节数-->R2
CLR C
SUBB A, Rec_Number
MOV R2, A
MOV R0, #30H
LCALL ChangeToMast ;切换到忽略 SS 脚的主模式
JC ExitMast ;切换失败, 跳转
SPI_Send_Loop:
MOV A, @R0
LCALL SPI_Send_Byte ;将 A 中的数据发送到从 SPI
INC R0
DJNZ R2, SPI_Send_Loop
ExitMast:
CLR TR0
LCALL ChangeToSlave ;SPI 接口切换到未选中的从模式
LJMP Check_Receive
;------------------------------------------------
SPI_GetFirstByte: ;SPI 收到第一个字节
MOV Rec_buffer, #30H
MOV Rec_Number, #0B0H ;最多接收176个字节,否则会破坏栈的内容
SPI_Received: ;SPI 收到一个字节
MOV R0, Rec_buffer ;保存收到的字节
MOV @R0, SPI_buffer
CLR SPI_Receive
DJNZ Rec_Number, SPI_Rec_Next;判断接收缓冲区是否已满
LJMP RS232_Send ;接收缓冲区满,跳转
SPI_Rec_Next: ;准备接收下一个字节
INC Rec_buffer
MOV TH0, #0
SETB TR0 ;启动 T0
CLR TimeOver
SPI_GetNextByteWait: ;等待 SPI 传来的下一个字节
JB TimeOver, RS232_Send ;超时, 用RS232口发送SPI收到的字节
JB SPI_Receive, SPI_Received
LJMP SPI_GetNextByteWait
;---------------------
RS232_Send: ;用 RS232 口发送 SPI 收到的字节
MOV A, #0B0H ;计算收到的字节数-->R2
CLR C
SUBB A, Rec_Number
MOV R2, A
MOV R0, #30H
RS232_Send_Loop:
MOV A, @R0
LCALL RS232_Send_Byte ;将 A 中的数据发送到计算机
INC R0
DJNZ R2, RS232_Send_Loop
LJMP Check_Receive
;------------------------------------------------
ChangeToMast: ;切换到忽略 SS 脚的主模式
SETB SS ;如果 SS 脚未被拉低, 就切换
JB SS, ChangeToMast_a
SETB C ;切换到主模式失败
RET
ChangeToMast_a:
ANL IE2,#0FDH ;令ESPI(IE2.1)=0,禁止SPIF产生中断
MOV SPCTL,#CONFIG_MASTER ;忽略 SS 脚, 设为主机。
MOV SPSTAT,#11000000B ;清标志位 SPSTAT
CLR SS ;拉低 SS 脚, 使对方成为从模式
CLR C ;本机切换到主模式成功
RET
;------------------------------------------------
ChangeToSlave: ;SPI 接口切换到未选中的从模式
SETB SS ;释放SS脚
MOV SPCTL,#CONFIG_SLAVE
MOV SPSTAT,#11000000B ;清标志位 SPSTAT
ORL IE2,#02H ;令ESPI(IE2.1)=1,允许SPIF产生中断
RET
;------------ 将A中的数据发送到计算机 -----------------
RS232_Send_Byte:
CLR TI ;清零串口发送中断标志
MOV SBUF, A
JNB TI, $ ;等待发送完毕, 未发送完毕跳回本行
CLR TI ;清零串口发送中断标志
RET
;----------------- 将A中的数据发送到从机SPI ------------------
SPI_Send_Byte:
MOV SPDAT, A
SPI_Send_Byte_Wait:
MOV A, SPSTAT
ANL A, #80H
JZ SPI_Send_Byte_Wait ;等待 SPIF=1 即等待 SPI 发送完毕
MOV SPSTAT,#11000000B ;清标志位SPSTAT, 放弃发送时对方传来的字节
RET
;--------------- 定时器0中断服务程序 ----------------
T0_ISR:
SETB TimeOver
RETI
;---------------- SPI 中断服务程序 ------------------
SPI_ISR:
MOV SPI_buffer, SPDAT ;保存收到的数据
MOV SPSTAT, #11000000B ;0C0H, 清零标志位 SPIF 和 WCOL
SETB SPI_Receive ;设置SPI端口收到数据标志
RETI
;------------------------------------------------
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -