打印

GD32 SPI 接收无时钟

[复制链接]
1936|28
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
最近在使用GD32E230K8T6配置SPI通信时,发现SPI1在主机模式下,接收时间段内居然无时钟输出,导致读取到的数据全部为0;而实际上MISO线上是有电平变化的;时序如下图所示:

因为刚开始使用GD库的时候,发现SPIEN位设置不成功,没办法只能自己写了SPI1的初始化程序了,如下:
void a7196_spi_init(void)
{
        uint32_t reg_value = 0;
        
        rcu_periph_clock_enable(RCU_SPI1);

        SPI_CTL0(SPI1) = 0x00;
        //SPI_CTL0(SPI1) |= SPI_PSC_16;                                //1,设置分频
        SPI_CTL0(SPI1) |= SPI_PSC_256;                                //1,设置分频
        SPI_CTL0(SPI1) |= SPI_CK_PL_LOW_PH_1EDGE;        //2,设置模式
        //SPI_CTL0(SPI1) |= SPI_CK_PL_LOW_PH_2EDGE;        //2,设置模式
                                                                                                //...3
        SPI_CTL1(SPI1) = 0x00;
        SPI_CTL1(SPI1) |= SPI_FRAMESIZE_8BIT;                //4,设置数据格式,8位
        SPI_CTL1(SPI1) |= SPI_CTL1_BYTEN;                        //4,设置数据寄存器的访问大小,一个字节
        //SPI_CTL1(SPI1) |= SPI_CTL1_NSSDRV;                        //5
                                                                                                //...6,...7
        SPI_CTL0(SPI1) |= SPI_CTL0_MSTMOD;                        //8
        SPI_CTL0(SPI1) |= SPI_CTL0_SWNSS;
        SPI_CTL0(SPI1) |= SPI_CTL0_SWNSSEN;
        SPI_CTL0(SPI1) |= SPI_CTL0_SPIEN;                        //...9,...10,11

        /* select SPI mode */
        SPI_I2SCTL(SPI1) &= (uint32_t)(~SPI_I2SCTL_I2SSEL);
}

收发采用GD的库函数的:
spi_i2s_data_transmit(SPI1, addr);
data = spi_i2s_data_receive(SPI1);


请问高手,这是哪里配置有问题呢?我该怎么修改呢?

使用特权

评论回复
沙发
xl071310| | 2022-4-14 10:03 | 只看该作者
有没有配置SPI1 对应的引脚啊,时钟啊?

使用特权

评论回复
评论
skay5288 2022-4-14 10:07 回复TA
引脚有配的,SPI1的写时序是已经出来的了;时钟也是有配的,8分频,16分频,256分频都有试过; 
板凳
skay5288|  楼主 | 2022-4-14 10:05 | 只看该作者
将SPI初始化函数更改为GD的库的也是问题依旧,接收时无时钟;
void a7196_spi_init(void)
{
        uint32_t reg_value = 0;
        spi_parameter_struct spi_init_struct;

    /* enable the gpio clock */
    rcu_periph_clock_enable(RCU_SPI1);

    /* SPI1 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;
    spi_init_struct.prescale             = SPI_PSC_8;
    spi_init_struct.endian               = SPI_ENDIAN_MSB;
    spi_init(SPI1, &spi_init_struct);

    spi_enable(SPI1);
}

使用特权

评论回复
地板
kfawj| | 2022-4-14 10:05 | 只看该作者
还是仿SPI方便,就是麻烦一点儿!实在没辙可以考虑一下哟……

使用特权

评论回复
5
skay5288|  楼主 | 2022-4-14 10:09 | 只看该作者
kfawj 发表于 2022-4-14 10:05
还是仿SPI方便,就是麻烦一点儿!实在没辙可以考虑一下哟……

是的,烦就烦在,GD32E239K8T6这个芯片的SPI1跟下载口复用,还不能配置为普通IO口来模拟;

使用特权

评论回复
6
王久强| | 2022-4-14 10:55 | 只看该作者
要不要检查一下硬件?虚焊,或者这个脚短接到地了?

使用特权

评论回复
7
lvben5d| | 2022-4-14 11:01 | 只看该作者
本帖最后由 lvben5d 于 2022-4-14 11:03 编辑

楼主, SPI使用的GPIO口 配置对不? 还要开下AF时钟。  我的是GD32E              你用你型号例程里去找 EXAMPLE\SPI      gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3 | GPIO_PIN_5);   //3和5  1个  CLK  MOSI
    gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_4);            //4  MISO

使用特权

评论回复
8
skay5288|  楼主 | 2022-4-14 11:12 | 只看该作者
lvben5d 发表于 2022-4-14 11:01
楼主, SPI使用的GPIO口 配置对不? 还要开下AF时钟。  我的是GD32E              你用你型号例程里去找 EX ...

GPIO有配为AF功能的,用的PB1-->CLK, PA13-->MISO, PA14-->MOSI, PA15-->NSS;
void a7196_gpio_init(void)
{
/* enable the SPI1_SCK clock */
    rcu_periph_clock_enable(SPI1_SCK_PORT_CLK);
    /* configure SPI1_SCK port */
    gpio_mode_set(SPI1_SCK_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, SPI1_SCK_PIN);
    gpio_output_options_set(SPI1_SCK_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI1_SCK_PIN);
gpio_af_set(SPI1_SCK_PORT, GPIO_AF_6, SPI1_SCK_PIN);

/* enable the SPI1_MISO clock */
    rcu_periph_clock_enable(SPI1_MISO_PORT_CLK);
    /* configure SPI1_MISO port */

    gpio_mode_set(SPI1_MISO_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, SPI1_MISO_PIN | SPI1_MOSI_PIN /*| SPI1_NSS_PIN*/);
    gpio_output_options_set(SPI1_MISO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI1_MISO_PIN | SPI1_MOSI_PIN /*| SPI1_NSS_PIN*/);
gpio_af_set(SPI1_MISO_PORT, GPIO_AF_6, SPI1_MISO_PIN | SPI1_MOSI_PIN /*| SPI1_NSS_PIN*/);

gpio_mode_set(SPI1_MISO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SPI1_MISO_PIN);

/* enable the SPI1_NSS clock */
    rcu_periph_clock_enable(SPI1_NSS_PORT_CLK);
    /* configure SPI1_NSS port */
    gpio_mode_set(SPI1_NSS_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, SPI1_NSS_PIN);
    gpio_output_options_set(SPI1_NSS_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SPI1_NSS_PIN);
A7196_CS_SET;

/* enable the GIO2 clock */
    rcu_periph_clock_enable(WTR_PORT_CLK);
    /* configure GIO2 port */
    gpio_mode_set(WTR_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, WTR_PIN);
}

使用特权

评论回复
9
lvben5d| | 2022-4-14 14:47 | 只看该作者
还没调试通嘛? 我这边是GD32E得 SPI驱动 可以给你借鉴,应该大同小异

使用特权

评论回复
10
skay5288|  楼主 | 2022-4-14 14:48 | 只看该作者
lvben5d 发表于 2022-4-14 14:47
还没调试通嘛? 我这边是GD32E得 SPI驱动 可以给你借鉴,应该大同小异

还没,是SPI1的吗?可以发邮箱吗?2168916131@qq.com;谢谢了;

使用特权

评论回复
11
lvben5d| | 2022-4-14 14:52 | 只看该作者
本帖最后由 lvben5d 于 2022-4-15 13:10 编辑

我发现还是有个别兄弟,开始卡在SPI 这个, 建议按照 对应芯片所自带的example 去看, 我想绝大部分 SPI都是做主机,  注意SPI时钟 引脚  重定义, SPI的4种模式,最容易出错得是 SPI 收发驱动,按照GD32E103  我贴上这个函数。
uint8_t SPI0_RcvByte(uint8_t byte)
{       
        uint8_t rval=0;
        while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_TBE));   
        spi_i2s_data_transmit(SPI0, byte);       
        while(RESET == spi_i2s_flag_get(SPI0, SPI_FLAG_RBNE));  //
        rval = spi_i2s_data_receive(SPI0);                                    
        return rval;
}


使用特权

评论回复
评论
qaqsd 2022-4-15 11:35 回复TA
大佬能给我发个吗遇到类似的问题了 1025616188@qq.com谢谢了 
12
豆杀包| | 2022-4-20 10:18 | 只看该作者
如何启动SPI的

使用特权

评论回复
13
skay5288|  楼主 | 2022-4-25 20:36 | 只看该作者
lvben5d 发表于 2022-4-14 14:52
我发现还是有个别兄弟,开始卡在SPI 这个, 建议按照 对应芯片所自带的example 去看, 我想绝大部分 SPI都 ...

你是对的,我后来修改为发完数据后立即收一下,发现就能收到数据了;

使用特权

评论回复
14
skay5288|  楼主 | 2022-4-25 20:37 | 只看该作者

调用GD的库的SPI初始化函数后,就能启动SPI的;

使用特权

评论回复
15
skay5288|  楼主 | 2022-4-25 21:27 | 只看该作者
谢谢大家,问题解决了,解决方法就是:在写完数据后,马上读一下;这样就能读取到SPI设备的数据了;
uint8_t spi_write_read_byte(uint32_t spi_periph,uint8_t byte)
{
    SPI_CTL1(spi_periph) |= SPI_CTL1_BYTEN;
    while(RESET == (SPI_STAT(spi_periph)&SPI_FLAG_TBE));
    SPI_DATA(spi_periph) = byte;

    while(RESET == (SPI_STAT(spi_periph)&SPI_FLAG_RBNE));
    return(SPI_DATA(spi_periph));
}

使用特权

评论回复
16
lvben5d| | 2022-4-26 16:50 | 只看该作者

直接塞入 SPI 数据寄存器, 就是发,接收数据的时候,也是靠主机 塞入字节到数据寄存器 来产生8个CLK, 把数据从从机那边移位到 主机这边移位寄存器,移完8Bit后,查询数据寄存器标志来判断是否就位,再读出来。

使用特权

评论回复
17
tpgf| | 2022-5-4 10:10 | 只看该作者
但是发送数据没有问题是吗

使用特权

评论回复
评论
skay5288 2022-5-5 17:33 回复TA
发送数据没有问题; 
18
drer| | 2022-5-4 10:22 | 只看该作者
使用的什么接收机制呢

使用特权

评论回复
评论
skay5288 2022-5-5 17:35 回复TA
调用 spi_write_read_byte()函数就可以读,该函数内那个byte参数可以用任意值的; 
19
tfqi| | 2022-5-4 10:30 | 只看该作者
接受完之后会自动清除标志位的

使用特权

评论回复
20
xdqfc| | 2022-5-4 10:36 | 只看该作者
本帖最后由 xdqfc 于 2022-5-4 10:43 编辑
lvben5d 发表于 2022-4-14 14:52
我发现还是有个别兄弟,开始卡在SPI 这个, 建议按照 对应芯片所自带的example 去看, 我想绝大部分 SPI都 ...

呵呵,有些人对硬件SPI的收发原理还没有弄清楚,就来玩SPI了,遇到问题又不仔细看厂家的例程,呵呵,有点逗,兄弟有这个耐心来指导,先顶一下。补充一下,while语句里面加个跳出机制吧,否则死到里面就麻烦了,我一般会加的。

使用特权

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

本版积分规则

5

主题

44

帖子

0

粉丝