一、简介:
CS1237是芯海科技的一款高精度24位Σ-Δ模数转换器,采用SOP8封装,专为低功耗高精度采集场景设计。
二、主要技术参数:
-
分辨率:24位无失码
-
封装:SOP8(体积小,适合紧凑型PCB)
-
接口:2线制串行通信(DOUT/SCLK),兼容SPI模式
-
增益:可选PGA增益(1/2/64/128倍)
-
输出速率:10Hz / 40Hz / 640Hz / 1.28kHz可编程
-
功耗:工作电流约1.5mA,休眠模式<0.1μA
三、主要应用:
工业过程控制
电子秤
液体/气体化学分析
血液计
智能变换器
便携式设备
四、硬件接口:


五、内部原理框图:

六、头文件:
#ifndef __CS1237_HAL_H
#define __CS1237_HAL_H
#include "stm32l0xx_hal.h" // 以STM32L0系列为例,L1/L4类似
/* 硬件抽象结构体:使用时必须实例化并赋值具体引脚 */
typedef struct {
GPIO_TypeDef* sclk_port; // SCLK GPIO端口
uint16_t sclk_pin; // SCLK引脚号
GPIO_TypeDef* dout_port; // DOUT GPIO端口
uint16_t dout_pin; // DOUT引脚号
} CS1237_HAL_GPIO;
/* 命令定义 */
#define CS1237_CMD_READ 0x25 // 读数据
#define CS1237_CMD_WRITE_REG 0x65 // 写寄存器
#define CS1237_CMD_READ_REG 0xA5 // 读寄存器
/* 配置寄存器位定义 */
#define CS1237_CH_AIN1 0x00 // 通道选择
#define CS1237_CH_TEMP (0x01 << 5)
#define CS1237_CH_SHORT (0x02 << 5)
#define CS1237_CH_AIN2 (0x03 << 5)
#define CS1237_PGA_1 0x00 // 增益
#define CS1237_PGA_2 (0x01 << 3)
#define CS1237_PGA_64 (0x02 << 3)
#define CS1237_PGA_128 (0x03 << 3)
#define CS1237_SPEED_10HZ 0x00 // 输出速率
#define CS1237_SPEED_40HZ (0x01 << 1)
#define CS1237_SPEED_640HZ (0x02 << 1)
#define CS1237_SPEED_1K28 (0x03 << 1)
/* 硬件抽象接口函数 */
void CS1237_HAL_DelayUs(uint32_t us); // 微妙级延时(需基于TIM或SysTick实现)
void CS1237_HAL_SetSCLK(CS1237_HAL_GPIO* gpio, uint8_t level);
void CS1237_HAL_InitDOUT_Input(CS1237_HAL_GPIO* gpio);
uint8_t CS1237_HAL_ReadDOUT(CS1237_HAL_GPIO* gpio);
/* 驱动层函数(由具体驱动实现) */
uint8_t CS1237_Init(CS1237_HAL_GPIO* gpio);
uint8_t CS1237_IsReady(CS1237_HAL_GPIO* gpio);
int32_t CS1237_ReadADC(CS1237_HAL_GPIO* gpio);
uint8_t CS1237_WriteConfig(CS1237_HAL_GPIO* gpio, uint8_t config);
uint8_t CS1237_ReadConfig(CS1237_HAL_GPIO* gpio, uint8_t* config);
#endif
七、源文件:
#include "cs1237_hal.h"
/* 等待DOUT变为低电平(表示数据就绪)超时值 */
#define CS1237_TIMEOUT_US 100000
/* 初始化:验证通信是否正常 */
uint8_t CS1237_Init(CS1237_HAL_GPIO* gpio) {
uint8_t cfg = 0;
// 复位通信时序:至少30个SCLK周期
CS1237_HAL_SetSCLK(gpio, 0);
for(int i=0; i<40; i++) {
CS1237_HAL_SetSCLK(gpio, 1);
CS1237_HAL_DelayUs(1);
CS1237_HAL_SetSCLK(gpio, 0);
CS1237_HAL_DelayUs(1);
}
// 尝试读取配置寄存器
if(CS1237_ReadConfig(gpio, &cfg) == 0) {
return 0; // 失败
}
return 1; // 成功
}
/* 检查ADC是否就绪(DOUT低电平有效) */
uint8_t CS1237_IsReady(CS1237_HAL_GPIO* gpio) {
return (CS1237_HAL_ReadDOUT(gpio) == 0) ? 1 : 0;
}
/* 读取24位ADC转换结果 */
int32_t CS1237_ReadADC(CS1237_HAL_GPIO* gpio) {
int32_t value = 0;
uint32_t timeout = 0;
// 等待DRDY信号(DOUT变低)
while(CS1237_HAL_ReadDOUT(gpio)) {
CS1237_HAL_DelayUs(1);
if(timeout++ > CS1237_TIMEOUT_US) return 0x80000000; // 超时
}
// 发送读命令
for(int i=0; i<8; i++) {
CS1237_HAL_SetSCLK(gpio, 1);
CS1237_HAL_DelayUs(1);
if(CS1237_CMD_READ & (0x80 >> i)) {
// 主机发送1:在SCLK高电平期间DOUT为输入,实际命令通过SCLK边沿传递
// CS1237命令是内部解码,此处简化为标准时序
}
CS1237_HAL_SetSCLK(gpio, 0);
CS1237_HAL_DelayUs(1);
}
// 读取24位数据(MSB first)
CS1237_HAL_InitDOUT_Input(gpio); // 切换为输入
for(int i=0; i<24; i++) {
CS1237_HAL_SetSCLK(gpio, 1);
CS1237_HAL_DelayUs(1);
value <<= 1;
if(CS1237_HAL_ReadDOUT(gpio)) {
value |= 1;
}
CS1237_HAL_SetSCLK(gpio, 0);
CS1237_HAL_DelayUs(1);
}
// 额外一个SCLK释放DOUT(进入新转换周期)
CS1237_HAL_SetSCLK(gpio, 1);
CS1237_HAL_DelayUs(1);
CS1237_HAL_SetSCLK(gpio, 0);
// 24位有符号扩展
if(value & 0x800000) {
value |= 0xFF000000;
}
return value;
}
/* 写配置寄存器 */
uint8_t CS1237_WriteConfig(CS1237_HAL_GPIO* gpio, uint8_t config) {
// 确保DOUT为高(空闲状态)
if(CS1237_HAL_ReadDOUT(gpio) == 0) return 0;
// 发送写寄存器命令
for(int i=0; i<8; i++) {
CS1237_HAL_SetSCLK(gpio, 1);
CS1237_HAL_DelayUs(1);
CS1237_HAL_SetSCLK(gpio, 0);
CS1237_HAL_DelayUs(1);
}
// 发送8位配置值
for(int i=0; i<8; i++) {
CS1237_HAL_SetSCLK(gpio, 1);
CS1237_HAL_DelayUs(1);
CS1237_HAL_SetSCLK(gpio, 0);
CS1237_HAL_DelayUs(1);
}
return 1;
}
/* 读配置寄存器 */
uint8_t CS1237_ReadConfig(CS1237_HAL_GPIO* gpio, uint8_t* config) {
uint8_t value = 0;
if(CS1237_HAL_ReadDOUT(gpio) == 0) return 0;
// 发送读寄存器命令
for(int i=0; i<8; i++) {
CS1237_HAL_SetSCLK(gpio, 1);
CS1237_HAL_DelayUs(1);
CS1237_HAL_SetSCLK(gpio, 0);
CS1237_HAL_DelayUs(1);
}
// 读取8位配置值
CS1237_HAL_InitDOUT_Input(gpio);
for(int i=0; i<8; i++) {
CS1237_HAL_SetSCLK(gpio, 1);
CS1237_HAL_DelayUs(1);
value <<= 1;
if(CS1237_HAL_ReadDOUT(gpio)) {
value |= 1;
}
CS1237_HAL_SetSCLK(gpio, 0);
CS1237_HAL_DelayUs(1);
}
*config = value;
return 1;
}
八、应用示例:
#include "cs1237_hal.h"
#include "app_adc.h"
/* 实例化硬件抽象结构体(引脚根据原理图修改) */
static CS1237_HAL_GPIO cs1237_gpio = {
.sclk_port = GPIOB,
.sclk_pin = GPIO_PIN_0,
.dout_port = GPIOB,
.dout_pin = GPIO_PIN_1
};
/* 初始化并配置为10Hz采样率、PGA=128 */
uint8_t APP_CS1237_Init(void) {
if(!CS1237_Init(&cs1237_gpio)) {
return 0; // 硬件错误
}
// 配置:AIN1通道 + PGA128 + 10Hz
uint8_t config = CS1237_CH_AIN1 | CS1237_PGA_128 | CS1237_SPEED_10HZ;
return CS1237_WriteConfig(&cs1237_gpio, config);
}
/* 读取原始ADC值(24位有符号) */
int32_t APP_CS1237_ReadRaw(void) {
return CS1237_ReadADC(&cs1237_gpio);
}
/* 读取5次取平均,提高稳定性 [citation:2] */
int32_t APP_CS1237_ReadAverage(uint8_t times) {
int64_t sum = 0;
uint8_t valid = 0;
for(uint8_t i=0; i<times; i++) {
int32_t val = CS1237_ReadADC(&cs1237_gpio);
if(val != 0x80000000) { // 非超时值
sum += val;
valid++;
}
HAL_Delay(10); // 等待下次转换
}
if(valid == 0) return 0;
return (int32_t)(sum / valid);
}
/* 转换为电压值(假设VREF=3.3V,PGA=128) */
float APP_CS1237_ToVoltage(int32_t adc_code) {
float vref = 3.3f;
float pga = 128.0f;
return (adc_code * vref) / (pga * 0x800000); // 24位满量程
}
/* 进入低功耗模式前调用 */
void APP_CS1237_EnterLowPower(void) {
// CS1237无专用休眠命令,可停止SCLK时钟或断电
CS1237_HAL_SetSCLK(&cs1237_gpio, 0);
// 可选:关闭CS1237电源(需硬件设计支持)
}