Master
SPI0_NSS PA4 AF5
SPI0_SCK PA5 AF5
SPI0_MISO PA6 AF5
SPI0_MOSI PA7 AF5
Slave
SPI4_NSS PK1 AF5
SPI4_SCK PK0 AF5
SPI4_MOSI PJ10 AF5
SPI4_MISO PJ11 AF5
spi_master_transmit_receive_dma 主机发送接收
spi_slave_transmit_receive_dma 从机发送接收
main.c
/*!
\file main.c
\brief running LED
\version 2023-03-31, V1.0.0, firmware for GD32H7xx
*/
#include "gd32h7xx.h"
#include "systick.h"
#include "string.h"
#include "stdio.h"
/*!
\brief enable the CPU Chache
\param[in] none
\param[out] none
\retval none
*/
static void cache_enable(void)
{
/* Enable I-Cache */
SCB_EnableICache();
/* Enable D-Cache */
// SCB_EnableDCache();
}
void led_config()
{
rcu_periph_clock_enable(RCU_GPIOJ);
gpio_mode_set(GPIOJ, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_8);
gpio_output_options_set(GPIOJ, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_8);
gpio_mode_set(GPIOJ, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN_9);
gpio_output_options_set(GPIOJ, GPIO_OTYPE_PP, GPIO_OSPEED_60MHZ, GPIO_PIN_9);
gpio_bit_set(GPIOJ, GPIO_PIN_8);
gpio_bit_set(GPIOJ, GPIO_PIN_9);
}
void usart_config()
{
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_USART0);
gpio_af_set(GPIOB, GPIO_AF_7, GPIO_PIN_6);
gpio_af_set(GPIOB, GPIO_AF_7, GPIO_PIN_7);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_6);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_6);
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_PULLUP, GPIO_PIN_7);
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_7);
usart_deinit(USART0);
usart_word_length_set(USART0, USART_WL_8BIT);
usart_stop_bit_set(USART0, USART_STB_1BIT);
usart_parity_config(USART0, USART_PM_NONE);
usart_baudrate_set(USART0, 921600U);
usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
usart_receive_config(USART0, USART_RECEIVE_ENABLE);
usart_enable(USART0);
}
void usart_transmit(char* buff, int size)
{
for (int i = 0; i < size; ++i) {
usart_data_transmit(USART0, buff[i]);
while (RESET == usart_flag_get(USART0, USART_FLAG_TBE)) {}
}
}
/*
* Master
* SPI0_NSS PA4 AF5
* SPI0_SCK PA5 AF5
* SPI0_MISO PA6 AF5
* SPI0_MOSI PA7 AF5
*/
void spi0_config()
{
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_SPI0);
gpio_af_set(GPIOA, GPIO_AF_5, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);
spi_i2s_deinit(SPI0);
spi_parameter_struct spi_init_struct;
spi_struct_para_init(&spi_init_struct);
spi_init_struct.device_mode = SPI_MASTER;
spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
spi_init_struct.data_size = SPI_DATASIZE_8BIT;
spi_init_struct.nss = SPI_NSS_SOFT;
spi_init_struct.endian = SPI_ENDIAN_MSB;
spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
spi_init_struct.prescale = SPI_PSC_64;
spi_init(SPI0, &spi_init_struct);
spi_byte_access_enable(SPI0);
spi_nss_output_enable(SPI0);
spi_nss_internal_high(SPI0);
spi_dma_enable(SPI0, SPI_DMA_TRANSMIT);
spi_dma_enable(SPI0, SPI_DMA_RECEIVE);
spi_enable(SPI0);
}
void spi0_dma_config()
{
rcu_periph_clock_enable(RCU_DMA0);
rcu_periph_clock_enable(RCU_DMAMUX);
nvic_irq_enable(DMA0_Channel0_IRQn, 1, 1);
nvic_irq_enable(DMA0_Channel1_IRQn, 1, 0);
dma_deinit(DMA0, DMA_CH1); //SPI0_RX
dma_single_data_parameter_struct dma_init_struct_rx;
dma_single_data_para_struct_init(&dma_init_struct_rx);
dma_init_struct_rx.request = DMA_REQUEST_SPI0_RX;
dma_init_struct_rx.direction = DMA_PERIPH_TO_MEMORY;
dma_init_struct_rx.memory0_addr = (uint32_t)0;
dma_init_struct_rx.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct_rx.periph_memory_width = DMA_MEMORY_WIDTH_8BIT;
dma_init_struct_rx.number = 0;
dma_init_struct_rx.periph_addr = (uint32_t)&SPI_RDATA(SPI0);
dma_init_struct_rx.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct_rx.priority = DMA_PRIORITY_ULTRA_HIGH;
dma_single_data_mode_init(DMA0, DMA_CH1, &dma_init_struct_rx);
dma_circulation_disable(DMA0, DMA_CH1); //用循环模式接收会出现问题,每次接收的第一个数据都是0x00
dma_interrupt_enable(DMA0, DMA_CH1, DMA_INT_FTF);
dma_deinit(DMA0, DMA_CH0); //SPI0_TX
dma_single_data_parameter_struct dma_init_struct_tx;
dma_single_data_para_struct_init(&dma_init_struct_tx);
dma_init_struct_tx.request = DMA_REQUEST_SPI0_TX;
dma_init_struct_tx.direction = DMA_MEMORY_TO_PERIPH;
dma_init_struct_tx.memory0_addr = (uint32_t)0;
dma_init_struct_tx.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct_tx.periph_memory_width = DMA_MEMORY_WIDTH_8BIT;
dma_init_struct_tx.number = 0;
dma_init_struct_tx.periph_addr = (uint32_t)&SPI_TDATA(SPI0);
dma_init_struct_tx.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct_tx.priority = DMA_PRIORITY_HIGH;
dma_single_data_mode_init(DMA0, DMA_CH0, &dma_init_struct_tx);
dma_circulation_disable(DMA0, DMA_CH0);
dma_interrupt_enable(DMA0, DMA_CH0, DMA_INT_FTF);
}
//主机DMA发送接收
void spi_master_transmit_receive_dma(uint8_t* tx_buff, uint8_t* rx_buff, int size)
{
dma_memory_address_config(DMA0, DMA_CH1, DMA_MEMORY_0, rx_buff);
dma_transfer_number_config(DMA0, DMA_CH1, size);
dma_channel_enable(DMA0, DMA_CH1);
dma_memory_address_config(DMA0, DMA_CH0, DMA_MEMORY_0, tx_buff);
dma_transfer_number_config(DMA0, DMA_CH0, size);
dma_channel_enable(DMA0, DMA_CH0);
spi_nss_internal_low(SPI0);
spi_master_transfer_start(SPI0, SPI_TRANS_START);
}
//主机发送DMA callback
void DMA0_Channel0_IRQHandler()
{
if (RESET != dma_interrupt_flag_get(DMA0, DMA_CH0, DMA_INT_FLAG_FTF)) {
dma_interrupt_flag_clear(DMA0, DMA_CH0, DMA_INT_FLAG_FTF);
spi_master_transfer_start(SPI0, SPI_TRANS_IDLE);
spi_nss_internal_high(SPI0);
}
}
//主机接收DMA callback
void DMA0_Channel1_IRQHandler()
{
if (RESET != dma_interrupt_flag_get(DMA0, DMA_CH1, DMA_INT_FLAG_FTF)) {
dma_interrupt_flag_clear(DMA0, DMA_CH1, DMA_INT_FLAG_FTF);
}
}
/*
* Slave
* SPI4_NSS PK1 AF5
* SPI4_SCK PK0 AF5
* SPI4_MOSI PJ10 AF5
* SPI4_MISO PJ11 AF5
*/
void spi4_config()
{
rcu_periph_clock_enable(RCU_GPIOK);
rcu_periph_clock_enable(RCU_GPIOJ);
rcu_periph_clock_enable(RCU_SPI4);
gpio_af_set(GPIOK, GPIO_AF_5, GPIO_PIN_0 | GPIO_PIN_1);
gpio_mode_set(GPIOK, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_0 | GPIO_PIN_1);
gpio_output_options_set(GPIOK, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_0 | GPIO_PIN_1);
gpio_af_set(GPIOJ, GPIO_AF_5, GPIO_PIN_10 | GPIO_PIN_11);
gpio_mode_set(GPIOJ, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10 | GPIO_PIN_11);
gpio_output_options_set(GPIOJ, GPIO_OTYPE_PP, GPIO_OSPEED_100_220MHZ, GPIO_PIN_10 | GPIO_PIN_11);
spi_i2s_deinit(SPI4);
spi_parameter_struct spi_init_struct;
spi_struct_para_init(&spi_init_struct);
spi_init_struct.device_mode = SPI_SLAVE;
spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
spi_init_struct.data_size = SPI_DATASIZE_8BIT;
spi_init_struct.nss = SPI_NSS_HARD;
spi_init_struct.endian = SPI_ENDIAN_MSB;
spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
spi_init_struct.prescale = SPI_PSC_64;
spi_init(SPI4, &spi_init_struct);
spi_byte_access_enable(SPI4);
spi_dma_enable(SPI4, SPI_DMA_TRANSMIT);
spi_dma_enable(SPI4, SPI_DMA_RECEIVE);
spi_enable(SPI4);
}
void spi4_dma_config()
{
rcu_periph_clock_enable(RCU_DMA0);
rcu_periph_clock_enable(RCU_DMAMUX);
nvic_irq_enable(DMA0_Channel2_IRQn, 0, 1);
nvic_irq_enable(DMA0_Channel3_IRQn, 0, 0);
dma_deinit(DMA0, DMA_CH2); //SPI1_TX
dma_single_data_parameter_struct dma_init_struct_tx;
dma_single_data_para_struct_init(&dma_init_struct_tx);
dma_init_struct_tx.request = DMA_REQUEST_SPI4_TX;
dma_init_struct_tx.direction = DMA_MEMORY_TO_PERIPH;
dma_init_struct_tx.memory0_addr = (uint32_t)0;
dma_init_struct_tx.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct_tx.periph_memory_width = DMA_MEMORY_WIDTH_8BIT;
dma_init_struct_tx.number = 0;
dma_init_struct_tx.periph_addr = (uint32_t)&SPI_TDATA(SPI4);
dma_init_struct_tx.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct_tx.priority = DMA_PRIORITY_ULTRA_HIGH;
dma_single_data_mode_init(DMA0, DMA_CH2, &dma_init_struct_tx);
dma_circulation_disable(DMA0, DMA_CH2);
dma_interrupt_enable(DMA0, DMA_CH2, DMA_INT_FTF);
dma_deinit(DMA0, DMA_CH3); //SPI1_RX
dma_single_data_parameter_struct dma_init_struct_rx;
dma_single_data_para_struct_init(&dma_init_struct_rx);
dma_init_struct_rx.request = DMA_REQUEST_SPI4_RX;
dma_init_struct_rx.direction = DMA_PERIPH_TO_MEMORY;
dma_init_struct_rx.memory0_addr = (uint32_t)0;
dma_init_struct_rx.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct_rx.periph_memory_width = DMA_MEMORY_WIDTH_8BIT;
dma_init_struct_rx.number = 0;
dma_init_struct_rx.periph_addr = (uint32_t)&SPI_RDATA(SPI4);
dma_init_struct_rx.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct_rx.priority = DMA_PRIORITY_ULTRA_HIGH;
dma_single_data_mode_init(DMA0, DMA_CH3, &dma_init_struct_rx);
dma_circulation_disable(DMA0, DMA_CH3); //用循环模式接收会出现问题,每次接收的第一个数据都是0x00
dma_interrupt_enable(DMA0, DMA_CH3, DMA_INT_FTF);
}
//从机DMA发送接收
void spi_slave_transmit_receive_dma(uint8_t* tx_buff, uint8_t* rx_buff, int size)
{
dma_memory_address_config(DMA0, DMA_CH2, DMA_MEMORY_0, tx_buff);
dma_transfer_number_config(DMA0, DMA_CH2, size);
dma_channel_enable(DMA0, DMA_CH2);
dma_memory_address_config(DMA0, DMA_CH3, DMA_MEMORY_0, rx_buff);
dma_transfer_number_config(DMA0, DMA_CH3, size);
dma_channel_enable(DMA0, DMA_CH3);
}
//从机发送DMA callback
void DMA0_Channel2_IRQHandler()
{
if (RESET != dma_interrupt_flag_get(DMA0, DMA_CH2, DMA_INT_FLAG_FTF)) {
dma_interrupt_flag_clear(DMA0, DMA_CH2, DMA_INT_FLAG_FTF);
}
}
//从机接收DMA callback
void DMA0_Channel3_IRQHandler()
{
if (RESET != dma_interrupt_flag_get(DMA0, DMA_CH3, DMA_INT_FLAG_FTF)) {
dma_interrupt_flag_clear(DMA0, DMA_CH3, DMA_INT_FLAG_FTF);
}
}
/*!
\brief main function
\param[in] none
\param[out] none
\retval none
*/
int main(void)
{
/* enable the CPU Cache */
cache_enable();
/* configure systick */
systick_config();
led_config();
usart_config();
spi0_dma_config();
spi0_config();
spi4_dma_config();
spi4_config();
int cnt = 0;
while(1) {
uint8_t master_tx_buff[4] = {0x11, 0x22, 0x33, 0x44};
uint8_t master_rx_buff[4] = {0};
uint8_t slave_tx_buff[4] = {0x44, 0x33, 0x22, 0x11};
uint8_t slave_rx_buff[4] = {0};
spi_slave_transmit_receive_dma(slave_tx_buff, slave_rx_buff, 4);
spi_master_transmit_receive_dma(master_tx_buff, master_rx_buff, 4);
delay_1ms(1);
usart_transmit(master_rx_buff, 4);
usart_transmit(slave_rx_buff, 4);
//上位机应该收到 0x44, 0x33, 0x22, 0x11, 0x11, 0x22, 0x33, 0x44
delay_1ms(1000);
}
}