AD7712属于Σ-Δ型 ADC,首先应对以下概念有所了解:①过采样、②噪声成形、③数字滤波和抽取。在此不对具体实现原理进行说明,本文主要描述实现过程:
1、使用硬件包括:MSP430G2553单片机;AD7712;PC机
2、实现功能:MSP430采集AD7712的数据,通过串口将采集数据上传至PC机串口助手。
以下为工程main函数:
#include <msp430.h>
#include <stdint.h>
#include "AD7712.h"
#define ad7712_DRDY1 P1IN &= BIT0 //P1.0口接ad7712的DRDY脚
#define ad7712_R_DATA P2IN &= BIT0 //P2.0口接ad7712的Data脚
#define ad7712_TFS1 P3OUT |= BIT1//P3.1口接ad7712的TFS脚
#define ad7712_TFS0 P3OUT &=~ BIT1
#define ad7712_RFS1 P3OUT |= BIT0//P3.0口接ad7712的RFS脚
#define ad7712_RFS0 P3OUT &=~ BIT0
#define ad7712_A0_1 P2OUT |= BIT2//P2.2口接ad7712的A0脚
#define ad7712_A0_0 P2OUT &=~ BIT2
#define ad7712_SCLK_1 P2OUT |= BIT1//P2.1口接ad7712的SCLK脚
#define ad7712_SCLK_0 P2OUT &=~ BIT1
#define ad7712_SDATA_1 P2OUT |= BIT0//P2.0口接ad7712的SDATA脚
#define ad7712_SDATA_0 P2OUT &=~ BIT0
#define uchar uint8_t
uint32_t return_data;
uint8_t data = 0;
void Send_Byte(uchar data);
void Init_TimerA0(void);
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
BCSCTL2 = SELM_3 | DIVM_0 | SELS | DIVS_0;
//MCLK使用外部晶振、MCLK不分频、SMCLK使用外部晶振、0分频
if (CALBC1_1MHZ != 0xFF)
{
DCOCTL = 0x00;
BCSCTL1 = CALBC1_1MHZ; /* Set DCO to 1MHz */
DCOCTL = CALDCO_1MHZ;
}
BCSCTL1 |= XT2OFF | DIVA_0; //ACLK 不分频
BCSCTL3 = XT2S_0 | LFXT1S_0 | XCAP_1;
/* 串口部分 */
P1SEL = BIT1 + BIT2; // P1.1 = RXD, P1.2=TXD
P1SEL2 = BIT1 + BIT2; // P1.1 = RXD, P1.2=TXD
UCA0CTL1 |= UCSWRST;
UCA0CTL1 |= UCSSEL_2 | UCSWRST; // SMCLK
//UCA0MCTL = UCBRF_0 | UCBRS_6; //2400bit
//UCA0BR0 = 13;
//UCA0MCTL = UCBRF_0 | UCBRS_7; //4800bit
//UCA0BR0 = 6;
UCA0MCTL = UCBRF_0 | UCBRS_3; //9600bit
UCA0BR0 = 3;
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
//_EINT();
Init_TimerA0();
AD7712_Init();
_enable_interrupts();
__bis_SR_register(GIE);
while(1)
{
}
}
void Send_Byte(uchar data)
{
while (!(IFG2&UCA0TXIFG));
UCA0TXBUF = data;
}
void Init_TimerA0(void)
{
TA0CTL = TASSEL_2 + MC_1; // 3:选择时钟源和计数模式//时钟源为MCLK并且为增计数模式
TA0CCTL0 = CCIE; //1:开启比较器0中断
TA0CCR0 = 3277;//16384; // 2:定时时间的选取100ms
}
/****************************************************
* 定时器0中断
****************************************************/
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A0(void)
{
// Init_TimerA0();
write_AD(0x00AC912C);//放大八倍 A895DC放大四倍,AC95DC放大八倍 ,AC35DC输出16bit
return_data = read_data();
data = (return_data & 0xFF0000) >> 16;
Send_Byte(data);
data = (return_data & 0x00FF00) >> 8;
Send_Byte(data);
Send_Byte(0x0A);
// Send_Byte(0xFF);
}
以下为AD7712.h文件,负责AD7712初始化、写控制与读数据功能函数:
/*
* AD7712.h
*/
#ifndef AD7712_H_
#define AD7712_H_
#define ad7712_DRDY1 P1IN &= BIT0 //P1.0口接ad7712的DRDY脚
#define ad7712_R_DATA P2IN &= BIT0 //P2.0口接ad7712的Data脚
#define ad7712_TFS1 P3OUT |= BIT1//P3.1口接ad7712的TFS脚
#define ad7712_TFS0 P3OUT &=~ BIT1
#define ad7712_RFS1 P3OUT |= BIT0//P3.0口接ad7712的RFS脚
#define ad7712_RFS0 P3OUT &=~ BIT0
#define ad7712_A0_1 P2OUT |= BIT2//P2.2口接ad7712的A0脚
#define ad7712_A0_0 P2OUT &=~ BIT2
#define ad7712_SCLK_1 P2OUT |= BIT1//P2.1口接ad7712的SCLK脚-
#define ad7712_SCLK_0 P2OUT &=~ BIT1
#define ad7712_SDATA_1 P2OUT |= BIT0//P2.0口接ad7712的SDATA脚
#define ad7712_SDATA_0 P2OUT &=~ BIT0
#define CPU_F ((double)32768)
#define delay_us(x) __delay_cycles((long)(CPU_F*(double)x/32768.0))
void AD7712_Init(void);
void write_AD(uint32_t data);
uint32_t read_conreg();
uint32_t read_data();
// 初始化AD7712
void AD7712_Init(void)
{
//-----设置IO为输出-----
P2DIR |= BIT0 + BIT1 + BIT2;
P3DIR |= BIT0 + BIT1;
P1DIR &= ~ BIT0; //使能DRDY线为输入
//-----设置IO初始状态-----
ad7712_RFS1;
ad7712_TFS1;
ad7712_A0_1;
ad7712_SCLK_0;
ad7712_SDATA_0;
}
/**
* data:写入的数据
* 32位输入,高8位无效
*/
void write_AD(uint32_t data)
{
int i = 0;
P2DIR |= BIT0;//使能SDATA线为输出
ad7712_SDATA_0;//SDATA置低
ad7712_SCLK_0;//时钟信号预位为低(上升沿有效)
ad7712_A0_0;//传输寄存器选择控制信号
//delay_us(1);//等待信号稳定,延时50us
ad7712_RFS1;
ad7712_TFS0;//传输写控制信号(低有效)
//delay_us(1); //等待写控制信号稳定,延时50us
data = data & (0x00FFFFFF); //屏蔽data高8位
for(i = 0;i < 24; i++) //循环发送data低24位
{
if(data & (1L << (23-i))) //从高位开始向低位判断
{
ad7712_SDATA_1; //若为1则SDATA输出高电平
}
else
{
ad7712_SDATA_0; //若为0则SDATA输出低电平
}
//delay_us(1); //等待SDATA信号稳定,以及控制SCLK低电平时长
ad7712_SCLK_1; //SCLK置高,此时产生上升沿
//delay_us(1); //控制SCLK高电平时长
ad7712_SCLK_0; //SCLK置低转入下一位数据发送
}//循环结束,数据发送完成
ad7712_SCLK_0; //关闭SCLK
ad7712_SDATA_0; //SDATA线置为低
//delay_us(1); //等待信号稳定
ad7712_TFS1; //释放写有效信号
//delay_us(1); //等待信号稳定
ad7712_A0_1; //A0置为高
}
// 读出数据,读出24位
uint32_t read_conreg()
{
int i = 0;
uint32_t data = 0; //创建接收数据寄存器
P2DIR &= ~BIT0; //SDATA设置为输入模式
// while(ad7712_DRDY1); //等待DRDY有效
ad7712_A0_0; //传送寄存器选通信号
delay_us(1); //等待A0信号稳定
ad7712_RFS0; //传送读有效信号
ad7712_TFS1;
ad7712_SCLK_0; //置位SCLK信号初值
delay_us(1); //等待信号稳定
for(i = 0;i < 24; i++)
{
ad7712_SCLK_1; //SCLK上升沿产生
data = data << 1; //先将接受数据左移一位
if(ad7712_R_DATA) //读取总线信号
{
data++; //若总线信号在SCLK上升时为高电平,data最低位置1
}
delay_us(1); //控制SCLK高电平时间
ad7712_SCLK_0; //SCLK下降沿产生,下一位数据被AD送入总线
delay_us(1); //控制SCLK低电平时间
} //传输完成
ad7712_SCLK_0; //初始化SCLK信号为低
ad7712_A0_1; //地址线初始化为高
delay_us(1); //等待信号稳定
ad7712_RFS1; //释放读有效
return data ; //返回接受数据低24位
}
// 读出数据,读出24位
uint32_t read_data()
{
int i = 0;
uint32_t data = 0; //创建接收数据寄存器
P2DIR &= ~BIT0; //SDATA设置为输入模式
while(ad7712_DRDY1); //等待DRDY有效
ad7712_A0_1; //传送寄存器选通信号
//delay_us(1); //等待A0信号稳定
ad7712_RFS0; //传送读有效信号
ad7712_TFS1;
ad7712_SCLK_0; //置位SCLK信号初值
//delay_us(1); //等待信号稳定
for(i = 0;i < 24; i++)
{
ad7712_SCLK_1; //SCLK上升沿产生
data = data << 1; //先将接受数据左移一位
if(ad7712_R_DATA) //读取总线信号
{
data++; //若总线信号在SCLK上升时为高电平,data最低位置1
}
//delay_us(1); //控制SCLK高电平时间
ad7712_SCLK_0; //SCLK下降沿产生,下一位数据被AD送入总线
//delay_us(1); //控制SCLK低电平时间
} //传输完成
ad7712_SCLK_0; //初始化SCLK信号为低
ad7712_A0_0; //地址线初始化为高
//delay_us(1); //等待信号稳定
ad7712_RFS1; //释放读有效
return data ; //返回接受数据低24位
}
#endif /* AD7712_H_ */