硬件SPI(查询方式)以STC15W408AS单片机为例
- 一、硬件接线
-
- 二、程序编写
-
- 1、和SPI相关的寄存器
-
- ① SPCTL寄存器
- ② SPSTAT寄存器
- ③ SPDAT寄存器
- ④ AUXR1/P_SW1寄存器
- 2、寄存器,数据类型重定义
- 3、寄存器相关位宏定义, CS引脚定义
- 4、SPI初始化代码
- 5、SPI数据交换代码
- 6、NRF24L01读写例程
- 7、GD25Q80BSIG读写例程
- 8、串口代码
一、硬件接线
1、普通SPI设备接线
如NRF24L01,可以直接连接IO
2、FLASH设备接线
如GD25Q80BSIG,需要加上拉电阻
二、程序编写
1、和SPI相关的寄存器
① SPCTL寄存器
② SPSTAT寄存器
③ SPDAT寄存器
④ AUXR1/P_SW1寄存器
2、寄存器,数据类型重定义
sfr P_SW1 = 0xA2;
sfr SPSTAT = 0xCD;
sfr SPCTL = 0xCE;
sfr SPDAT = 0xCF;
#ifndef uchar
#define uchar unsigned char
#endif
#ifndef uint
#define uint unsigned int
#endif
3、寄存器相关位宏定义, CS引脚定义
#define SPI_S0 0x04
#define SPI_S1 0x08
#define SPIF 0x80
#define WCOL 0x40
#define SSIG 0x80
#define SPEN 0x40
#define DORD 0x20
#define MSTR 0x10
#define CPOL 0x08
#define CPHA 0x04
#define SPDHH 0x00
#define SPDH 0x01
#define SPDL 0x02
#define SPDLL 0x03
sbit SS_1 = P1^2;
sbit SS_2 = P2^4;
4、SPI初始化代码
void InitSPI_1(void)
{
uchar temp;
temp = P_SW1;
temp &= ~(SPI_S0 | SPI_S1);
P_SW1 = temp;
SPDAT = 0;
SPSTAT = SPIF | WCOL;
SPCTL = SPEN | MSTR | SSIG | SPDLL;
}
void InitSPI_2(void)
{
uchar temp;
temp = P_SW1;
temp &= ~(SPI_S0 | SPI_S1);
temp |= SPI_S0;
P_SW1 = temp;
SPDAT = 0;
SPSTAT = SPIF | WCOL;
SPCTL = SPEN | MSTR | SSIG | SPDLL;
}
5、SPI数据交换代码
uchar SPISwap(uchar dat)
{
SPDAT = dat;
while (!(SPSTAT & SPIF));
SPSTAT = SPIF | WCOL;
return SPDAT;
}
6、NRF24L01读写例程
#define NOP 0xFF
#define READ_REG 0x00
#define WRITE_REG 0x20
#define TX_ADDR 0x10
sbit CE = P2^5;
sbit IRQ = P3^2;
uchar SPI_RW_Reg(uchar reg, uchar value)
{
uchar status;
SS_2 = 0;
status = SPISwap(reg);
SPISwap(value);
SS_2 = 1;
return status;
}
uchar SPI_Read(uchar reg)
{
uchar reg_val;
SS_2 = 0;
SPISwap(reg);
reg_val = SPISwap(NOP);
SS_2 = 1;
return reg_val;
}
uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar bytes)
{
uchar status, byte_ctr;
SS_2 = 0;
status = SPISwap(reg);
for(byte_ctr = 0; byte_ctr < bytes; byte_ctr++){
SPISwap(*pBuf++);
}
SS_2 = 1;
return status;
}
uchar SPI_Read_Buf(uchar reg, uchar *pBuf, uchar bytes)
{
uchar status, byte_ctr;
SS_2 = 0;
status = SPISwap(reg);
for(byte_ctr = 0; byte_ctr < bytes; byte_ctr++){
pBuf[byte_ctr] = SPISwap(NOP);
}
SS_2 = 1;
return status;
}
uchar NRF24L01_Check(void)
{
uchar buf[5] = {
0xA5, 0xA5, 0xA5, 0xA5, 0xA5};
uchar buf1[5];
uchar i;
CE = 0;
SPI_Write_Buf(WRITE_REG + TX_ADDR, buf, 5);
SPI_Read_Buf(TX_ADDR, buf1, 5);
CE = 1;
for(i = 0; i < 5; i++)
if(buf1[i] != 0xA5)
break;
if(i != 5)
return 1;
return 0;
}
void main(void)
{
Init_Uart();
EA = 1;
InitSPI_2();
NRF24L01_Check();
NRF24L01_Check();
if(!NRF24L01_Check()){
SendString("NRF24L01 Checked OK!\r\n");
}
else{
SendString("NRF24L01 Checked Fail!\r\n");
}
while(1);
}
7、GD25Q80BSIG读写例程
#define NOP 0xFF
#define Write_Enable 0x06
#define Write_Disable 0x04
#define Read_Status_Register 0x05
#define Read_Status_Register_1 0x35
#define Read_Data 0x03
#define Page_Program 0x02
#define Chip_Erase_1 0xC7
#define Chip_Erase_2 0x60
#define Read_Identification 0x9F
sbit WP = P1^6;
void Write_Enable_Cmd(void)
{
SS_1 = 0;
SPISwap(Write_Enable);
SS_1 = 1;
}
void Write_Disable_Cmd(void)
{
SS_1 = 0;
SPISwap(Write_Disable);
SS_1 = 1;
}
uchar Read_Status_Register_Sta(void)
{
uchar sta;
SS_1 = 0;
SPISwap(Read_Status_Register);
sta = SPISwap(NOP);
SS_1 = 1;
return sta;
}
void Read_Data_Cmd(uchar ad1, uchar ad2, uchar ad3, uchar *dat, uint len)
{
uchar i, cmd[4];
cmd[0] = Read_Data;
cmd[1] = ad1;
cmd[2] = ad2;
cmd[3] = ad3;
SS_1 = 0;
for(i = 0; i < 4; i++){
SPISwap(cmd[i]);
}
for(i = 0; i < len; i++){
*dat++ = SPISwap(NOP);
}
SS_1 = 1;
}
void Page_Program_Cmd(uchar ad1, uchar ad2, uchar ad3, uchar *dat, uint len)
{
uchar i, cmd[4];
uint count = 0, temp = 0;
cmd[0] = Page_Program;
cmd[1] = ad1;
cmd[2] = ad2;
cmd[3] = ad3;
temp = 256 - ad3;
Write_Enable_Cmd();
SS_1 = 0;
for(i = 0; i < 4; i++){
SPISwap(cmd[i]);
}
for(i = 0; i < temp; i++){
SPISwap(*dat++);
}
SS_1 = 1;
while(Read_Status_Register_Sta() & 0x01);
if(len > temp){
cmd[0] = Page_Program;
cmd[1] = ad1;
cmd[2] = ad2 + 1;
cmd[3] = 0;
temp = len - temp;
Write_Enable_Cmd();
SS_1 = 0;
for(i = 0; i < 4; i++){
SPISwap(cmd[i]);
}
for(i = 0; i < temp; i++){
SPISwap(*dat++);
}
SS_1 = 1;
while(Read_Status_Register_Sta() & 0x01);
}
}
void Chip_Erase_1_Cmd(void)
{
Write_Enable_Cmd();
SS_1 = 0;
SPISwap(Chip_Erase_2);
SS_1 = 1;
while(Read_Status_Register_Sta() & 0x01);
}
void Read_Identification_Sta(uchar *rdid)
{
uchar i;
SS_1 = 0;
SPISwap(Read_Identification);
for(i = 0; i < 3; i++){
*rdid++ = SPISwap(NOP);
}
SS_1 = 1;
}
void HexToAscii(uchar *pHex, uchar *pAscii, uchar nLen)
{
uchar Nibble[2];
uint i,j;
for (i = 0; i < nLen; i++){
Nibble[0] = (pHex[i] & 0xF0) >> 4;
Nibble[1] = pHex[i] & 0x0F;
for (j = 0; j < 2; j++){
if (Nibble[j] < 10){
Nibble[j] += 0x30;
}
else{
if (Nibble[j] < 16)
Nibble[j] = Nibble[j] - 10 + 'A';
}
*pAscii++ = Nibble[j];
}
}
*pAscii++ = '\0';
}
void main(void)
{
uchar sta, dis[2], rdid[3];
uchar write[10] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 11}, read[10] = {
0x00};
uchar play[20] = {
0x00};
WP = 1;
Init_Uart();
EA = 1;
InitSPI_1();
Read_Identification_Sta(rdid);
Read_Identification_Sta(rdid);
Read_Identification_Sta(rdid);
HexToAscii(&rdid[0], dis, 1);
SendString("Manufacturer ID: 0x");
SendString(dis);
SendString("\r\n");
HexToAscii(&rdid[1], dis, 1);
SendString("Memory Type: 0x");
SendString(dis);
SendString("\r\n");
HexToAscii(&rdid[2], dis, 1);
SendString("Capacity: 0x");
SendString(dis);
SendString("\r\n");
sta = Read_Status_Register_Sta();
HexToAscii(&sta, dis, 1);
SendString("GD25Q80BSIG Status Register: 0x");
SendString(dis);
SendString("\r\n");
Chip_Erase_1_Cmd();
Page_Program_Cmd(0x00, 0x01, 0xFA, write, 10);
Read_Data_Cmd(0x00, 0x01, 0xFA, read, 10);
HexToAscii(read, play, 10);
SendString("Read Address 0x0001FA: ");
SendString(play);
SendString("\r\n");
while(1);
}
8、串口代码
sfr AUXR = 0x8E;
sfr P_SW1 = 0xA2;
sfr T2H = 0xD6;
sfr T2L = 0xD7;
#ifndef FOSC
#define FOSC 24000000L
#endif
#define BAUD 115200
#define S1_S0 0x40
#define S1_S1 0x80
bit busy;
void Init_Uart(void)
{
uchar temp;
temp = P_SW1;
temp &= ~(S1_S0 | S1_S1);
P_SW1 = temp;
SCON = 0x50;
T2L = (65536 - (FOSC / 4 / BAUD));
T2H = (65536 - (FOSC / 4 / BAUD)) >> 8;
AUXR |= 0x14;
AUXR |= 0x01;
ES = 1;
}
void Uart() interrupt 4 using 1
{
if(RI){
RI = 0;
}
if(TI){
TI = 0;
busy = 0;
}
}
void SendData(uchar dat)
{
while(busy);
busy = 1;
SBUF = dat;
}
void SendString(uchar *s)
{
while(*s)
{
SendData(*s++);
}
}