电赛总结(二)——AD芯片总结之AD7705
1、特性参数
(1)16位无丢失代码性AD转化器
(2)只需要3.3V供电(即只需要单片机即可供电)
(3)双通道差分输入
(4)基准电压为2.5V时,在单极性信号下,输入范围是0到2.5V,在双极性输入下,输入范围是-1.25到+1.25
(5)低功耗CMOS芯片,功耗一般为20uW
(6)可编程,可编程增益,以及降噪参数等。
2、引脚排列
3、引脚功能说明
管脚名称 | 功能 |
SCLK | 串行时钟,施密特逻辑输入。将一个外部的串行时钟加于这一输入端口,以访问AD7705/7706 的串行数据。和单片机传输数据时的控制时钟 |
MCLKIN | 为转换器提供主时钟信号。能以晶体/谐振器或外部时钟的形式提供。晶体/谐振器可以接在MCLKIN 和MCLKOUT 二引脚之间。此外,MCLKIN 也可用CMOS 兼容的时钟驱动, 而MCLKOUT 不连接。时钟频率的范围为500kHz~5MHz |
MCLKOUT | 当主时钟为晶体/谐振器时,晶体/谐振器被接在MCLKIN 和MCLKOUT 之间。如果在MCLKIN 引脚处接上一个外部时钟,MCLKOUT 将提供一个反相时钟信号。这个时钟可以用来为外部电路提供时钟源,且可以驱动一个CMOS 负载。如果用户不需要,MCLKOUT 可以通过时钟寄存器中的CLKDIS位关掉。这样,器件不会在MCLKOUT 脚上驱动电容负载而消耗不必要的功率 |
CS’ | 片选,低电平有效的逻辑输入,选择AD7705/7706。将该引脚接为低电平,AD7705/7706 能以三线接口模式运行(以SCLK、DIN 和DOUT 与器件接口)。在串行总线上带有多个器件的系统中,可由CS’对这些器件作出选择,或在与AD7705/7706 通信时,CS’可用作帧同步信号 |
RESET | 复位输入。低电平有效的输入,将器件的控制逻辑、接口逻辑、校准系数、数字滤波器和模拟调制器复位至上电状态 |
AIN2(+) | 差分模拟输入通道2 的正输入端。 |
AIN1(+) | 差分模拟输入通道1 的正输入端; |
REFIN(+) | 基准输入端,基准输入是差分的,并规定REFIN(+)必须大于REFIN(-)。REFIN(+)可以取VDD 和GND 之间的任何值 |
REFIN(-) | 基准输入端,REFIN(-)可以取VDD 和GND 之间的任何值,且满足REFIN(+)大于REFIN(-) |
DRDY’ | 逻辑输出。这个输出端上的逻辑低电平表示可从AD7705/7706 的数据寄存器获取新的输出字。完成对一个完全的输出字的读操作后,DRDY’引脚立即回到高电平。如果在两次输出更新之间,不发生数据读出,DRDY’将在下一次输出更新前500×tCLKIN 时间返回高电平。当DRDY’处于高电平时,不能进行读操作,以免数据寄存器中的数据正在被更新时进行读操作。当数据被更新后, |
DOUT | 串行数据输出端 |
DIN | 串行数据输入端 |
VDD | 电源电压,+3.3V |
GND | 内部电路的地电位基准点 |
4、片内寄存器
(1)概述
AD7705/7706 片内包括8 个寄存器,这些寄存器通过器件的串行口访问。第一个是通信寄存器,它管理通道选择,决定下一个操作是读操作还是写操作,以及下一次读或写哪一个寄存器。所有与器件的通信必须从写入通信寄存器开始。上电或复位后,器件等待在通信寄存器上进行一次写操作。这一写到通信寄存器的数据决定下一次操作是读还是写,同时决定这次读操作或写操作在哪个寄存器上发生。所以,写任何其它寄存器首先要写通信寄存器,然后才能写选定的寄存器。
(2)通信寄存器
通信寄存器是一个8 位寄存器,既可以读出数据也可以把数据写进去。所有与器件的通信必须从写该寄存器开始。写上去的数据决定下一次读操作或写操作在哪个寄存器上发生。一旦在选定的寄存器上完成了下一次读操作或写操作,接口返回到通信寄存器接收一次写操作的状态。
(3)设置寄存器
(4)时钟寄存器
名称 | 功能 |
ZERO | 必须在这些位上写零,以确保AD7705/7706 正确操作。 |
CLKDIS | 主时钟禁止位。逻辑“ 1” 表示阻止主时钟在MCLKOUT 引脚上输出。禁止时,MCLKOUT 输出引脚处于低电平。 |
CLKDIV | CLKDIV 时钟分频器位。CLKDIV 置为逻辑1 时,MCLKIN 引脚处的时钟频率在被AD7705/7706,使用前进行2 分频。“1”是二分频,“0”没有分频。 |
CLK | 时钟位。CLK 位应根据AD7705/7706 的工作频率而设置。如果转换器的主时钟频率为2.4576MHz(CLKDIV=0)或为4.9152MHz(CLKDIV=1),CLK 应置“0”。如果器件的主时钟频率为1MHz(CLKDIV=0)或2MHz (CLKDIV=1),则该位应置“1”。该位为给定的工作频率设置适当的标度电流,并且也(与FS1 和FS0 一起)选择器件的输出更新率。 |
FS1,FS2 | 滤波器选择位,它与CLK 一起决定器件的输出更新率。表12 显示了滤波器的第一陷波和-3dB 频率。 |
(5)数据寄存器
数据寄存器是一个16 位只读寄存器,它包含了来自AD7705/7706 最新的转换结果。如果通信寄存器将器件设置成对该寄存器写操作,则必定会实际上发生一次写操作以使器件返回到准备对通信寄存器的写操作,但是向器件写入的16 位数字将被AD7705/7706 忽略。
(6)测试寄存器
测试寄存器用于测试器件时。建议用户不要改变测试寄存器的任何位的默认值(上电或复位时自动置入全0),否则当器件处于测试模式时,不能正确运行。
(7)零标度校准寄存器、满标度校准寄存器一般不进行设置
5、芯片外围电路图
6、STM32F103ZE驱动程序
使用SPI模式驱动的AD7705
#ifndef __SPI_H #define __SPI_H #include "stm32f10x.h" #include "pbdata.h" //×ԱຯÊý #include "timer.h" #include "gpio.h" #include "baseFunc.h" /* ???? SPI1_REMAP = 0 SPI1_NSS PA4 CS SPI1_SCK PA5 CLK SPI1_MISO PA6 DOUT SPI1_MOSI PA7 DIN PA8 DRDY */ #define LCD_CS Pin4 #define CLK Pin5 #define DOUT Pin6 #define Din Pin7 #define DRDY Pin8 #define CS_ADC_LOW() GPIO_ResetBits(GPIOA,GPIO_Pin_4) /*??*/ #define CS_ADC_HIGH() GPIO_SetBits(GPIOA,GPIO_Pin_4) void SPIx_Init(void); u8 SPIx_ReadWriteByte(u8 TxData); #endif
#include "spi.h" /* ???? SPI1_REMAP = 0 SPI1_NSS PA4 CS SPI1_SCK PA5 CLK SPI1_MISO PA6 DOUT SPI1_MOSI PA7 DIN PA8 DRDY */ int temp; SPI_InitTypeDef SPI_InitStructure; void SPIx_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_SPI1|RCC_APB2Periph_AFIO, ENABLE ); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;// AdDrdy GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;//PC8 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_SetBits(GPIOA,GPIO_Pin_8); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; 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_4); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP ; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); SPI_Cmd(SPI1, DISABLE); SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(SPI1, &SPI_InitStructure); SPI_Cmd(SPI1, ENABLE); CS_ADC_LOW(); temp=SPIx_ReadWriteByte(0xff); CS_ADC_HIGH(); } u8 SPIx_ReadWriteByte(u8 TxData) { u8 retry=0; while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET) { retry++; if(retry>200)return 0; } SPI_I2S_SendData(SPI1, TxData); retry=0; while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET) { retry++; if(retry>200)return 0; } return SPI_I2S_ReceiveData(SPI1); }
#ifndef __ADC7705_H #define __ADC7705_H #include "stm32f10x.h" //×ԱຯÊý #include "timer.h" #include "gpio.h" #include "baseFunc.h" #include "spi.h" #include "LCD3.2.h" void Init_AD7705(u8 chnanel) ; u16 GetData7705_CH1(void) ; u16 GetData7705_CH2(void) ; void ADC_7705_single(void); void ADC_7705_double(void); void AD7705_WriteByte(u8 Dst_Addr); #endif
#include "adc7705.h" #include "usart1.h" int tag=1; /********AD7705?????***********/ void AD7705_WriteByte(u8 Dst_Addr) { CS_ADC_LOW(); delay_us(20); SPIx_ReadWriteByte(Dst_Addr); delay_us(100); CS_ADC_HIGH(); } void Init_AD7705(u8 chnanel) { u8 i; for(i=0;i<150;i++) { AD7705_WriteByte(0xff); } delay_ms(1); switch(chnanel) { case 1: AD7705_WriteByte(0x20); delay_ms(1); AD7705_WriteByte(0x03); delay_ms(1); AD7705_WriteByte(0x10); delay_ms(1); if(tag==1) { AD7705_WriteByte(0x4C); //µ¥¼«ÐÔ } else { AD7705_WriteByte(0x48); } break; case 2: AD7705_WriteByte(0x21); delay_ms(1); AD7705_WriteByte(0x03); delay_ms(1); AD7705_WriteByte(0x11); delay_ms(1); if(tag==1) { AD7705_WriteByte(0x4C); //µ¥¼«ÐÔ } else { AD7705_WriteByte(0x48); } break; default: break; } } /* ?AD7705???? ????channel */ u16 GetData7705_CH1(void) { u16 temp1 = 0; u16 DataL = 0; u16 DataH = 0; Init_AD7705(1); //?????1 delay_ms(1); AD7705_WriteByte(0x38); //??CH1?????? while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8)==1); //??????AdDrdy=0 CS_ADC_LOW(); delay_us(20); DataH = SPIx_ReadWriteByte(0xff); DataL = SPIx_ReadWriteByte(0xff); delay_us(200); CS_ADC_HIGH(); DataH = DataH << 8; temp1 = DataH | DataL; return temp1; } u16 GetData7705_CH2(void) { u16 temp2 = 0; u16 DataL = 0; u16 DataH = 0; Init_AD7705(2); //?????2 delay_ms(1); AD7705_WriteByte(0x39); //??CH2?????? while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8)==1); //??????AdDrdy=0 CS_ADC_LOW(); //???? delay_us(20); DataH = SPIx_ReadWriteByte(0xff); DataL = SPIx_ReadWriteByte(0xff); delay_us(100); CS_ADC_HIGH(); //???? DataH = DataH << 8; temp2 = DataH | DataL; return temp2; } void ADC_7705_single(void) { u8 num1[]={"0000.0mV"}; u8 num2[]={"0000.0mV"}; u16 RCH1_16bit,RCH2_16bit; u32 l_ncm1,l_ncm2; tag=1; RCH1_16bit = GetData7705_CH1(); l_ncm1 = (u32)(RCH1_16bit*(25000.0/65535)); RCH2_16bit = GetData7705_CH2(); l_ncm2 = (u32)(RCH2_16bit*(25000.0/65535)); num1[0] = l_ncm1/10000+'0'; num1[1] = (l_ncm1%10000)/1000+'0'; num1[2] = (l_ncm1%1000)/100+'0'; num1[3] = (l_ncm1%100)/10+'0'; num1[5] = l_ncm1%10+'0'; num2[0] = l_ncm2/10000+'0'; num2[1] = (l_ncm2%10000)/1000+'0'; num2[2] = (l_ncm2%1000)/100+'0'; num2[3] = (l_ncm2%100)/10+'0'; num2[5] = l_ncm2%10+'0'; LCD_PutString(0,0,num1,Blue,White); LCD_PutString(0,20,num2,Blue,White); } void ADC_7705_double(void) { u8 num1[]={"+0000.0MV"}; u8 num2[]={"+0000.0MV"}; u16 RCH1_16bit,RCH2_16bit; u32 l_ncm1,l_ncm2,NUM1[20],NUM2[20],temp,temp2; int i,j,x,y; int fuhao1=0; int fuhao2=0; tag=0; for(i=0;i<10;i++) { RCH1_16bit = GetData7705_CH1(); RCH2_16bit = GetData7705_CH2(); if(RCH1_16bit>=0x8000) { fuhao1++; l_ncm1 = (u32)((RCH1_16bit-0x8000)*(25000.0/65535*2)); } else { fuhao1--; l_ncm1 = (u32)((0x8000-RCH1_16bit)*(25000.0/65535*2)); } if(RCH2_16bit>=0x8000) { fuhao2++; l_ncm2 = (u32)((RCH2_16bit-0x8000)*(25000.0/65535*2)); } else { fuhao2--; l_ncm2 = (u32)((0x8000-RCH2_16bit)*(25000.0/65535*2)); } NUM1[i]=l_ncm1; NUM2[i]=l_ncm2; } for(i=0;i<9;i++) { x=i; for(j=i+1;j<10;j++) { if(NUM1[x]>NUM1[j]) { x=j; } if(NUM2[y]>NUM2[j]) { y=j; } } temp=NUM1[x]; NUM1[x]=NUM1[i]; NUM1[i]=temp; temp2=NUM2[y]; NUM2[y]=NUM2[i]; NUM2[i]=temp2; } for(i=3,l_ncm1=NUM1[2];i<9;i++) { l_ncm1=(l_ncm1+NUM1[i])/2; } for(i=3,l_ncm2=NUM2[2];i<9;i++) { l_ncm2=(l_ncm2+NUM2[i])/2; } if(fuhao1>=0) { num1[0] = '+'; num1[1] = l_ncm1/10000+'0'; num1[2] = (l_ncm1%10000)/1000+'0'; num1[3] = (l_ncm1%1000)/100+'0'; num1[4] = (l_ncm1%100)/10+'0'; num1[6] = l_ncm1%10+'0'; } else { num1[0] = '-'; num1[1] = l_ncm1/10000+'0'; num1[2] = (l_ncm1%10000)/1000+'0'; num1[3] = (l_ncm1%1000)/100+'0'; num1[4] = (l_ncm1%100)/10+'0'; num1[6] = l_ncm1%10+'0'; } if(fuhao2>=0) { num2[0] = '+'; num2[1] = l_ncm2/10000+'0'; num2[2] = (l_ncm2%10000)/1000+'0'; num2[3] = (l_ncm2%1000)/100+'0'; num2[4] = (l_ncm2%100)/10+'0'; num2[6] = l_ncm2%10+'0'; } else { num2[0] = '-'; num2[1] = l_ncm2/10000+'0'; num2[2] = (l_ncm2%10000)/1000+'0'; num2[3] = (l_ncm2%1000)/100+'0'; num2[4] = (l_ncm2%100)/10+'0'; num2[6] = l_ncm2%10+'0'; } // printf("%s \n",num1); // printf("%s \n",num2); Show_RGB(0,72,0,8,White); Show_RGB(LCDRight-80,LCDRight,0,8,White); LCD_PutString(0,0,num1,Blue,White); LCD_PutString(LCDRight-80,0,num2,Blue,White); }