gd32 spi dma全双工发送接收例程

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




  • 15
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
GD32 SPI DMA通信是指在GD32系列微控制器中使用SPI接口和DMA进行数据传输的一种通信方式。 SPI(Serial Peripheral Interface)是一种同步串行通信总线,它在微控制器和外设之间传输数据。GD32系列微控制器通过SPI接口与外设(如传感器、存储器等)进行数据交互。为了提高数据传输效率,GD32系列微控制器还支持DMA(Direct Memory Access)技术。 DMA是一种无需CPU介入的数据传输方式,通过配置DMA控制器,可以实现在SPI接口和内存之间直接传输数据。在SPI DMA通信中,可以通过配置GD32DMA控制器,实现SPI数据的输入输出。具体流程如下: 1. 配置SPI接口:包括设置SPI的工作模式(主从模式)、数据位宽、传输速度等参数。 2. 配置DMA通道:包括设置DMA通道的传输方向、传输数据的长度、传输数据的地址等参数。 3. 开启SPIDMA:使能SPI接口和DMA通道,准备数据传输。 4. 启动DMA传输:通过触发信号(例如SPI中断)启动DMA传输,DMA控制器将根据配置的参数自动进行数据传输。 5. 数据传输完成:当DMA传输完成时,触发相应的中断或通过检测标志位完成数据传输的判断。 6. 数据处理:根据需要,对传输的数据进行处理,例如存储、计算、显示等。 7. 重复上述步骤:如果还有需要传输的数据,可以重复上述步骤进行数据传输。 通过使用SPI DMA通信,可以降低CPU的负担,提高系统的并行处理能力,并加快数据传输速度。GD32微控制器提供了相应的库函数和例程,方便开发者进行SPI DMA通信的配置和编程,实现更高效的数据交互。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值