SPI通信

#include "stm32f4xx.h"
#include "flashspi.h"
#include "stdio.h"


uint8_t spi_flash_errnum_callback(uint8_t err)
{
    // 打印错误编号到控制台
    printf("错误编号是:%d\r\n", err);
    return err;
}


//配置主机模式
void FLASH_SPI_Iint(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    SPI_InitTypeDef  SPI_InitStructure;
	
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);//使能SPI1时钟
    
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5; 
	GPIO_InitStructure.GPIO_Mode= GPIO_Mode_AF; //复用模式
	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_UP; //上拉模式
	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP; //推挽输出
	GPIO_InitStructure.GPIO_Speed=GPIO_High_Speed; //引脚响应速度
	GPIO_Init(GPIOB ,&GPIO_InitStructure);
    
    //PB3、4、5引脚复用
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource3, GPIO_AF_SPI1);
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource4, GPIO_AF_SPI1);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource5, GPIO_AF_SPI1);
    
    //这里只针对SPI口初始化
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,ENABLE);//复位SPI1
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1,DISABLE);//停止复位SPI1

    //SPI配置
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;		//设置SPI工作模式:设置为主SPI
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;		//设置SPI的数据大小:SPI发送接收8位帧结构
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;		//串行同步时钟的空闲状态为高电平
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;	//串行同步时钟的第二个跳变沿(上升或下降)数据被采样
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;		//NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;		//定义波特率预分频的值:波特率预分频值为256
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;	//指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始
    SPI_Init(SPI1, &SPI_InitStructure);  //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器


        //PB14配置
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_14; 
        GPIO_InitStructure.GPIO_Mode= GPIO_Mode_OUT; //输出模式
        GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL; //上拉模式
        GPIO_InitStructure.GPIO_OType=GPIO_OType_PP; //推挽输出
        GPIO_InitStructure.GPIO_Speed=GPIO_High_Speed; //引脚响应速度
        GPIO_Init(GPIOB ,&GPIO_InitStructure);

        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);//使能GPIOG时钟
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;//PG7
        GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化
        GPIO_SetBits(GPIOG,GPIO_Pin_7);//PG7输出1,防止NRF干扰SPI FLASH的通信 

    SPI_Cmd(SPI1, ENABLE); //使能SPI外设
}


//启动flash的初始化并读取flash的ID号
void Flash_init(void)
{
    //1.拉高CS不进行片选;
	GPIO_ResetBits(GPIOB ,GPIO_Pin_14);

    //读取ID
    printf("ID : %x\r\n",FLASH_SPI_READID());
}


//读取FLASH ID
uint32_t FLASH_SPI_READID(void)
{
    uint32_t Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
    // 拉低CS,开始通讯
    GPIO_ResetBits(GPIOB, GPIO_Pin_14);

    FLASH_SPI_WRITEByte(0x9f);  // 发送读取ID命令

    //读取第一个字节数据
    Temp0 = FLASH_SPI_WRITEByte(0xff);

    //读取第2个字节数据
    Temp1 = FLASH_SPI_WRITEByte(0xff);

    //读取第3个字节数据
    Temp2 = FLASH_SPI_WRITEByte(0xff);

    //拉高CS,结束通讯
    GPIO_SetBits(GPIOB, GPIO_Pin_14);

    Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;

    return Temp;
}


//写入一字节数据
uint8_t FLASH_SPI_WRITEByte(uint8_t writebyte)
{
	int timeout = 0xffff;
	//1.判断缓冲区,等待发送缓冲区为空
	while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE) == RESET)
	{
		if((timeout--) == 0)
		{
			return spi_flash_errnum_callback(5);
		}
	}
	//2.写入缓冲区
	SPI_I2S_SendData(SPI1, writebyte);
	
	//3.判断缓冲区,等待接收缓冲区为空
    timeout = 0xffff;
	while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE) == RESET)
	{
		if((timeout--) == 0)
		{
			return spi_flash_errnum_callback(6);
		}
	}
	//4.返回通过SPIx最近接收的数据
	return SPI_I2S_ReceiveData(SPI1);
}


//读取数据
void FLASH_SPI_bufread(uint8_t *readdatabuf, uint32_t readadd, uint16_t readlenth)
{	
    //1.拉低CS,开始通讯
	GPIO_ResetBits(GPIOB ,GPIO_Pin_14);
	
	//发送读取数据命令
	FLASH_SPI_WRITEByte(0x03);
	
	FLASH_SPI_WRITEByte((readadd & 0xff0000)>>16);  //发送扇区高位地址
	FLASH_SPI_WRITEByte((readadd & 0xff00)>>8);  //发送扇区中位地址
	FLASH_SPI_WRITEByte(readadd & 0xff);  //发送扇区地位地址
	
    uint16_t i;
	for(i = 0; i<readlenth; i++)
	{
		readdatabuf[i] = FLASH_SPI_WRITEByte(0xff);
	}
	
	GPIO_SetBits(GPIOB ,GPIO_Pin_14);
    printf("读取数据成功\r\n");
}


//作用是在执行写入或擦除操作之后,确保这些操作完全完成,
//Flash进入就绪状态,以便接受后续命令
void FLASH_SPI_WriteWaitANDEND(void)
{
    uint8_t flashstatus = 0;
    
    //1.拉低CS,开始通讯
	GPIO_ResetBits(GPIOB ,GPIO_Pin_14);
    
    // 发送“读状态寄存器”指令
    //2.读取状态标志
	FLASH_SPI_WRITEByte(0x05);
    
    // 只要内存忙于写周期就循环
    do
    {
        // 发送一个虚拟字节以生成Flash所需的时钟
        // 并将状态寄存器的值放入flashstatus变量
        flashstatus = FLASH_SPI_WRITEByte(0xff);
        
    } while ((flashstatus & 0xff) == SET); // 写入进行
    
    // 设置Flash芯片选择线高电平
    //3.拉高CS,结束通讯
	GPIO_SetBits(GPIOB ,GPIO_Pin_14);
}


//写使能
void FLASH_SPI_WriteEnable(void)
{
	//1.拉低CS,开始通讯
	GPIO_ResetBits(GPIOB ,GPIO_Pin_14);
	
	//2.发送写使能命令
	FLASH_SPI_WRITEByte(0x06);

	//3.拉高CS,结束通讯
	GPIO_SetBits(GPIOB ,GPIO_Pin_14);
}


//擦除一个扇区
//sectoradd:扇区地址
//擦除一个山区的最少时间:150ms
void FLASH_SPI_SectorErase(uint32_t sectoradd)
{
    //使能flash寄存器
	FLASH_SPI_WriteEnable();
	FLASH_SPI_WriteWaitANDEND();
    
	//监视falsh擦除情况,测试用   
 	printf("fe:%x\r\n",sectoradd);
    sectoradd*=4096;
    
	GPIO_ResetBits(GPIOB ,GPIO_Pin_14);
	
	//发送扇区擦除命令
	FLASH_SPI_WRITEByte(0x20);
	
	//例如扇区地址为0xaabbcc,每次发送一个字节(8位),则高位为aa,中为bb,低为cc
	FLASH_SPI_WRITEByte((sectoradd & 0xFF0000)>>16);	//发送扇区高位地址
	FLASH_SPI_WRITEByte((sectoradd & 0xFF00)>>8);			//发送扇区中位地址
	FLASH_SPI_WRITEByte(sectoradd & 0xFF);						//发送扇区地位地址
	
	GPIO_SetBits(GPIOB ,GPIO_Pin_14);
	FLASH_SPI_WriteWaitANDEND();
    printf("擦除扇区成功\r\n");
}


//对FLASH按页写入
//第一个参数是待写入数据缓冲区的地址,
//第二个参数是写入flash区域地址
//第三个参数是写入数据长度
void FLASH_SPI_PageWrite(uint8_t *writedatabuf, uint32_t writeadd, uint16_t writelenth)
{
	FLASH_SPI_WriteEnable();
	
	GPIO_ResetBits(GPIOB ,GPIO_Pin_14);
	
	//发送页面操作命令
	FLASH_SPI_WRITEByte(0x02);
	
	FLASH_SPI_WRITEByte((writeadd & 0xff0000)>>16);	//发送扇区高位地址
	FLASH_SPI_WRITEByte((writeadd & 0xff00)>>8);			//发送扇区中位地址
	FLASH_SPI_WRITEByte(writeadd & 0xff);						//发送扇区地位地址
	
	//写数据
	while(writelenth--)
	{
		FLASH_SPI_WRITEByte(*writedatabuf);
		writedatabuf++;
	}
	
	GPIO_SetBits(GPIOB ,GPIO_Pin_14);
	FLASH_SPI_WriteWaitANDEND();
    printf("写入成功\r\n");
}

//main函数
int main(void)
{
    SysTick_Init();
	
    //初始化IIC
	IIC_init();
	
    ///初始化OLED
	OLED_Init();
    
    usart1_init(115200);
    //硬件IIC通信,上传
	Hardware_IIC_Init();
    
    OLED_ShowString(1, 1, "Autonomic");
   uint8_t writedatabuf[] = "123456789";
      //初始化
     FLASH_SPI_Iint();
     Flash_init();
    Delay_ms(2000);
    FLASH_SPI_SectorErase(0x000000);
    Delay_ms(2000);
    FLASH_SPI_PageWrite(writedatabuf, 0x000000, sizeof(writedatabuf));
    Delay_ms(2000);
    uint8_t readdatabuf[12] = {0};
    FLASH_SPI_bufread(readdatabuf, 0x000000, sizeof(readdatabuf));
    printf("%s\r\n",readdatabuf);
	while(1)
	{
		Get_BH1750Data ();
		Delay_ms(100);
	}
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.
  • 137.
  • 138.
  • 139.
  • 140.
  • 141.
  • 142.
  • 143.
  • 144.
  • 145.
  • 146.
  • 147.
  • 148.
  • 149.
  • 150.
  • 151.
  • 152.
  • 153.
  • 154.
  • 155.
  • 156.
  • 157.
  • 158.
  • 159.
  • 160.
  • 161.
  • 162.
  • 163.
  • 164.
  • 165.
  • 166.
  • 167.
  • 168.
  • 169.
  • 170.
  • 171.
  • 172.
  • 173.
  • 174.
  • 175.
  • 176.
  • 177.
  • 178.
  • 179.
  • 180.
  • 181.
  • 182.
  • 183.
  • 184.
  • 185.
  • 186.
  • 187.
  • 188.
  • 189.
  • 190.
  • 191.
  • 192.
  • 193.
  • 194.
  • 195.
  • 196.
  • 197.
  • 198.
  • 199.
  • 200.
  • 201.
  • 202.
  • 203.
  • 204.
  • 205.
  • 206.
  • 207.
  • 208.
  • 209.
  • 210.
  • 211.
  • 212.
  • 213.
  • 214.
  • 215.
  • 216.
  • 217.
  • 218.
  • 219.
  • 220.
  • 221.
  • 222.
  • 223.
  • 224.
  • 225.
  • 226.
  • 227.
  • 228.
  • 229.
  • 230.
  • 231.
  • 232.
  • 233.
  • 234.
  • 235.
  • 236.
  • 237.
  • 238.
  • 239.
  • 240.
  • 241.
  • 242.
  • 243.
  • 244.
  • 245.
  • 246.
  • 247.
  • 248.
  • 249.
  • 250.
  • 251.
  • 252.
  • 253.
  • 254.
  • 255.
  • 256.
  • 257.
  • 258.
  • 259.
  • 260.
  • 261.
  • 262.
  • 263.
  • 264.
  • 265.
  • 266.
  • 267.
  • 268.
  • 269.
  • 270.
  • 271.
  • 272.
  • 273.
  • 274.
  • 275.
  • 276.
  • 277.
  • 278.
  • 279.
  • 280.
  • 281.
  • 282.
  • 283.
  • 284.
  • 285.
  • 286.
  • 287.
  • 288.
  • 289.
  • 290.
  • 291.
  • 292.

SPI通信_SPI