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

}

相关推荐
-Springer-2 小时前
STM32 学习 —— 个人学习笔记7(ADC 模数转换器 & 单通道及多通道)
笔记·stm32·学习
代码无bug抓狂人3 小时前
C语言之合唱队形——动态规划
c语言·开发语言·动态规划
风痕天际3 小时前
ESP32-S3开发教程五-按键中断2(使用FreeRTOS)
单片机·嵌入式硬件·esp32·vs code·esp32s3·esp-idf
【 】4233 小时前
stm32江协科技笔记(更新至3-3led流水灯和蜂鸣器)
笔记·stm32
天天爱吃肉82183 小时前
新能源汽车多测试设备联调与多物理信息融合测试方法及数据价值挖掘
人工智能·嵌入式硬件·机器学习·汽车
Struggle to dream12 小时前
STM32对于中断的简单理解
stm32·单片机·嵌入式硬件
常利兵13 小时前
吃透Java操作符高阶:位操作符+赋值操作符全解析(Java&C区别+实战技巧+面试考点)
java·c语言·面试
口袋物联14 小时前
模板方法模式在 C 语言中的应用(含 Linux 内核实例)
linux·c语言·模板方法模式
敲皮裤的代码14 小时前
《C语言》深入理解指针(3)
c语言