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,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 获取通道电压代码如下所示:
- 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://www.cnblogs.com/lifexy/p/11019237.html