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初始化过程

     /*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 上面的函数如下所示:

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,);
command &= ~AD7799_CONF_GAIN(0xFF);
command |= AD7799_CONF_GAIN(gain);
AD7799_SetRegisterValue(
AD7799_REG_CONF,
command, );
} void AD7799_SetBurnoutCurren(u8 enable)//设置BO
{
unsigned long command;
command = AD7799_GetRegisterValue(AD7799_REG_CONF,);
command &= ~0X2000;
if(enable)
command |= 0X2000;
AD7799_SetRegisterValue(
AD7799_REG_CONF,
command, ); } void AD7799_SetBufMode(u8 enable) //设置buf
{
unsigned long command;
command = AD7799_GetRegisterValue(AD7799_REG_CONF,);
command &= ~0X10;
if(enable)
command |= 0X10;
AD7799_SetRegisterValue(
AD7799_REG_CONF,
command, );
} void AD7799_SetChannel(unsigned long channel)
{
unsigned long command;
command = AD7799_GetRegisterValue(AD7799_REG_CONF,);
command &= ~AD7799_CONF_CHAN(0xFF);
command |= AD7799_CONF_CHAN(channel);
AD7799_SetRegisterValue(
AD7799_REG_CONF,
command, );
} void AD7799_SetMode(unsigned long mode,u8 rate)
{
unsigned long command;
command = AD7799_GetRegisterValue(AD7799_REG_MODE,);
command &= ~AD7799_MODE_SEL(0xFF);
command |= AD7799_MODE_SEL(mode);
command &= 0XFFF0;
command |= rate; //设置频率 AD7799_SetRegisterValue(
AD7799_REG_MODE,
command, );
}
void AD7799_SetReference(unsigned char state)
{
unsigned long command = ;
command = AD7799_GetRegisterValue(AD7799_REG_CONF,);
command &= ~AD7799_CONF_REFDET();
command |= AD7799_CONF_REFDET(state);
AD7799_SetRegisterValue(AD7799_REG_CONF, command, ); } void AD7799_SetRegisterValue(unsigned char regAddress,
unsigned long regValue,
unsigned char size)
{
unsigned char data[] = {0x03, 0x00, 0x00, 0x00, 0x00};
data[] = AD7799_COMM_WRITE | AD7799_COMM_ADDR(regAddress);
if(size == )
{
data[] = (unsigned char)regValue;
}
if(size == )
{
data[] = (unsigned char)((regValue & 0x0000FF) >> );
data[] = (unsigned char)((regValue & 0x00FF00) >> );
}
if(size == )
{
data[] = (unsigned char)((regValue & 0x0000FF) >> );
data[] = (unsigned char)((regValue & 0x00FF00) >> );
data[] = (unsigned char)((regValue & 0xFF0000) >> );
}
AD7799_CS_LOW;
SPI_Write(data,( + size));
AD7799_CS_HIGH;
} unsigned long AD7799_GetRegisterValue(unsigned char regAddress, unsigned char size)
{
unsigned char data[] = {0x00, 0x00, 0x00, 0x00, 0x00};
unsigned long receivedData = 0x00;
data[] = AD7799_COMM_READ | AD7799_COMM_ADDR(regAddress);
AD7799_CS_LOW;
SPI_Write(data,);
SPI_Read(data,size);
AD7799_CS_HIGH;
if(size == )
{
receivedData += (data[] << );
}
if(size == )
{
receivedData += (data[] << );
receivedData += (data[] << );
}
if(size == )
{
receivedData += (data[] << );
receivedData += (data[] << );
receivedData += (data[] << );
}
return receivedData;
}

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

      while()
{
if(Serial_Post_ChannelValue!=0XFF) //0:不选择 1~2:更改通道
{
CurrentChannelValue = Serial_Post_ChannelValue;
Serial_Post_ChannelValue =0XFF; if(CurrentChannelValue && CurrentChannelValue<=) //1~2
{
AD7799_SetChannel(ChannelBuf[CurrentChannelValue-]);//通道设置. 0~1
delay_ms();
AD7799_GetRegisterValue(AD7799_REG_DATA,);//清空之前的AD
}
else if(CurrentChannelValue == )
{
printf("%s value0 0 0 \r\n",Board_Name);
}
} if(CurrentChannelValue) //选择了通道?
{
for(i=;i<;i++) //获取每个通道数据
if(CurrentChannelValue == (i+))
{
while( !AD7799_Ready()) //1~2
{
delay_ms();
}
ADValues[i]= analyzeAD7799_Data(AD7799_GetRegisterValue(AD7799_REG_DATA,));
}
else
ADValues[i] = 0.0000; printf("%s 当前通道为:%d %.3fmV %.3fmV \r\n",Board_Name,CurrentChannelValue,ADValues[],ADValues[]);
}
LED0 =!LED0;
delay_ms();
}

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

STM32-24位AD7799驱动之手册代码详解,支持模拟SPI和硬件SPI的更多相关文章

  1. 联盛德 HLK-W806 (四): 软件SPI和硬件SPI驱动ST7735液晶LCD

    目录 联盛德 HLK-W806 (一): Ubuntu20.04下的开发环境配置, 编译和烧录说明 联盛德 HLK-W806 (二): Win10下的开发环境配置, 编译和烧录说明 联盛德 HLK-W ...

  2. Linux驱动开发必看详解神秘内核(完全转载)

    Linux驱动开发必看详解神秘内核 完全转载-链接:http://blog.chinaunix.net/uid-21356596-id-1827434.html   IT168 技术文档]在开始步入L ...

  3. 联盛德 HLK-W806 (九): 软件SPI和硬件SPI驱动ST7789V液晶LCD

    目录 联盛德 HLK-W806 (一): Ubuntu20.04下的开发环境配置, 编译和烧录说明 联盛德 HLK-W806 (二): Win10下的开发环境配置, 编译和烧录说明 联盛德 HLK-W ...

  4. 联盛德 HLK-W806 (十一): 软件SPI和硬件SPI驱动ST7567液晶LCD

    目录 联盛德 HLK-W806 (一): Ubuntu20.04下的开发环境配置, 编译和烧录说明 联盛德 HLK-W806 (二): Win10下的开发环境配置, 编译和烧录说明 联盛德 HLK-W ...

  5. ALSA声卡驱动中的DAPM详解之七:dapm事件机制(dapm event)

    前面的六篇文章,我们已经讨论了dapm关于动态电源管理的有关知识,包括widget的创建和初始化,widget之间的连接以及widget的上下电顺序等等.本章我们准备讨论dapm框架中的另一个机制:事 ...

  6. ALSA声卡驱动中的DAPM详解之四:在驱动程序中初始化并注册widget和route

    前几篇文章我们从dapm的数据结构入手,了解了代表音频控件的widget,代表连接路径的route以及用于连接两个widget的path.之前都是一些概念的讲解以及对数据结构中各个字段的说明,从本章开 ...

  7. ALSA声卡驱动中的DAPM详解之三:如何定义各种widget

    上一节中,介绍了DAPM框架中几个重要的数据结构:snd_soc_dapm_widget,snd_soc_dapm_path,snd_soc_dapm_route.其中snd_soc_dapm_pat ...

  8. ARM Cortex-M底层技术(2)—启动代码详解

    杂谈 工作了一天,脑袋比较乱.一直想把底层的知识写成一个系列,希望可以坚持下去.为什么要写底层的东西呢?首先,工作用到了这部分内容,最近和内部Flash打交道比较多,自然而然会接触到一些底层的东西:第 ...

  9. ALSA声卡驱动中的DAPM详解之六:精髓所在,牵一发而动全身

    设计dapm的主要目的之一,就是希望声卡上的各种部件的电源按需分配,需要的就上电,不需要的就下电,使得整个音频系统总是处于最小的耗电状态,最主要的就是,这一切对用户空间的应用程序是透明的,也就是说,用 ...

随机推荐

  1. [译]C#8.0中一个使接口更加灵活的新特性-默认接口实现

    9月份的时候,微软宣布正式发布C#8.0,作为.NET Core 3.0发行版的一部分.C#8.0的新特性之一就是默认接口实现.在本文中,我们将一起来聊聊默认接口实现. 众所周知,对现有应用程序的接口 ...

  2. iOS 音频开发之CoreAudio

    转自:http://www.cnblogs.com/javawebsoa/archive/2013/05/20/3089511.html 接 触过IOS音频开发的同学都知道,Core Audio 是I ...

  3. 一篇文章教你轻松使用fastjson

    前言 只有光头才能变强. 文本已收录至我的GitHub精选文章,欢迎Star:https://github.com/ZhongFuCheng3y/3y JSON相信大家对他也不陌生了,前后端交互中常常 ...

  4. java异常有效实践

    异常在我们的平时开发过程中是非常寻常并且经常会面对的,我们有很多方式来处理和使用异常.充分发挥异常的优点可以提高程序的可读性,可靠性和可维护性.但是如果使用不当,也会带来很多负面影响. 参考 effe ...

  5. 【JS】374- 重学 this 关键字

    为什么要学习this关键字 1. 面试会问啊!总有一些面试官喜欢问你一段不可能这么写的代码.看一道经典且古老的面试题(学完本文后,文末会有一道更复杂的面试题等着你哦!) 代码如下: let a = 5 ...

  6. 小白学 Python 爬虫(20):Xpath 进阶

    人生苦短,我用 Python 前文传送门: 小白学 Python 爬虫(1):开篇 小白学 Python 爬虫(2):前置准备(一)基本类库的安装 小白学 Python 爬虫(3):前置准备(二)Li ...

  7. ConcurrentHashMap比其他并发集合的安全效率要高一些?

    前言 我们知道,ConcurrentHashmap(1.8)这个并发集合框架是线程安全的,当你看到源码的get操作时,会发现get操作全程是没有加任何锁的,这也是这篇博文讨论的问题——为什么它不需要加 ...

  8. 咪咕音乐链接歌词封面搜索等接口API

    搜索 pd.musicapp.migu.cn/MIGUM2.0/v1.0/content/search_all.do?&ua=Android_migu&version=5.0.1&am ...

  9. SpringBoot2基础,进阶,数据库,中间件等系列文章目录分类

    本文源码:GitHub·点这里 || GitEE·点这里 一.文章分类 1.入门基础 SpringBoot2:环境搭建和RestFul风格接口 2.日志管理 SpringBoot2:配置Log4j2, ...

  10. STT-MRMA技术优点

    到目前为止,设计人员可以使用的存储技术是易变的,这意味着在断电后,存储器中的数据内容会丢失.但是,随着Everspin Technologies推出256Mb STT-MRAM,系统现在可以拥有像DR ...