TI论坛
直播中

刘波

7年用户 955经验值
私信 关注
[问答]

stm32f103RDT6+SPI+ADS1256单通道连续采集配置PGA失败的原因?


  • STM32f103RDT6+SPI+ADS1256 连续采集电压,无论是设置PGA为1或者其他倍数,采集到的的数据一直是一样的,并且传感器变化数据也随之变化,采用单次采集电压PGA设置为32倍采集数据没问题。
    部分代码
    ADS1256配置代码
    #include "ADS1256.h"
    #include "sys.h"
    #include "delay.h"
    void SPI2_Init(void)
    {
      SPI_InitTypeDef  SPI_InitStructure;
      GPIO_InitTypeDef GPIO_InitStructure;
      /****Initial SPI2******************/

      /* Enable SPI2 and GPIOB clocks */
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);        //PORTB时钟使能
      RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);         //SPI2时钟使能

      /* Configure SPI2 pins: NSS, SCK, MISO and MOSI */
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; //PB131415 输入输出时钟
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;           //复用推挽输出
      GPIO_Init(GPIOB, &GPIO_InitStructure);

      // SPI2 configuration
      SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;   //SPI2设置为双线全双工
      SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                       //设置SPI2为主模式
      SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                     //SPI发送接收8位帧结构
      SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                        //串行时钟在不操作时,时钟为低电平
      SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;                      //第一个时钟沿开始采样数据
      SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                        //NSS信号由软件(使用SSI位)管理
      SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;  //定义波特率预分频:预分频值为8
      SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;              //数据传输从MSB位开始
      SPI_InitStructure.SPI_CRCPolynomial = 7;                     //CRC值计算的多项式
      SPI_Init(SPI2, &SPI_InitStructure);
      // Enable SPI2
      SPI_Cmd(SPI2, ENABLE);
      
      //片选初始化PB12
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
      GPIO_Init(GPIOB, &GPIO_InitStructure);
      PBout(12)=0;
      
    }
    //初始化ADS1256 GPIO
       void Init_ADS1256_GPIO(void)
    {
        GPIO_InitTypeDef GPIO_InitStructure;
      RCC_APB2PeriphClockCmd(RCC_ADS1256Reset | RCC_ADS1256DRDY, ENABLE); //复位等待IO时钟使能
       GPIO_InitStructure.GPIO_Pin = GPIO_RCC_ADS1256Reset;
       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
       GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

       GPIO_Init(GPIO_RCC_ADS1256Reset_PORT, &GPIO_InitStructure);
       GPIO_ResetBits(GPIO_RCC_ADS1256Reset_PORT, GPIO_RCC_ADS1256Reset );
      GPIO_InitStructure.GPIO_Pin = GPIO_ADS1256DRDY;
       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
       GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

       GPIO_Init(GPIO_ADS1256DRDY_PORT, &GPIO_InitStructure);
      SPI2_Init();
    }

    //-----------------------------------------------------------------//
    // 功    能:  模拟SPI通信
    // 入口参数:  发送的SPI数据一个字节
    // 出口参数:  接受的SPI数据一个字节
    // 全局变量:  无
    // 备    注:  发送接收一个字节数据
    //-----------------------------------------------------------------//
    unsigned char SPI_WriteByte(unsigned char TxData)
    {
      unsigned char RxData=0;
      while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_TXE)==RESET); //                                                  
      SPI_I2S_SendData(SPI2,TxData);
       while(SPI_I2S_GetFlagStatus(SPI2,SPI_I2S_FLAG_RXNE)==RESET);
       RxData=SPI_I2S_ReceiveData(SPI2);
        return RxData;
    }
    //-----------------------------------------------------------------//
    // 功    能:ADS1256写数据
    // 入口参数: /
    // 出口参数: /
    // 全局变量: /
    // 备    注: 向ADS1256中地址为regaddr的寄存器写入一个字街databyte
    //-----------------------------------------------------------------//
    void ADS1256WREG(unsigned char regaddr,unsigned char databyte)
    {
      while(ADS1256_DRRY);     //当ADS1256_DRDY为低的时候才能写寄存器
        SPI_WriteByte(ADS1256_CMD_WREG | (regaddr & 0x0F));//向寄存器写入数据地址
        SPI_WriteByte(0x00);//写入数据的个数n-1
        SPI_WriteByte(databyte);//向regaddr地址指向的寄存器写入数据databyte
    }
    //初始化ADS1256
    void ADS1256_Init(void)
    {
    ADS1256WREG(ADS1256_STATUS,0x06);               //高位在前、校准、使用缓冲
    ADS1256WREG(ADS1256_MUX,0x01);                 //初始化端口A0为“+”,AINCOM位为“-”    龙修改
    ADS1256WREG(ADS1256_ADCON,0x05);                //放大倍数32
    ADS1256WREG(ADS1256_DRATE,ADS1256_DRATE_2000SPS);         //数据7500sps
    ADS1256WREG(ADS1256_IO,0x00);          //  

    ADS1256_SELFCAL();
    //SPI_WriteByte(ADS1256_CMD_SYNC);

      ADS1256_RDATAC();

    }
    //读取AD值
    unsigned int ADS1256ReadData()
    {
      unsigned int sum=0;
    while(ADS1256_DRRY);                 //当ADS1256_DRDY为低时才能写寄存器
    //SPI_WriteByte(ADS1256_CMD_SYNC);
      sum |= (SPI_WriteByte(0xff) << 16);
    sum |= (SPI_WriteByte(0xff) << 8);
    sum |= SPI_WriteByte(0xff);
      return sum;
    }

    //-----------------------------------------------------------------//
    // 功    能:读取ADS1256单路数据
    // 入口参数: /
    // 出口参数: /
    // 全局变量: /
    // 备    注: /
    //-----------------------------------------------------------------//
    unsigned int ADS_sum(unsigned char channel)
    {
    //ADS1256WREG(ADS1256_MUX,channel);  //设置通道
    return ADS1256ReadData();      //读取AD值,返回24位数据
    }
    //-----------------------------------------------------------------//
    // 功    能:ADS1256唤醒
    // 入口参数: /
    // 出口参数: /
    // 全局变量: /
    // 备    注: 唤醒待机和同步
    //-----------------------------------------------------------------//
    void ADS1256_WAKEUP(void)
    {
    SPI_WriteByte(ADS1256_CMD_WAKEUP);
    }
    //-----------------------------------------------------------------//
    // 功    能:ADS1256读一次数据命令
    // 入口参数: /
    // 出口参数: /
    // 全局变量: /
    // 备    注: /在DRDY为低是读出一个数据
    //-----------------------------------------------------------------//
    void ADS1256_RDATA(void)
    {
    SPI_WriteByte(ADS1256_CMD_RDATA);
    }
    //-----------------------------------------------------------------//
    // 功    能:ADS1256连续读取数据命令
    // 入口参数: /
    // 出口参数: /
    // 全局变量: /
    // 备    注: /在DRDY为低时连续读出数据
    //-----------------------------------------------------------------//
    void ADS1256_RDATAC(void)
    {
    SPI_WriteByte(ADS1256_CMD_RDATAC);
    }
    //-----------------------------------------------------------------//
    // 功    能:ADS1256停止连续读取数据命令
    // 入口参数: /
    // 出口参数: /
    // 全局变量: /
    // 备    注: 在ADS1256连续读取24位数据当中的任何八位时写入,停止连续读取数据命令
    //-----------------------------------------------------------------//
    void ADS1256_SDATAC(void)
    {
    SPI_WriteByte(ADS1256_CMD_SDATAC);
    }
    //-----------------------------------------------------------------//
    // 功    能:ADS1256偏移和增益自校准
    // 入口参数: /
    // 出口参数: /
    // 全局变量: /
    // 备    注: 偏移和增益自校准,也可以用STATUS寄存器中的ACAL来自校准
    //-----------------------------------------------------------------//
    void ADS1256_SELFCAL(void)
    {
    SPI_WriteByte(ADS1256_CMD_SELFCAL);
    }
    //-----------------------------------------------------------------//
    // 功    能:ADS1256同步
    // 入口参数: /
    // 出口参数: /
    // 全局变量: /
    // 备    注: 同步用在命令的开始快速执行,紧接着用WAKEUP命令进行同步
    //-----------------------------------------------------------------//
    void ADS1256_SYNC(void)
    {
    SPI_WriteByte(ADS1256_CMD_SYNC);
    }
    //-----------------------------------------------------------------//
    // 功    能:ADS1256复位
    // 入口参数: /
    // 出口参数: /
    // 全局变量: /
    // 备    注: 复位后不管ACAL位如何都执行一个自校准
    //-----------------------------------------------------------------//
    void ADS1256_RESET(void)
    {
    SPI_WriteByte(ADS1256_CMD_REST);
    }
    //-----------------------------------------------------------------//
    // 功    能:ADS1256第一路采集数据
    // 入口参数: /
    // 出口参数: /
    // 全局变量: /
    // 备    注: 单路采集功能
    //-----------------------------------------------------------------//
      unsigned int GetADS1256_0(void)
    {
    long ulResult;
    int nVolutage;
    ulResult = ADS1256ReadData();
    if(ulResult & 0x800000 )
    {
       ulResult = ~(unsigned long)ulResult;
       ulResult &= 0x7fffff;
       ulResult += 1;
       ulResult = -ulResult;
    };
    nVolutage=ulResult/10;
    return nVolutage+2000;
    }
    主程序
    int main(void)
    {
    SystemInit();      //系统时钟初始化
    delay_init();         //延时函数初始化
    NVIC_Configuration();   //NVIC
    __enable_irq();     //开启总中断
    uart_init(BAUDRATE);   //串口初始化为19200
    LED_Init();        //初始化与LED连接的硬件接口
    KEY_Init();       //按键初始化   
    Init_ADS1256_GPIO();  //初始ADS1256IO
    PCout(7)=1;       //复位拉高
    ADS1256_Init();

    while(1)
    {
      if(KEY1==0)
      {
       if(nCounter!=nDynamicCountFlag)               //如果 动态测量的计数器标志 不等于 计数器 说明上一次是静态称重,将计数器与标志全部置0
       {
        nCounter=0;
        nDynamicCountFlag=0;
       }
      }
      else if(KEY1==1)
      {
       if(nCounter!=nStaticCountFlag)               //如果静态测量的计数器标志 不等于 计数器说明上一次是动态称重,将计数器与标志全部置0
       {
        nStaticSum=0;                       //累加器置0;
        nCounter=0;
        nStaticCountFlag=0;
       }
       nStaticSum+=GetADS1256_0();                 //累加采集到的的数据
       nStaticCalculationTimes++;                 //累加 静态状态下已经累加计算值的个数
       if(nCounter>=10000)                     //如果计数器超过10000计数器置0
        nCounter=0;
        if(nStaticCalculationTimes==nLoopNum)           //判断如果静态状态下已经累加计算值的个数等于设定的静态状态下的累加计算循环的次数,进入循环进行计算发送数据
        {
         ZeroPiont1 = nStaticSum/nLoopNum;            //全局变量,零点码值
         nStaticSum=0;                       //累加器置0;
         nStaticCalculationTimes=0;               //静态状态下已经累加计算值的个数置0,因为已经够数了,下次重新开始
         PackMySend(LOCALXINDAO1,CMDZEROPOINT,0,ZeroPiont1);   //按照协议发送动态数据
        }
        if(nStaticCountFlag==0)                  //判断如果静态测量的计数器标志为0,清空动态测量的计数器标志为0,说明动态测量已经结束必须进入静态测量了。
         nDynamicCountFlag=0;                  //将动态测量的计数器标志置0
        nStaticCountFlag=nCounter+1;               //将静态测量的计数器标志更改为总计数器+1
      }
      nCounter++;
    }
    }

回帖(3)

邢东

2024-12-5 10:01:07
ADS1256默认PGA为1,采用PGA默认值,单通道连续采集时,采集的数据是正确的吗,如果是正确的,可能是在连续采集模式下,PGA配置问题;如果不正确,请用示波器查看连续采集时通信波形,看下是否存在时序问题。
举报

常静娜

2024-12-5 10:01:28
我感觉应该是连续采集数据时序问题,可以用示波器看下连续采集数据时信号波形吗
举报

远不及你

2024-12-5 10:36:33
根据您提供的信息,您在使用STM32F103RDT6+SPI+ADS1256进行单通道连续采集时,配置PGA失败。以下是一些可能的原因和解决方案:

1. 确保SPI通信正确配置:
   检查SPI初始化代码,确保SPI通信参数(如时钟频率、CPOL、CPHA等)与ADS1256的要求相匹配。同时,检查GPIO初始化代码,确保SPI引脚(如SCK、MISO、MOSI、CS)正确配置。

2. 检查ADS1256配置寄存器设置:
   确保您正确设置了ADS1256的配置寄存器,包括PGA增益、采样率、输入通道等。您提到单次采集时PGA设置为32倍可以正常工作,那么请检查连续采集时是否正确设置了这些参数。

3. 检查ADS1256的连续采集模式设置:
   确保您正确设置了ADS1256的连续采集模式。在连续采集模式下,ADS1256会不断采集数据,直到您停止它。请检查您的代码中是否正确设置了连续采集模式。

4. 检查数据读取代码:
   确保您的数据读取代码正确地从ADS1256读取数据。检查是否正确处理了SPI通信和数据缓冲区。

5. 检查硬件连接:
   检查STM32F103RDT6与ADS1256之间的硬件连接,确保所有引脚都正确连接,没有松动或短路。

6. 检查电源和地线:
   确保STM32F103RDT6和ADS1256的电源和地线连接正确,没有电压波动或接地问题。

7. 检查ADS1256固件版本:
   检查您的ADS1256固件版本是否支持您正在使用的配置。如果需要,尝试更新ADS1256的固件。

8. 使用调试工具:
   使用调试工具(如串口调试助手)来检查SPI通信过程中的数据传输,以便更好地了解问题所在。

综上所述,您需要检查SPI通信配置、ADS1256配置寄存器设置、连续采集模式设置、数据读取代码、硬件连接、电源和地线以及ADS1256固件版本。通过逐步排查这些问题,您应该能够找到导致配置PGA失败的原因,并采取相应的解决方案。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分