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. Android 内存泄漏原因

    Android 手机给应用分配的堆内存通常是8 M 左右, 如果内存处理不当很容易造成 OOM (OutOfMemoryError),OOM 主要由于一下这些原因引起的: 1.  数据库 Cursor ...

  2. 翻转二叉树(深搜-先序遍历-交换Node)

    题目:翻转二叉树,例如 4 / \ 2 7 / \ / \ 1 3 6 9 to 4 / \ 7 2 / \ / \ 9 6 3 1 已知二叉树的节点定义如下: class TreeNode { in ...

  3. 分享一个Vue数组赋值的错误

    今天在写项目用到Vue的时候,遇到的一个问题,纠结了好一会,首先我的代码是这样的 有没有毛病!!  开始我感觉是没啥毛病啊,按照之前写Java代码的逻辑,我感觉这没一点毛病 . 但是它就是有毛病, 假 ...

  4. KubeSphere 日志备份与恢复实践

    为什么需要日志备份 KubeSphere 日志系统使用 Fluent Bit + ElasticSearch 的日志采集存储方案,并通过 Curator 实现对 Index 的生命周期管理,定期清理久 ...

  5. BZOJ 3107 [cqoi2013]二进制a+b (DP)

    3107: [cqoi2013]二进制a+b Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 995  Solved: 444[Submit][Stat ...

  6. Qt5教程: (9) Qt多线程

    目录 0. 创建工程 1. QThread 源码一览 2. QThread相关方法介绍 2.1 启动线程 2.2 关闭线程 2.3 阻塞线程 2.4线程状态判断 2.5 设置优先级 2.6 信号 3. ...

  7. Linux(CentOS)安装SQL Server

    1.下载Microsoft SQL Server Red Hat 存储库配置文件 curl -o /etc/yum.repos.d/mssql-server.repo https://packages ...

  8. visual studio code开发代码片段扩展插件

    背景 visual studio code编辑器强大在于可以自己扩展插件,不仅可以去插件市场下载,也可以按照官方的API很方便的制作适合自己的插件: 自己最近在开发一个手机端网站项目,基于vant项目 ...

  9. item()方法遍历字典

    Python字典的遍历方法有好几种,其中一种是for...in,这个我就不说明,在Python了几乎随处都可见for...in.下面说的这种遍历方式是item()方法. item() item()方法 ...

  10. 使用littlefs-fuse在PC端调试littlefs文件系统

    背景 littlefs是arm面向嵌入式设备推出的一款掉电安全的小型文件系统,具有抗掉电,动态磨损均衡,RAM/ROM需求少等特点,具体介绍可见 https://github.com/ARMmbed/ ...