找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5684|回复: 4
打印 上一主题 下一主题
收起左侧

便宜、好用的12位双通道ADC模块-TM7705源程序

  [复制链接]
跳转到指定楼层
楼主
最近打算做俱arduino的“高精度”数控电源,但arduino的ADC只有10位,精度远远不够,网上乱看,发现了便宜、好用的12位双通道ADC模块-TM7705,模块的价格只要6元钱。
网上找了一圈,只找到了一个很远古的spi读写库。我的板子已经打好,spi接口不太方便用,就参考了网上的资料,顺带学习了tm7705的数据手册,写了个软spi的读定程序。程序加了详细的注释,结合数据手册,其实这个程序也是一个学习根据手册时序,自己写外设驱动例子。搞懂了,以后碰到没有现成库的外设(如LCD、DAC、ADC等等),也可以自己写,不用求人了。

刚学习arduino,写得不规范,仅供参考。




/*软件spi 输入双通道12位ADC Tm7705
  arduino nano +  Tm7705模块。   工具->arduino nano  处理器 -> Atmega328p (old bootloader)
  (CS)  LE   -> PC1(D10)pc1(a1)
  (DIN) DIN  -> PC2(D11)pc2(a2)
  (SCK) CLK  -> PC0(D13)PC0(A0)
  (DOUT)DOUT -> PC3(D12)PC3(a3)
  arduino nano 需要与tm7705板子共地,不然有严重干扰。
*/

//----声明引脚--------------
int  SCLK_TM7705 = A0;
int  DIN_TM7705 = A2;
int  DOUT_TM7705 = A3;
int  LE_TM7705 = A1;
//int  DRDY_TM7705 = 5; //DRDY既可以专门用1个IO读,也可以读通信寄存器的最高位。此程序采用读寄存器方法,省一个IO口。


unsigned char n, temp1, temp2;
unsigned int V_adc0, V_adc1;
float v0, v1;
int errDRDY = 0;



//   ---------------------------------------------------

void write_byte_TM7705(unsigned char dat1)  //将数据dat1写入TM7705,CLK下降沿写
{
  unsigned char i;
  digitalWrite(SCLK_TM7705, 1); //拉高时钟
  digitalWrite(LE_TM7705, 0); //片选
  delayMicroseconds(1);
  for (i = 0; i < 8; i++)      //写8位数据
  {
    digitalWrite(SCLK_TM7705, 0); //下降沿
    delayMicroseconds(1);
    if (dat1 & 0x80)
    {
      digitalWrite(DIN_TM7705, 1);
    }   //先写高位
    else
    { //再写低位
      digitalWrite(DIN_TM7705, 0);
    }

    delayMicroseconds(1);
    digitalWrite(SCLK_TM7705, 1);  //时钟空闲时,置高电平。
    delayMicroseconds(1);
    dat1 <<= 1; //下一位
  }
  digitalWrite(SCLK_TM7705, 1); //时钟空闲,高。
  digitalWrite(DIN_TM7705, 1); //输入脚,置高。(抗干扰)
  digitalWrite(LE_TM7705, 1); //

}

unsigned char read_byte_TM7705()   //从TM7705寄存器读8位数据,在DOUT_TM7705上读。
{
  unsigned char i, read_dat, dat2 = 0;
  digitalWrite(SCLK_TM7705, 1);  //时钟空闲,高。
  delayMicroseconds(1);
  digitalWrite(LE_TM7705, 0); //片选
  for (i = 0; i < 8; i++)
  {
    digitalWrite(SCLK_TM7705, 0); //下降沿
    delayMicroseconds(1);
    read_dat = digitalRead(DOUT_TM7705);
    dat2 = (dat2 << 1) | read_dat; // 高位先读
    delayMicroseconds(1);
    digitalWrite(SCLK_TM7705, 1);  //时钟空闲,高。
    delayMicroseconds(1);
  }
  digitalWrite(SCLK_TM7705, 1);  //时钟空闲,高。
  digitalWrite(LE_TM7705, 1); //
  return dat2;
}

//------------通过读“通信寄存器”的DRDY位是否0,来判断DRDY是否已经就绪------------------
bool DRDY_OK() {
  unsigned char rd = 1;

  errDRDY = 0;

  while (rd) {

    write_byte_TM7705(B00001000);   //写通讯寄存器下一步读通信寄存器
    delayMicroseconds(10);
    rd =  read_byte_TM7705();
    rd = (rd >> 7) & B00000001; //取通讯寄存器第1位(DRDY)
    errDRDY++;
    delayMicroseconds(1);
    if (errDRDY > 1000) {
      Serial.println("----errDRDY---");
      return 0;
    }
  }
  return 1;
}

//----------通过IO读DRDY电平是否0,判断是否就绪,此程序不用--------------------
/*
bool IO_DRDY_OK() {

  unsigned char rd = 1;

  errDRDY = 0;

  while (rd) {
    rd = digitalRead(DRDY_TM7705);

    delayMicroseconds(10);
    if (errDRDY > 1000) {

      Serial.println("----errDRDY---");
      return 0;
    }
  }
  return 1;
}

*/
//----------------------------------------------------
/*

   在写程序时SCLK管脚的高、低电平的延时都要大于2US,程序流程大致上电40个时钟用于软件复位,
   然后发寄存器配置指令,在自校准后需要200MS的延时后才能接收到有效的输出数据,且每次通道
   切换都要进行自校准(即每次切换都要等待200MS)。
*/
void TM7705_init(byte channel)  //channel1:0   channel2:1
{
  char i;
  digitalWrite(SCLK_TM7705, 1);  //时钟空闲,高。
  digitalWrite(DIN_TM7705, 1);  //
  digitalWrite(DOUT_TM7705, 1);  //此脚为arduino读tm7705数据的IO,应该是输入口,pinmode设置为input_pullup,空闲时为高
//  digitalWrite(DRDY_TM7705, 1);
  //-------------step:1----------------------
  for (i = 0; i < 40; i++)     //连续40个下降沿
  {
    digitalWrite(SCLK_TM7705, 0); //下降沿
    delayMicroseconds(1);
    digitalWrite(SCLK_TM7705, 1); //下降沿
    delayMicroseconds(1);
  }
  delayMicroseconds(1000);
  delayMicroseconds(1);
  //------------step:2.写时钟寄存器----------------------------------
  write_byte_TM7705(0x20);    //通道1和2共用(0 0 1 0 0 0 0 0),写通讯寄存器下一步写时钟寄存器
  //write_byte_TM7705(0x04);    //50HZ(0 0 0 0 0 1 0 0)  若晶振为2.4576MHZ需设置CLKDIV=0,CLK=1
  //write_byte_TM7705(0x08);    //20HZ(0 0 0 0 1 0 0 0)  若晶振为2MHZ需设置CLKDIV=1,CLK=0
  write_byte_TM7705(0x0c);      //50HZ(0 0 0 0 1 1 0 0)  若晶振为4.9152MHZ需设置CLKDIV=1,CLK=1,频率50HZ。
  //------------step:3.写设置寄存器----------------------------------
  write_byte_TM7705(0x10 | channel);   //通道1(0 0 0 1 0 0 0 0),写通讯寄存器下一步写设置寄存器
  //write_byte_TM7705(0x44);   //写入设置寄存器(0 1 0 0 0 1 0 0),自校准模式0 1,1倍增益0 0 0,单极性B/U=1,buf串联设置为0,FSYNC=0;
  //write_byte_TM7705(0x40);   //写入设置寄存器(0 1 0 0 0 0 0 0),自校准模式0 1,1倍增益0 0 0,双极性B/U=0,buf串联设置为0,FSYNC=0;
  write_byte_TM7705(0x44);     //写入设置寄存器(0 1 0 0 0 1 0 0),自校准模式0 1,1倍增益0 0 0,单极性B/U=0,buf串联设置为0,FSYNC=0;
  delay(200);

}

//-----------------------------------------------------
unsigned int readADC(byte channel) {
  unsigned int rd = 0;
  //  if (IO_DRDY_OK()) {
  if (DRDY_OK()) {
    write_byte_TM7705(0x38 | channel); //(0b00111000读通道0)
    delayMicroseconds(1);
    rd = read_byte_TM7705(); //先读高8位
    rd = (rd << 8) | read_byte_TM7705(); //再读低8位
    delayMicroseconds(1);
    return rd;
  }
  else
  {
    Serial.println("--errDRDY------");
    return -1;
  }

}



//-------------------------------------------------
void setup() {
  pinMode(SCLK_TM7705, OUTPUT);
  pinMode(DIN_TM7705, OUTPUT);
  pinMode(DOUT_TM7705, INPUT_PULLUP);
  pinMode(LE_TM7705, OUTPUT);
//  pinMode(DRDY_TM7705, INPUT_PULLUP);

  TM7705_init(0);
  delayMicroseconds(50);
  TM7705_init(1);
  Serial.begin(9600);


}

void loop() {

  // put your main code here, to run repeatedly:

  V_adc0 = readADC(0);
  v0 = 5 * (V_adc0 / 65535.0);
  Serial.println(V_adc0);
  Serial.println(v0, 6);
  Serial.println("========");


  V_adc1 = readADC(1);
  v1 = 5 * (V_adc1 / 65535.0);

  Serial.println(V_adc0);
  Serial.println(v0, 6);
  Serial.println("========");

  delay(1000);

}

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏9 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:288629 发表于 2021-2-3 11:30 | 只看该作者
12位的AD,很多单片机都集成了啊,不用单配吧
回复

使用道具 举报

板凳
ID:880257 发表于 2021-2-8 09:35 | 只看该作者
正在搜索ADC+Arduino相关资料,多谢楼主!
回复

使用道具 举报

地板
ID:882386 发表于 2021-2-8 09:55 | 只看该作者
wjcxy3166 发表于 2021-2-3 11:30
12位的AD,很多单片机都集成了啊,不用单配吧

是16位的,帖子里写错了。

12位的只能分辨4069位,我的数控电源需要测量1mv-20V,12位的ADC不够 。
回复

使用道具 举报

5#
ID:115923 发表于 2021-2-8 12:20 | 只看该作者
TM7705 是应用于低频测量的 2/3 通道的模拟前端。该器件可以接受直接来自传感器的低电平的输入信号,然后产生串行的数字输出。利用 Σ-Δ 转换技术实现了 16 位无丢失代码性能
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表