STC15系列单片机SPI使用教程(三)

软件模拟SPI

以STC15W408AS单片机为例

一、硬件接线

STC15系列单片机SPI使用教程(一)


二、程序编写

1、相关宏定义和引脚定义

//数据类型重定义
#ifndef uchar
	#define uchar unsigned char
#endif
#ifndef uint
	#define uint  unsigned int
#endif

//IO端口定义
sbit MISO = P2^2;		//主机读从设备(主入从出)
sbit MOSI = P2^3;		//主机写从设备(主出从入)
sbit SCK  = P2^1;		//时钟信号
sbit CE   = P2^5; 
sbit CS   = P2^4;		//片选信号(控制芯片是否被选中)
sbit IRQ  = P3^2;		//INT0

2、SPI数据交换代码

uchar SPI_RW(uchar byte)
{
    
    
	uchar bit_ctr;
	for(bit_ctr = 0; bit_ctr < 8; bit_ctr++){
    
    
		MOSI = (byte & 0x80); 	//获得byte的最高位数据
		byte = (byte << 1); 	//移动下一位到MSB
		SCK = 1; 				//设置SCK为高
		byte |= MISO; 			//从MISO获得的一位数据
		SCK = 0; 				//设置SCK为低
	}
	return byte;				//最后返回从MISO读出的数据 				
}

3、NRF24L01读写例程

//NRF24L01相关宏定义
#define NOP			0xFF	//空操作
#define READ_REG    0x00 
#define WRITE_REG   0x20
#define TX_ADDR     0x10

//SPI写寄存器
//reg:指定寄存器地址
//value:写入的值
uchar SPI_RW_Reg(uchar reg, uchar value)
{
    
    
	uchar status;
	CS = 0;              // 使能SPI传输
	status = SPI_RW(reg); //返回从MISO读出的数据,status应为上次向该寄存器内写的value
	SPI_RW(value);        //写入寄存器的值
	CS = 1; 		// 禁止SPI传输
	return status;       // 返回状态值
}

//读取SPI寄存器值
//reg:要读的寄存器
uchar SPI_Read(uchar reg)
{
    
    
	uchar reg_val;
	CS = 0; 		     // 使能SPI传输
	SPI_RW(reg);         // 发送寄存器号
	reg_val = SPI_RW(NOP); // 读取寄存器内容
	CS = 1;             // 禁止SPI传输
	return reg_val;     // 返回状态值
}

//在指定位置写指定长度的数据
//reg:寄存器(位置)
//*pBuf:数据指针
//bytes:数据长度
//返回值,此次读到的状态寄存器值
uchar SPI_Write_Buf(uchar reg, uchar *pBuf, uchar bytes)
{
    
    
	uchar status,byte_ctr;
	CS = 0; // 使能SPI传输
	status = SPI_RW(reg);// 发送寄存器值(位置),并读取状态值
	for(byte_ctr = 0; byte_ctr < bytes; byte_ctr++){
    
     // 写入数据	 
		SPI_RW(*pBuf++);
	}
	CS = 1;//关闭SPI传输
	return status; // 返回读到的状态值
}
//在指定位置读出指定长度的数据
//reg:寄存器(位置)
//*pBuf:数据指针
//bytes:数据长度
//返回值,此次读到的状态寄存器值 
unsigned char SPI_Read_Buf(unsigned char reg, unsigned char *pBuf, unsigned char bytes)
{
    
    
	uchar status,byte_ctr;
	CS = 0; // 使能SPI传输
	status = SPI_RW(reg); // 发送寄存器值(位置),并读取状态值   	   
	for(byte_ctr = 0; byte_ctr < bytes; byte_ctr++){
    
    
		pBuf[byte_ctr] = SPI_RW(NOP); // 读出数据
	}
	CS = 1; // 关闭SPI传输
	return status; // 返回读到的状态值
}

//检测24L01是否存在
//返回值:0,成功;1,失败
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;//检测24L01错误	
	return 0;	//检测到24L01
}

//主函数
void main(void)
{
    
    
	Init_Uart();
	EA = 1;			//开总中断

	NRF24L01_Check();    //切换SPI后需要读多几次,等待SPI稳定
	NRF24L01_Check();
	if(!NRF24L01_Check()){
    
    
		SendString("NRF24L01 Checked OK!\r\n");
	}
	else{
    
    
		SendString("NRF24L01 Checked Fail!\r\n");
	}
	while(1);
}

4、串口代码

STC15系列单片机SPI使用教程(一)

猜你喜欢

转载自blog.csdn.net/baidu_25117757/article/details/108912377