欲速则不达,还是要慢一点,再慢一点~
一、说明
PART 3 SPI (SCLK,SDO,SDI) 全双工
SCLK 时钟 ,SDO(MOSI) 数据输出,SDI (MISO) 数据输入
8051SPI 和 I2C一样也是需要用IO模拟
SPI总线传输共有4种类型,
CPOL位,高电平为:1,低电平为:0
CPHA位, 边沿,先读后写:0,先写后读:1
传输时候,先传输高位再传输低位
实验程序采用SPI 串行总线的EEPROM,25AA040A
过程
读数据: 先写入读命令,再写读地址
写数据: 先使写地址锁存,然后使用写命令,写地址,然后再写入数据
A8 如果是9位寄存器有效 1,8位为0
二、演示
三、时序
命令字
读写时序
写使能
代码:
/**
* 8051/2 DEMO 3
* 常用的本地通讯方式
* 1. 串口UART, 波特率:9600
* 接设备的时候,一般只接GND RX TX,不会接Vcc,避免与目标设备上的供电冲突。
* 1.1 RS485标准( +2V ~ +6V:1 / -6V ~ -2V:0)
* 1.2 RS232标准( -15V ~ -3V:1 / +3V ~ +15V:0),需要MAX232进行电平反转后,才能与MCU进行通讯
* 1.3 TTL标准( 2.4V--5V:1 / 0V--0.5V:0 )
*
* 2. I2C(SCL,SDA)
* 3. SPI (SCLK,SDO,SDI) 全双工
*/
#include "REG52.H"
#include <string.h>
typedef unsigned char U8;
/**
* PART 3 SPI (SCLK,SDO,SDI) 全双工
* SCLK 时钟
* SDO(MOSI) 数据输出
* SDI (MISO) 数据输入
* 8051SPI 和 I2C一样也是需要用IO模拟
* SPI总线传输共有4种类型,
* CPOL位,高电平为:1,低电平为:0
* CPHA位, 边沿,先读后写:0,先写后读:1
* 传输时候,先传输高位再传输低位
*
* 实验程序采用SPI 串行总线的EEPROM,25AA040A
* 过程
* 读数据: 先写入读命令,再写读地址
* 写数据: 先使写地址锁存,然后使用写命令,写地址,然后再写入数据
*
* A8 如果是9位寄存器有效 1,8位为0
**/
#define READ 0x03
#define WRITE 0x02
#define WREN 0x06
sbit SCK = P2^4;
sbit SI = P2^5;
sbit SO = P2^6;
sbit CS = P2^7;
//串口初始化 - 为了打印数据用
void uart_init()
{
SCON = 0x50;
TMOD = 0x20; //选择 定时器1
//装在波特率 高8位和低8位,9600
TH1 = 0xFD;
TL1 = 0xFD;
ES = 1; //打开串口中断
TR1 = 1; //打开定时器1
EA = 1; //打开总中断
}
//发送一个字符
void uart_send_char(char str)
{
SBUF = str; //将待发送的字符串放入缓冲器
while(TI==0); //等待完发送
TI=0; // 发送中断标志 清0
}
//串口中断业务处理
void uart_handle() interrupt 4
{
}
//写入1个字节
void spi_write(U8 dat)
{
U8 i=0;
for(i=0;i<8;i++)
{
SCK = 0; //产生上升沿的时候来读SI的数据
//依次取数据位,给SI
SI=dat>>7;
dat=dat<<1;
SCK = 1;
}
}
//读取 上升沿后,读取数据
U8 spi_read()
{
U8 i=0;
U8 dat=0;
for(i=0;i<8;i++)
{
SCK = 0;
SCK = 1;
//依次把数据位放到 SO
dat <<= 1;
dat|=SO;
}
return dat;
}
//读eeprom操作
U8 spi_device_read(U8 addr)
{
U8 dat=0;
CS = 0;
spi_write(READ);
spi_write(addr);
dat = spi_read();
CS = 1; //读完后把cs拉回到高电平
return dat;
}
void delay5ms() //误差 -0.000000000001us
{
unsigned char a,b;
for(b=15;b>0;b--)
for(a=152;a>0;a--);
}
//写eeprom操作
void spi_device_write(U8 addr,U8 dat){
//写就绪
CS = 0;
spi_write(WREN);
CS = 1; //拉高
CS = 0;
spi_write(WRITE); //使用写命令
spi_write(addr);
spi_write(dat);
//是否写入成功延迟5ms
delay5ms();
CS = 1;
}
void delay1s() //误差 0us
{
unsigned char a,b,c;
for(c=167;c>0;c--)
for(b=171;b>0;b--)
for(a=16;a>0;a--);
}
void main()
{
U8 res1;
//初始化串口,为了把数据显示到串口
uart_init();
//写入数据 , 1号地址,写入数值2
delay1s();
spi_device_write(1,0x11);
delay1s();
res1 = spi_device_read(1);
//发送到串口
uart_send_char(res1);
while (1){
}
}
感谢您的支持,写的文章如对您有所帮助,开源不易,请您打赏,谢谢啦~