前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >STM32-24位AD7799驱动之手册代码详解,支持模拟SPI和硬件SPI

STM32-24位AD7799驱动之手册代码详解,支持模拟SPI和硬件SPI

作者头像
诺谦
发布2019-07-02 17:39:37
2.3K0
发布2019-07-02 17:39:37
举报
文章被收录于专栏:Linux驱动

1.AD7799介绍

AD7799结构图如下所示:

其中REFIN参考电压建议为2.5V, REFIN电压低于0.1V时,则差分输入ad值就无法检测了,如下图所示:

注意:

如果REG_CONFIG的REF_DET开启的话,那么输入AD值电压低于0.5V时,则差分输入ad值就无法检测了,如下图所示:

2.AD7799差分信号的输入模式

如下图所示,差分输入电压有3种模式:

注意:

单端输入电压(AIN-接地,只有正电压)则支持任意范围,比如In-Amp模式下,单端输入如果为10mv的话,也能检测到.

2.1 Unbuffered Mode非缓冲模式

该模式可测的AD值可以在 -30mV ~ (AVDD+30mv)范围之间,如果开了双极型模式(双极型模式通过将REG_CONFIG的U/B位设0实现),则也可以测-(AVDD+30mv)~30mV之间AD值.

也就是说假如我们要测的AD值位于-100mV~100mV之间,则用这个模式.

该模式优缺点:可测范围最大,但是精度误差不是很高

2.2 Buffered Mode缓冲模式

缓冲的作用就是减少测的AD误差,并且功耗相应地会增高点,该模式主要是测100mV~( AVDD-100mV)之间.

该模式优缺点:可测范围比Unbuffered小一点,并且精度误差高一点

2.3 In-Amp 高增益模式

需要将REG_CONFIG的Gain调到4及以上才是该模式,否则的话,就会根据REG_CONFIG的BUF位来自动判断是Buffered Mode还是Unbuffered Mode.

并且AD值必须位于300mv~(AVDD+1100mv)之间,否则的话该模式是无法检测AD值的,之前笔者就是测差分输入的正负20mV,却一直没有反应,后来才发现是处于这个模式的原因.

该模式优缺点:可测范围可以通过设置Gain来设置测试范围,比如VREF为3V,Gain=4,则可测量程为正负600mv.

注意:

当使用Buffered Mode或者In-Amp模式时,需要将REG_CONFIG的BO位开启,介绍如下图所示:

3.代码效果

串口截图如下:

通过电压发生器不停修改AD值时,可以看到万用表和串口打印的数据相差不大:

PS:由于GIF录制的像素位数太低,所以不清晰

4.代码实现

支持硬件SPI1或者GPIO模拟方式

代码通过宏AD7799_INTERFACE_MODE判断,能够支持硬件SPI1或者GPIO模拟方式,如下图所示:

通过宏定义VREF参考电压,以及GAIN增益值

如下图所示,只需修改下面宏,就可以实现转换电压数据自动转换:

实现通道1和通道2来回切换

串口发送select 1,表示选择通道1:

发送select 2,则表示选择通道2.

4.1初始化过程

代码语言:javascript
复制
     /*ad7799初始化*/

         AD7799_gpio_init();
         while(!AD7799_Init())
         {
                          LED0 = !LED0;
                          delay_ms(50);
         }      
         LED0 = 1;
         AD7799_Calibrate();                           //通道校准

         AD7799_SetGain(AD7799_CHIP_GAIN);               
         AD7799_SetBurnoutCurren(0);                  //关闭BO
         AD7799_SetBufMode(0);                        //由于我们要测的电压低于100mV,所以设置为Unbuffered Mode
         AD7799_SetChannel(ChannelBuf[0]);            //通道设置.
         AD7799_SetMode(AD7799_MODE_CONT,5);          //默认双极性   频率为5
         AD7799_SetReference(0);                      //关闭参考检测,因为我们的 AD7799_RefmV 参考电压低于0.5V

4.2 上面的函数如下所示:

代码语言:javascript
复制
void AD7799_gpio_init(void)
{
         GPIO_InitTypeDef GPIO_InitStructure;
         GPIO_InitStructure.GPIO_Pin = AD_CS_PIN;
         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      
         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
         GPIO_Init(AD_CS_GPIO, &GPIO_InitStructure);                              //CS片选

#if ( AD7799_INTERFACE_MODE == AD7799_INTERFACE_SPI1 )
         //spi1 mode
         SPI1_Init();
         SPI1_SetSpeed(SPI_BaudRatePrescaler_2);
#else
         //gpio模拟spi mode
         GPIO_InitStructure.GPIO_Pin = AD_DI_PIN;
         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      
         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
         GPIO_Init(AD_DI_GPIO, &GPIO_InitStructure);

         GPIO_InitStructure.GPIO_Pin = AD_SCK_PIN;
         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      
         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
         GPIO_Init(AD_SCK_GPIO, &GPIO_InitStructure);

         GPIO_InitStructure.GPIO_Pin = AD_DO_PIN;
         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;      
         GPIO_Init(AD_DO_GPIO, &GPIO_InitStructure);
         spi_AD7799_init();
#endif  
         AD7799_Reset();
}
void AD7799_SetGain(unsigned long gain)
{
    unsigned long command;
    command = AD7799_GetRegisterValue(AD7799_REG_CONF,2);
    command &= ~AD7799_CONF_GAIN(0xFF);
    command |= AD7799_CONF_GAIN(gain);
    AD7799_SetRegisterValue(
            AD7799_REG_CONF,
            command,
            2
    );
}

void AD7799_SetBurnoutCurren(u8 enable)//设置BO
{
    unsigned long command;
    command = AD7799_GetRegisterValue(AD7799_REG_CONF,2);
    command &= ~0X2000;
    if(enable)
       command |= 0X2000;
    AD7799_SetRegisterValue(
            AD7799_REG_CONF,
            command,
            2
    );
 
}

void AD7799_SetBufMode(u8 enable)           //设置buf      
{
    unsigned long command;
    command = AD7799_GetRegisterValue(AD7799_REG_CONF,2);
    command &= ~0X10;
    if(enable)
       command |= 0X10;
    AD7799_SetRegisterValue(
            AD7799_REG_CONF,
            command,
            2
    );
}

void AD7799_SetChannel(unsigned long channel)
{
    unsigned long command;
    command = AD7799_GetRegisterValue(AD7799_REG_CONF,2);
    command &= ~AD7799_CONF_CHAN(0xFF);
    command |= AD7799_CONF_CHAN(channel);
    AD7799_SetRegisterValue(
            AD7799_REG_CONF,
            command,
            2
    );
}

void AD7799_SetMode(unsigned long mode,u8  rate)
{
    unsigned long command;
    command = AD7799_GetRegisterValue(AD7799_REG_MODE,2);
    command &= ~AD7799_MODE_SEL(0xFF);
    command |= AD7799_MODE_SEL(mode);
    command &= 0XFFF0;
    command |= rate;                   //设置频率

    AD7799_SetRegisterValue(
            AD7799_REG_MODE,
            command,
            2
    );
}
void AD7799_SetReference(unsigned char state)
{
    unsigned long command = 0;
    command = AD7799_GetRegisterValue(AD7799_REG_CONF,2);
    command &= ~AD7799_CONF_REFDET(1);
    command |= AD7799_CONF_REFDET(state);
    AD7799_SetRegisterValue(AD7799_REG_CONF,  command, 2);

}

void AD7799_SetRegisterValue(unsigned char regAddress,
                             unsigned long regValue,
                             unsigned char size)
{
    unsigned char data[5] = {0x03, 0x00, 0x00, 0x00, 0x00};   
    data[0] = AD7799_COMM_WRITE |  AD7799_COMM_ADDR(regAddress);
    if(size == 1)
    {
        data[1] = (unsigned char)regValue;
    }
    if(size == 2)
    {
        data[2] = (unsigned char)((regValue & 0x0000FF) >> 0);
        data[1] = (unsigned char)((regValue & 0x00FF00) >> 8);
    }
    if(size == 3)
    {
        data[3] = (unsigned char)((regValue & 0x0000FF) >> 0);
        data[2] = (unsigned char)((regValue & 0x00FF00) >> 8);
        data[1] = (unsigned char)((regValue & 0xFF0000) >> 16);
    }
         AD7799_CS_LOW;     
         SPI_Write(data,(1 + size));
         AD7799_CS_HIGH;
}

unsigned long AD7799_GetRegisterValue(unsigned char regAddress, unsigned char size)
{
         unsigned char data[5] = {0x00, 0x00, 0x00, 0x00, 0x00};
         unsigned long receivedData = 0x00;    
         data[0] = AD7799_COMM_READ |  AD7799_COMM_ADDR(regAddress);
         AD7799_CS_LOW; 
         SPI_Write(data,1);
         SPI_Read(data,size);
         AD7799_CS_HIGH;
         if(size == 1)
         {
                  receivedData += (data[0] << 0);
         }
         if(size == 2)
         {
                  receivedData += (data[0] << 8);
                  receivedData += (data[1] << 0);
         }
         if(size == 3)
         {
                  receivedData += (data[0] << 16);
                  receivedData += (data[1] << 8);
                  receivedData += (data[2] << 0);
         }
    return receivedData;
}

4.3 获取通道电压代码如下所示:

代码语言:javascript
复制
      while(1)
         {
                  if(Serial_Post_ChannelValue!=0XFF)              //0:不选择   1~2:更改通道
                  {
                          CurrentChannelValue = Serial_Post_ChannelValue;
                          Serial_Post_ChannelValue =0XFF;

                          if(CurrentChannelValue && CurrentChannelValue<=2)        //1~2
                          {
                                   AD7799_SetChannel(ChannelBuf[CurrentChannelValue-1]);//通道设置.          0~1
                                   delay_ms(10);
                                   AD7799_GetRegisterValue(AD7799_REG_DATA,3);//清空之前的AD
                          }
                          else if(CurrentChannelValue == 0)
                          {
                                   printf("%s value0 0 0 \r\n",Board_Name);
                          }
                  }

                 
                  if(CurrentChannelValue)                  //选择了通道?
                  {
                          for(i=0;i<2;i++)                 //获取每个通道数据
                          if(CurrentChannelValue == (i+1))
                          {
                                   while( !AD7799_Ready())                //1~2
                                   {
                                            delay_ms(5);
                                   }
                                   ADValues[i]=  analyzeAD7799_Data(AD7799_GetRegisterValue(AD7799_REG_DATA,3));
                          }
                          else
                                   ADValues[i] = 0.0000;    

                          printf("%s 当前通道为:%d %.3fmV %.3fmV \r\n",Board_Name,CurrentChannelValue,ADValues[0],ADValues[1]);
                  }      
                  LED0 =!LED0;
                  delay_ms(100);
         }

具体下载地址:https://download.csdn.net/download/qq_37997682/11240699

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-06-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档