8051/2单片机常用的本地通讯方式 UART,RS485,I2C,SPI 之 SPI 25AA040A 读写 E2PROM 4

欲速则不达,还是要慢一点,再慢一点~

一、说明

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){
   }
}

感谢您的支持,写的文章如对您有所帮助,开源不易,请您打赏,谢谢啦~

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值