IO口模拟SPI总线

SPI是一种全双工同步串行接口,四总线结构SCK、MOSI、MISO、CS分别是时钟、主机输出、主机接收、片选。其中各个厂商的写法可能不一致。SPI总线有四种工作模式,在不再做介绍。最常用的SPI总线时序CS为低时SCK上冲沿数据有效,数据从MISO、MOSI输入和输出。我们只要有这个概念就行,具体时序可以直接看芯片手册。很多芯片都集成了SPI总线接口,没有SPI接口的芯片同样可以用IO口模拟其时序加深理解其时序。最近工作中也用到了SPI接口,闲暇之余用SISI软件用51单片机IO口模拟SPI总线和25LC1024 EEPROM通信。电路连接如下:

IO口模拟SPI总线_第1张图片

用25LC1024的两种操作方式来测试IO口模拟的SPI,这种两种方式分别是连续读、连续写。当然还有其他操作方式如擦写等。连续读、连续写时序如下:

连续读方式:

读操作流程:读指令->24bit地址->数据

连续读的时序:

IO口模拟SPI总线_第2张图片

写数据时首先发送读指令和24bit的地址。值得注意的是整个过程CS总是为低的,中间不能跳回高电平。之前我没有注意导致了读写失败。


连续写方式:

写操作比较特殊,具体流程比读操作多一个使能:写使能->写指令->24bit地址->数据

写使能命令时序:

IO口模拟SPI总线_第3张图片

发送了写使能之后就可以进一步操作,写时序如下:

IO口模拟SPI总线_第4张图片

测试思路:将0到15的七段数码管十六进制模数据写入到SPI EEPROM中然后读出,再用七段数码管显示出来具体代码如下:

#include 
#include//包含_nop_()函数

//定义命令
#define READ 0x03
#define WRITE 0x02
#define WREN 0x06
#define WRDI 0x04
#define RDSR 0x05
#define WRSR 0x01
#define PE 0x42
#define SE 0xd8
#define CE 0xc7
#define RDID 0xab
#define DPD 0xb9

//端口定义
sbit SCK = P1^4;
sbit MOSI = P1^5;
sbit MISO = P1^6;
sbit CS = P1^7;

//延时程序
void delay_ms(int n)
{
	int i, j;
	for(i=0;i4us
{
	_nop_();//空指令
	_nop_();
	_nop_();
	_nop_();
}

//SPI写一个byte
void SPI_byte_write(const char *dat)
{
	char tmp = *dat, i;
	
	for(i=0;i<8;++i){
		SCK = 0;
		MOSI = (bit)(tmp >> 7); //先输出高bit
		tmp <<= 1; //数据左移一位
		SCK = 1; //SCK为高发送bit
		delay_ns(); //延时防止芯片为响应
	}
}

//SPI读一个byte
void SPI_byte_read(char *dat)
{
	char tmp = 0, i;

	for(i=0;i<8;++i){
		SCK = 0;
		tmp <<= 1; //左移一位
		tmp |= MISO; //接收最高位
		SCK = 1;//SCK为高接收bit
		delay_ns();
	}
	
	*dat = tmp;
}

//SPI写多个byte	
void SPI_nbyte_write(const char *addr, const char *dat, char num)
{
	char inst_wren = WREN, inst_write = WRITE, i;
	
	CS = 0;
	SPI_byte_write(&inst_wren); //写使能
	CS = 1;
	
	delay_ms(1);
	
	CS = 0;
	SPI_byte_write(&inst_write); //写指令
	
	for(i=0;i<3;++i){
		SPI_byte_write(addr + i);//写地址
	}
	
	for(i=0;i

源代码地址:http://download.csdn.net/detail/a16839678/6394585





你可能感兴趣的:(嵌入式,单片机,基础,C语言,我的学习笔记)