GD32F310 SPI开发

#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);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值