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

}

相关推荐
Doraemomo3 小时前
IMX6ULL裸机开发——系统主频和时钟配置
arm开发·嵌入式硬件·makefile·imx6ull
白色的北极熊3 小时前
c语言 scanf 输入流有空格,逗号 说明
c语言
Logic1014 小时前
C语言/数据结构位运算题解:异或XOR找出货船中的“独特载货量“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
深圳市恒锐丰科技杨生4 小时前
EG1192H 零功耗使能集成上管非同步降压 DC‑DC|屹晶 EGmicro
嵌入式硬件·硬件工程
星栖与芯5 小时前
LiteOS-M 切换汇编逐行图解(1):汇编是什么·寄存器与栈
汇编·stm32·嵌入式硬件·harmonyos·鸿蒙系统
xx~t6 小时前
嵌入式——单片机2
嵌入式硬件·学习·51单片机·串口·蜂鸣器
JNX_SEMI7 小时前
OC5138T 8V~100V超宽输入降压恒流驱动:覆盖12V汽车至72V电动车全场景
单片机·嵌入式硬件
xx~t7 小时前
嵌入式——51单片机3
linux·c语言·嵌入式硬件·51单片机
Zw-awa8 小时前
重新认识结构体:为什么 STM32 库函数喜欢接收一大包参数
stm32
云栖梦泽8 小时前
网络设备驱动(1)
linux·arm开发·嵌入式硬件