基于STM32LXXX的模数转换芯片ADC(CS1237-SOP8)驱动C程序设计

一、简介:

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电源(需硬件设计支持)

}

相关推荐
玩转单片机与嵌入式7 小时前
深入浅出TinyML 16:FFT、频带能量和MFCC分别适合什么任务?
stm32·深度学习·tinyml
M78佐菲7 小时前
c语言学习笔记:排序与查找方法整理
linux·c语言·笔记·学习·算法
wWYy.9 小时前
C++与C的区别
c语言·c++
LuminousCPP10 小时前
数据结构‑二叉树(二):二叉堆从零实现|Heap结构设计 + 建堆优化 + 堆排序深度解析
c语言·数据结构·笔记·二叉树
程序员与背包客_CoderZ13 小时前
高性能分布式KV存储引擎RocksDB入门与C/C++编码实战
c语言·开发语言·数据库·c++·分布式·分布式数据库·rocksdb
william_yangshun13 小时前
【大模型部署实战】kimi-k3-in-c 中文版:用 176KB 纯 C99 引擎在 CPU 上跑 Kimi K3 上手指南
c语言·开发语言
深圳市宝华视联14 小时前
Python 读取 IP 视频流简单 Demo
python·嵌入式硬件·opencv·网络协议·tcp/ip·实时音视频·嵌入式实时数据库
恒锐丰科技韩生14 小时前
RB6005A|晶准 单节锂电池内置 MOS 保护芯片 DFN2×3‑8
嵌入式硬件·硬件工程
youshi666814 小时前
stm32-PWR、低功耗模式
stm32·单片机·嵌入式硬件
ACP广源盛1392462567315 小时前
Qwen3.8‑2.4T 开源落地@ACP#国产 Serdes 长距离视频传输芯片 GSV5800 在私有化 AI 服务中的价值与应用场景
大数据·数据库·人工智能·嵌入式硬件·矩阵·开源·音视频