⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ex8-8.asm

📁 《增强型8051单片机实用开发技术》例程代码
💻 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 + -