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

}

相关推荐
yongui4783429 分钟前
基于STM32的Lora SX1278程序设计与实现
stm32·单片机·嵌入式硬件
csdn_aspnet1 小时前
C/C++ 两个凸多边形之间的切线(Tangents between two Convex Polygons)
c语言·c++·算法
剑心诀4 小时前
02 数据结构(C) | 线性表——顺序表的基本操作
c语言·开发语言·数据结构
m0_488633324 小时前
Windows环境下编译运行C语言程序,合适工具与方法很关键
c语言·windows·git·开发工具·编译器
m0_488633325 小时前
C语言变量命名规则、入门自学、运算符优先级及数据结构介绍
c语言·数据结构·运算符优先级·变量命名·入门自学
Book思议-5 小时前
【数据结构实战】川剧 “扯脸” 与栈的 LIFO 特性 :用 C 语言实现 3 种栈结构
c语言·数据结构·算法·
永霖光电_UVLED5 小时前
意法半导体:华虹40nm代工生产的STM32 MCU开启交付
stm32·单片机·嵌入式硬件
爱喝纯牛奶的柠檬7 小时前
STM32红外遥控解码,NEC协议驱动
单片机·嵌入式硬件
炸膛坦客7 小时前
单片机/C/C++八股:(二十一)include <> 和 include ““ 的区别
c语言·c++
羽获飞8 小时前
从零开始学嵌入式之STM32——30.使用触发输入和从模式测量PWM信号的占空比
stm32·单片机·嵌入式硬件