ssczmy 2024-04-10 22:09 采纳率: 0%
浏览 83
已结题

GD32F303读取ADS1118芯片传输的电压

各位同好们,我遇到一个棘手的问题,需要读取ADS1118芯片传给GD32F303芯片引脚上的电压,但是初学单片机,不知道怎么配置,目前只知道通讯是SPI,程序修修改改好多天了,读不出任何数据,电路图附上,希望大家指点迷津。

img

img

#include "gd32f30x.h"
#include "gd32f30x_gpio.h"
#include "spi.h"
#include "systick.h"
#include "stdio.h"
#include "gd32f30x_usart.h"
#include "ADS1118.h"

// 定义 ADC 通道
#define CURRENT_SENSOR_CHANNEL  ADC_CHANNEL_0
//延时函数
void delay_ms(int32_t ms)
{
    int32_t i;
    while(ms--)
    {
        i=7500;
        while(i--);
    }
}

// 初始化 ADC
void adc_init(void) 
{
    // 使能 ADC 时钟
    rcu_periph_clock_enable(RCU_ADC0);

    // 配置 ADC 工作模式为扫描模式
    adc_special_function_config(ADC0, ADC_SCAN_MODE, ENABLE);

    // 配置 ADC 通道
    adc_channel_length_config(ADC0, ADC_INSERTED_CHANNEL, 1);
    adc_inserted_channel_config(ADC0, 0, CURRENT_SENSOR_CHANNEL, ADC_SAMPLETIME_239POINT5);

    // 使能 ADC
    adc_enable(ADC0);

    // 校准 ADC
    adc_calibration_enable(ADC0);
}


void spi_gpio_init(void) {
    // 使能 GPIO 时钟
    rcu_periph_clock_enable(RCU_GPIOA);

    // 配置 SPI 引脚
    gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7);

    // 配置 SPI 引脚的复用功能
    gpio_pin_remap_config(GPIO_USART2_FULL_REMAP, ENABLE);
}

void MySPI_W_SS(uint8_t BitValue)
{
        gpio_bit_write(SPI_Port,SPI_NSS,BitValue);
}

void MySPI_Init(void) {
    spi_parameter_struct spi_structure = {0};
    spi_parameter_struct spi_init_struct;

    // 使能 SPI 时钟
    rcu_periph_clock_enable(RCU_SPI1);

    // SPI 外设初始化
    spi_struct_para_init(&spi_init_struct);
    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_2EDGE;
    spi_init_struct.nss                  = SPI_NSS_SOFT;

    spi_init(SPI1, &spi_init_struct);

    // 使能 SPI
    spi_enable(SPI1);
    MySPI_W_SS(1);                                               //拉高片选
}

/******************************************************************
 * 函 数 名 称:MySPI_SwapByte
 * 函 数 说 明:向从机交换16位数据,并从从机读取16位数据
 * 函 数 形 参:ByteSend = 发送的16位数据
 * 函 数 返 回:从机数据
******************************************************************/
uint16_t MySPI_SwapByte(uint16_t ByteSend)
{
        while (spi_i2s_flag_get(SPI1, SPI_FLAG_TBE) != SET);   //读取发送缓冲区空标志
        
        spi_i2s_data_transmit(SPI1, ByteSend);                 //发送数据
        
        while (spi_i2s_flag_get(SPI1, SPI_FLAG_RBNE) != SET);  //读取接收缓冲区非空标志
        
        return spi_i2s_data_receive(SPI1);                     //接收数据
}

/******************************************************************
 * 函 数 名 称:MySPI_Start()
 * 函 数 说 明:拉低片选脚开始通信
 * 函 数 形 参:无
 * 函 数 返 回:无
******************************************************************/
void MySPI_Start()
{
        MySPI_W_SS(0);
}
/******************************************************************
 * 函 数 名 称:MySPI_STOP()
 * 函 数 说 明:拉高片选脚结束通信
 * 函 数 形 参:无
 * 函 数 返 回:无
******************************************************************/
void MySPI_STOP()
{
        MySPI_W_SS(1);
}


//ADS1118 supply voltage 2 - 5.5V
//analog input voltage max VDD+0.3V.    VIN<VDD!!!!!
//(VDD-->3v3,PGA-->4096,)无法获得满量程ADC输出代码,这种意味着一些动态范围的丢失.

/******************************************************************
 * 函 数 名 称:ADS1118_ADC_Continuous_Init
 * 函 数 说 明:初始化ADS1118
 * 函 数 形 参:channel = ADC外部通道选择,PGA = ADC满量程选择,SPS = ADC数据传输率选择
 * 函 数 返 回:无
 * 备       注:连续模式使用前,调用此函数完成初始化,之后调用ADS1118_Get_ADC_Continuous_Data()
******************************************************************/
void ADS1118_ADC_Continuous_Init(uint16_t channel,uint16_t PGA,uint16_t SPS)
{
        MySPI_Init();
        ADS1118_ENABLE;//拉低CS开始通信
        delay_ms(300);
        MySPI_SwapByte(ADS1118_SS_START|channel|PGA|ADS1118_Continuous_MODE
                                        |SPS|ADS1118_Temp_MODE|ADS1118_PUUP_EN|ADS1118_NOP_UPDATA);//发送寄存器命令,交换数据
        delay_ms(300);
        ADS1118_DISABLE;//拉高CS复位ADS1118结束通信
        delay_ms(300);
        
}
/******************************************************************
 * 函 数 名 称:ADS1118_Get_Tempture_Data()
 * 函 数 说 明:单次获取ADC内部Temp温度
 * 函 数 形 参:无
 * 函 数 返 回:返回内部温度传感器温度
******************************************************************/
float ADS1118_Get_Tempture_Data()
{
        uint16_t ADC_Data = 0;
        float Tempture_data= 0;
        ADS1118_ENABLE;//拉低CS开始通信
        delay_ms(300);
        ADC_Data = MySPI_SwapByte(ADS1118_SS_START|ADS1118_MUX_AIN0|ADS1118_PGA_4096|
                                                          ADS1118_Sigle_SHOT_MODE|ADS1118_DR_8SPS|ADS1118_Temp_MODE|
                                                                ADS1118_PUUP_EN|ADS1118_NOP_UPDATA);//发送寄存器命令,交换数据

        delay_ms(5);
        ADS1118_DISABLE;//拉高CS复位ADS1118结束通信
        
        delay_ms(1);
        
        ADS1118_ENABLE;//拉低CS开始通信
        delay_ms(5);
        while(gpio_input_bit_get(GPIOA,GPIO_PIN_6));//DOUT拉低ADC1118数据更新准备完毕

        ADC_Data = MySPI_SwapByte(ADS1118_SS_START|ADS1118_MUX_AIN0|ADS1118_PGA_4096|
                                                          ADS1118_Sigle_SHOT_MODE|ADS1118_DR_8SPS|ADS1118_Temp_MODE|
                                                                ADS1118_PUUP_EN|ADS1118_NOP_UPDATA);//发送寄存器命令,交换数据
        delay_ms(5);
        ADS1118_DISABLE;//拉高CS复位ADS1118结束通信
        if(ADC_Data&0X8000)//MSB=1
        {
                ADC_Data = (~ADC_Data)+1 ;
        }
        else Tempture_data = (ADC_Data >> 2)*0.03125;
        return Tempture_data;        
}
/******************************************************************
 * 函 数 名 称:ADS1118_Get_ADC_SIGLE_SHOT_Data
 * 函 数 说 明:单次获取AD电压值
 * 函 数 形 参:channel = ADC外部通道选择,PGA = ADC满量程选择,SPS = ADC数据传输率选择
 * 函 数 返 回:AD电压值
******************************************************************/
float ADS1118_Get_ADC_SIGLE_SHOT_Data(uint16_t channel,uint16_t PGA,uint16_t SPS)
{
        uint16_t ADC_Data = 0;
        float Tempture_data= 0;
        ADS1118_ENABLE;//拉低CS开始通信
        delay_ms(15);
        ADC_Data = MySPI_SwapByte(ADS1118_SS_START|channel|PGA|ADS1118_Sigle_SHOT_MODE
                                                        |SPS|ADS1118_ADC_MODE|ADS1118_PUUP_EN|ADS1118_NOP_UPDATA);//发送寄存器命令,交换数据

        delay_ms(15);
        ADS1118_DISABLE;//拉高CS复位ADS1118结束通信
        
        delay_1ms(1);
        
        ADS1118_ENABLE;//拉低CS开始通信
        delay_ms(15);
        while(gpio_input_bit_get(GPIOA,GPIO_PIN_6));//DOUT拉低ADC1118数据更新准备完毕

        ADC_Data = MySPI_SwapByte(ADS1118_SS_START|channel|PGA|ADS1118_Sigle_SHOT_MODE
                                                         |SPS|ADS1118_ADC_MODE|ADS1118_PUUP_EN|ADS1118_NOP_UPDATA);//发送寄存器命令,交换数据

        delay_ms(15);
        ADS1118_DISABLE;//拉高CS复位ADS1118结束通信
        if(ADC_Data&0X8000)//MSB=1
        {
                ADC_Data = (~ADC_Data)+1 ;
                if(PGA == ADS1118_PGA_6144)Tempture_data=ADC_Data*0.1875;
                else if(PGA == ADS1118_PGA_6144)Tempture_data=ADC_Data*0.1875;
                else if(PGA == ADS1118_PGA_4096)Tempture_data=ADC_Data*0.125;
                else if(PGA == ADS1118_PGA_2048)Tempture_data=ADC_Data*0.0625;
                else if(PGA == ADS1118_PGA_1024)Tempture_data=ADC_Data*0.03125;
                else if(PGA == ADS1118_PGA_0512)Tempture_data=ADC_Data*0.015625;
                else Tempture_data=ADC_Data*0.0078125;
                return Tempture_data;
        }
        else if(PGA == ADS1118_PGA_6144)Tempture_data=ADC_Data*0.1875;
        else if(PGA == ADS1118_PGA_6144)Tempture_data=ADC_Data*0.1875;
        else if(PGA == ADS1118_PGA_4096)Tempture_data=ADC_Data*0.125;
        else if(PGA == ADS1118_PGA_2048)Tempture_data=ADC_Data*0.0625;
        else if(PGA == ADS1118_PGA_1024)Tempture_data=ADC_Data*0.03125;
        else if(PGA == ADS1118_PGA_0512)Tempture_data=ADC_Data*0.015625;
        else Tempture_data=ADC_Data*0.0078125;
        return Tempture_data;        
}
/******************************************************************
 * 函 数 名 称:ADS1118_Get_ADC_Continuous_Data
 * 函 数 说 明:连续获取AD电压值
 * 函 数 形 参:channel = ADC外部通道选择,PGA = ADC满量程选择,SPS = ADC数据传输率选择
 * 函 数 返 回:AD电压值
 * 备       注:使用此函数前调用ADS1118_ADC_Continuous_Init()
******************************************************************/
float  ADS1118_Get_ADC_Continuous_Data(uint16_t channel,uint16_t PGA,uint16_t SPS)
{
        uint16_t ADC_Data = 0;
        float Tempture_data= 0;
        ADS1118_ENABLE;//拉低CS开始通信
        delay_ms(300);
        while(gpio_input_bit_get(GPIOA,GPIO_PIN_6));//DOUT拉低ADC1118数据更新准备完毕

        ADC_Data = MySPI_SwapByte(ADS1118_SS_START|channel|PGA|ADS1118_Continuous_MODE
                                                         |SPS|ADS1118_ADC_MODE|ADS1118_PUUP_EN|ADS1118_NOP_UPDATA);//发送寄存器命令,交换数据

        delay_ms(300);
        ADS1118_DISABLE;//拉高CS复位ADS1118结束通信
        if(ADC_Data&0X8000)//MSB=1
        {
                ADC_Data = (~ADC_Data)+1 ;
                if(PGA == ADS1118_PGA_6144)Tempture_data=ADC_Data*0.1875;
                else if(PGA == ADS1118_PGA_6144)Tempture_data=ADC_Data*0.1875;
                else if(PGA == ADS1118_PGA_4096)Tempture_data=ADC_Data*0.125;
                else if(PGA == ADS1118_PGA_2048)Tempture_data=ADC_Data*0.0625;
                else if(PGA == ADS1118_PGA_1024)Tempture_data=ADC_Data*0.03125;
                else if(PGA == ADS1118_PGA_0512)Tempture_data=ADC_Data*0.015625;
                else Tempture_data=ADC_Data*0.0078125;
                return Tempture_data;
        }
        else if(PGA == ADS1118_PGA_6144)Tempture_data=ADC_Data*0.1875;
        else if(PGA == ADS1118_PGA_6144)Tempture_data=ADC_Data*0.1875;
        else if(PGA == ADS1118_PGA_4096)Tempture_data=ADC_Data*0.125;
        else if(PGA == ADS1118_PGA_2048)Tempture_data=ADC_Data*0.0625;
        else if(PGA == ADS1118_PGA_1024)Tempture_data=ADC_Data*0.03125;
        else if(PGA == ADS1118_PGA_0512)Tempture_data=ADC_Data*0.015625;
        else Tempture_data=ADC_Data*0.0078125;
        return Tempture_data;
} 

int main(void)
{
    float AD_value;
    nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);  // 优先级分组
    systick_config();                //滴答定时器初始化 1us
    MySPI_Init();                    //初始化spi
    ADS1118_ADC_Continuous_Init(ADS1118_MUX_AIN0 ,ADS1118_PGA_4096,ADS1118_DR_8SPS);
    while(1)
    {
                AD_value = ADS1118_Get_ADC_SIGLE_SHOT_Data(ADS1118_MUX_AIN0 ,ADS1118_PGA_4096,ADS1118_DR_8SPS);
                //AD_value = ADS1118_Get_Tempture_Data();
                printf("%f",AD_value);
                delay_ms(300);
        
    }
}     





  • 写回答

22条回答 默认 最新

  • 专家-赤兔[在线] 优质创作者: 编程框架技术领域 2024-04-10 22:09
    关注
    获得0.45元问题酬金

    引自免费微信小程序:皆我百晓生

    在您的问题中,您正在尝试使用GD32F303单片机通过SPI接口读取ADS1118模数转换器(ADC)芯片的数据。您已经提供了电路图和部分代码,但表示在多次尝试修改后仍然无法成功读取数据。为了帮助您解决这个问题,我会按照以下步骤详细分析并提供可能的解决方案:

    1. 检查硬件连接: 请确保您的硬件连接正确无误。根据您提供的信息,ADS1118与GD32F303之间的连接应如下所示:

      • SCLK: GD32F303的PB13引脚连接到ADS1118的SCLK引脚。
      • DIN: GD32F303的PB15引脚连接到ADS1118的DIN引脚。
      • DOUT: ADS1118的DOUT引脚连接到GD32F303的PB14引脚。
      • CS: GD32F303的PB12引脚连接到ADS1118的CS引脚。

      检查实物连线是否与上述描述一致,且所有接线牢固可靠,无短路、断路情况。

    2. 检查电源和接地: 确保ADS1118的供电电压(VDD)在2V至5.5V范围内,且与GD32F303共地。检查电源线是否有波动或噪声干扰。

    3. 分析现有代码: 从您提供的代码来看,存在一些潜在问题和不一致性,以下是具体的建议和修改:

      a. 定义和使用正确的GPIO端口: 在代码中,SPI端口定义似乎与实际连接不符。根据电路图,应将SPI端口定义更改为:

      #define SPI_NSS    GPIO_PIN_12     // PB12, CS for ADS1118
      #define SPI_SCK    GPIO_PIN_13     // PB13, SCLK for ADS1118
      #define SPI_MISO   GPIO_PIN_14     // PB14, DOUT for ADS1118
      #define SPI_MOSI   GPIO_PIN_15     // PB15, DIN for ADS1118
      
      #define SPI_PORT   GPIOB
      

      b. 修正SPI初始化参数: 将spi_init_struct变量名改为spi_init_struct,以避免与函数参数同名导致混淆。同时,将device_mode设置为SPI_MASTER,其他参数保持不变:

      spi_parameter_struct spi_init_struct;
      spi_struct_para_init(&spi_init_struct);
      spi_init_struct.trans_mode           = SPI_TRANSMODE_FULLDUPLEX;
      spi_init_struct.device_mode          = SPI_MASTER; // 修改为 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(SPI1, &spi_init_struct);
      

      c. 简化片选操作: 直接使用spi_i2s_nss_output_cmd()函数控制NSS(CS)信号,替换现有的MySPI_W_SS()函数。例如:

      void MySPI_Start()
      {
          spi_i2s_nss_output_cmd(SPI1, DISABLE);
      }
      
      void MySPI_Stop()
      {
          spi_i2s_nss_output_cmd(SPI1, ENABLE);
      }
      

      d. 优化数据交换函数: 使用spi_i2s_data_transmit_receive()函数一次完成发送和接收数据,替换现有的MySPI_SwapByte()函数。例如:

      uint16_t MySPI_SwapByte(uint16_t data)
      {
          while (spi_i2s_flag_get(SPI1, SPI_FLAG_TBE) != SET); // Wait for TX buffer empty
      
          spi_i2s_data_transmit_receive(SPI1, data); // Send and receive data in one operation
      
          while (spi_i2s_flag_get(SPI1, SPI_FLAG_RBNE) != SET); // Wait for RX buffer not empty
      
          return spi_i2s_data_receive(SPI1); // Return received data
      }
      

      e. 修正ADS1118读取函数: 由于代码中多次出现重复的条件分支,可能存在逻辑错误。请仔细检查并修正ADS1118_Get_ADC_SIGLE_SHOT_Data()ADS1118_Get_ADC_Continuous_Data()函数中的计算逻辑。

    4. 验证SPI通信: 在尝试读取ADS1118数据之前,先编写简单的SPI通信测试代码,确保GD32F303与ADS1118之间的SPI通信正常。可以发送已知数据并检查接收结果是否一致。

    5. 遵循ADS1118通信协议: 请仔细阅读ADS1118的数据手册,确保发送的控制字(包括通道选择、PGA设置、数据速率等)以及读取数据的时序符合ADS1118的通信协议要求。

    综上所述,首先确保硬件连接正确,然后按照上述建议修改代码。接着进行SPI通信测试,最后按照ADS1118数据手册的指导调整与之通信的代码逻辑。这样应该有助于您成功读取ADS1118芯片的数据。如果您在实施过程中遇到具体问题,欢迎继续提问。

    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 4月18日
  • 创建了问题 4月10日