1.0 软件驱动NOR FLASH
MOSI:主机发送,从机接收
MISO:主机接收,从机发送
CS:表示的是片选信号
2.0 宏定义各个引脚
// 片选
#define SET_SPI_NSS() gpio_bit_set(GPIOE,GPIO_PIN_2)
#define CLR_SPI_NSS() gpio_bit_reset(GPIOE_GPIO_PIN_2)
// SPI引脚电平
#define SET_SPI_SCK() gpio_bit_set(GPIOB,GPIO_PIN_13)
#define CLR_SPI_SCK() gpio_bit_reset(GPIOB,GPIO_PIN_13)
// 主机输出从机输出
#define READ_SPI_MISO() gpio_input_bit_get(GPIOB,CPIO_PIN_14)
// 主机输出从机输入
#define SET_SPI_MOSI() gpio_bit_set(GPIOB,GPIO_PIN_15)
#define CLR_SPI_MOSI() gpio_bit_reset(GPIOB,GPIO_PIN_15)
3.0 SPI 初始化
static void SPI_Init(void)
{
// GPIO 初始化
GPIO_Init();
// 片选信号设置为高电平
SET_SPI_NSS();
// 时钟信号设置为低电平
CLR_SPI_SCK();
}
NOR FLASH支持两种模式,此处使用的是模式0
4.0 SPI 起始信号和结束信号
// 起始信号:片选信号从高电平变为低电平
static void SPIStart(void)
{
CLR_SPI_NSS();
}
// 结束信号:片选信号从低电平变为高电平
static void SPIStop(void)
{
SET_SPI_NSS();
}
5.0 SPI 读写字节
此处并没有使用延时,SPI总线的时钟频率是很快的,并且不需要额外的增加延时的函数
// SPI读写一个字节的数据
static uint8_t SPIReadWriteByte(uint8_t sendData)
{
uint8_t rcvData = 0;
uint8_t i = 0;
for(i = 0; i < 8; i++)
{
if((sendData & 0x80))
{
SET_SPI_MOSI();
}
else
{
CLR_SPI_MOSI();
}
sendData <<= 1;
SET_SPI_SCK();
rcvData <<= 1;
rcvData |= READ_SPI_MISO();
CLR_SPI_SCK();
}
return rcvData;
}
6.0 完整代码
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include "gd32f30x.h"
#include "delay.h"
#define SET_SPI_NSS() gpio_bit_set(GPIOE,GPIO_PIN_2)
#define CLR_SPI_NSS() gpio_bit_reset(GPIOE,GPIO_PIN_2)
#define SET_SPI_SCK() gpio_bit_set(GPIOB,GPIO_PIN_13)
#define CLR_SPI_SCK() gpio_bit_reset(GPIOB,GPIO_PIN_13)
#define READ_SPI_MISO() gpio_input_bit_get(GPIOB, GPIO_PIN_14)
#define SET_SPI_MOSI() gpio_bit_set(GPIOB,GPIO_PIN_15)
#define CLR_SPI_MOSI() gpio_bit_reset(GPIOB,GPIO_PIN_15)
static void GPIO_Init()
{
// PE2片选SS
rcu_periph_clock_enable(RCU_GPIOE);
gpio_init(GPIOE,GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_2);
gpio_bit_set(GPIOE,GPIO_PIN_2);
// PB13作为SCK
rcu_periph_clock_enable(RCU_GPIOB);
gpio_init(GPIOB,GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_2);
gpio_bit_set(GPIOE,GPIO_PIN_2);
// PB14作为MISO
gpio_init(GPIOB,GPIO_MODE_IPU,GPIO_OSPEED_50MHZ,GPIO_PIN_14);
// PB15作为MOSI
gpio_init(GPIOB,GPIO_MODE_OUT_PP,GPIO_OSPEED_50MHZ,GPIO_PIN_15);
gpio_bit_set(GPIOB,GPIO_PIN_15);
};
static void SPI_Init(void)
{
// GPIO 初始化
GPIO_Init();
// 片选信号设置为高电平
SET_SPI_NSS();
// 时钟信号设置为低电平
CLR_SPI_SCK();
}
// 起始信号:片选信号从高电平变为低电平
static void SPIStart(void)
{
CLR_SPI_NSS();
}
// 结束信号:片选信号从低电平变为高电平
static void SPIStop(void)
{
SET_SPI_NSS();
}
// SPI读写一个字节的数据
static uint8_t SPIReadWriteByte(uint8_t sendData)
{
uint8_t rcvData = 0;
uint8_t i = 0;
for(i = 0; i < 8; i++)
{
if((sendData & 0x80))
{
SET_SPI_MOSI();
}
else
{
CLR_SPI_MOSI();
}
sendData <<= 1;
SET_SPI_SCK();
rcvData <<= 1;
rcvData |= READ_SPI_MISO();
CLR_SPI_SCK();
}
return rcvData;
}