一、概述

该博客介绍使用软件模拟 SPI驱动16位 ADTM7705(兼容AD7705)
TM7705 使用SPI串行通信协议,使用十分方便快捷.并且兼容 2.7~3.3V 或 4.75~5.25V 单电源。可以直接使用单片机引脚进行供电. TM7705 是用于智能系统、微控制器系统和基于 DSP 系统的理想产品。其串行接口可配置为三线接口。增益值、信号极性以及更新速率的选择可用串行输入口由软件来配置。该器件还包括自校准和系统校准选项,以消除器件本身或系统的增益和偏移误差。TM7705 采用 16 脚塑料双列直插(DIP)和 16 脚宽体(0.3 英寸)SOIC 封装和 16 脚 TSSOP 封装。

二、特点

TM7705:2 个全差分输入通道的 ADC
	16 位无丢失代码
	0.003%非线性
	可编程增益前端
	增益:1~128
	三线串行接口
	有对模拟输入缓冲的能力
	2.7~3.3V 或 4.75~5.25V 工作电压
	3V 电压时,最大功耗为 1mW
	等待电流的最大值为 8μA
	16 脚 DIP、SOIC 和 TSSOP 封装

三.引脚排列

esp32 tm Esp32 tm7705_物联网

四.引脚功能

esp32 tm Esp32 tm7705_物联网_02


五.代码讲解

esp32WROOM 32D 驱动AD 7705代码

AD7705.h头文件

#include "driver/gpio.h"

#ifndef __AD7705_H__
#define __AD7705_H__


#define ADC_DI 23//DIN引脚
#define ADC_DO1 25//DOUT引脚
#define ADC_CLK 19//SCK引脚
#define ADC_RESET 18//RST引脚

#define ADC1_CS 22//CS引脚
#define ADC1_DRDY1 21//DRDY引脚

#define ADC_CLK0 gpio_set_level(ADC_CLK, 0)//CLK引脚设置为低电平
#define ADC_CLK1 gpio_set_level(ADC_CLK, 1)//CLK引脚设置为高电平

#define ADC_RESET0 gpio_set_level(ADC_RESET, 0)//RST引脚设置为低电平
#define ADC_RESET1 gpio_set_level(ADC_RESET, 1)//RST引脚设置为高电平

#define ADC_DI0 gpio_set_level(ADC_DI, 0)//DIN引脚设置为低电平
#define ADC_DI1 gpio_set_level(ADC_DI, 1)//DIN引脚设置为高电平

#define ADC1_CS0 gpio_set_level(ADC1_CS, 0)//CS引脚设置为低电平
#define ADC1_CS1 gpio_set_level(ADC1_CS, 1)//CS引脚设置为高电平


#define ADC_DO gpio_get_level(ADC_DO1)//获取DOUT引脚电平
#define ADC1_DRDY gpio_get_level(ADC1_DRDY1)//获取DRDY引脚电平
//Operation modes
#define ADC_NORMAL 			0x00
#define ADC_SELF       		0x40
#define ADC_ZERO_SCALE 		0x80
#define ADC_FULL_SCALE 		0xc0

//Gain settings
#define ADC_GAIN_1 			0x00
#define ADC_GAIN_2 			0x08
#define ADC_GAIN_4 			0x10
#define ADC_GAIN_8 			0x18
#define ADC_GAIN_16 		0x20
#define ADC_GAIN_32 		0x28
#define ADC_GAIN_64 		0x30
#define ADC_GAIN_128 		0x38

//Polar operations
#define ADC_BIPOLAR 		0x00
#define ADC_UNIPOLAR 		0x04

//update rates
#define ADC_50 				0x04
#define ADC_60 				0x05
#define ADC_250 			0x06
#define ADC_500 			0x07
extern void TM7705_CaliSelf(unsigned char ch);
extern void adc_rest();
extern void adc1_init(unsigned char calmode, unsigned char gainsetting, unsigned char operation, unsigned char rate);
extern unsigned int adc1_read_value(unsigned char ch);
#endif

AD7705.C文件

#include "AD7705.h"
#include "driver/gpio.h"
enum
{

	REG_COMM	= 0x00,	//通信寄存器
	REG_SETUP	= 0x10,//设置寄存器
	REG_CLOCK	= 0x20,	//时钟寄存器
	REG_DATA	= 0x30,	//数据寄存器
	REG_ZERO_CH1	= 0x60,	//CH1偏移寄存器
	REG_FULL_CH1	= 0x70,//CH1满量程寄存器
	REG_ZERO_CH2	= 0x61,	//CH2偏移寄存器
	REG_FULL_CH2	= 0x71,	//CH2满量程寄存器

	WRITE 		= 0x00,	//写操作
	READ 		= 0x08,	//读操作

	CH_1		= 0,
	CH_2		= 1,
	CH_3		= 2,	
	CH_4		= 3	
};
enum
{
	CLKDIS_0	= 0x00,		//时钟输出使能
	CLKDIS_1	= 0x10,	//时钟禁止

	CLK_4_9152M = 0x08,//4.9152MHZ晶振
	CLK_2_4576M = 0x00,//2.456MHZ晶振
	CLK_1M 		= 0x04,
	CLK_2M 		= 0x0C,

	FS_50HZ		= 0x00,
	FS_60HZ		= 0x01,
	FS_250HZ	= 0x02,
	FS_500HZ	= 0x04,

	ZERO_0		= 0x00,
	ZERO_1		= 0x80
};
enum
{
	MD_NORMAL		= (0 << 6),	//正常模式
	MD_CAL_SELF		= (1 << 6),	//自校准模式
	MD_CAL_ZERO		= (2 << 6),	//标准零刻度模式
	MD_CAL_FULL		= (3 << 6),//标准满刻度模式

	GAIN_1			= (0 << 3),//增益
	GAIN_2			= (1 << 3),	//增益
	GAIN_4			= (2 << 3),//增益
	GAIN_8			= (3 << 3),//增益
	GAIN_16			= (4 << 3),	//增益
	GAIN_32			= (5 << 3),	//增益
	GAIN_64			= (6 << 3),//增益
	GAIN_128		= (7 << 3),//增益

	BIPOLAR			= (0 << 2),	//双极性输入
	UNIPOLAR		= (1 << 2),	//单极性输入

	BUF_NO			= (0 << 1),	
	BUF_EN			= (1 << 1),

	FSYNC_0			= 0,
	FSYNC_1			= 1		
};
/*通道1和通道2 的增益,输入缓冲,极性设置*/
#define _CH1_GAIN_BIPOLAR_BUF (GAIN_1|UNIPOLAR|BUF_EN)
#define _CH2_GAIN_BIPOLAR_BUF (GAIN_1|UNIPOLAR|BUF_EN)

void adc_delay(unsigned char NUM)	//延时函数		
	{
		for(;NUM>0;NUM--);		 
	}

void write_adc_byte(unsigned char chr)//写字节函数
{
	unsigned char i;

	for(i=0;i<8;i++)//循环写八次
	{
		if (chr & 0x80)//位与操作,写出数据
		{
			ADC_DI1;//SPI 数据MOSI 接口 按位输出
		}
		else
		{
			ADC_DI0;//SPI 数据MOSI 接口
		}
		ADC_CLK0;//时钟信号
		chr=chr<<1;//右移一位数据,循环按位写出数据
		ADC_CLK1;
	}
	//ADC_CLK1;
}

unsigned int read_adc_word()//读数据函数
{
	unsigned char i;
	unsigned int coder = 0;

	for(i=0;i<16;i++)//16位数据,循环读入两个字节
	{
		ADC_CLK0;//时钟信号
		adc_delay(1);
		coder = coder<<1;
		if(ADC_DO)coder+=1;	//检测引脚电平,读入数据	
		ADC_CLK1;
	}
	ADC_CLK1;
	return(coder);
}

void adc_rest()//AD 7705复位函数
{
	unsigned char i,j;
	ADC_DI1;
	ADC_CLK1; 
	ADC1_CS1;
	ADC_RESET1;
	for(i=200;i>0;i--)
		for(j=200;j>0;j--);	
	ADC_RESET0;
	for(i=400;i>0;i--)
		for(j=200;j>0;j--);	
	ADC_RESET1;
	for(i=200;i>0;i--)
		for(j=200;j>0;j--);	
	
}
void TM7705_CaliSelf(unsigned char ch)//自校准函数
{
	if(ch==1){
		ADC1_CS0;
		write_adc_byte(REG_SETUP|WRITE|CH_1);
		ADC1_CS1;
		adc_delay(10);
		ADC1_CS0;
		write_adc_byte(MD_CAL_SELF|_CH1_GAIN_BIPOLAR_BUF|FSYNC_0);
		ADC1_CS1;
		adc_delay(10);
		ADC1_CS0;
		while (ADC1_DRDY);
		ADC1_CS1;
		}
		else if(ch==2){
		ADC1_CS0;
		write_adc_byte(REG_SETUP|WRITE|CH_2);
		ADC1_CS1;
		adc_delay(10);
		ADC1_CS0;
		write_adc_byte(MD_CAL_SELF|_CH2_GAIN_BIPOLAR_BUF|FSYNC_0);
		ADC1_CS1;
		adc_delay(10);
		ADC1_CS0;
		while (ADC1_DRDY);
		ADC1_CS1;
		}


}
void adc1_init(unsigned char calmode, unsigned char gainsetting, unsigned char operation, unsigned char rate)
{
	ADC1_CS0;
	write_adc_byte(0xFF);
	write_adc_byte(0xFF);
	write_adc_byte(0xFF);
	write_adc_byte(0xFF);
	ADC1_CS1;
	adc_delay(100);
	ADC1_CS0;
	//write_adc_byte( 0x20 );//
	write_adc_byte( REG_CLOCK|WRITE|CH_1 );//
	ADC1_CS1;
	adc_delay(100); 
	ADC1_CS0;
	write_adc_byte( CLKDIS_0|CLK_4_9152M|FS_50HZ );//
	ADC1_CS1;
	TM7705_CaliSelf(1);
	TM7705_CaliSelf(2);
	adc_delay(100);
}

unsigned int adc1_read_value(unsigned char ch)
{
	unsigned int  value;
	if(!ADC1_DRDY)
	{
		ADC1_CS0;
		if(ch == 1)
      			write_adc_byte(0x38);//
   		else if(ch == 2)
      			write_adc_byte(0x39);//
		else    {ADC1_CS1;return 0;}
		ADC1_CS1;
		adc_delay(1);
		ADC1_CS0;
		value = read_adc_word();
		ADC1_CS1;
		return value;
	}
	else
	{
		return 0;
	}
}

main.c文件

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/gpio.h"
#include "AD7705.h"
void delay(unsigned int NUM)			
	{
	unsigned int i;
	unsigned char j;
	for(i=NUM;i>0;i--)
		for(j=200;j>0;j--);		 
	}
void app_main(void)
{  int volt1,volt2;
     unsigned char i,stat=0x03;
unsigned int temp1,temp2,ADcode1,ADcode2;

    //Initialize non-SPI GPIOs
    gpio_set_direction(ADC_CLK, GPIO_MODE_OUTPUT);
    gpio_set_direction(ADC_RESET, GPIO_MODE_OUTPUT);
      gpio_set_direction(ADC1_CS, GPIO_MODE_OUTPUT);
    gpio_set_direction(ADC_DI, GPIO_MODE_OUTPUT);
    gpio_set_pull_mode(ADC_DO1,GPIO_PULLUP_ENABLE);
     gpio_set_direction(ADC_DO1, GPIO_MODE_INPUT);
    gpio_set_direction(ADC1_DRDY1, GPIO_MODE_INPUT);

    adc_rest();
    adc1_init(ADC_SELF,ADC_GAIN_128,ADC_BIPOLAR,ADC_50);
    TM7705_CaliSelf(1);
     temp1 = adc1_read_value(1);
     TM7705_CaliSelf(2);
     temp2 = adc1_read_value(2);
     while(1){
     printf("初始化代码\n");
    vTaskDelay(500/ portTICK_PERIOD_MS);
     temp1 = adc1_read_value(1);
     volt1=((int)temp1*5000)/65536;
    printf("channel1:   %d    V:%d\n",temp1,volt1);
       vTaskDelay(500/ portTICK_PERIOD_MS);
     temp2 = adc1_read_value(2);
    volt2=((int)temp2*5000)/65536;
    printf("channel2:   %d    V:%d\n",temp2,volt2);
    }
}