8051/2单片机常用的本地通讯方式 UART,RS485,I2C,SPI 之 SPI 25AA040A 读写 E2PROM 4
2022-05-19 来源:eefocus
一、说明
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 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){ } }