打印

两个重要前提PA15一直低电平

[复制链接]
1030|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
GD32F405内部SPI模块(和STM32F4很像)在硬件NSS输出模式时,有两个重要前提必须同时满足:


条件        解释
SPI设置为主机模式        SPI_CTL0寄存器,必须主机(SPI_CTL0::MSTMOD = 1)
使能了SSOE位SPI_CTL0::SSOEN = 1,允许硬件控制NSS脚
如果SSOE没设置对,即使启用了硬件NSS,PA15仍然是"软锁"低电平!

总结核心一句话:

硬件NSS模式想让PA15正常跟随SPI状态变化,必须配置SSOEN位。

使用特权

评论回复
沙发
家有两宝呀|  楼主 | 2025-4-29 01:28 | 只看该作者
更深入细节:GD32 SPI2内部NSS控制机制
当硬件NSS模式时:

SSOEN = 0:NSS输出恒为低(锁住)

SSOEN = 1:NSS输出跟随SPI总线状态

即:


发送/忙碌状态        NSS拉低
空闲/结束        NSS拉高
而默认复位状态下,SSOEN是**关闭(0)**的!

这就是为什么你配置好SPI2,NSS一直低的真正原因。

使用特权

评论回复
板凳
家有两宝呀|  楼主 | 2025-4-29 01:29 | 只看该作者
正确解决方案
在初始化SPI2时,明确打开SSOEN(Slave Select Output Enable)!

标准配置示例:

c
复制
编辑
spi_parameter_struct spi_init_struct;

/* SPI2 clock enable */
rcu_periph_clock_enable(RCU_SPI2);

/* SPI2 GPIO config (PA15, PB13, PB14, PB15) */

/* SPI2 parameter config */
spi_init_struct.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
spi_init_struct.device_mode = SPI_MASTER;
spi_init_struct.frame_size = SPI_FRAMESIZE_8BIT;
spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
spi_init_struct.nss = SPI_NSS_SOFT;         // 先软NSS,后硬NSS开SSOE
spi_init_struct.prescale = SPI_PSC_8;
spi_init_struct.endian = SPI_ENDIAN_MSB;
spi_init(SPI2, &spi_init_struct);

/* 打开硬件NSS管理 */
spi_nss_output_enable(SPI2);   // === 关键点 ===

/* 启动SPI2 */
spi_enable(SPI2);
注意:

spi_nss_output_enable(SPI2);
➔ 这个宏内部实际上是把SSOEN置1
➔ 之后NSS才能自动控制

使用特权

评论回复
地板
家有两宝呀|  楼主 | 2025-4-29 01:29 | 只看该作者
十有**是因为忘了打开SSOEN——spi_nss_output_enable函数,这是硬性机制

使用特权

评论回复
5
成熟芒果箱| | 2025-4-29 11:00 | 只看该作者
感谢,一会我尝试一下这样配置

使用特权

评论回复
6
成熟芒果箱| | 2025-4-29 11:37 | 只看该作者
补充:这是参照给出的代码段的配置以及示波器测量的SCK和NSS引脚  硬件NSS仍然没有拉高

void spi2_config(void) {
       
                spi_parameter_struct spi_init_struct;
    rcu_periph_clock_enable(RCU_GPIOC);   // 使能GPIOC时钟
    rcu_periph_clock_enable(RCU_GPIOA);   // 使能GPIOA时钟(PA15)
    rcu_periph_clock_enable(RCU_SPI2);    // 使能SPI2时钟
       


    /* 配置引脚复用功能 */
  // CS PA15 : 复用推挽输出
        gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_15);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_15);
    gpio_af_set(GPIOA, GPIO_AF_6, GPIO_PIN_15);

    // SCK PC10 : 复用推挽输出
          gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
    gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_10);
    gpio_af_set(GPIOC, GPIO_AF_6, GPIO_PIN_10);
    // MISO PC11: 复用浮空输入
                gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_11);
    gpio_af_set(GPIOC, GPIO_AF_6, GPIO_PIN_11);

    // MOSI PC12: 复用推挽输出
     gpio_mode_set(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_12);
                 gpio_output_options_set(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_12);
    gpio_af_set(GPIOC, GPIO_AF_6, GPIO_PIN_12);

    /* 复位并配置SPI2 */
    //spi_i2s_deinit(SPI2);

    /* configure SPI1 parameter */
    spi_init_struct.trans_mode           = SPI_TRANSMODE_FULLDUPLEX;
    spi_init_struct.device_mode          = SPI_MASTER;
    spi_init_struct.frame_size           = SPI_FRAMESIZE_16BIT;
    spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_2EDGE;
    spi_init_struct.nss                  = SPI_NSS_SOFT;
    spi_init_struct.prescale             = SPI_PSC_64;
    spi_init_struct.endian               = SPI_ENDIAN_MSB;
    spi_init(SPI2, &spi_init_struct);
                //SPI_CTL0(SPI2) = ((uint32_t)0x0000084cU);
                spi_nss_output_enable(SPI2);

    /* 使能SPI2 */
    spi_enable(SPI2);
}

/* 发送16位数据 */
void spi2_send_data(uint16_t data) {
    while(RESET == spi_i2s_flag_get(SPI2, SPI_FLAG_TBE)); // 等待发送缓冲区空

    spi_i2s_data_transmit(SPI2, data);

}


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

61

主题

584

帖子

0

粉丝