目录
最近有小伙伴问我,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));
}