找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6754|回復(fù): 4
打印 上一主題 下一主題
收起左側(cè)

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

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:882386 發(fā)表于 2021-2-2 20:19 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
最近打算做俱arduino的“高精度”數(shù)控電源,但arduino的ADC只有10位,精度遠(yuǎn)遠(yuǎn)不夠,網(wǎng)上亂看,發(fā)現(xiàn)了便宜、好用的12位雙通道ADC模塊-TM7705,模塊的價格只要6元錢。
網(wǎng)上找了一圈,只找到了一個很遠(yuǎn)古的spi讀寫庫。我的板子已經(jīng)打好,spi接口不太方便用,就參考了網(wǎng)上的資料,順帶學(xué)習(xí)了tm7705的數(shù)據(jù)手冊,寫了個軟spi的讀定程序。程序加了詳細(xì)的注釋,結(jié)合數(shù)據(jù)手冊,其實這個程序也是一個學(xué)習(xí)根據(jù)手冊時序,自己寫外設(shè)驅(qū)動例子。搞懂了,以后碰到?jīng)]有現(xiàn)成庫的外設(shè)(如LCD、DAC、ADC等等),也可以自己寫,不用求人了。

剛學(xué)習(xí)arduino,寫得不規(guī)范,僅供參考。




/*軟件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板子共地,不然有嚴(yán)重干擾。
*/

//----聲明引腳--------------
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)  //將數(shù)據(jù)dat1寫入TM7705,CLK下降沿寫
{
  unsigned char i;
  digitalWrite(SCLK_TM7705, 1); //拉高時鐘
  digitalWrite(LE_TM7705, 0); //片選
  delayMicroseconds(1);
  for (i = 0; i < 8; i++)      //寫8位數(shù)據(jù)
  {
    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位數(shù)據(jù),在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是否已經(jīng)就緒------------------
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個時鐘用于軟件復(fù)位,
   然后發(fā)寄存器配置指令,在自校準(zhǔn)后需要200MS的延時后才能接收到有效的輸出數(shù)據(jù),且每次通道
   切換都要進(jìn)行自校準(zhǔn)(即每次切換都要等待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數(shù)據(jù)的IO,應(yīng)該是輸入口,pinmode設(shè)置為input_pullup,空閑時為高
//  digitalWrite(DRDY_TM7705, 1);
  //-------------step:1----------------------
  for (i = 0; i < 40; i++)     //連續(xù)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需設(shè)置CLKDIV=0,CLK=1
  //write_byte_TM7705(0x08);    //20HZ(0 0 0 0 1 0 0 0)  若晶振為2MHZ需設(shè)置CLKDIV=1,CLK=0
  write_byte_TM7705(0x0c);      //50HZ(0 0 0 0 1 1 0 0)  若晶振為4.9152MHZ需設(shè)置CLKDIV=1,CLK=1,頻率50HZ。
  //------------step:3.寫設(shè)置寄存器----------------------------------
  write_byte_TM7705(0x10 | channel);   //通道1(0 0 0 1 0 0 0 0),寫通訊寄存器下一步寫設(shè)置寄存器
  //write_byte_TM7705(0x44);   //寫入設(shè)置寄存器(0 1 0 0 0 1 0 0),自校準(zhǔn)模式0 1,1倍增益0 0 0,單極性B/U=1,buf串聯(lián)設(shè)置為0,F(xiàn)SYNC=0;
  //write_byte_TM7705(0x40);   //寫入設(shè)置寄存器(0 1 0 0 0 0 0 0),自校準(zhǔn)模式0 1,1倍增益0 0 0,雙極性B/U=0,buf串聯(lián)設(shè)置為0,F(xiàn)SYNC=0;
  write_byte_TM7705(0x44);     //寫入設(shè)置寄存器(0 1 0 0 0 1 0 0),自校準(zhǔn)模式0 1,1倍增益0 0 0,單極性B/U=0,buf串聯(lián)設(shè)置為0,F(xiàn)SYNC=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);

}

評分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏9 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

沙發(fā)
ID:288629 發(fā)表于 2021-2-3 11:30 | 只看該作者
12位的AD,很多單片機都集成了啊,不用單配吧
回復(fù)

使用道具 舉報

板凳
ID:880257 發(fā)表于 2021-2-8 09:35 | 只看該作者
正在搜索ADC+Arduino相關(guān)資料,多謝樓主!
回復(fù)

使用道具 舉報

地板
ID:882386 發(fā)表于 2021-2-8 09:55 | 只看該作者
wjcxy3166 發(fā)表于 2021-2-3 11:30
12位的AD,很多單片機都集成了啊,不用單配吧

是16位的,帖子里寫錯了。

12位的只能分辨4069位,我的數(shù)控電源需要測量1mv-20V,12位的ADC不夠 。
回復(fù)

使用道具 舉報

5#
ID:115923 發(fā)表于 2021-2-8 12:20 | 只看該作者
TM7705 是應(yīng)用于低頻測量的 2/3 通道的模擬前端。該器件可以接受直接來自傳感器的低電平的輸入信號,然后產(chǎn)生串行的數(shù)字輸出。利用 Σ-Δ 轉(zhuǎn)換技術(shù)實現(xiàn)了 16 位無丟失代碼性能
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機教程網(wǎng)

快速回復(fù) 返回頂部 返回列表