#include "gd32f3x0.h"
#include "stdint.h"
#include "private_drives_gpio.h"
/* spi时钟模式,*/
//空闲低电平,第一个跳边沿采样
#define SPI_MODE_0 SPI_CK_PL_LOW_PH_1EDGE
//空闲低电平,第二个跳边沿采样
#define SPI_MODE_1 SPI_CK_PL_LOW_PH_2EDGE
//空闲高电平,第一个跳边沿采样
#define SPI_MODE_2 SPI_CK_PL_HIGH_PH_1EDGE
//空闲高电平,第二个跳边沿采样
#define SPI_MODE_3 SPI_CK_PL_HIGH_PH_2EDGE
//spi配置结构体
typedef struct
{
// SPI选择
uint32_t spi;
//spi时钟
rcu_periph_enum rcu_spi;
//GPIO时钟
rcu_periph_enum rcu_gpio;
//时钟引脚
uint32_t gpio_periph_sck;
uint32_t pin_sck;
//miso引脚
uint32_t gpio_periph_miso;
uint32_t pin_miso;
//mosi引脚
uint32_t gpio_periph_mosi;
uint32_t pin_mosi;
//时钟模式
uint32_t spi_mode;
} private_drives_spi_struct_spi_config;
//spi0配置
static private_drives_spi_struct_spi_config private_drives_spi_struct_spi0_config =
{
.spi = SPI0,
.rcu_spi = RCU_SPI0,
.rcu_gpio = RCU_GPIOA,
.gpio_periph_sck = GPIOA,
.pin_sck = GPIO_PIN_5,
.gpio_periph_miso = GPIOA,
.pin_miso = GPIO_PIN_6,
.gpio_periph_mosi = GPIOA,
.pin_mosi = GPIO_PIN_7,
.spi_mode = SPI_MODE_1
};
//spi1配置
static private_drives_spi_struct_spi_config private_drives_spi_struct_spi1_config =
{
.spi = SPI1,
.rcu_spi = RCU_SPI1,
.rcu_gpio = RCU_GPIOB,
.gpio_periph_sck = GPIOB,
.pin_sck = GPIO_PIN_13,
.gpio_periph_miso = GPIOB,
.pin_miso = GPIO_PIN_14,
.gpio_periph_mosi = GPIOB,
.pin_mosi = GPIO_PIN_15,
.spi_mode = SPI_MODE_1
};
/*!
\brief 初始化SPI
\param[in] spi_config spi配置
\param[out] none
\retval none
*/
static void private_packs_spi_init(private_drives_spi_struct_spi_config spi_config)
{
spi_parameter_struct spi_init_struct;
rcu_periph_clock_enable(spi_config.rcu_spi);
rcu_periph_clock_enable(spi_config.rcu_gpio);
// 设置gpio管脚复用SPI
gpio_af_set(spi_config.gpio_periph_sck, GPIO_AF_0, spi_config.pin_sck);
gpio_af_set(spi_config.gpio_periph_miso, GPIO_AF_0, spi_config.pin_miso);
gpio_af_set(spi_config.gpio_periph_mosi, GPIO_AF_0, spi_config.pin_mosi);
// 设置gpio管脚为替代功能模式,即为上一步设置的SPI模式
gpio_mode_set(spi_config.gpio_periph_sck, GPIO_MODE_AF, GPIO_PUPD_NONE, spi_config.pin_sck);
gpio_mode_set(spi_config.gpio_periph_miso, GPIO_MODE_AF, GPIO_PUPD_NONE, spi_config.gpio_periph_miso);
gpio_mode_set(spi_config.gpio_periph_mosi, GPIO_MODE_AF, GPIO_PUPD_NONE, spi_config.gpio_periph_mosi);
// 设置gpio引脚输出模式为推挽式
gpio_output_options_set(spi_config.gpio_periph_sck, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, spi_config.pin_sck);
gpio_output_options_set(spi_config.gpio_periph_miso, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, spi_config.gpio_periph_miso);
gpio_output_options_set(spi_config.gpio_periph_mosi, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, spi_config.gpio_periph_mosi);
/* SPI 参数配置 */
// 全双工模式
spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
// 主设备模式
spi_init_struct.device_mode = SPI_MASTER;
// 8bit数据宽度
spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT;
// SPI时钟极性,空闲为低电平,第二个跳变边缘取样
spi_init_struct.clock_polarity_phase = spi_config.spi_mode;
// NSS软件控制,软件spi控制模式
spi_init_struct.nss = SPI_NSS_SOFT;
// 预分频32
spi_init_struct.prescale = SPI_PSC_32;
// 大端传输
spi_init_struct.endian = SPI_ENDIAN_MSB;
spi_init(spi_config.spi, &spi_init_struct);
/* eanble SPI */
spi_enable(spi_config.spi);
}
/*!
\brief 初始化SPI0
\param[in] none
\param[out] none
\retval none
*/
void private_drives_spi_init_spi0()
{
private_packs_spi_init(private_drives_spi_struct_spi0_config);
}
/*!
\brief 初始化SPI1
\param[in] none
\param[out] none
\retval none
*/
void private_drives_spi_init_spi1()
{
private_packs_spi_init(private_drives_spi_struct_spi1_config);
}
/*!
\brief SPI,发送接收字节
\param[in] spi_periph, spi选择
byte,需要发送的字节内容
\param[out] none
\retval 收到的字节内容
*/
static uint8_t spi_write_byte(uint32_t spi_periph, uint8_t byte)
{
while(RESET == (SPI_STAT(spi_periph)&SPI_FLAG_TBE));
SPI_DATA(spi_periph) = byte;
while(RESET == (SPI_STAT(spi_periph)&SPI_FLAG_RBNE));
return(SPI_DATA(spi_periph));
}
/*!
\brief SPI,发送接收数据
\param[in] spi_periph, spi选择
send_buf,需要发送的字节缓存
recv_buf,接收数据缓存
len,需要发送的数据长度
\param[out] none
\retval none
*/
static void private_drives_spi_send(uint32_t spi_periph, uint8_t *send_buf, uint8_t *recv_buf, int len)
{
for(int i = 0; i < len; i++)
{
recv_buf[i] = spi_write_byte(spi_periph, send_buf[i]);
}
}
/*!
\brief SPI0,发送接收数据
\param[in] send_buf,需要发送的字节缓存
len,需要发送的数据长度
recv_buf,接收数据缓存
\param[out] none
\retval none
*/
void private_drives_spi0_send(uint8_t *send_buf, uint8_t *recv_buf, int len)
{
private_drives_spi_send(SPI0, send_buf, recv_buf, len);
}
/*!
\brief SPI1,发送接收数据
\param[in] send_buf,需要发送的字节缓存
len,需要发送的数据长度
recv_buf,接收数据缓存
\param[out] none
\retval none
*/
void private_drives_spi1_send(uint8_t *send_buf, uint8_t *recv_buf, int len)
{
private_drives_spi_send(SPI1, send_buf, recv_buf, len);
}
GD32F310 SPI开发
最新推荐文章于 2024-03-08 09:49:21 发布