本文将介绍一款差分放大电路,通过使用数字电位器来调节电路的放大倍数。
1 芯片知识
AD8226 是一款低成本、宽电源电压范围的仪表放大器,仅需一个外部电阻器即可设置 1 至 1000 之间任何增益。AD8226 可支持多种信号电压。宽输入范围和轨到轨输出允许信号充分利用电源轨。由于输入范围还包括低于负电源电压的能力,因此无需双电源即可放大接近地电压的小信号。AD8226 可采用 ±1.35 V 至 ±18 V 的双电源供电,或采用 2.2 V 至 36 V 的单电源供电。
AD5293是一款单通道、1024位数字电位计1 ,端到端电阻容差<1%。该器件可实现与机械电位计相同的电子调整功能,而且具有增强的分辨率、固态可靠性和出色的低温度系数性能。它可在高电压下工作,既可采用±10.5 V至±15 V双电源供电,也可采用21 V至33 V单电源供电。MCU通过SPI方式与其通信。
2. 电路连接
本项目使用的MCU芯片为STM32F103R6(用于proteus仿真),MCU通过spi方式与AD5293连接,使用了PA3,PA4,PA5,PA6,PA7引脚,其中PA3用于片选,PA4引脚设为模拟输入,连接到AD5293的RDY引脚,用于监测数据写入是否完成(此功能可不使用)。
电路连接如下图所示:
3. 代码部分
本项目的代码开发使用Keil 5软件,生成kex文件后,拷入到Proteus中。
首先是SPI的初始化代码,使用的是SPI1,代码参考正点原子。
void SPI1_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;SPI_InitTypeDef SPI_InitStructure;RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );//PORTA时钟使能 RCC_APB2PeriphClockCmd( RCC_APB2Periph_SPI1, ENABLE );//SPI1时钟使能 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //PB5/6/7复用推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOBGPIO_SetBits(GPIOA, GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7); //PB5/6/7上拉SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //设置SPI单向或者双向的数据模式:SPI设置为双线双向全双工SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //设置SPI工作模式:设置为主SPISPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //设置SPI的数据大小:SPI发送接收8位帧结构SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //串行同步时钟的空闲状态为低电平SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; //串行同步时钟的第二个跳变沿(上升或下降)数据被采样SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由硬件(NSS管脚)还是软件(使用SSI位)管理:内部NSS信号有SSI位控制SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; //定义波特率预分频的值:波特率预分频值为256SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //指定数据传输从MSB位还是LSB位开始:数据传输从MSB位开始SPI_InitStructure.SPI_CRCPolynomial = 7; //CRC值计算的多项式SPI_Init(SPI1, &SPI_InitStructure); //根据SPI_InitStruct中指定的参数初始化外设SPIx寄存器SPI_Cmd(SPI1, ENABLE); //使能SPI外设SPI1_ReadWriteByte(0xff);//启动传输 } void SPI1_SetSpeed(u8 SPI_BaudRatePrescaler)
{assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_BaudRatePrescaler));SPI1->CR1&=0XFFC7;SPI1->CR1|=SPI_BaudRatePrescaler; //设置SPI1速度 SPI_Cmd(SPI1,ENABLE); } //SPIx 读写一个字节
//TxData:要写入的字节
//返回值:读取到的字节
u8 SPI1_ReadWriteByte(u8 TxData)
{ u8 retry=0; while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位{retry++;if(retry>200)return 0;} SPI_I2S_SendData(SPI1, TxData); //通过外设SPIx发送一个数据retry=0;while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位{retry++;if(retry>200)return 0;} return SPI_I2S_ReceiveData(SPI1); //返回通过SPIx最近接收的数据
}
其次是配置AD5293的头文件,将功能码宏定义,包括解锁,写入数据,写入控制指令等等,然后编写了AD5293的初始化函数,解锁函数,写入数据函数等等
#ifndef __AD5293_H
#define __AD5293_H
#include "sys.h"#define AD5293_RDY PAin(4) #define unlock 0x1802
#define nop 0x00
#define write 0x01
#define reset 0x04
#define read_data 0x02
#define read_com 0x07void AD5293_CS_HIGH(void);
void AD5293_CS_LOW(void);void AD5293_Init(void);
void AD5293_Unlock(void);
void AD5293_Write(u8 com, u16 data);
u16 AD5293_Read_data(u8 com);#endif
AD5293的初始化
void AD5293_Init()
{GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE );//PORTA时钟使能 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 ; // PA3 推挽 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_SetBits(GPIOA,GPIO_Pin_3);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; // PA4 推挽 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);AD5293_CS_HIGH();SPI1_Init();SPI1_SetSpeed(SPI_BaudRatePrescaler_2);
}
AD5293的片选函数以及写入数据函数
void AD5293_CS_HIGH(void)
{GPIO_SetBits(GPIOA, GPIO_Pin_3);
}void AD5293_CS_LOW(void)
{GPIO_ResetBits(GPIOA, GPIO_Pin_3);
}void AD5293_Unlock(){AD5293_CS_LOW();SPI1_ReadWriteByte(unlock>>8);SPI1_ReadWriteByte(unlock&0xff);AD5293_CS_HIGH();}
void AD5293_Write(u8 com, u16 data){AD5293_CS_LOW();SPI1_ReadWriteByte((com<<2)|((data>>8)&0x03));SPI1_ReadWriteByte((data&0xff));AD5293_CS_HIGH();
}
最后是主函数部分,向其发送写入指令,并配置阻值为0x100(1/4电阻)。
int main(void){ delay_init();//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //uart_init(115200);AD5293_Init();AD5293_Unlock();AD5293_Write(write,0x0100);while(1){}
}
4. 结果验证
将MCU单独接AD5293,在芯片的A端接入15V电压,W和B口接入电压表,将上述hex文件加载到MCU中,可观察到输出电压值为3.75V,因为此时阻值为总电阻的1/4,所以分压占总电压的1/4。
接入AD8226再进行验证,输入为0.3V,输出为1.47V,放大了4.9倍,通过公式