基于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 小时前
《C语言学习:位运算》17
c语言·开发语言·c++·学习·visual studio
szxinmai主板定制专家7 小时前
基于 ARM+FPGA精密多轴实时运动控制卡设计方案,适用于半导体设备等高精度领域(一)
arm开发·人工智能·嵌入式硬件·fpga开发·架构·语音识别
社交怪人8 小时前
【最大数】信息学奥赛一本通C语言解法(题号2056)
c语言
社交怪人8 小时前
【判断正负】信息学奥赛一本通C语言解法(题号1039)
c语言
龙腾AI白云9 小时前
数字孪生:虚拟调试,真实交付
c语言·virtualenv·知识图谱
不做无法实现的梦~9 小时前
常见工程分析软件
stm32·嵌入式硬件·算法
我不是懒洋洋9 小时前
手写一个异步日志库:从printf到高性能无锁日志
java·c语言·开发语言·c++·visual studio
国产电子元器件10 小时前
电流检测信号漂移问题分析
单片机·嵌入式硬件
梁朝辉11 小时前
筛选运算放大器时对于开环增益这一项参数怎么看?
嵌入式硬件·硬件工程
Sean_VIP11 小时前
FreeRTOS项目程序框架介绍(五)
笔记·stm32