详细资料参考ADI官方资料
ADI官网:http://www.analog.com/cn/
AD7705原理图和PCB可以参考ADI官方的Evaluation Board:http://www.analog.com/media/en/technical-documentation/evaluation-documentation/140293408AD7705_06.pdf
电路部分
官方给出的电路原理图和PCB是通过并口与计算机通信的,因此需要把与并口通信相关的电路去掉,下图是经过修改后的原理图
实物图(做的很丑)
STM32程序
1、选用的是STM32F407ZET6的开发板
2、使用I/O模拟SPI通信
3、参考AD7705芯片手册对寄存器的介绍,将其大部分功能写入了 AD7705.H
4、已将部分功能写进类中,部分类成员函数为空函数,现有的函数能够完成寄存器写入和读取的操作。
5、下一步计划是将函数再进行封装,将AD7705的所有功能实现
SPI.cpp
#include "project.h"
// SCLK PC10
// CS PC12
// RES PD1
// DOUT PD3 receive
// DIN PD5
// DRDY PD7 receive
void GPIO_SPI_Init()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); //使能PD端口时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_5;//PD 1,5推挽输出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化GPIOD 1 5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_12;//PC 10,12推挽输出
GPIO_Init(GPIOC,&GPIO_InitStructure);//初始化GPIOG
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_7;//PD 3 7 输入
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化GPIOD 3 7
RES = 1;
SCLK = 1;
CS = 0;
}
AD_Resgister::AD_Resgister()
{
//Register
Commu_Register=0;
Setup_Register=0;
Clock_Register=0;
//Data
Data_Receive=0;
CS=0;//chip select AD board
}
//Initialize
void AD_Resgister::AD_Init()
{
Commu_Register=0;
SPI_Write(Commu_Register | Reg_Setup);
SPI_Write(Setup_Register);
Commu_Register=0;
SPI_Write(Commu_Register | Reg_Clock);
SPI_Write(Clock_Register);
}
//Register
void AD_Resgister::Communication()//Read and write
{
Commu_Register |= Read;
SPI_Write(Commu_Register);
SPI_Read(bits_8);
Data_Receive=0;
}
void AD_Resgister::Setup(u8 reg_setup)//Only write
{
Commu_Register &= 0x87; //clear RS2 RS1 RS0 R/W
Commu_Register |= Reg_Setup; //RS2 RS1 RS0
Commu_Register |= Write; //R/W
Setup_Register = reg_setup;
SPI_Write(Commu_Register);
SPI_Write(Setup_Register);
}
void AD_Resgister::Clock(u8 reg_setup)//Only write
{
Commu_Register &= 0x87; //clear RS2 RS1 RS0 R/W
Commu_Register |= Reg_Clock; //RS2 RS1 RS0
Commu_Register |= Write; //R/W
Clock_Register = reg_setup;
SPI_Write(Commu_Register);
SPI_Write(Clock_Register);
}
void AD_Resgister::Data()//Only read
{
Commu_Register &= 0x87; //clear RS2 RS1 RS0 R/W
Commu_Register |= Reg_Data; //RS2 RS1 RS0
Commu_Register |= Read; //R/W
SPI_Write(Commu_Register);
SPI_Read(bits_16);
}
//hardly use
void AD_Resgister::Test()//Only read
{}
void AD_Resgister::Offset()//Offset register
{}
void AD_Resgister::Gain()//Gain register
{}
//ad operation
void AD_Resgister::Reset_AD()//Reset AD7705
{
RES = 0;
delay_us(5);
RES = 1;
delay_us(500);
}
void AD_Resgister::Default_AD()
{
u8 i=32;
DIN = 1;
for(;i>0;i--)
{
SCLK = 0;
delay_us(1);
SCLK = 1;
delay_us(1);
}
delay_us(500);
}
//SPI operation
void AD_Resgister::SPI_Write(u8 ad_register)
{
u8 i = 0;
u8 temp = 0x01<<7;
for(;i<8;i++)
{
if((temp & ad_register) == 0)
DIN = 0;
else
DIN = 1;
temp = temp>>1;
SCLK=0;
delay_us(1);
SCLK = 1;
delay_us(1);
}
}
void AD_Resgister::SPI_Read(u8 register_bits)
{
u8 i = 0;
Data_Receive = 0;
for(;i<register_bits;i++)
{
SCLK = 0;
delay_us(1);
SCLK = 1;
delay_us(1);
if(DOUT == 0)
Data_Receive = Data_Receive<<1;
else
{
Data_Receive = Data_Receive<<1;
Data_Receive += 0x01;
}
}
}
SPI.h
#ifndef _SPI_H
#define _SPI_H
extern "C"{
void GPIO_SPI_Init(void);//Init GPIO
}
#define u8 unsigned char
#define u32 unsigned int
class AD_Resgister
{
public:
//Register
u8 Commu_Register;
u8 Setup_Register;
u8 Clock_Register;
//Data
u32 Data_Receive;
//structure function
AD_Resgister(void);
//Initialize
void AD_Init(void);
//Register
void Communication(void);//Read and write
void Setup(u8 reg_setup);//Only write
void Clock(u8 reg_clock);//Only write
void Data(void);//Only read
void Test(void);//Only read
//hardly use
void Offset(void);//Offset register
void Gain(void);//Gain register
//ad operation
void Reset_AD(void);
void Default_AD(void);
//SPI operation
void SPI_Write(u8 ad_register);
void SPI_Read(u8 register_bits);
};
#endif
AD7705.H 里面是和AD7705寄存器相关的宏定义
#ifndef _AD7705_H
#define _AD7705_H
//refer to datasheet page 16 to 37
//register bits
#define bits_8 8
#define bits_16 16
#define bits_24 24
//define GPIO
#define SCLK PCout(10)
#define CS PCout(12)
#define RES PDout(1)
#define DOUT PDin(3)
#define DIN PDout(5)
#define DRDY PDin(7)
/******************Communication Register******************/
/*
| 0/DRDY | RS2 | RS1 | RS0 | R/W | STBY | CH1 | CH0 |
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
*/
//register selection RS2 RS1 RS0
#define Reg_Com 0x00<<4 //8bits register
#define Reg_Setup 0x01<<4 //8bits register
#define Reg_Clock 0x02<<4 //8bits register
#define Reg_Data 0x03<<4 //16bits register
#define Reg_Test 0x04<<4 //8bits register
#define Reg_OffSet 0x06<<4 //24bits register
#define Reg_Gain 0x07<<4 //24bitss register
//read or write R/W
#define Read 1<<3
#define Write 0<<3
//standby or normal STBY
#define Normal 0<<2
#define Standby 1<<2
//channel select CH1 CH0
#define CH1_difference 0x00
#define CH2_difference 0x01
#define CH1_AIN1_N 0x02
#define CH_AIN_N 0x03
/******************Setup Register******************/
/*
| MD1 | MD0 | G 2 | G 1 | G 0 | B/U | BUF | FSYNC |
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
*/
//Operating mode MD1 MD0
#define Mode_Normal 0x00<<6
#define Self_Calinration 0x01<<6
#define Zero_Scale 0x02<<6
#define Full_Scale 0x03<<6
//gain select G2 G1 G0
#define Gain_1 0x00<<3
#define Gain_2 0x01<<3
#define Gain_4 0x02<<3
#define Gain_8 0x03<<3
#define Gain_16 0x04<<3
#define Gain_32 0x05<<3
#define Gain_64 0x06<<3
#define Gain_128 0x07<<3
//Bipolar/Unipolar Operation B/U
#define Bipolar 0<<2
#define Unipolar 1<<2
//Filter Sync
#define Filter_On 0
#define Filter_OFF 1
/******************Clock Register******************/
/*
| ZERO | ZERO | ZERO | CLKDIS | CLKDIV | CLK | FS1 | FS0 |
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
*/
//clock devide CLKDIV
#define CLKDIV_0 0<<3 //internal clock equal to crystal oscillator
#define CLKDIV_1 1<<3 //internal clock equal to half crystal oscillator
//XALT determined CLK register CLK
#ifndef XALT_Lowspeed
#define CLK 1<<2
#else
#define CLK 0<<2
#endif
//output update rate (HZ) FS1 FS0
#if CLK==1<<2
#define Rate_50 0x00
#define Rate_60 0x01
#define Rate_250 0x02
#define Rate_500 0x03
#else
#define Rate_20 0x00
#define Rate_25 0x01
#define Rate_100 0x02
#define Rate_200 0x03
#endif
#endif
main.cpp
#include "project.h"
AD_Resgister AD_7705;
u32 AD_average = 0;
u8 Receive = 0; //TIM3 IRQ flag
int main()
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//Set system exit priority group 2
uart_init(115200);//Set serial bound 115200
delay_init(168);
LED_Init();
GPIO_SPI_Init();
LED0=1;
LED1=0;
//Reset AD7705
AD_7705.Reset_AD();
//AD Initialization
AD_7705.AD_Init();
//Communication register configure
AD_7705.Commu_Register = CH1_difference;//channel 1 difference input
AD_7705.Communication();
//Setup register configure
AD_7705.Setup( Mode_Normal | Gain_1 | Bipolar | Filter_On );
//Clock register configure
AD_7705.Clock( CLKDIV_1 | CLK | Rate_60 );
//Wait AD7705 500us
delay_us(500);
//Read data
AD_7705.Data();
AD_average = AD_7705.Data_Receive;
TIM3_Init();
while(1)
{
if(Receive)
{
printf("AD \n");
printf("%d\n",AD_average);
Receive = 0;
}
}
}
TIM3.c
#include "project.h"
extern AD_Resgister AD_7705;
extern u32 AD_average;
extern u8 Receive;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
extern "C"{
void TIM3_Init(void)
{
/* -----------------------------------------------------------------------
default SystemInit
{
APB1 clock Prescaler=4,APB1_Frequence=42M
TIM2~TIM7、TIM12~TIM14 Frequence=2*APB1_Frequence=84M
TIMx_CLK=84M
APB2 clock Prescaler=2,APB2_Frequence=84M
TIM1、TIM8~TIM11 Frequence=2*APB2_Frequence=168M
TIMx_CLK=168M
}
TIM3 Configuration: generate 4 PWM signals with 4 different duty cycles.
In this example TIM3 input clock (TIM3CLK) is set to 2 * APB1 clock (PCLK1),
since APB1 prescaler is different from 1.
TIM3CLK = 2 * PCLK1
PCLK1 = HCLK / 4
=> TIM3CLK = HCLK / 2 = SystemCoreClock /2
To get TIM3 counter clock at 21 MHz, the prescaler is computed as follows:
Prescaler = (TIM3CLK / TIM3 counter clock) - 1
Prescaler = ((SystemCoreClock /2) /21 MHz) - 1
To get TIM3 output clock at 30 KHz, the period (ARR)) is computed as follows:
ARR = (TIM3 counter clock / TIM3 output clock) - 1 = 665
----------------------------------------------------------------------- */
//PrescalerValue = (uint16_t) ((SystemCoreClock /2) / 21000000) - 1;
uint16_t TIM3_Counter_CLK = 1;//Set TIM3 CLK MHz
uint16_t TIM3_Output_CLK = 60;//Set TIM3 clock Hz
uint32_t TIM3_Period = ((TIM3_Counter_CLK * 1000000) / TIM3_Output_CLK) - 1;
uint16_t PrescalerValue = (uint16_t)((SystemCoreClock / 2) / (TIM3_Counter_CLK * 1000000)) - 1;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //Enable TIM3 clock
TIM_TimeBaseStructure.TIM_Period = TIM3_Period; //Set period 0~65535
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue; //Clock division
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //Count up mode
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseStructure);
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //Enable TIM3 interrupt
TIM_Cmd(TIM3,ENABLE); //Enable TIM3
NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
{
AD_7705.Data();
AD_average = AD_7705.Data_Receive;
Receive=1;
LED0=~LED0;
LED1=~LED1;
}
TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //clear interrupt flag
}
}