(文章目錄)
一、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個到第24個SCLK,讀取ADC數據。如果不需要配置寄存器或者讀取寄存器,可以省略下面的步驟。
- 第25個到第26個SCLK,讀取寄存器寫操作狀態。
- 第27個SCLK,把DOUT DRDY/輸出拉高。
- 第28個到第29個SCLK,切換DOUT DRDY/為輸入。
- 第30個到第36個SCLK,輸入寄存器寫或讀命令字數據(高位先輸入)。
- 第37個SCLK,切換DOUT DRDY/的方向(如果是寫寄存器,DOUT DRDY/為輸入;如果是讀寄存器,DOUT DRDY/為輸出)。
- 第38個到第45個SCLK,輸入寄存器配置數據或輸出寄存器配置數據(高位先輸入/輸出)。
- 第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。
最後,如需源碼,點贊收藏+關注,評論留言!!!