GD32 SPI — SPI 主发从收中断

GD32 GD32F30x_Firmware_Library V3.0.3 SPI SPI 主发从收中断 示例教学

SPI — SPI 主发从收中断

固件库: GD32F30x_Firmware_Library V3.0.3
芯片: GD32
源文件: GD32F30x_Firmware_Library_V3.0.3/Examples/SPI/SPI_master_transmit_slave_receive_interrupt/main.c


功能简介

本示例演示 SPI 总线通信。SPI 是高速同步串行接口,常用于连接 Flash、LCD、传感器等外设。

硬件准备

  • 需要主机和从机两块板子,或使用回环连接(MOSI→MISO)

完整代码

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include "gd32f30x.h"
#include "gd32f30x_it.h"
#include "gd32f307c_eval.h"
#define SPI_CRC_ENABLE                 1
#define ARRAYSIZE                      10
#define SET_SPI0_NSS_HIGH              gpio_bit_set(GPIOA,GPIO_PIN_3);
#define SET_SPI0_NSS_LOW               gpio_bit_reset(GPIOA,GPIO_PIN_3);
__IO uint32_t send_n = 0, receive_n = 0;

void rcu_config(void);
void gpio_config(void);
void spi_config(void);

/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/
int main(void)
{
    /* init led2 */
    gd_eval_led_init(LED2);

    /* NVIC config */
    nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
    nvic_irq_enable(SPI0_IRQn,1,1);
    nvic_irq_enable(SPI2_IRQn,0,1);

    /* peripheral clock enable */
    rcu_config();
    /* GPIO config */
    gpio_config();
    /* SPI config */
    spi_config();

    SET_SPI0_NSS_HIGH

    /* SPI int enable */
    spi_i2s_interrupt_enable(SPI0, SPI_I2S_INT_TBE);
    spi_i2s_interrupt_enable(SPI2, SPI_I2S_INT_RBNE);

    SET_SPI0_NSS_LOW

    /* SPI enable */
    spi_enable(SPI2);
    spi_enable(SPI0);

    /* wait transmit complete */
    while(receive_n < ARRAYSIZE);

#if SPI_CRC_ENABLE
    /* check the CRC error status  */
    if(SET != spi_i2s_flag_get(SPI2, SPI_FLAG_CRCERR)) {
        gd_eval_led_on(LED2);
    } else {
        gd_eval_led_off(LED2);
    }

    SET_SPI0_NSS_HIGH

#else
    /* compare receive data with send data */
    if(memory_compare(spi2_receive_array, spi0_send_array, ARRAYSIZE))
        gd_eval_led_on(LED2);
    else
        gd_eval_led_off(LED2);
#endif /* enable CRC function */

    while(1);
   
}

void rcu_config(void)
{
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_GPIOC);
    rcu_periph_clock_enable(RCU_SPI0);
    rcu_periph_clock_enable(RCU_SPI2);
    rcu_periph_clock_enable(RCU_AF);
}

void gpio_config(void)
{
    /* SPI0 GPIO config:SCK/PA5, MOSI/PA7 */
    gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_5 | GPIO_PIN_7);
    /* config PA3 as SPI0_NSS */
    gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3);

    gpio_pin_remap_config(GPIO_SPI2_REMAP,ENABLE);
    /* SPI2 GPIO config: NSS/PA4, SCK/PC10, MISO/PC11 */
    gpio_init(GPIOC, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_10 |GPIO_PIN_11);
    gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_4);
}

void spi_config(void)
{
    spi_parameter_struct  spi_init_struct;

    /* SPI0 parameter config */
    spi_init_struct.trans_mode           = SPI_TRANSMODE_BDTRANSMIT;
    spi_init_struct.device_mode          = SPI_MASTER;
    spi_init_struct.frame_size           = SPI_FRAMESIZE_8BIT;
    spi_init_struct.clock_polarity_phase = SPI_CK_PL_HIGH_PH_2EDGE;
    spi_init_struct.nss                  = SPI_NSS_SOFT;
    spi_init_struct.prescale             = SPI_PSC_256;
    spi_init_struct.endian               = SPI_ENDIAN_MSB;
    spi_init(SPI0, &spi_init_struct);

    /* SPI2 parameter config */
    spi_init_struct.trans_mode  = SPI_TRANSMODE_BDRECEIVE;
    spi_init_struct.device_mode = SPI_SLAVE;
    spi_init_struct.nss         = SPI_NSS_HARD;
    spi_init(SPI2, &spi_init_struct);
#if SPI_CRC_ENABLE
    /* configure SPI CRC function */
    spi_crc_polynomial_set(SPI0, 7);
    spi_crc_polynomial_set(SPI2, 7);
    spi_crc_on(SPI0);
    spi_crc_on(SPI2);
#endif /* enable CRC function */
}

代码讲解

GPIO 配置:设置引脚为输出/输入模式,选择推挽/开漏输出,配置上拉/下拉。

SPI 配置:设置主/从模式、时钟极性(CPOL)、时钟相位(CPHA)、分频系数。主机和从机的 CPOL/CPHA 必须一致。

中断优先级配置:NVIC 设置中断的抢占优先级和子优先级。数字越小优先级越高。

实验现象

  • 主机和从机互相交换数据
  • 数据校验通过则 LED 指示成功

注意事项

  • CPOL 和 CPHA 必须主机从机一致
  • 片选(CS)信号要手动拉低选中从机
  • 时钟频率不能超过从设备的最大速率
世界是你们
使用 Hugo 构建
主题 StackJimmy 设计