这款 AD7705 来自于 Analog Devices
公司的一款Sigma-Delta ADC。具有两路差分输入ADC通道,本文记录利用STC8H1K28单片机开发该芯片组成双通道AD转换芯片应用过程。
▲ AD7705内部功能框图与参考设计电路
相关应用:
▲ AD元器件以及TSSOP-16封装
在设计中,AD7705的时钟信号来自于STC8H1K的主时钟的分频输出。具体设置可以参见STC8H1K的MCLKOCR寄存器的设置。
▲ STC8H1K281K主时钟分频输出
PIN1 | PIN2 | PIN3 | PIN4 | PIN5 | PIN6 | PIN7 | PIN8 |
---|---|---|---|---|---|---|---|
+5V | GND | AGND | AIN1+ | AIN1- | AIN2+ | AIN2- | ADC0 |
(1) MCLK的输出设置
#if MCLKOUT_EN
void MClkOutInit(void) {
_push_(P_SW2);
P_SW2 = 0x80;
MCLKOCR = MCLKOUT_DIVIDE | MCLKOS_1;
PM_PP(MCLKOUT_PIN);
_pop_(P_SW2);
}
#endif // MCLKOUT_EN
测量P5.4(MCLK)的波形,频谱为5MHz。
(2) SPI设置
根据AD7705的数据手册以及其中的范例,编写了对于AD7705的初始化程序。但是!不知为什么始终无法进行正常的初始化和得到转化结果。
直道在 电赛总结(二)–AD芯片总结 博文中,看到在它的初始化程序中有这么一段程序:
void Init_AD7705(u8 chnanel)
{
u8 i;
for(i=0;i<150;i++)
{
AD7705_WriteByte(0xff);
}
delay_ms(1);
。。。。。。。。。。。。。。
实在是太奇怪了。不过仿照上述的部分,在AD7705的初始化程序中总增加了下面的语句,突然,整个程序就跑通了!!!
对于这个请到现在还不知道具体的原因是什么!
for(i = 0; i < 10; i ++) AD7705WriteByte(0xff);
WaitTime(2);
/*
**==============================================================================
** AD7705.H: -- by Dr. ZhuoQing, 2020-08-02
**
** Description:
**
**==============================================================================
*/
#ifndef __AD7705__
#define __AD7705__
//------------------------------------------------------------------------------
#ifdef AD7705_GLOBALS
#define AD7705_EXT
#else
#define AD7705_EXT extern
#endif // AD7705_GLOBALS
//------------------------------------------------------------------------------
//==============================================================================
//------------------------------------------------------------------------------
#define AD7705_CS 1,2
#define AD7705_RESET 1,1
#define AD7705_DRRDY 1,6
#define AD7705_CLK 1,5
#define AD7705_MOSI 1,3
#define AD7705_MISO 1,4
//------------------------------------------------------------------------------
unsigned char AD7705SPIWriteRead(unsigned char ucByte);
void AD7705SPIDelay(unsigned int nLoop);
//------------------------------------------------------------------------------
void AD7705Init(void);
#define AD7705_SETUP_DEF 0x44 // Unipolar,
#define AD7705_CLOCK_DEF 0x02 // 100Hz, 1MHz
//------------------------------------------------------------------------------
#define MCLK_FREQUENCY 1000000
#define AD7705_COMM_DEF 0x0
AD7705_EXT unsigned char g_ucAD7705Channel;
#define AD7705_CHANNEL_1 0x0
#define AD7705_CHANNEL_2 0x1
#define AD7705_SET_CHANNEL_1 (g_ucAD7705Channel = AD7705_CHANNEL_1)
#define AD7705_SET_CHANNEL_2 (g_ucAD7705Channel = AD7705_CHANNEL_2)
//------------------------------------------------------------------------------
void AD7705WriteReg(unsigned char ucReg, unsigned char ucByte);
void AD7705WriteByte(unsigned char ucByte);
#define AD7705_REG_COMM 0x00
#define AD7705_REG_SETUP 0x10
#define AD7705_REG_CLOCK 0x20
#define AD7705_REG_DATA 0x30
#define AD7705_REG_TEST 0x40
#define AD7705_REG_NOP 0x50
#define AD7705_REG_OFFSET 0x60
#define AD7705_REG_GAIN 0x70
unsigned int AD7705ReadData(void);
unsigned char AD7705ReadReg(unsigned char ucReg);
unsigned int AD7705ReadChannel(unsigned char ucChannel);
//==============================================================================
// END OF THE FILE : AD7705.H
//------------------------------------------------------------------------------
#endif // __AD7705__
/*
**==============================================================================
** AD7705.C: -- by Dr. ZhuoQing, 2020-08-02
**
**==============================================================================
*/
//------------------------------------------------------------------------------
#define AD7705_GLOBALS 1 // Define the global variables
#include "AD7705.H"
#include "STC8H.H"
#include "STC8HREG.H"
#include "C51BASIC.H"
#include "INTRINS.H"
#include "STDIO.H"
//------------------------------------------------------------------------------
void AD7705Init(void) {
unsigned int i;
ON(AD7705_CS);
ON(AD7705_RESET);
ON(AD7705_DRRDY);
PM_PP(AD7705_CS);
PM_PP(AD7705_RESET);
PM_INPUT(AD7705_DRRDY);
PM_PP(AD7705_CLK);
PM_PP(AD7705_MOSI);
PM_BIDIR(AD7705_MISO);
ON(AD7705_MISO);
OFF(AD7705_CLK);
OFF(AD7705_MOSI);
g_ucAD7705Channel = AD7705_CHANNEL_1;
//--------------------------------------------------------------------------
// OFF(AD7705_RESET);
// WaitTime(2);
// ON(AD7705_RESET);
//--------------------------------------------------------------------------
for(i = 0; i < 10; i ++) AD7705WriteByte(0xff); // *******************
WaitTime(2);
AD7705WriteReg(AD7705_REG_CLOCK, AD7705_CLOCK_DEF); // 100Hz, -3db Filter Cutoff 26.2
// 1MHz : MCLK
AD7705WriteReg(AD7705_REG_SETUP, AD7705_SETUP_DEF); // Gain=1, Self-Calibration, Bipolar
//--------------------------------------------------------------------------
// printf("%bx %bx \r\n", AD7705ReadReg(AD7705_REG_CLOCK), AD7705ReadReg(AD7705_REG_SETUP));
}
//------------------------------------------------------------------------------
unsigned char AD7705SPIWriteRead(unsigned char ucByte) {
unsigned char i, ucMask, ucReturn;
ON(AD7705_CLK);
ucReturn = 0x0;
ucMask = 0x80;
for(i = 0; i < 8; i ++) {
OFF(AD7705_CLK);
if(ucByte & ucMask)
ON(AD7705_MOSI);
else OFF(AD7705_MOSI);
AD7705SPIDelay(0x40);
if(VAL(AD7705_MISO)) ucReturn |= ucMask;
ON(AD7705_CLK);
AD7705SPIDelay(0x40);
ucMask >>= 1;
}
return ucReturn;
}
void AD7705SPIDelay(unsigned int nLoop) {
while(--nLoop) {
_nop_();
}
}
//------------------------------------------------------------------------------
void AD7705WriteReg(unsigned char ucReg, unsigned char ucByte) {
unsigned char ucCmd;
ucCmd = g_ucAD7705Channel | ucReg;
AD7705WriteByte(ucCmd);
AD7705WriteByte(ucByte);
}
//------------------------------------------------------------------------------
void AD7705WriteByte(unsigned char ucByte) {
OFF(AD7705_CS);
AD7705SPIDelay(0x20);
AD7705SPIWriteRead(ucByte);
AD7705SPIDelay(0x20);
ON(AD7705_CS);
}
unsigned char AD7705ReadReg(unsigned char ucReg) {
unsigned ucByte;
ucByte = ucReg | g_ucAD7705Channel | 0x8;
AD7705WriteByte(ucByte);
OFF(AD7705_CS);
ucByte = AD7705SPIWriteRead(0x0);
ON(AD7705_CS);
return ucByte;
}
//------------------------------------------------------------------------------
unsigned int AD7705ReadData(void) {
unsigned char ucByte, ucNum;
unsigned int nNumber;
while(VAL(AD7705_DRRDY));
ucByte = AD7705_REG_DATA | g_ucAD7705Channel | 0x8;
AD7705WriteByte(ucByte);
// printf("%bx ", ucByte);
OFF(AD7705_CS);
// AD7705SPIWriteRead(ucByte);
ucNum = AD7705SPIWriteRead(0x8);
nNumber = ucNum;
ucNum = AD7705SPIWriteRead(0x08);
nNumber = (nNumber << 8) + ucNum;
ON(AD7705_CS);
return (unsigned int)nNumber;
}
//------------------------------------------------------------------------------
unsigned int AD7705ReadChannel(unsigned char ucChannel) {
g_ucAD7705Channel = ucChannel;
AD7705WriteReg(AD7705_REG_SETUP, AD7705_SETUP_DEF);
WaitTime(5);
return AD7705ReadData();
}
//==============================================================================
// END OF THE FILE : AD7705.C
//------------------------------------------------------------------------------
在STC8H1K单片机中提供了串口如下的采集命令集合:
else IFARG0("ad7705c1") {
sscanf(SDA(1), "%d", &nNumber);
nPeriod = 0;
if(STD_NUM > 2) {
sscanf(SDA(2), "%d", &nPeriod);
}
AD7705ReadChannel(0);
while(nNumber --) {
printf("%u ", AD7705ReadData());
if(nPeriod > 0) WaitTime(nPeriod);
}
printf("\r\n");
} else IFARG0("ad7705c2") {
sscanf(SDA(1), "%d", &nNumber);
nPeriod = 0;
if(STD_NUM > 2) {
sscanf(SDA(2), "%d", &nPeriod);
}
AD7705ReadChannel(1);
while(nNumber --) {
printf("%u ", AD7705ReadData());
if(nPeriod > 0) WaitTime(nPeriod);
}
printf("\r\n");
} else IFARG0("ad7705c12") {
nPeriod = 0;
if(STD_NUM > 2) {
sscanf(SDA(2), "%d", &nPeriod);
}
while(nNumber --) {
printf("%u %u ", AD7705ReadChannel(0), AD7705ReadChannel(1));
if(nPeriod > 0) WaitTime(nPeriod);
}
printf("\r\n");
}
▲ 采集的正弦波信号
▲ 采集到三角波信号
▲ 采集到的方波信号
#!/usr/local/bin/python
# -*- coding: gbk -*-
#============================================================
# TEST1.PY -- by Dr. ZhuoQing 2020-08-02
#
# Note:
#============================================================
from headm import *
from tsmodule.tsstm32 import *
stm32cmd('CLEAR')
stm32cmd('ad7705c1 1000')
while True:
if stm32val()[12] > 0: break
data = stm32memo(1)
plt.plot(data)
plt.xlabel("Sample")
plt.ylabel("Voltage")
plt.grid(True)
plt.tight_layout()
plt.show()
#------------------------------------------------------------
# END OF FILE : TEST1.PY
#============================================================
使用STC8H1K28单片机设计了基于AD7705的16bit Sigma-DeltaAD转换器。在时钟设置为0x02, MCLK 设置为1MHz的时候输出数据的频率为100Hz。这一点可以通过AD7705的DATAREADY管脚测量得到。
▲ AD7705 DRRDY管脚显示数据更新频率为100Hz
在调试过程中,初始化有一个往AD7705写入一连串(个数大于5个)0xff的过程。这个过程增加之后,AD7705便可以正常的完成读写操作。
那么问题是:为什么需要增加这个过程?
AD设计工程文件:AD\Test\2020\AD7705\AD77058H1K.SchDoc ↩︎
MCU C51工程文反面:C51\STC\Tools\2020\AD7705STC8H1K28\AD7705STC8H1K28.uvproj ↩︎