[研电赛技术支持] GD32 的SPI驱动程序编写与调试中的两个重要参数

[复制链接]
1442|0
小海师 发表于 2025-9-4 09:08 | 显示全部楼层 |阅读模式
      SPI 驱动初始化其实是标准的这里我们要驱动的是TI 的 ADC 芯片 ADS124S08,代码如下

头文件GPIO 定义

//GPIOA
#define N_ADC_DRDY_PIN             GPIO_PIN_0
#define N_ADC_CS_PIN                GPIO_PIN_4
#define ADC_SCK_PIN                 GPIO_PIN_5
#define ADC_DOUT_PIN                GPIO_PIN_6               //SPI0 INPUT PIN
#define ADC_DIN_PIN                 GPIO_PIN_7
#define COM_SPI_OUT_PINS            GPIO_PIN_5|GPIO_PIN_7    //SPI0 OUTPUT PINS

#define N_ADC_DRDY_PORT            GPIOA

#define N_ADC_CS_PORT              GPIOA
#define ADC_SCK_PORT               GPIOA
#define ADC_DOUT_PORT              GPIOA
#define COM_SPI_OUT_PORT           GPIOA   //SPI0 OUTPUT PINS
#define ADC_DIN_PORT               GPIOA

SPI 初始化函数大家写的都差不多,关键注意标黄的两个参数(我们调整过)。

void spi_configuration(void) {
    spi_parameter_struct spi_init_struct;
    rcu_periph_clock_enable(RCU_GPIOA); // 使能GPIOA时钟
    rcu_periph_clock_enable(RCU_SPI0);  // 使能SPI0时钟

    // SPI0配置为Master模式,全双工,波特率设置为1MHz
    spi_i2s_deinit(SPI0);
    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_HIGH_PH_1EDGE;   

   // 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; // 设置波特率分频系数为8,即1MHz
    spi_init_struct.endian               = SPI_ENDIAN_MSB;

//    spi_init_struct.endian               = SPI_ENDIAN_LSB;
    spi_init(SPI0, &spi_init_struct);



    // enable SPI0
    spi_enable(SPI0);
}

      黄色的两行是我们在调试中修改的。一个是上升沿还是下降沿数据打入的问题,另一个是大小端的问题。不要只看文档,最好调试的时候try下。具体方法不是上来就配置寄存器,读ADC值,而是把ADC(或是您使用的其他SPI设备)的寄存器的default 的值读出来。如果以上这两个参数设的不对,那么能读出来数值,但是和文档的default 值对不上,就是知道错了。不要一上来就想trigger 一个写配置,读ADC值。一定会绕弯路。

我们配置 ADS124S08 并读取21个寄存器的代码如下:

unsigned char confige_124s08(unsigned char adc_addr_offset , unsigned char channel)
{

      printf_("\r\nADS124S08 Init ");

      gpio_init(N_ADC_CS_PORT, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, N_ADC_CS_PIN); //  ADC /CS PIN
      gpio_init(COM_SPI_OUT_PORT, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, COM_SPI_OUT_PINS); // SCK/MOSI
      gpio_init(ADC_DOUT_PORT, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, ADC_DOUT_PIN); // MISO
      amz_gpio_set_value(N_ADC_CS_PORT, N_ADC_CS_PIN, 0);   // 初始化为低电平,选中ADS124S08
      spi_configuration() ;

      SPI_SendByte(0x20) ;  // 读 reg 的 command , 从寄存器 0x0 开始读
      SPI_SendByte(20) ; //读 20+1个寄存器


      uint8_t i;

      for(i=0 ; i<=20 ; i++)
        printf_("\r\n 0x%x read: 0x%x" , i,SPI_SendByte(DUMMY_BYTE)) ;

  return 0;
}


      通过以上print_打印的串口log 我们就能看到读出的寄存器的值,和ADS124S08的手册对比,我们调整了这两个参数最终读到了正确值。

ADS124S08 Init
0x0 read: 0x8
0x1 read: 0x80
0x2 read: 0x1
0x3 read: 0x0
0x4 read: 0x14
0x5 read: 0x10
0x6 read: 0x0
0x7 read: 0xff
0x8 read: 0x0
0x9 read: 0x10
0xa read: 0x0
0xb read: 0x0
0xc read: 0x0
0xd read: 0x0
0xe read: 0x0
0xf read: 0x40
0x10 read: 0x0
0x11 read: 0x0
0x12 read: 0x0
0x13 read: 0x0
0x14 read: 0x0

      这里我们再附上SPI 发送操作的代码,由于SPI是一个循环移位操作,DOUT发送完一个字节后(用 spi_i2s_data_transmit(SPI0,byte) 发送),DIN也能收回一个字节(用spi_i2s_data_receive(SPI0) 可以读出)。

uint8_t SPI_SendByte(uint8_t byte)
{
    /* loop while data register in not emplty */
    while (RESET == spi_i2s_flag_get(SPI0,SPI_FLAG_TBE));

    /* send byte through the SPI0 peripheral */
    spi_i2s_data_transmit(SPI0,byte);

    /* wait to receive a byte */
    while(RESET == spi_i2s_flag_get(SPI0,SPI_FLAG_RBNE));

    /* return the byte read from the SPI bus */
    return(spi_i2s_data_receive(SPI0));                   // send a byte
}

      以上是相对正规的范例代码。实际工程中,函数可以优化成根据实际SPI设备,可变字节数的读写。
————————————————
版权声明:本文为CSDN博主「小庐知行」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/tideyin123/article/details/151087181

您需要登录后才可以回帖 登录 | 注册

本版积分规则

79

主题

242

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部