CS1237 多通道驱动代码实现

文章提供了CS1237芯片的驱动代码,包括初始化、读取数据和配置的函数。修复了一个写入配置后读取固定为0x20的bug,并展示了如何扩展为多通道,涉及GPIO配置和时序控制。代码适用于STM32F103C8T6平台,并使用了卡尔曼滤波处理ADC数据。
摘要由CSDN通过智能技术生成

目录

CS1237芯片

Github 

多通道

源码



最近有小伙伴问我,CS1237多通道代码,可以参考下。我建议他这颗芯片出来很长时间了,先不要自己造轮子

CS1237芯片

Github 

个人比较喜欢第三个作者的代码

   /* Infinite loop */
    kalman_init(&g_kfp_st);
    // 这个任务进行初始化, 在完成后删除自身

    // 设置cs1237参数
    cs1237_init(&g_cs1237_device_st, DEV_FREQUENCY_640, DEV_PGA_1, DEV_CH_A);


// 输出计算的数据, 前一个原始值,后一个卡尔曼滤波值
        printf("%d %f\r\n", g_cs1237_device_st.get_adc_data(&g_cs1237_device_st), kalman_filter(&g_kfp_st, (float)g_cs1237_device_st.adc_calculate_deal_data));
/*
 * @Description: cd1237 驱动
 * @Author: TOTHTOT
 * @Date: 2023-03-23 16:42:25
 * @LastEditTime: 2023-03-28 16:11:18
 * @LastEditors: TOTHTOT
 * @FilePath: \MDK-ARMe:\Work\MCU\stm32\read_cs1237_STM32F103C8T6(HAL+FreeRTOS)\HARDWARE\CS1237\cs1237.h
 */
#ifndef __CS1237_H__
#define __CS1237_H__

#include "main.h"

#define CS1237_CIONFIG_WRITE_REGISTER 0x65 // 设置写入寄存器
#define CS1237_CIONFIG_READ_REGISTER 0x56  // 设置读取寄存器

#define CS1237_SCL_H HAL_GPIO_WritePin(CS1237_SCL_GPIO_Port, CS1237_SCL_Pin, GPIO_PIN_SET)
#define CS1237_SCL_L HAL_GPIO_WritePin(CS1237_SCL_GPIO_Port, CS1237_SCL_Pin, GPIO_PIN_RESET)

#define CS1237_SDA_H HAL_GPIO_WritePin(CS1237_DOUT_GPIO_Port, CS1237_DOUT_Pin, GPIO_PIN_SET)
#define CS1237_SDA_L HAL_GPIO_WritePin(CS1237_DOUT_GPIO_Port, CS1237_DOUT_Pin, GPIO_PIN_RESET)

#define CS1237_SDA_READ HAL_GPIO_ReadPin(CS1237_DOUT_GPIO_Port, CS1237_DOUT_Pin)

/* 设置IO方向 */
#define CS1237_SDA_IN                                    \
    {                                                    \
        CS1237_DOUT_GPIO_Port->CRL &= 0XFFFF0FFF;        \
        CS1237_DOUT_GPIO_Port->CRL |= (uint32_t)8 << 12; \
    }
#define CS1237_SDA_OUT                                   \
    {                                                    \
        CS1237_DOUT_GPIO_Port->CRL &= 0XFFFF0FFF;        \
        CS1237_DOUT_GPIO_Port->CRL |= (uint32_t)3 << 12; \
    }

/* cs1237 设备结构体 */
struct cs1237_device
{
#define CS1237_DEFAULT_FREQUENCY 10 // 默认输出频率
#define RAW_DATA_MAX_NUM 8			// 用于滤波, 连续读取 RAW_DATA_MAX_NUM 次数据然后去掉最高, 最低, 
									// 再计算平均值,平均值带入卡尔曼滤波器
    int32_t adc_data;                                 // 读取到的数据, 原始adc数据, 单次读取
    int32_t adc_calculate_raw_data[RAW_DATA_MAX_NUM]; // 读取数据后存入, 用于滤波, 连续采集12次
    int32_t adc_calculate_deal_data;                  // 读取数据后存入, 用于滤波
    uint8_t adc_config;                               // 模块配置参数
    uint16_t output_frequency;                        // 模块输出频率

    enum dev_ch
    {
        DEV_CH_NONE,          // 默认状态
        DEV_CH_A,             // 通道A
        DEV_CH_SAVE,          // 保留
        DEV_CH_TEMPERERATURE, // 温度
        DEV_CH_SHORT,         // 内部短路
        DEV_CH_TOTAL_STATE    // 状态统计
    } dev_ch_em;              // cs1237 通道选择

    enum dev_pga
    {
        DEV_PGA_NONE,
        DEV_PGA_1,
        DEV_PGA_2,
        DEV_PGA_64,
        DEV_PGA_128,
        DEV_PGA_TOTAL_STATE
    } dev_pga_em; // cs1237 pga选择, 在测温时选择 DEV_PGA_1

    enum dev_frequency
    {
        DEV_FREQUENCY_NONE,
        DEV_FREQUENCY_10,
        DEV_FREQUENCY_40,
        DEV_FREQUENCY_640,
        DEV_FREQUENCY_1280,
        DEV_FREQUENCY_TOTAL_STATE
    } dev_frequency_em; // cs1237 输出频率选择

    enum dev_state
    {
        DEV_NONE,       // 默认状态
        DEV_ONLINE,     // 设备在线
        DEV_OFFLINE,    // 设备掉线
        DEV_TOTAL_STATE // 所有状态数量
    } dev_state_em;     // cs1237 是否在线, 不在线就不读取数据

    int32_t (*get_adc_data)(struct cs1237_device *dev);   // 读取数据, 外部操作的函数
    uint8_t (*get_adc_config)(struct cs1237_device *dev); // 读取配置数据, 外部操作的函数
};
extern struct cs1237_device g_cs1237_device_st;
/* 外部调用函数 */
uint8_t cs1237_init(struct cs1237_device *dev, enum dev_frequency frequency, enum dev_pga pga, enum dev_ch ch);

#endif /* __CS1237_H__ */

/*
 * @Description: cs1237 设备驱动文件
 * @Author: TOTHTOT
 * @Date: 2023-03-23 16:41:59
 * @LastEditTime: 2023-03-28 13:23:27
 * @LastEditors: TOTHTOT
 * @FilePath: \MDK-ARMe:\Work\MCU\stm32\read_cs1237_STM32F103C8T6(HAL+FreeRTOS)\HARDWARE\CS1237\cs1237.c
 */
#include "cs1237.h"
#include "delay.h"
#include "usart1.h"
#include "stdio.h"

#define setbit(x, y) x |= (1 << y)     // x的y位置1
#define clrbit(x, y) x &= ~(1 << y)    // x的y位置0
#define reversebit(x, y) x ^= (1 << y) // x的y位异或
#define getbit(x, y) ((x) >> (y)&1)    // 获取x的第y位

struct cs1237_device g_cs1237_device_st = {0};
int32_t cs1237_read_data(struct cs1237_device *dev);
uint8_t cs1237_read_config(struct cs1237_device *dev);
int32_t calculate_adc_num(struct cs1237_device *dev);

/**
 * @name: cs1237_nop
 * @msg: cs1237 模块内部使用延时 调用一次460ns
 * @return {*} 无
 * @author: TOTHTOT
 * @date: 2023年3月24日11:43:50
 */
// static void cs1237_nop(void)
// {
//     unsigned int i = 0;
//     for (i = 0; i < 20; i++)
//         __asm {
//     nop
//         }
// }

/**
 * @name:cs1237_send_bit
 * @msg:发送一位数据
 * @param {uint8_t} bit 1位数据
 * @param {uint8_t} time_us 时钟高电平时间, 单位:us
 * @return {*} 无
 * @author: TOTHTOT
 * @date: 2023年3月24日10:34:08
 */
void cs1237_send_bit(uint8_t bit, uint8_t time_us)
{
    CS1237_SDA_OUT; // 切换输出模式
    CS1237_SCL_H;
    delay_us(time_us);
    if (bit == 1)
        CS1237_SDA_H;
    else
        CS1237_SDA_L;
    CS1237_SCL_L;
    delay_us(time_us);
}

/**
 * @name: cs1237_read_bit
 * @msg: cs1237 读取1位数据, 使用前确保SDA已经处于输入态
 * @param {uint8_t} time_us 电平持续时间
 * @return {*}  读取到的电平
 * @author: TOTHTOT
 * @date: 2023年3月24日11:24:52
 */
uint8_t cs1237_read_bit(uint8_t time_us)
{
    uint8_t recv_data = 0;

    CS1237_SCL_H;
    delay_us(time_us);
    recv_data = CS1237_SDA_READ;
    CS1237_SCL_L;
    delay_us(time_us);

    return recv_data;
}

/**
 * @name: cs1237_check
 * @msg: 检测模块是否在线
 * @param {cs1237_device} *dev
 * @return {*} == 0 成功
 *             == 1, 失败, 不在线
 * @author: TOTHTOT
 * @date:
 */
uint8_t cs1237_check(struct cs1237_device *dev)
{
    uint32_t retry = 0;

    // dev->dev_state_em = dev_online;

    CS1237_SCL_L; // 时钟拉低
    CS1237_SDA_OUT;
    CS1237_SDA_H; // OUT引脚拉高
    CS1237_SDA_IN;
    while (CS1237_SDA_READ == 1) // 等待CS237准备好
    {
        delay_us(1);
        retry++;
        if (retry > 30000000)
        {
            CS1237_SDA_OUT;
            CS1237_SDA_H; // OUT引脚拉高
            CS1237_SCL_H; // CLK引脚拉高
            ERROR_PRINT("time out\r\n");
            return 1; // 超时,则直接退出程序
        }
    }

    return 0;
}

/**
 * @name: cs1237_send_byte
 * @msg: 发送1字节
 * @param {uint8_t} byte
 * @return {*}
 * @author: TOTHTOT
 * @date:
 */
void cs1237_send_byte(uint8_t byte)
{
    for (uint8_t i = 0; i < 8; i++) // 38 - 45个脉冲了,写8位数据
    {
        CS1237_SCL_H; // CLK=1;
        delay_us(1);
        if (byte & 0x80)
            CS1237_SDA_H; // OUT = 1
        else
            CS1237_SDA_L;
        byte <<= 1;
        CS1237_SCL_L; // CLK=0;
        delay_us(1);
    }
}

/**
 * @name: cs1237_init
 * @msg: cs1237 初始化
 * @param {cs1237_device} *dev 设备
 * @param {enum dev_frequency} frequency 输出频率
 * @param {enum dev_pga} pga
 * @param {enum dev_ch} ch 通道
 * @return {*}  == 0 初始化成功
 *              == 1, 初始化失败
 * @author: TOTHTOT
 * @date: 2023年3月23日17:35:15
 */
uint8_t cs1237_init(struct cs1237_device *dev, enum dev_frequency frequency, enum dev_pga pga, enum dev_ch ch)
{
    uint8_t cs1237_config = 0; // cs1237 的寄存器配置 0100 1000
    uint8_t ret;

    // 初始化频率
    switch (frequency)
    {
    case DEV_FREQUENCY_10:
        clrbit(cs1237_config, 4);
        clrbit(cs1237_config, 5);
        break;
    case DEV_FREQUENCY_40:
        setbit(cs1237_config, 4);
        clrbit(cs1237_config, 5);
        break;
    case DEV_FREQUENCY_640:
        setbit(cs1237_config, 5);
        clrbit(cs1237_config, 4);
        break;
    case DEV_FREQUENCY_1280:
        setbit(cs1237_config, 4);
        setbit(cs1237_config, 5);
        break;
    default:
        clrbit(cs1237_config, 4);
        clrbit(cs1237_config, 5);
        break;
    }

    // 初始化 pga
    switch (pga)
    {
    case DEV_PGA_1:
        clrbit(cs1237_config, 2);
        clrbit(cs1237_config, 3);
        break;
    case DEV_PGA_2:
        clrbit(cs1237_config, 3);
        setbit(cs1237_config, 2);
        break;
    case DEV_PGA_64:
        clrbit(cs1237_config, 2);
        setbit(cs1237_config, 3);
        break;
    case DEV_PGA_128:
        setbit(cs1237_config, 2);
        setbit(cs1237_config, 3);
        break;
    default:
        clrbit(cs1237_config, 2);
        clrbit(cs1237_config, 3);
        break;
    }

    // 初始化 通道
    switch (ch)
    {
    case DEV_CH_A:
        clrbit(cs1237_config, 0);
        clrbit(cs1237_config, 1);
        break;
    case DEV_CH_SAVE:
        clrbit(cs1237_config, 1);
        setbit(cs1237_config, 0);
        break;
    case DEV_CH_TEMPERERATURE:
        clrbit(cs1237_config, 0);
        setbit(cs1237_config, 1);
        break;
    case DEV_CH_SHORT:
        setbit(cs1237_config, 1);
        setbit(cs1237_config, 1);
        break;
    default:
        clrbit(cs1237_config, 0);
        clrbit(cs1237_config, 1);
        break;
    }

    // cs1237_config = 0X0C;
    /* 初始化设备结构体 */
    dev->adc_data = 0;
    dev->output_frequency = frequency;
    dev->get_adc_data = calculate_adc_num;
    dev->get_adc_config = cs1237_read_config;
    dev->adc_config = cs1237_config;

    ret = cs1237_check(dev);
    if (ret != 0)
    {
        dev->dev_state_em = DEV_OFFLINE;
        ERROR_PRINT("cs1237_check failed!\r\n");
        return 1;
    }
    dev->dev_state_em = DEV_ONLINE;

    /* 配置 CS1237 工作模式 */
    // 发送1到29个脉冲
    for (uint8_t i = 0; i < 29; i++)
    {
        CS1237_SCL_H;
        delay_us(40);
        CS1237_SCL_L;
        delay_us(40);
    }

    CS1237_SDA_OUT;
    CS1237_SCL_H;
    delay_us(1);
    CS1237_SDA_H;
    CS1237_SCL_L;
    delay_us(1); // 30
    CS1237_SCL_H;
    delay_us(1);
    CS1237_SDA_H;
    CS1237_SCL_L;
    delay_us(1); // 31
    CS1237_SCL_H;
    delay_us(1);
    CS1237_SDA_L;
    CS1237_SCL_L;
    delay_us(1); // 32
    CS1237_SCL_H;
    delay_us(1);
    CS1237_SDA_L;
    CS1237_SCL_L;
    delay_us(1); // 33
    CS1237_SCL_H;
    delay_us(1);
    CS1237_SDA_H;
    CS1237_SCL_L;
    delay_us(1); // 34
    CS1237_SCL_H;
    delay_us(1);
    CS1237_SDA_L;
    CS1237_SCL_L;
    delay_us(1); // 35
    CS1237_SCL_H;
    delay_us(1);
    CS1237_SDA_H;
    CS1237_SCL_L;
    delay_us(1); // 36
    // 37     写入了0x65
    CS1237_SCL_H; // CLK=1;
    delay_us(1);
    CS1237_SCL_L; // CLK=0;
    delay_us(1);

    cs1237_send_byte(cs1237_config);

    CS1237_SDA_H; // OUT = 1
    CS1237_SCL_H; // CLK=1;
    delay_us(1);
    CS1237_SCL_L; // CLK=0;
    delay_us(1);

    INFO_PRINT("adc config = %x\r\n", cs1237_config);
    return 0;
}

/**
 * @name: cs1237_read_config
 * @msg: 读取芯片的配置数据
 * @param {cs1237_device} *dev 设备结构体
 * @return {*} 读取到的寄存器数据
 * @author: TOTHTOT
 * @date:
 */
uint8_t cs1237_read_config(struct cs1237_device *dev)
{
    unsigned char i = 0;
    unsigned char dat = 0; // 读取到的数据
    uint8_t ret = 0;

    ret = cs1237_check(dev);
    if (ret != 0)
    {
        dev->dev_state_em = DEV_OFFLINE;
        ERROR_PRINT("cs1237_check failed!\r\n");
        return 1;
    }

    for (i = 0; i < 29; i++) // 产生第1到29个时钟
    {
        CS1237_SCL_H; // CLK=1;
        delay_us(1);
        CS1237_SCL_L; // CLK=0;
        delay_us(1);
    }

    dev->dev_state_em = DEV_ONLINE;
    CS1237_SDA_OUT;

    CS1237_SCL_H; // CLK=1;
    delay_us(1);
    CS1237_SDA_H;
    CS1237_SCL_L; // CLK=0;
    delay_us(1);  // 这是第30个时钟

    CS1237_SCL_H; // CLK=1;
    delay_us(1);
    CS1237_SDA_L;
    CS1237_SCL_L; // CLK=0;
    delay_us(1);  // 这是第31个时钟

    CS1237_SCL_H; // CLK=1;
    delay_us(1);
    CS1237_SDA_H;
    CS1237_SCL_L; // CLK=0;
    delay_us(1);  // 32

    CS1237_SCL_H; // CLK=1;
    delay_us(1);
    CS1237_SDA_L;
    CS1237_SCL_L; // CLK=0;
    delay_us(1);  // 33

    CS1237_SCL_H; // CLK=1;
    delay_us(1);
    CS1237_SDA_H;
    CS1237_SCL_L; // CLK=0;
    delay_us(1);  // 34

    CS1237_SCL_H; // CLK=1;
    delay_us(1);
    CS1237_SDA_H;
    CS1237_SCL_L; // CLK=0;
    delay_us(1);  // 35

    CS1237_SCL_H; // CLK=1;
    delay_us(1);
    CS1237_SDA_L;
    CS1237_SCL_L; // CLK=0;
    delay_us(1);  // 36

    CS1237_SDA_H;
    CS1237_SCL_H; // CLK=1;
    delay_us(1);
    CS1237_SCL_L; // CLK=0;
    delay_us(1);  // 37     写入0x56 即读命令

    dat = 0;
    CS1237_SDA_IN;
    for (i = 0; i < 8; i++) // 第38 - 45个脉冲了,读取数据
    {
        CS1237_SCL_H; // CLK=1;
        delay_us(1);
        CS1237_SCL_L; // CLK=0;
        delay_us(1);
        dat <<= 1;
        if (CS1237_SDA_READ == 1)
            dat++;
    }

    // 第46个脉冲
    CS1237_SCL_H; // CLK=1;
    delay_us(1);
    CS1237_SCL_L; // CLK=0;
    delay_us(1);

    CS1237_SDA_OUT;
    CS1237_SDA_H; // OUT引脚拉高

    dev->adc_config = dat;

    return dat;
}

/**
 * @name: cs1237_read_data
 * @msg: 读取ADC数据,返回的是一个有符号数据
 * @param {cs1237_device} *dev  设备结构体
 * @return {*} 读取到的adc数据
 * @author: TOTHTOT
 * @date:
 */
int32_t cs1237_read_data(struct cs1237_device *dev)
{
    unsigned char i = 0;
    uint32_t dat = 0; // 读取到的数据
    uint8_t ret = 0;

    ret = cs1237_check(dev);
    if (ret != 0)
    {
        dev->dev_state_em = DEV_OFFLINE;
        ERROR_PRINT("cs1237_check failed!\r\n");
        return 1;
    }

    dev->dev_state_em = DEV_ONLINE;
    dat = 0;
    for (i = 0; i < 24; i++) // 获取24位有效转换
    {
        CS1237_SCL_H; // CLK=1;
        delay_us(1);
        dat <<= 1;
        if (CS1237_SDA_READ == 1)
            dat++;
        CS1237_SCL_L; // CLK=0;
        delay_us(1);
    }

    for (i = 0; i < 3; i++) // 接着前面的时钟 再来3个时钟
    {
        cs1237_send_bit(1, 1);
    }

    CS1237_SDA_OUT;
    CS1237_SDA_H; // OUT = 1;

    if (dat & 0x00800000) // 判断是负数 最高位24位是符号位
    {
        dev->adc_data = -(((~dat) & 0x007FFFFF) + 1); // 补码变源码
    }
    else
        dev->adc_data = dat; // 正数的补码就是源码

    return dev->adc_data;
}

/**
 * @name: calculate_adc_num
 * @msg:
 * @param {cs1237_device} *dev
 * @return {*}
 * @author: TOTHTOT
 * @date:
 */
int32_t calculate_adc_num(struct cs1237_device *dev)
{
    int32_t max = 0, max_2 = 0, max_pos = 0, max_2_pos = 0;
    int32_t min = 0, min_pos = 0;

    // 采集 RAW_DATA_MAX_NUM 次 数据去掉最高和最低
    for (uint8_t i = 0; i < RAW_DATA_MAX_NUM; i++)
    {
        dev->adc_calculate_raw_data[i] = cs1237_read_data(dev);
        if (dev->adc_calculate_raw_data[i] > max)
        {
            max = dev->adc_calculate_raw_data[i];
            max_pos = i;
            // INFO_PRINT("max = %d, pos = %d\r\n", max, max_pos);
        }
        if (i == 0)
        {
            min = dev->adc_calculate_raw_data[0];
            min_pos = 0;
            // INFO_PRINT("min = %d, pos = %d\r\n", min, min_pos);
        }
        if (dev->adc_calculate_raw_data[i] < min)
        {
            min = dev->adc_calculate_raw_data[i];
            min_pos = i;
            // INFO_PRINT("min = %d, pos = %d\r\n", min, min_pos);
        }
    }

    for (uint8_t i = 0; i < RAW_DATA_MAX_NUM; i++)
    {
        if (i == max_pos || i == min_pos)
        {
            continue;
        }

        dev->adc_calculate_deal_data += dev->adc_calculate_raw_data[i];
    }
    return (int)(dev->adc_calculate_deal_data = dev->adc_calculate_deal_data / (RAW_DATA_MAX_NUM - 2));
}

多通道

        可以看到上面代码中只实现了单通道。

        多通道的方法需要

GPIO_TypeDef* sck_gpio_ports[NUM_CS1237_CHIPS] = {GPIOA, GPIOA, GPIOB, GPIOB};
uint16_t sck_gpio_pins[NUM_CS1237_CHIPS] = {GPIO_PIN_4, GPIO_PIN_5, GPIO_PIN_0, GPIO_PIN_1};

GPIO_TypeDef* dout_gpio_ports[NUM_CS1237_CHIPS] = {GPIOA, GPIOA, GPIOB, GPIOB};
uint16_t dout_gpio_pins[NUM_CS1237_CHIPS] = {GPIO_PIN_4, GPIO_PIN_5, GPIO_PIN_0, GPIO_PIN_1};

在读写函数参数中添加参数:

uint8_t chip

源码

只要硬件允许可以无限添加通道数量。

修复原作者代码bug一处:

        现象:写进去的配置读出来固定为0x20;

        修复方法,将写延时40us 改为4us 正常。

/*
 * @Description: cd1237 驱动
 * @Author: TOTHTOT
 * @Date: 2023-03-23 16:42:25
 * @LastEditTime: 2023-03-28 16:11:18
 * @LastEditors: mainbp
 * @FilePath: \MDK-ARMe:\Work\MCU\stm32\read_cs1237_STM32F103C8T6(HAL+FreeRTOS)\HARDWARE\CS1237\cs1237.h
 */
#ifndef __CS1237_H__
#define __CS1237_H__

#include "main.h"
#include "stdio.h"

#define CS1237_CIONFIG_WRITE_REGISTER 0x65 		// 设置写入寄存器
#define CS1237_CIONFIG_READ_REGISTER 	0x56  	// 设置读取寄存器



/* cs1237 设备结构体 */
struct cs1237_device
{
#define CS1237_DEFAULT_FREQUENCY 10 // 默认输出频率
#define RAW_DATA_MAX_NUM 8			// 用于滤波, 连续读取 RAW_DATA_MAX_NUM 次数据然后去掉最高, 最低, 
									// 再计算平均值,平均值带入卡尔曼滤波器
    int32_t adc_data;                                 // 读取到的数据, 原始adc数据, 单次读取
    int32_t adc_calculate_raw_data[RAW_DATA_MAX_NUM]; // 读取数据后存入, 用于滤波, 连续采集12次
    int32_t adc_calculate_deal_data;                  // 读取数据后存入, 用于滤波
    uint8_t adc_config;                               // 模块配置参数
    uint16_t output_frequency;                        // 模块输出频率

    enum dev_ch
    {
        DEV_CH_NONE,          // 默认状态
        DEV_CH_A,             // 通道A
        DEV_CH_SAVE,          // 保留
        DEV_CH_TEMPERERATURE, // 温度
        DEV_CH_SHORT,         // 内部短路
        DEV_CH_TOTAL_STATE    // 状态统计
    } dev_ch_em;              // cs1237 通道选择

    enum dev_pga
    {
        DEV_PGA_NONE,
        DEV_PGA_1,
        DEV_PGA_2,
        DEV_PGA_64,
        DEV_PGA_128,
        DEV_PGA_TOTAL_STATE
    } dev_pga_em; // cs1237 pga选择, 在测温时选择 DEV_PGA_1

    enum dev_frequency
    {
        DEV_FREQUENCY_NONE,
        DEV_FREQUENCY_10,
        DEV_FREQUENCY_40,
        DEV_FREQUENCY_640,
        DEV_FREQUENCY_1280,
        DEV_FREQUENCY_TOTAL_STATE
    } dev_frequency_em; // cs1237 输出频率选择

    enum dev_state
    {
        DEV_NONE,       // 默认状态
        DEV_ONLINE,     // 设备在线
        DEV_OFFLINE,    // 设备掉线
        DEV_TOTAL_STATE // 所有状态数量
    } dev_state_em;     // cs1237 是否在线, 不在线就不读取数据

    int32_t (*get_adc_data)(uint8_t chip ,struct cs1237_device *dev);   // 读取数据, 外部操作的函数
    uint8_t (*get_adc_config)(uint8_t chip ,struct cs1237_device *dev); // 读取配置数据, 外部操作的函数
};
extern struct cs1237_device g_cs1237_device_st;
/* 外部调用函数 */
uint8_t cs1237_init(uint8_t chip ,struct cs1237_device *dev, enum dev_frequency frequency, enum dev_pga pga, enum dev_ch ch);

#endif /* __CS1237_H__ */
/*
 * @Description: cs1237 设备驱动文件
 * @Author: TOTHTOT
 * @Date: 2023-03-23 16:41:59
 * @LastEditTime: 2023-03-28 13:23:27
 * @LastEditors: mainbp
 * @FilePath: \MDK-ARMe:\Work\MCU\stm32\read_cs1237_STM32F103C8T6(HAL+FreeRTOS)\HARDWARE\CS1237\cs1237.c
 */
#include "cs1237.h"
#include "delay.h"
//#include "usart1.h"


//SCK1	PA1
//SCK2	PD11
gpio_type* sck_gpio_ports[NUM_CS1237_CHIPS] = {GPIOA, 			GPIOD, 				GPIOD, 				GPIOD};
uint16_t sck_gpio_pins[NUM_CS1237_CHIPS]	 	= {GPIO_PINS_1, GPIO_PINS_11, GPIO_PINS_2, 	GPIO_PINS_2};
//DOUT1	PD10
//DOUT2	PD13
gpio_type* dout_gpio_ports[NUM_CS1237_CHIPS] = {GPIOD, 				GPIOD, 				GPIOD, 				GPIOD};
uint16_t dout_gpio_pins[NUM_CS1237_CHIPS]		 = {GPIO_PINS_10, GPIO_PINS_13, GPIO_PINS_2, 	GPIO_PINS_2};


#define setbit(x, y) x |= (1 << y)     // x的y位置1
#define clrbit(x, y) x &= ~(1 << y)    // x的y位置0
#define reversebit(x, y) x ^= (1 << y) // x的y位异或
#define getbit(x, y) ((x) >> (y)&1)    // 获取x的第y位

struct cs1237_device g_cs1237_device_st[NUM_CS1237_CHIPS] = {0};
int32_t cs1237_read_data(uint8_t chip ,struct cs1237_device *dev);
uint8_t cs1237_read_config(uint8_t chip ,struct cs1237_device *dev);
int32_t calculate_adc_num(uint8_t chip ,struct cs1237_device *dev);

/**
 * @name: cs1237_nop
 * @msg: cs1237 模块内部使用延时 调用一次460ns
 * @return {*} 无
 * @author: TOTHTOT
 * @date: 2023年3月24日11:43:50
 */
// static void cs1237_nop(void)
// {
//     unsigned int i = 0;
//     for (i = 0; i < 20; i++)
//         __asm {
//     nop
//         }
// }
void cs1237_gpio_init(void)
{
	gpio_init_type gpio_init_struct;

	/* enable the gpioa clock */
	crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE);

	/* set default parameter */
	gpio_default_para_init(&gpio_init_struct);

	/* configure the gpio SCK */
	gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
	gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
	gpio_init_struct.gpio_pins = GPIO_PINS_1;
	gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
	gpio_init(GPIOA, &gpio_init_struct);
	gpio_bits_reset(GPIOA, GPIO_PINS_1);
	
	gpio_init_struct.gpio_pins = GPIO_PINS_11;
	gpio_init(GPIOD, &gpio_init_struct);
	gpio_bits_reset(GPIOD, GPIO_PINS_11);
	
	
	/* configure the gpio DOUT */	
	gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_OPEN_DRAIN;
	gpio_init_struct.gpio_pins = GPIO_PINS_10;
	gpio_init(GPIOD, &gpio_init_struct);
	gpio_bits_set(GPIOD, GPIO_PINS_10);
	
	gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_OPEN_DRAIN;
	gpio_init_struct.gpio_pins = GPIO_PINS_13;
	gpio_init(GPIOD, &gpio_init_struct);
	gpio_bits_set(GPIOD, GPIO_PINS_13);
}

void set_cs1237_sck(uint8_t chip)
{
	gpio_bits_set(sck_gpio_ports[chip], sck_gpio_pins[chip]);
}

void reset_cs1237_sck(uint8_t chip)
{
	gpio_bits_reset(sck_gpio_ports[chip], sck_gpio_pins[chip]);
}

void set_cs1237_dout(uint8_t chip)
{
	gpio_bits_set(dout_gpio_ports[chip], dout_gpio_pins[chip]);
}

void reset_cs1237_dout(uint8_t chip)
{
	gpio_bits_reset(dout_gpio_ports[chip], dout_gpio_pins[chip]);
}
flag_status read_cs1237_dout(uint8_t chip)
{
	return gpio_input_data_bit_read(dout_gpio_ports[chip], dout_gpio_pins[chip]);
}


/**
 * @name:cs1237_send_bit
 * @msg:发送一位数据
 * @param {uint8_t} bit 1位数据
 * @param {uint8_t} time_us 时钟高电平时间, 单位:us
 * @return {*} 无
 * @author: TOTHTOT
 * @date: 2023年3月24日10:34:08
 */
void cs1237_send_bit(uint8_t chip,uint8_t bit, uint8_t time_us)
{
    set_cs1237_dout(chip); // 切换输出模式
    set_cs1237_sck(chip);
    delay_us(time_us);
    if (bit == 1)
        set_cs1237_dout(chip);
    else
        reset_cs1237_dout(chip);
    reset_cs1237_sck(chip);
    delay_us(time_us);
}

/**
 * @name: cs1237_read_bit
 * @msg: cs1237 读取1位数据, 使用前确保SDA已经处于输入态
 * @param {uint8_t} time_us 电平持续时间
 * @return {*}  读取到的电平
 * @author: TOTHTOT
 * @date: 2023年3月24日11:24:52
 */
uint8_t cs1237_read_bit(uint8_t chip,uint8_t time_us)
{
    uint8_t recv_data = 0;

    set_cs1237_sck(chip);
    delay_us(time_us);
    recv_data = read_cs1237_dout(chip);
    reset_cs1237_sck(chip);
    delay_us(time_us);

    return recv_data;
}

/**
 * @name: cs1237_check
 * @msg: 检测模块是否在线
 * @param {cs1237_device} *dev
 * @return {*} == 0 成功
 *             == 1, 失败, 不在线
 * @author: TOTHTOT
 * @date:
 */
uint8_t cs1237_check(uint8_t chip , struct cs1237_device *dev)
{
    uint32_t retry = 0;

    // dev->dev_state_em = dev_online;

    reset_cs1237_sck(chip); // 时钟拉低
    set_cs1237_dout(chip); 			// OUT引脚拉高
    while (read_cs1237_dout(chip) == 1) // 等待CS237准备好
    {
        delay_us(1);
        retry++;
        if (retry > 30000000)
        {
            set_cs1237_dout(chip); 	// OUT引脚拉高
            set_cs1237_sck(chip); 	// CLK引脚拉高
            ERROR_PRINT("time out\r\n");
            return 1; // 超时,则直接退出程序
        }
    }
    return 0;
}

/**
 * @name: cs1237_send_byte
 * @msg: 发送1字节
 * @param {uint8_t} byte
 * @return {*}
 * @author: TOTHTOT
 * @date:
 */
void cs1237_send_byte(uint8_t chip ,uint8_t byte)
{
    for (uint8_t i = 0; i < 8; i++) // 38 - 45个脉冲了,写8位数据
    {
        set_cs1237_sck(chip); 				// CLK=1;
        delay_us(1);
        if (byte & 0x80)
            set_cs1237_dout(chip); 		// OUT = 1
        else
            reset_cs1237_dout(chip);
        byte <<= 1;
        reset_cs1237_sck(chip); 			// CLK=0;
        delay_us(1);
    }
}

/**
 * @name: cs1237_init
 * @msg: cs1237 初始化
 * @param {cs1237_device} *dev 设备
 * @param {enum dev_frequency} frequency 输出频率
 * @param {enum dev_pga} pga
 * @param {enum dev_ch} ch 通道
 * @return {*}  == 0 初始化成功
 *              == 1, 初始化失败
 * @author: TOTHTOT
 * @date: 2023年3月23日17:35:15
 */
uint8_t cs1237_init(uint8_t chip ,struct cs1237_device *dev, enum dev_frequency frequency, enum dev_pga pga, enum dev_ch ch)
{
    uint8_t cs1237_config = 0; // cs1237 的寄存器配置 0100 1000
    uint8_t ret;

    // 初始化频率
    switch (frequency)
    {
    case DEV_FREQUENCY_10:
        clrbit(cs1237_config, 4);
        clrbit(cs1237_config, 5);
        break;
    case DEV_FREQUENCY_40:
        setbit(cs1237_config, 4);
        clrbit(cs1237_config, 5);
        break;
    case DEV_FREQUENCY_640:
        setbit(cs1237_config, 5);
        clrbit(cs1237_config, 4);
        break;
    case DEV_FREQUENCY_1280:
        setbit(cs1237_config, 4);
        setbit(cs1237_config, 5);
        break;
    default:
        clrbit(cs1237_config, 4);
        clrbit(cs1237_config, 5);
        break;
    }

    // 初始化 pga
    switch (pga)
    {
    case DEV_PGA_1:
        clrbit(cs1237_config, 2);
        clrbit(cs1237_config, 3);
        break;
    case DEV_PGA_2:
        clrbit(cs1237_config, 3);
        setbit(cs1237_config, 2);
        break;
    case DEV_PGA_64:
        clrbit(cs1237_config, 2);
        setbit(cs1237_config, 3);
        break;
    case DEV_PGA_128:
        setbit(cs1237_config, 2);
        setbit(cs1237_config, 3);
        break;
    default:
        clrbit(cs1237_config, 2);
        clrbit(cs1237_config, 3);
        break;
    }

    // 初始化 通道
    switch (ch)
    {
    case DEV_CH_A:
        clrbit(cs1237_config, 0);
        clrbit(cs1237_config, 1);
        break;
    case DEV_CH_SAVE:
        clrbit(cs1237_config, 1);
        setbit(cs1237_config, 0);
        break;
    case DEV_CH_TEMPERERATURE:
        clrbit(cs1237_config, 0);
        setbit(cs1237_config, 1);
        break;
    case DEV_CH_SHORT:
        setbit(cs1237_config, 1);
        setbit(cs1237_config, 1);
        break;
    default:
        clrbit(cs1237_config, 0);
        clrbit(cs1237_config, 1);
        break;
    }

    // cs1237_config = 0X0C;
    /* 初始化设备结构体 */
    dev->adc_data = 0;
    dev->output_frequency = frequency;
    dev->get_adc_data = calculate_adc_num;
    dev->get_adc_config = cs1237_read_config;
    dev->adc_config = cs1237_config;

    ret = cs1237_check(0,dev);
    if (ret != 0)
    {
        dev->dev_state_em = DEV_OFFLINE;
        ERROR_PRINT("cs1237_check failed!\r\n");
        return 1;
    }
    dev->dev_state_em = DEV_ONLINE;

    /* 配置 CS1237 工作模式 */
    // 发送1到29个脉冲
		for (uint8_t i = 0; i < 29; i++)
		{
				set_cs1237_sck(chip);
				delay_us(4);
				reset_cs1237_sck(chip);
				delay_us(4);
		}

		//set_cs1237_dout(chip); 
		set_cs1237_sck(chip);
		delay_us(1);
		set_cs1237_dout(chip); 
		reset_cs1237_sck(chip);
		delay_us(1); // 30
		set_cs1237_sck(chip);
		delay_us(1);
		set_cs1237_dout(chip); 
		reset_cs1237_sck(chip);
		delay_us(1); // 31
		set_cs1237_sck(chip);
		delay_us(1);
		reset_cs1237_dout(chip); 
		reset_cs1237_sck(chip);
		delay_us(1); // 32
		set_cs1237_sck(chip);
		delay_us(1);
		reset_cs1237_dout(chip); 
		reset_cs1237_sck(chip);
		delay_us(1); // 33
		set_cs1237_sck(chip);
		delay_us(1);
		set_cs1237_dout(chip); 
		reset_cs1237_sck(chip);
		delay_us(1); // 34
		set_cs1237_sck(chip);
		delay_us(1);
		reset_cs1237_dout(chip); 
		reset_cs1237_sck(chip);
		delay_us(1); // 35
		set_cs1237_sck(chip);
		delay_us(1);
		set_cs1237_dout(chip); 
		reset_cs1237_sck(chip);
		delay_us(1); // 36
		// 37     写入了0x65
		set_cs1237_sck(chip); // CLK=1;
		delay_us(1);
		reset_cs1237_sck(chip); // CLK=0;
		delay_us(1);

		cs1237_send_byte(chip,cs1237_config);

		set_cs1237_dout(chip);	// OUT = 1
		set_cs1237_sck(chip); 	// CLK=1;
		delay_us(1);
		reset_cs1237_sck(chip); // CLK=0;
		delay_us(1);

		INFO_PRINT("cs1237%x adc write config = %x\r\n",chip,cs1237_config);
		cs1237_read_config( chip ,dev);
		INFO_PRINT("cs1237%x adc read config = %x\r\n",chip,dev->adc_config);
    return 0;
}

/**
 * @name: cs1237_read_config
 * @msg: 读取芯片的配置数据
 * @param {cs1237_device} *dev 设备结构体
 * @return {*} 读取到的寄存器数据
 * @author: TOTHTOT
 * @date:
 */
uint8_t cs1237_read_config(uint8_t chip ,struct cs1237_device *dev)
{
    unsigned char i = 0;
    unsigned char dat = 0; // 读取到的数据
    uint8_t ret = 0;

    ret = cs1237_check(chip,dev);
    if (ret != 0)
    {
        dev->dev_state_em = DEV_OFFLINE;
        ERROR_PRINT("cs1237%x_check failed!\r\n",chip);
        return 1;
    }

    for (i = 0; i < 29; i++) // 产生第1到29个时钟
    {
        set_cs1237_sck(chip); ; // CLK=1;
        delay_us(1);
        reset_cs1237_sck(chip); // CLK=0;
        delay_us(1);
    }

    dev->dev_state_em = DEV_ONLINE;
    set_cs1237_dout(chip);

    set_cs1237_sck(chip); // CLK=1;
    delay_us(1);
    set_cs1237_dout(chip);
    reset_cs1237_sck(chip); // CLK=0;
    delay_us(1);  // 这是第30个时钟

    set_cs1237_sck(chip); // CLK=1;
    delay_us(1);
    reset_cs1237_dout(chip);
    reset_cs1237_sck(chip); // CLK=0;
    delay_us(1);  // 这是第31个时钟

    set_cs1237_sck(chip); // CLK=1;
    delay_us(1);
    set_cs1237_dout(chip);
    reset_cs1237_sck(chip); // CLK=0;
    delay_us(1);  // 32

    set_cs1237_sck(chip); // CLK=1;
    delay_us(1);
    reset_cs1237_dout(chip);
    reset_cs1237_sck(chip); // CLK=0;
    delay_us(1);  // 33

    set_cs1237_sck(chip); // CLK=1;
    delay_us(1);
    set_cs1237_dout(chip);
    reset_cs1237_sck(chip); // CLK=0;
    delay_us(1);  // 34

    set_cs1237_sck(chip); // CLK=1;
    delay_us(1);
    set_cs1237_dout(chip);
    reset_cs1237_sck(chip); // CLK=0;
    delay_us(1);  // 35

    set_cs1237_sck(chip); // CLK=1;
    delay_us(1);
    reset_cs1237_dout(chip);
    reset_cs1237_sck(chip); // CLK=0;
    delay_us(1);  // 36

    set_cs1237_dout(chip);
    set_cs1237_sck(chip); // CLK=1;
    delay_us(1);
    reset_cs1237_sck(chip); // CLK=0;
    delay_us(1);  // 37     写入0x56 即读命令

    dat = 0;
    set_cs1237_dout(chip);
    for (i = 0; i < 8; i++) // 第38 - 45个脉冲了,读取数据
    {
        set_cs1237_sck(chip); // CLK=1;
        delay_us(1);
        reset_cs1237_sck(chip); // CLK=0;
        delay_us(1);
        dat <<= 1;
        if (read_cs1237_dout(chip) == 1)
            dat++;
    }

    // 第46个脉冲
    set_cs1237_sck(chip); // CLK=1;
    delay_us(1);
    reset_cs1237_sck(chip); // CLK=0;
    delay_us(1);

//    CS1237_SDA_OUT_CH1;
    set_cs1237_dout(chip); // OUT引脚拉高

    dev->adc_config = dat;

    return dat;
}

/**
 * @name: cs1237_read_data
 * @msg: 读取ADC数据,返回的是一个有符号数据
 * @param {cs1237_device} *dev  设备结构体
 * @return {*} 读取到的adc数据
 * @author: TOTHTOT
 * @date:
 */
int32_t cs1237_read_data(uint8_t chip ,struct cs1237_device *dev)
{
    unsigned char i = 0;
    uint32_t dat = 0; // 读取到的数据
    uint8_t ret = 0;

    ret = cs1237_check(chip,dev);
    if (ret != 0)
    {
        dev->dev_state_em = DEV_OFFLINE;
        ERROR_PRINT("cs1237_check failed!\r\n");
        return 1;
    }

    dev->dev_state_em = DEV_ONLINE;
    dat = 0;
    for (i = 0; i < 24; i++) // 获取24位有效转换
    {
        set_cs1237_sck(chip); // CLK=1;
        delay_us(1);
        dat <<= 1;
        if (read_cs1237_dout(chip) == 1)
            dat++;
        reset_cs1237_sck(chip); // CLK=0;
        delay_us(1);
    }

    for (i = 0; i < 3; i++) // 接着前面的时钟 再来3个时钟
    {
        cs1237_send_bit(chip,1, 1);
    }

//    CS1237_SDA_OUT_CH1;
    set_cs1237_dout(chip); // OUT = 1;

    if (dat & 0x00800000) // 判断是负数 最高位24位是符号位
    {
        dev->adc_data = -(((~dat) & 0x007FFFFF) + 1); // 补码变源码
    }
    else
        dev->adc_data = dat; // 正数的补码就是源码

    return dev->adc_data;
}

/**
 * @name: calculate_adc_num
 * @msg:
 * @param {cs1237_device} *dev
 * @return {*}
 * @author: TOTHTOT
 * @date:
 */
int32_t calculate_adc_num(uint8_t chip ,struct cs1237_device *dev)
{
    int32_t max = 0, max_2 = 0, max_pos = 0, max_2_pos = 0;
    int32_t min = 0, min_pos = 0;

    // 采集 RAW_DATA_MAX_NUM 次 数据去掉最高和最低
    for (uint8_t i = 0; i < RAW_DATA_MAX_NUM; i++)
    {
        dev->adc_calculate_raw_data[i] = cs1237_read_data(chip,dev);
        if (dev->adc_calculate_raw_data[i] > max)
        {
            max = dev->adc_calculate_raw_data[i];
            max_pos = i;
            // INFO_PRINT("max = %d, pos = %d\r\n", max, max_pos);
        }
        if (i == 0)
        {
            min = dev->adc_calculate_raw_data[0];
            min_pos = 0;
            // INFO_PRINT("min = %d, pos = %d\r\n", min, min_pos);
        }
        if (dev->adc_calculate_raw_data[i] < min)
        {
            min = dev->adc_calculate_raw_data[i];
            min_pos = i;
            // INFO_PRINT("min = %d, pos = %d\r\n", min, min_pos);
        }
    }

    for (uint8_t i = 0; i < RAW_DATA_MAX_NUM; i++)
    {
        if (i == max_pos || i == min_pos)
        {
            continue;
        }

        dev->adc_calculate_deal_data += dev->adc_calculate_raw_data[i];
    }
    return (int)(dev->adc_calculate_deal_data = dev->adc_calculate_deal_data / (RAW_DATA_MAX_NUM - 2));
}

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值