前言
网上例程多为GD32(STM32)做主机的案例代码,个人试验总结出一套可用的MCU做SPI从机的案例
实现功能:
GD32通过配置为SPI 从机00工作模式,接收上位机(调试软件)下发的一帧数据,进入SPI中断后,通过USART0原样返回数据。
直接上干货
代码部分:
主函数:
#include <stdio.h>
#include "systick.h"
#include "usart_comm.h"
#include "gd_slave_spi.h"
//程序功能,实现单片机与电脑之间的通信,通过电脑(SPI主机)
//下发数据,然后,单片机通过USART原样返回数据
//用SPI调试工具发送数据,要配置成模式00,msb,主模式
extern uint8_t spi0_receive_array[10];//SPI接收数据的下脚游标
extern uint8_t i;//定义全局变量i
int main (void)
{
systick_config(); //
gd32_slave_spi_init();
usart0_init(9600);
uint8_t t = 0;
while (1)
{
//uint8_t read_buffer[10];
while (i) //等待i状态反转,一旦反转说明SPI0接收到了数据
{
i = 0;
usart_interrupt_disable(USART0, USART_INT_RBNE);
for (t = 0; t < sizeof(spi0_receive_array); t++)
{
usart0_send_byte(spi0_receive_array[t]);
}
usart_interrupt_enable(USART0, USART_INT_RBNE);
}
}
}
.C函数
#include "gd_slave_spi.h"
uint8_t spi0_receive_array[10] = {0};
uint8_t receive_n = 0;//SPI接收数据的下脚游标
uint8_t i = 0;//反应SPI状态的变量
void gd32_slave_spi_init(void)
{
//使能外设时钟
spi_slave_rcu_init();
//首先对IO口进行配置,使之被复用为SPI,这里使用的是SPI0,对应PA4,PA5,PA6,PA7,NSS,SCK,MISO,MOSI
spi_slave_io_init();
//SPI0初始化
spi_slave_config();
}
void spi_slave_rcu_init(void)
{
rcu_periph_clock_enable(RCU_GPIOA);//使能GPIO0时钟
// rcu_periph_clock_enable(RCU_AF);//
rcu_periph_clock_enable(RCU_SPI0);//使能SPI0时钟
}
//SPI从机初始化
void spi_slave_io_init(void)
{
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6); //PA6为MISO
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_5 | GPIO_PIN_7); //PA7为MOSI
gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_4); //NSS片选口,
}
//SPI0初始化
void spi_slave_config(void)
{
spi_parameter_struct spi_struct;//定义结构体
spi_struct.device_mode = SPI_SLAVE; /*!< SPI master or slave */
spi_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX; /*!< SPI transfer type */
spi_struct.frame_size = SPI_FRAMESIZE_8BIT ; /*!< SPI frame size */
spi_struct.nss = SPI_NSS_HARD; /*!< SPI NSS control by handware or software */
spi_struct.endian = SPI_ENDIAN_MSB; /*!< SPI big endian or little endian */
spi_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE; /*模式0工作*/
spi_struct.prescale = SPI_PSC_8; /*!< SPI prescaler factor 预分频器配置*/
spi_init(SPI0, &spi_struct);
nvic_irq_enable(SPI0_IRQn,1,0);//设置中断优先级
/* SPI int enable */
//spi_i2s_interrupt_enable(SPI1, SPI_I2S_INT_TBE);
spi_i2s_interrupt_enable(SPI0, SPI_I2S_INT_RBNE); //接收缓冲区非空中断使能
spi_enable(SPI0);//使能SPI0
}
void SPI0_IRQHandler(void)
{
/* receive data */
if(RESET != spi_i2s_interrupt_flag_get(SPI0,SPI_I2S_INT_FLAG_RBNE))
{
spi0_receive_array[receive_n++] = spi_i2s_data_receive(SPI0); //SPI0接收到的数据赋值给数组
// while(RESET == spi_i2s_flag_get(SPI1, SPI_FLAG_TBE));
// spi_i2s_data_transmit(SPI1, slave_tx_buf[tx_n++]);
if (receive_n == 10)
{
// handle_spi1_message(spi1_receive_array,16);
receive_n = 0;
i = 1;
}
}
}
调试器配置:
最终,SPI调试软件发送以上10字节数据,串口返回相同的10字节数据。