📄 spi.s
字号:
.module spi.c
.area data(ram, con, rel)
_Spi_Receive_Buffer::
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.blkw 1
.area idata
.word _Spi_Receive_Data
.area data(ram, con, rel)
.blkb 1
.area idata
.byte 255
.area data(ram, con, rel)
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\SPI\spi.c
.dbstruct 0 9 .1
.dbfield 0 front c
.dbfield 1 rear c
.dbfield 2 count c
.dbfield 3 data pc
.dbfield 5 queuesize c
.dbfield 6 errorcode c
.dbfield 7 status c
.dbfield 8 memo c
.dbend
.dbsym e Spi_Receive_Buffer _Spi_Receive_Buffer S[.1]
_Spi_Send_Buffer::
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\SPI\spi.c
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\SPI\spi.c
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\SPI\spi.c
.blkw 1
.area idata
.word _Spi_Send_Data
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\SPI\spi.c
.blkb 1
.area idata
.byte 10
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\SPI\spi.c
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\SPI\spi.c
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\SPI\spi.c
.blkb 1
.area idata
.byte 0
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\SPI\spi.c
.dbsym e Spi_Send_Buffer _Spi_Send_Buffer S[.1]
.area vector(rom, abs)
.org 48
jmp _spi_stc_isr
.area data(ram, con, rel)
.dbfile D:\桌面\mp3\SPI\spi.c
.area text(rom, con, rel)
.dbfile D:\桌面\mp3\SPI\spi.c
.dbfunc e spi_stc_isr _spi_stc_isr fV
.even
_spi_stc_isr::
xcall push_lset
.dbline -1
.dbline 63
; /*********************************************************************************************************
; ** SPI 驱动程序
; ** (c) Copyright 2006-2008, limaokui
; ** All Rights Reserved
; **
; ** V1.0.0
; **
; **
; **--------------文件信息--------------------------------------------------------------------------------
; **文 件 名:SPI.c
; **创 建 人: 李茂奎
; **最后修改日期: 2006年9月2日
; **描 述: SPI驱动程序
; **
; **--------------历史版本信息----------------------------------------------------------------------------
; ** 创建人: 李茂奎
; ** 版 本: V1.00
; ** 日 期: 2006年9月2日
; ** 描 述: 原始版本
; **
; **------------------------------------------------------------------------------------------------------
; ** 修改人: 李茂奎
; ** 版 本:
; ** 日 期:
; ** 描 述:
; **
; **--------------当前版本修订------------------------------------------------------------------------------
; ** 修改人: 李茂奎
; ** 日 期: 2006年9月2日
; ** 描 述:
; **
; **------------------------------------------------------------------------------------------------------
; *********************************************************************************************************/
; /*
; ATmega128的SPI采用硬件方式实现面向字节的全双工3线同步通信,
; 支持主机、从机和2种不同极性的SPI时序,通信速率有7种选择,
; 主机方式的最高速率为1/2系统时钟,从机方式最高速率为1/4系统时钟。
;
; AVR的SPI由一个16位的循环移位寄存器构成,当数据从主机方移出时,从机的数据同时也被移入,
; 因此SPI的发送和接收在一个中断服务中完成。
; 在SPI中断服务程序中,先从SPDR中读一个接收的字节存入接收数据缓冲器中,再从发送数据缓冲
; 器取出一个字节写入SPDR中,由SPI发送到从机。
; 数据一旦写入SPDR,ISP硬件开始发送数据。
; 下一次ISP中断时,表示发送完成,并同时收到一个数据。
; SPI为硬件接口和传输完成中断申请,所以使用SPI传输数据的有效方法是采用中断方式+数据缓存器的设计方法。
;
; 在对SPI初始化时,应注意以下几点:
; .正确选择和设置主机或从机,以及工作模式(极性),数据传输率;
; .注意传送字节的顺序,是低位优先(LSB First)还是高位优先(MSB Frist);
; .正确设置MOSI和MISO接口的输入输出方向,输入引脚使用上拉电阻,可以节省总线上的吊高电阻。
;
;
; */
; #include "config.h"
;
; static uint8 Spi_Receive_Data[SPI_RECEIVE_DATA_BUFFER_SIZE];
; static uint8 Spi_Send_Data[SPI_SEND_DATA_BUFFER_SIZE];
; CirQueue Spi_Receive_Buffer={0,0,0,Spi_Receive_Data,SPI_RECEIVE_DATA_BUFFER_SIZE,0,0,0};
; CirQueue Spi_Send_Buffer={0,0,0,Spi_Send_Data,SPI_SEND_DATA_BUFFER_SIZE,0,0,0};
;
; #pragma interrupt_handler spi_stc_isr:iv_SPI_STC
; void spi_stc_isr(void)
; {
.dbline 64
; if(Spi_Receive_Buffer.status==SPI_DATA_RECEIVE)
lds R24,_Spi_Receive_Buffer+7
cpi R24,1
brne L8
.dbline 65
; EnQueue(&Spi_Receive_Buffer,SPDR); //从SPI口读出收到的字节
in R18,0xf
ldi R16,<_Spi_Receive_Buffer
ldi R17,>_Spi_Receive_Buffer
xcall _EnQueue
L8:
.dbline 66
; if (Spi_Send_Buffer.status==SPI_DATA_SEND)
lds R24,_Spi_Send_Buffer+7
cpi R24,2
brne L11
.dbline 67
; {
.dbline 68
; if(!EmptyQueue(&Spi_Send_Buffer))//如果发送缓冲区中有待发的数据
lds R2,_Spi_Send_Buffer+2
tst R2
breq L14
.dbline 69
; {
.dbline 70
; SPDR = DeQueue(&Spi_Send_Buffer); //发送一个字节数据,并调整指针
ldi R16,<_Spi_Send_Buffer
ldi R17,>_Spi_Send_Buffer
xcall _DeQueue
out 0xf,R16
.dbline 71
; }
xjmp L15
L14:
.dbline 73
; else
; {
.dbline 74
; Spi_Send_Buffer.status=SPI_DATA_FREE;
clr R2
sts _Spi_Send_Buffer+7,R2
.dbline 75
; }
L15:
.dbline 76
L11:
.dbline -2
L7:
xcall pop_lset
.dbline 0 ; func end
reti
.dbend
.dbfunc e Spi_Get_Char _Spi_Get_Char fc
; data -> R20
.even
_Spi_Get_Char::
xcall push_gset1
.dbline -1
.dbline 82
; }
; }
;
;
;
; uint8 Spi_Get_Char(void)
; {
L19:
.dbline 84
L20:
.dbline 84
; uint8 data;
; while (EmptyQueue(&Spi_Receive_Buffer)); //无接收数据,等待
lds R2,_Spi_Receive_Buffer+2
tst R2
breq L19
.dbline 85
; data = DeQueue(&Spi_Receive_Buffer); //从接收缓冲区取出一个SPI收到的数据
ldi R16,<_Spi_Receive_Buffer
ldi R17,>_Spi_Receive_Buffer
xcall _DeQueue
mov R20,R16
.dbline 86
; return data;
.dbline -2
L18:
xcall pop_gset1
.dbline 0 ; func end
ret
.dbsym r data 20 c
.dbend
.dbfunc e Spi_Put_Char _Spi_Put_Char fV
; c -> R20
.even
_Spi_Put_Char::
xcall push_gset1
mov R20,R16
.dbline -1
.dbline 90
; }
;
; void Spi_Put_Char(uint8 c)
; {
L24:
.dbline 91
L25:
.dbline 91
; while (FullQueue(&Spi_Send_Buffer));//发送缓冲区满,等待
lds R2,_Spi_Send_Buffer+5
lds R3,_Spi_Send_Buffer+2
cp R3,R2
breq L24
.dbline 92
; if (Spi_Send_Buffer.count)//发送缓冲区已中有待发数据
tst R3
breq L29
.dbline 93
; { //或SPI正在发送数据时
.dbline 94
; EnQueue(&Spi_Send_Buffer,c);//将数据放入发送缓冲区排队
mov R18,R20
ldi R16,<_Spi_Send_Buffer
ldi R17,>_Spi_Send_Buffer
xcall _EnQueue
.dbline 95
; }
xjmp L30
L29:
.dbline 97
out 0xf,R20
L30:
.dbline -2
L23:
xcall pop_gset1
.dbline 0 ; func end
ret
.dbsym r c 20 c
.dbend
.dbfunc e Spi_Receive _Spi_Receive fc
; i -> R20,R21
; length -> R22,R23
; buffer -> R10,R11
.even
_Spi_Receive::
xcall push_gset3
movw R22,R18
movw R10,R16
.dbline -1
.dbline 102
; else
; SPDR = c; //发送缓冲区中空且SPI口空闲,直接放入SPDR由SIP口发送
; }
;
;
; uint8 Spi_Receive(uint8 *buffer,uint16 length)
; {
.dbline 104
; uint16 i;
; Spi_Receive_Buffer.status=SPI_DATA_RECEIVE;
ldi R24,1
sts _Spi_Receive_Buffer+7,R24
.dbline 105
; for(i=0;i<length;i++)
clr R20
clr R21
xjmp L37
L34:
.dbline 106
.dbline 107
xcall _Spi_Get_Char
movw R30,R10
st Z+,R16
movw R10,R30
.dbline 108
L35:
.dbline 105
subi R20,255 ; offset = 1
sbci R21,255
L37:
.dbline 105
cp R20,R22
cpc R21,R23
brlo L34
.dbline 109
; {
; *buffer++=Spi_Get_Char();
; }
; Spi_Receive_Buffer.status=SPI_DATA_FREE;
clr R2
sts _Spi_Receive_Buffer+7,R2
.dbline 110
; return i;
mov R16,R20
.dbline -2
L32:
xcall pop_gset3
.dbline 0 ; func end
ret
.dbsym r i 20 i
.dbsym r length 22 i
.dbsym r buffer 10 pc
.dbend
.dbfunc e Spi_Send _Spi_Send fc
; i -> R20,R21
; length -> R22,R23
; buffer -> R10,R11
.even
_Spi_Send::
xcall push_gset3
movw R22,R18
movw R10,R16
.dbline -1
.dbline 114
; }
;
; uint8 Spi_Send(uint8 *buffer,uint16 length)
; {
.dbline 116
; uint16 i;
; Spi_Send_Buffer.status=SPI_DATA_SEND;
ldi R24,2
sts _Spi_Send_Buffer+7,R24
.dbline 117
; for(i=0;i<length;i++)
clr R20
clr R21
xjmp L44
L41:
.dbline 118
.dbline 119
movw R30,R10
ld R16,Z+
movw R10,R30
xcall _Spi_Put_Char
.dbline 120
L42:
.dbline 117
subi R20,255 ; offset = 1
sbci R21,255
L44:
.dbline 117
cp R20,R22
cpc R21,R23
brlo L41
.dbline 121
; {
; Spi_Put_Char(*buffer++);
; }
; Spi_Send_Buffer.status=SPI_DATA_FREE;
clr R2
sts _Spi_Send_Buffer+7,R2
.dbline 122
; return i;
mov R16,R20
.dbline -2
L39:
xcall pop_gset3
.dbline 0 ; func end
ret
.dbsym r i 20 i
.dbsym r length 22 i
.dbsym r buffer 10 pc
.dbend
.dbfunc e Spi_SendReceive _Spi_SendReceive fc
; ptr -> R22,R23
; i -> R20,R21
; receivelength -> R10,R11
; sendlength -> R12,R13
; buffer -> R14,R15
.even
_Spi_SendReceive::
xcall push_gset5
movw R12,R18
movw R14,R16
ldd R10,y+10
ldd R11,y+11
.dbline -1
.dbline 126
; }
;
; uint8 Spi_SendReceive(uint8 *buffer,uint16 sendlength,uint16 receivelength)
; {
.dbline 129
; uint16 i;
; uint8 *ptr;
; ptr=buffer;
movw R22,R14
.dbline 130
; if (receivelength!=0)
tst R10
brne X0
tst R11
breq L47
X0:
.dbline 131
; {
.dbline 132
; Spi_Receive_Buffer.status=SPI_DATA_RECEIVE;
ldi R24,1
sts _Spi_Receive_Buffer+7,R24
.dbline 133
; }
L47:
.dbline 134
; Spi_Send_Buffer.status=SPI_DATA_SEND;
ldi R24,2
sts _Spi_Send_Buffer+7,R24
.dbline 135
; for(i=0;i<sendlength;i++)
clr R20
clr R21
xjmp L54
L51:
.dbline 136
.dbline 137
movw R30,R22
ld R16,Z+
movw R22,R30
xcall _Spi_Put_Char
.dbline 138
L52:
.dbline 135
subi R20,255 ; offset = 1
sbci R21,255
L54:
.dbline 135
cp R20,R12
cpc R21,R13
brlo L51
.dbline 139
; {
; Spi_Put_Char(*ptr++);
; }
; ptr=buffer;
movw R22,R14
.dbline 140
; for(i=0;(i<receivelength)&&(i<sendlength);i++)
clr R20
clr R21
xjmp L58
L55:
.dbline 141
.dbline 142
xcall _Spi_Get_Char
movw R30,R22
st Z+,R16
movw R22,R30
.dbline 143
L56:
.dbline 140
subi R20,255 ; offset = 1
sbci R21,255
L58:
.dbline 140
cp R20,R10
cpc R21,R11
brsh L59
cp R20,R12
cpc R21,R13
brlo L55
L59:
.dbline 144
; {
; *ptr++=Spi_Get_Char();
; }
; Spi_Send_Buffer.status=SPI_DATA_FREE;
clr R2
sts _Spi_Send_Buffer+7,R2
.dbline 145
; Spi_Receive_Buffer.status=SPI_DATA_FREE;
sts _Spi_Receive_Buffer+7,R2
.dbline 146
; return i;
mov R16,R20
.dbline -2
L46:
xcall pop_gset5
.dbline 0 ; func end
ret
.dbsym r ptr 22 pc
.dbsym r i 20 i
.dbsym r receivelength 10 i
.dbsym r sendlength 12 i
.dbsym r buffer 14 pc
.dbend
.dbfunc e Spi_Init _Spi_Init fV
; temp -> R16
.even
_Spi_Init::
.dbline -1
.dbline 151
; }
;
;
; void Spi_Init(void)
; {
.dbline 178
; uint8 temp;
;
; #if (CPU_TYPE == M32)|| (CPU_TYPE == M16) // MISO-PB6,MOSI-PB5,SCK-PB7,SS-PB4
; #define DDR_SPI DDRB
; #define PORT_SPI PORTB
; #define DD_MOSI 5
; #define DD_MISO 6
; #define DD_SCK 7
; #define DD_SS 4
; #endif
; #if CPU_TYPE == M8 // MISO-PB6,MOSI-PB5,SCK-PB7,SS-PB4
; #define DDR_SPI DDRB
; #define PORT_SPI PORTB
; #define DD_MOSI 3
; #define DD_MISO 4
; #define DD_SCK 5
; #define DD_SS 2
; #endif
; #if (CPU_TYPE == M128)||(CPU_TYPE == M64 ) // MISO-PB6,MOSI-PB5,SCK-PB7,SS-PB4
; #define DDR_SPI DDRB
; #define PORT_SPI PORTB
; #define DD_MOSI 2
; #define DD_MISO 3
; #define DD_SCK 1
; #define DD_SS 0
; #endif
; DDR_SPI = DDR_SPI|(1<<DD_SS)|(1<<DD_MOSI)|(1<<DD_SCK); //MISO=input and MOSI,SCK,SS = output
in R24,0x17
ori R24,176
out 0x17,R24
.dbline 179
; PORTB |=(1<<DD_MISO)|(1<<DD_SS); //MISO上拉电阻有效
in R24,0x18
ori R24,80
out 0x18,R24
.dbline 180
; SPCR = (1<<SPIE)|(1<<SPE)|(1<<MSTR); //SPI允许,4X 主机模式,MSB先发,SPI模式0 (CPOL CPHA 00(0) 01(1) 10(2) 11(3))
ldi R24,208
out 0xd,R24
.dbline 182
; // SPSR = 0;
; SPSR = (1<<SPI2X); //enable spi2x
ldi R24,1
out 0xe,R24
.dbline 183
; temp = SPSR;
in R16,0xe
.dbline 184
; temp = SPDR; //清空SPI,和中断标志,使SPI空闲
in R16,0xf
.dbline -2
L62:
.dbline 0 ; func end
ret
.dbsym r temp 16 c
.dbend
.area bss(ram, con, rel)
.dbfile D:\桌面\mp3\SPI\spi.c
_Spi_Send_Data:
.blkb 10
.dbsym s Spi_Send_Data _Spi_Send_Data A[10:10]c
_Spi_Receive_Data:
.blkb 255
.dbsym s Spi_Receive_Data _Spi_Receive_Data A[255:255]c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -