(文章目錄)

一、CS1237簡介

  CS1237是一款高精度、低功耗Sigma-Delta模數轉換芯片,內置一路Sigma-Delta ADC,一路差分輸入通道和一路温度傳感器,ADC採用兩階sigma delta 調製器,通過低噪聲儀用放大器結構實現PGA放大,放大倍數可選:1、2、64、128。在PGA=128時,有效分辨率可達20位(工作在5V)。 CS1237內置RC振盪器,無需外置晶振。   CS1237可以通過DOUT DRDY/和SCLK進行多種功能模式的配置,例如用作温度檢測、PGA選擇、ADC數據輸出速率選擇等等。 具有Power down模式。 主要特性

  • 供電電壓:3.3 / 5V
  • 內置晶振
  • 集成温度傳感器
  • 帶Power down功能
  • 2線SPI接口,最快速率為1.1MHz

ADC功能特性:

  • 24位無失碼
  • PGA放大倍數可選:1、2、64、128
  • 1路24位無失碼的差分輸入,在PGA=128時ENOB為20位(5V) \ 19.5位(3.3V)
  • P-P噪聲:PGA=128、10Hz:180nV;
  • INL小於0.0015%
  • 輸出速率可選:10Hz、40Hz、640Hz、1.28kHz
  • 帶內短功能

應用場景

  • 工業過程控制
  • 電子秤
  • 液體/氣體化學分析
  • 血液計
  • 智能變換器
  • 便攜式設備

二、引腳説明

DVDD 電源正極(3 - 5V)
DGND 電源負極
AVDD 基準源輸入正
AGND 基準源輸入負
SCLK SPI時鐘輸入
DOUT SPI數據輸入/輸出
A+ 通道正輸入
A- 通道負輸入

  基準源輸入説明:基準電壓可以由外部輸入也可是內部輸出,如果要使用外部基準電壓,要先關閉內部基準,內部基準控制由寄存器(refo_off)控制。

三、讀寫時序和數據輸出格式説明

讀寫參數配置過程簡述,在DOUT DRDY/由高變低之後:

  1. 第1個到第24個SCLK,讀取ADC數據。如果不需要配置寄存器或者讀取寄存器,可以省略下面的步驟。
  2. 第25個到第26個SCLK,讀取寄存器寫操作狀態。
  3. 第27個SCLK,把DOUT DRDY/輸出拉高。
  4. 第28個到第29個SCLK,切換DOUT DRDY/為輸入。
  5. 第30個到第36個SCLK,輸入寄存器寫或讀命令字數據(高位先輸入)。
  6. 第37個SCLK,切換DOUT DRDY/的方向(如果是寫寄存器,DOUT DRDY/為輸入;如果是讀寄存器,DOUT DRDY/為輸出)。
  7. 第38個到第45個SCLK,輸入寄存器配置數據或輸出寄存器配置數據(高位先輸入/輸出)。
  8. 第46個SCLK,切換DOUT DRDY/為輸出,並把DOUT DRDY/拉高。update1/ update2被置位或清零。

讀數據   CS1237可以持續的轉換模擬輸入信號,當將DOUT DRDY/拉低後,表明數據已經準備好接受,輸入的第一個SCLK來就可以將輸出的最高位讀出,在24個SCLK後將所有的24位數據讀出,如果這時暫停SCLK的發送,DOUT DRDY/會保持着最後一位的數據,直到其被拉高,第25和26個SCLK輸出配置寄存器是否有寫操作標誌,第25個SCLK對應的DOUT DRDY/為1時表明配置寄存器Config被寫入了新的值,第26個SCLK對應的DOUT DRDY/為芯片擴展保留位,目前輸出一直為0,通過第27個SCLK可以將DOUT DRDY/拉高,此後當DOUT DRDY/被再次拉低,表示新的數據已經準備好接受,進行下一個數據的轉換。

數據輸出格式   CS1237輸出的數據為24位的2進制補碼,最高位(MSB)最先輸出。最小有效位(LSB)為(0.5VREF/Gain)/(2^23-1)。正值滿幅輸出碼為7FFFFFH,負值滿幅輸出碼為800000H。下表為不同模擬輸入信號對應的理想輸出碼。 根據上表可知,不同的增益,輸入信號Vin範圍也不同。

PGA VIN+ - VIN-
1 ±1.25V
2 ±0.625V
64 ±0.01953125V
128 ±0.009765625V

注意:因為 CS1237 內部的前置放大器和 Σ-Δ 調製器都需要一個共模電壓範圍 (Vcm),所以輸入信號要滿足以下三個條件,有一個條件不符合,輸出可能就會不正常。   差分電壓:|AIN+ - AIN-| ≤ Vref / 2 x Gain。   共模電壓:Vcm = (AIN+ + AIN-) / 2,Vcm最好接近Vref / 2。   AIN+,AIN-的輸入電壓:DGND ≤ AINx ≤ DVDD。

四、寄存器説明

讀寫參數配置,需要通過7bits 命令字去配置。 CS1237只有一組Config寄存器

五、電壓和温度換算

電壓的換算:   CS1237 是 24 位ADC,輸出 24 位補碼格式的數據,代表輸入的差分電壓:Vin(diff)​=AIN+ − AIN−。 其輸出碼值範圍為:   正滿量程:理論輸出碼為+8,388,607 (0x7FFFFF),對應輸入電壓為+Vref / 2x增益。   負滿量程:理論輸出碼為-8,388,608 (0x800000),對應輸入電壓為-Vref / 2x增益。   即換算有符號的數據公式:Vin(diff)​=輸出碼值 / 2^23 x Vref / 2x增益。

温度的換算:   測量內部温度時,需要先校準再測量,芯片沒有出廠校準,必須用兩個已知温度點進行標定。注意:測量温度時,AIN+、AIN- 對外引腳無效,即採集不了輸入信號。

六、STM32F103驅動CS1237

準備工作

  STM32F103C8T6最小系統板,CS1237 ADC模數轉換模塊,OLED顯示模塊等

接線説明

STM32F103 CS1237
3.3V DVDD
GND DGND
PA0 SLCK
PA1 DOUT
PB8 OLED->SLC
PB9 OLED->SDA
A + - A- 差分信號

示例代碼

CS1237.c

#include "cs1237.h"

void CS1237_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	GPIO_ResetBits(GPIOA, GPIO_Pin_0);
}

void CS1237_DOUT_Input(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
}

void CS1237_DOUT_Output(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
}

int8_t CS1237_WirteByte(uint8_t data)  //寫配置
{
	uint8_t i;
	uint32_t t=0;
	
	CS1237_DOUT_Input();
	
	while (DOUT_READ != 0)		//超時
	{
		if((t += 5) > CS1237_DEFAULT_TIMEOUT_US)
			return -1;
	}
	
	for (i = 0; i < 26; i++) {	//1-26 SCLK
        CS1237_SCLK_H
		Delay_us(2);
        CS1237_SCLK_L
		Delay_us(2);
    }
	
	CS1237_DOUT_Output();	//27 SCLK
	CS1237_DOUT_H 
	CS1237_SCLK_H
	Delay_us(2);
	CS1237_SCLK_L
	Delay_us(2);
		
	for (i = 0; i < 2; i++) {	//28-29 SCLK
		CS1237_SCLK_H
		Delay_us(2);
        CS1237_SCLK_L
		Delay_us(2); 
    }
	
	for (i = 0; i < 7; i++) {	//30-36 SCLK
        if (CS1237_WRITE_REG & (0x40 >> i)) CS1237_DOUT_H  
        else CS1237_DOUT_L
        CS1237_SCLK_H
		Delay_us(2);
		CS1237_SCLK_L
		Delay_us(2);
    }
		
	CS1237_SCLK_H		//37 SCLK
	Delay_us(2);
	CS1237_SCLK_L
	Delay_us(2);
	
	for (i = 0; i < 8; i++) {	//38-45 SCLK
        if (data & (0x80 >> i)) CS1237_DOUT_H
        else CS1237_DOUT_L
        CS1237_SCLK_H
		Delay_us(2);
		CS1237_SCLK_L
		Delay_us(2);
    }

	CS1237_DOUT_H
	CS1237_DOUT_Input();	//46 SCLK
	CS1237_SCLK_H
	Delay_us(2);
	CS1237_SCLK_L
	Delay_us(2);
	
	return 0;
}

int8_t CS1237Reg(uint8_t *out)  //讀配置
{ 
	uint8_t i;
	uint32_t t=0;
	uint8_t Data = 0x00;
	
	CS1237_DOUT_Input();
	
	while (DOUT_READ != 0)	//超時
	{
		if((t += 5) > CS1237_DEFAULT_TIMEOUT_US)
			return -1;
	}
	
	for (i = 0; i < 26; i++) {	//1-26 SCLK
        CS1237_SCLK_H
		Delay_us(2);
        CS1237_SCLK_L
		Delay_us(2);
    }
	
	CS1237_DOUT_Output();	
	CS1237_DOUT_H
	CS1237_SCLK_H	//27 SCLK
	Delay_us(2);
	CS1237_SCLK_L
	Delay_us(2);
		
	for (i = 0; i < 2; i++) {	//28-29 SCLK
		CS1237_SCLK_H
		Delay_us(2);
        CS1237_SCLK_L
		Delay_us(2); 
    }

	for (i = 0; i < 7; i++) {	//30-36 SCLK
        if (CS1237_READ_REG & (0x40 >> i)) CS1237_DOUT_H  
        else CS1237_DOUT_L
        CS1237_SCLK_H
		Delay_us(2);
		CS1237_SCLK_L
		Delay_us(2);
    }
	
	CS1237_DOUT_Input(); //37 SCLK
	CS1237_SCLK_H
	Delay_us(2);
	CS1237_SCLK_L
	Delay_us(2);
	
	for (i = 0; i < 8; i++) {	//38-45 SCLK
		CS1237_SCLK_H
		Delay_us(2);
        Data = ((Data << 1) | (DOUT_READ ? 1 : 0));
		CS1237_SCLK_L
		Delay_us(2);
    }

	CS1237_DOUT_Output();
	CS1237_DOUT_H
	CS1237_SCLK_H
	Delay_us(2);
	CS1237_SCLK_L
	Delay_us(2);
	
	*out = Data;
	
	return 0;
}

int8_t CS1237_ReadRaw24(int32_t *signed_out)
{
    uint8_t i;
    uint32_t raw = 0;
    uint32_t t = 0;

    CS1237_DOUT_Input();
	
	while (DOUT_READ != 0)	//超時
	{
		Delay_us(2);
		if((t += 10) > CS1237_DEFAULT_TIMEOUT_US)
			return -1;
	}

    for (i = 0; i < 24; i++) {
        CS1237_SCLK_H
		Delay_us(2);
        raw = (raw << 1) | (DOUT_READ ? 1 : 0);
        CS1237_SCLK_L
		Delay_us(2);
    }

    for (i = 0; i < 2; i++) {
		CS1237_SCLK_H
		Delay_us(2);
        CS1237_SCLK_L
		Delay_us(2); 
    }

    raw &= 0xFFFFFFUL;
    if (raw & (1UL << 23)) *signed_out = (int32_t)(raw | 0xFF000000UL);
    else *signed_out = (int32_t)raw;

    return 0;
}

float CS1237_Temperature(uint32_t Yb)
{
	int8_t error;
	float tempB;
	
	error = CS1237_WirteByte(0x02);
	
	if(error != 0)	OLED_ShowString(4, 1, "ERROR3");
	
	tempB = ((float)Yb * (273.15f + CS1237_TEMPA)) / ((float)CS1237_YA - 273.15f);  //單位℃
	
	return tempB;
}

main.c

#include "stm32f10x.h"
#include "delay.h"
#include "oled.h"
#include "cs1237.h"

uint8_t status;
int32_t val;
float diff_V, Temp;
uint8_t gain_table[4] = {1, 2, 64, 128};	//設置不同增益,輸入差分範圍也不一樣,1:±1.25V;2:±0.625V;64:±0.01953125V;128:±0.009765625V

int main(void)
{
	OLED_Init();
	CS1237_Init();
	Delay_ms(100);
	
	OLED_ShowString(1, 1, "CS1237");
	OLED_ShowString(3, 4, "000.000V");
//	OLED_ShowString(4, 4, "0000.00");	//温度顯示
	
	CS1237_WirteByte(0x00);
	Delay_ms(100);
	
	if(CS1237Reg(&status) == 0)
	{
		OLED_ShowString(1, 10, "0x");
		OLED_ShowHexNum(1,12,status,2);
	}else{
		OLED_ShowString(1, 10, "ERROR1");
	}
	
	while (1)
	{
        if (CS1237_ReadRaw24(&val) == 0) {
//            OLED_ShowSignedNum(4,1,val,7);
//			
			diff_V = ((float)val / 8388607.0f) * (1.25f / (float)gain_table[(status>>2) & 0x03]);
			
			OLED_ShowSignedFloat(3,4,diff_V,2,3);
			Delay_ms(100);
        } else {
            OLED_ShowString(3,4," ERROR2 ");
        }
		
		//温度檢測
//		Temp = CS1237_Temperature(val);
//		OLED_ShowSignedFloat(4,4,Temp,3,2);
//		Delay_ms(100);
	}
}

效果展示

圖一:A+接1.2V,A-接1.496V;圖二:A+接1.815V,A-接1.2V。

七、常見問題説明

Q:CS1237/CS1238 主要適用領域有哪些? A:CS1237/CS1238是針對橋式傳感器的低成本解決方案。一般應用於稱重測量、壓力測量等細分領域。如下圖所示:

Q:除了橋式傳感器,CS1237/CS1238 還適用於其它應用領域嗎? A:取決於 AINP/AINN 端口的差分信號範圍以及共模電壓範圍是否滿足 Datasheet 的要求。如下圖所示:

Q:CS1237/CS1238 是否有單次轉換模式? A:否。CS1237/CS1238 只有連續轉換模式。

Q:CS1237/CS1238 是否可以單端輸入模式(AINN 接地)? A:如問題 2 所述,輸入信號需要滿足共模與差模範圍,一般情況下不建議單端輸入的應用使用該系列產品。當 PGA=64/128 時,不允許 AINP 或 AINN 直接接地,否則測量信號異常;當PGA=1/2 時,由於 Buffer 開啓的緣故,單端輸入阻抗不宜太大(建議前端電路的輸出阻抗幾十歐姆以下),否則會影響線性。

Q:CS1237/CS1238 的工作電壓範圍是多少?為什麼數據手冊裏面描述 4.5-5.5V、3.0V-3.6V 的? A: 1、工作電壓範圍是 2.7V~5.5V。   2、數據手冊描述的是兩個典型電壓值(5V/3.3V)的工作電流,並不是只能工作在這兩個電壓區間。

Q:CS1237/CS1238 上電默認配置是什麼? A:上電默認配置是 PGA=128、DataRate=10Hz。

Q:CS1237/CS1238 的外置參考電壓是否可以高於 VDD? A:不可以。外置參考電壓需滿足條件:REFIN=1.5V~VDD。舉例:橋式傳感器的應用不允許傳感器激勵源以及參考輸入使用 5.0V,而 VDD 使用 3.3V。

Q:在橋式傳感器應用裏,為什麼 REFIN 與 REFOUT 連在一起? A:使用傳感器的激勵源作為 ADC 的參考源,(橋式傳感器應用)可以有效抑制漂移,降低系統對參考源的要求。其中 REFIN 為參考源輸入,REFOUT 為傳感器激勵源。對於一般應用,兩者通常連在一起,可以通過 REFOUT 引腳控制激勵源的開啓/關閉。如果系統使用外部激勵源/參考源,則懸空 REFOUT 引腳即可,因此並不規定 REFIN 引腳必須與REFOUT 引腳連在一起。

Q:CS1237/CS1238 是否內置參考電壓源? A:否。CS1237/CS1238 的 REFOUT 引腳輸出的激勵信號為 VDD,起到控制激勵源的作用。如有必要可以進入休眠模式,關閉激勵源節省橋式傳感器功耗。如下圖所示: Q:實際應用中,多個稱重傳感器應該怎麼與 ADC 連接? A:如果傳感器是測量同一物體(例如:廚房垃圾處理器),一般建議使用並聯的方式。則相同類型的信號線連接在一起。對於傳感器的要求是產品規格儘量一致,尤其是靈敏度需要一致,否則會導致偏載問題。如果使用 REFOUT 引腳輸出 VS,需要注意傳感器的激勵電流是否在合理範圍內。舉例:   如果系統不是測量同一個物體,則傳感器單獨連接不同的模擬通道或不同的 ADC。

最後,如需源碼,點贊收藏+關注,評論留言!!!