51 单片机实战教程(13 外围芯片驱动程序之CS1237芯片驱动)

48 篇文章 19 订阅

        CS1237芯片是一枚国产24位A/D转换芯片,输出速率可选:10Hz、40Hz、640Hz、1.28kHz。内置时钟电路,不需外部晶振。带可编程PGA,PGA放大倍数可选:1、2、64、128。2 线 SPI通信接口,最快速率为 1.1MHz。供电电压:5V/3.3V。芯片应用场合:工业过程控制、电子秤、血压计、智能变换器、便携式设备等。

          CS1237采用SOP8封装,Pin脚定义如下:

       CS1237 SPI  串口通信

其基本时序如图所示:

CS1237读取数据时序图1:

CS1237读取数据时序图 2:

 读取数据时序表:

功能配置:

SPI命令字:

 CS1237有 2 个命令字,命令字的长度为 7bits,命令字描述如下:

CS1237命令字说明表:

CS1237 Config寄存器:

有了这些,就可以写CS1237的驱动库函数了。新建两个文件分别以cs1237.h,cs1237.c存入C51 Template文件夹下Library文件夹中。完成后的头文件如下:

/*cs1237.h
  Designed by Bill Liu
  Version 0.0 
  Modified last by Bill Liu on 12/10/2021
*/
#ifndef __CS1237_H__
#define __CS1237_H__

#include "mtype.h"
#include "delay.h"
#include "myport.h"    //CS1237_SCLK and CS1237_DOUT were defined

extern FSYSCLOCK FSCLK;
//************************************************************************************************************
typedef enum
{
	C1237_10HZ = 0,
	C1237_40HZ = 1,
	C1237_640HZ = 2,
	C1237_1280HZ = 3
}C1237_SPEED;

//************************************************************************************************************
typedef enum
{
	C1237_PGA_1 = 0,
	C1237_PGA_2 = 1,
	C1237_PGA_64 = 2,
	C1237_PGA_128 = 3
}C1237_PGA;

//************************************************************************************************************
typedef enum
{
	C1237_CHA = 0, //adc channel
	C1237_RST = 1, //cheap reserved
	C1237_TEM = 2, //temperature test
	C1237_INS = 3 //internal short
}C1237_CHN;

/************************************************************************************************************
Function: C1237_InClk();
Return value: void
Discription: C1237 input a clk pusle for to read or write
Example:
  C1237_InClk();
*************************************************************************************************************/
void C1237_InClk();

/************************************************************************************************************
Function: CS1237_ReadReg();
Return value: ui8
Discription: read CS1237 register
Example:
  CS1237_ReadReg();
*************************************************************************************************************/
ui8 CS1237_ReadReg();

/************************************************************************************************************
Function: C1237_WriteReg(ui8 mData);
Return value: void
Discription: wreite data to C1237 register
Example:
  C1237_WriteReg(mData);
*************************************************************************************************************/
void C1237_WriteReg(ui8 mData);

/************************************************************************************************************
Function: C1237_Init(BOOL refOutable,C1237_SPEED msel,C1237_PGA mselPga,C1237_CHN mselChn);
Return value: void
Discription: CS1237 init
Example:
  C1237_Init(0,C1237_10HZ,C1237_PGA_1,C1237_CHA);//ref voltage out disable,speed 10Hz,Pga 1, work at Adc mode
*************************************************************************************************************/
void C1237_Init(BOOL refOutable,C1237_SPEED msel,C1237_PGA mselPga,C1237_CHN mselChn);

/************************************************************************************************************
Function: C1237_ReadResult();
Return value: ui32
Discription: read C1237 A/D result
Example:
  C1237_ReadResult();
*************************************************************************************************************/
ui32 C1237_ReadResult();

#endif

完成后的源代码如下:

/*cs1237.c
  Designed by Bill Liu
  Version 0.1 
  Modified last by Bill Liu on 2/18/2022
*/

#include "cs1237.h"

//*************************************************************************************************************
void C1237_InClk()
{
  CS1237_SCLK= 1;
  Delayxus(2,FSCLK); 
  CS1237_SCLK = 0;
  Delayxus(2,FSCLK); 
}
//End of C1237_InClk()

//*************************************************************************************************************
ui8 CS1237_ReadReg() 
{
  ui8 i = 0;
	ui8 tem = 0;
	CS1237_SCLK = 0;
	CS1237_DOUT = 1;
	while( CS1237_DOUT);
	for(i = 0; i < 27; i++) //1-26th CLK
			C1237_InClk();;
	CS1237_DOUT = 1; //cs1237 direction input
	//C1237_InClk();	 //27th CLK
	C1237_InClk();	 //28th CLK
	C1237_InClk();   //29th CLK
	tem = 0x56;
	for(i = 0; i < 7; i++) //30~36th CLK
	{
		
		if(tem &0x40)
			CS1237_DOUT = 1;
		else
			CS1237_DOUT = 0;
		C1237_InClk();;
		tem <<= 1;
	}
	CS1237_DOUT = 1; //cs1237 change to output direction
	C1237_InClk();; //37th CLK
	for(i = 0; i < 8; i++) //37~45th CLK
	{
		tem <<= 1;
		C1237_InClk();
		if(CS1237_DOUT)
			tem++;
	}
	C1237_InClk();; //46th CLK
  return tem;
}
//End of CS1237_ReadReg()

//*************************************************************************************************************
void C1237_WriteReg(ui8 mData)
{
  ui8 i = 0;
	ui8 tem = 0;
	CS1237_SCLK = 0;
	CS1237_DOUT = 1;
	while(CS1237_DOUT);
	for(i = 0; i < 27; i++) //1~26th CLK
		C1237_InClk();
	CS1237_DOUT = 1; //force high
	//C1237_InClk();//27th CLK
	C1237_InClk();//28th CLK
	C1237_InClk();//29th CLK
	tem = 0x65;
	for(i = 0; i < 7; i++)//30~36th CLK
	{
		
		if(tem & 0x40)
			CS1237_DOUT = 1;
		else
			CS1237_DOUT = 0;
		C1237_InClk();
		tem <<= 1;
	}
	CS1237_DOUT = 0; //direction chage to intput direction
	C1237_InClk(); //37th CLK
	for(i = 0; i < 8; i++) //38~45th CLK
	{
		
		if(mData&0x80)
			CS1237_DOUT = 1;
		else
			CS1237_DOUT = 0;
		mData <<= 1;
		C1237_InClk(); 
	}
	C1237_InClk();//46th CLK

}
//End of C1237_WriteReg(ui8 mData)

//*************************************************************************************************************
void C1237_Init(BOOL refOutable,C1237_SPEED msel,C1237_PGA mselPga,C1237_CHN mselChn)
{
  ui8 tem = 0;
  if(refOutable)
    ResetBit(&tem, 6);
  else
    SetBit(&tem, 6);
  SetBits(&tem,5,4,msel);
  SetBits(&tem,3,2,mselPga);
  SetBits(&tem,1,0,mselChn);
  C1237_WriteReg(tem);
}
//End of C1237_Init(BOOL refOutable,C1237_SPEED msel,C1237_PGA mselPga,C1237_CHN mselChn) 

//*************************************************************************************************************
ui32 C1237_ReadResult()
{
  ui8 i;
	ui32 rdata = 0;
  CS1237_SCLK= 0;
	CS1237_DOUT = 1;
  while(CS1237_DOUT);          //waite ADC finish
  for(i = 0; i < 24; i++)
  {
    rdata <<= 1;
    C1237_InClk();
    if(CS1237_DOUT) //read data
      rdata++;
  }
  C1237_InClk();
  C1237_InClk();
  C1237_InClk();
  return rdata;
}
//End of C1237_ReadResult()

受一些因素影响,可能个别ADC数据不是很准确,需要消除或减小其影响,我们可以采用多值平均法,阀值剔除法等数字滤波手法,有了以上库函数就可以轻松实现。读写验证如下:

 上面串口接收区的值为寄存器读出值。

下面是AD转换结果。

 

 

  • 17
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论
下面是一个基于C语言的CS1237驱动程序示例,供参考: ``` #include <stdint.h> #include <stdlib.h> #include "spi.h" #define CS_PIN 10 #define W_CMD 0x80 #define R_CMD 0x00 /* 读取CS1237的一个寄存器值 */ uint16_t read_cs1237_reg(uint8_t reg_addr) { uint16_t reg_val = 0; uint8_t cmd_buf[3] = {W_CMD, reg_addr, 0}; uint8_t val_buf[2] = {0}; spi_start_transaction(CS_PIN); spi_transfer(cmd_buf, 3); spi_transfer(val_buf, 2); spi_end_transaction(CS_PIN); reg_val = (val_buf[0] << 8) | val_buf[1]; return reg_val; } /* 初始化CS1237芯片 */ void init_cs1237() { spi_init(); pinMode(CS_PIN, OUTPUT); digitalWrite(CS_PIN, HIGH); } /* 读取电压值 */ float read_voltage() { uint16_t raw_val = read_cs1237_reg(0x03); float voltage = (float)raw_val * 0.00030518; // 转换为实际电压值 return voltage; } /* 读取电流值 */ float read_current() { uint16_t raw_val = read_cs1237_reg(0x05); float current = (float)raw_val * 0.00001526; // 转换为实际电流值 return current; } /* 读取功率值 */ float read_power() { uint16_t raw_val = read_cs1237_reg(0x07); float power = (float)raw_val * 0.00152588; // 转换为实际功率值 return power; } /* 读取能量值 */ float read_energy() { uint32_t raw_val = read_cs1237_reg(0x09); float energy = (float)raw_val * 0.0000000954; // 转换为实际能量值 return energy; } /* 主函数 */ int main() { init_cs1237(); while (1) { float voltage = read_voltage(); float current = read_current(); float power = read_power(); float energy = read_energy(); // 输出读取的数据 printf("Voltage: %f V\tCurrent: %f A\tPower: %f W\tEnergy: %f J\r\n", voltage, current, power, energy); delay_ms(1000); // 延时1秒 } return 0; } ``` 该驱动程序使用了一个SPI库,需要提前初始化SPI接口。在主函数中,循环读取电压、电流、功率和能量,并将其转换为实际值输出到串口。请注意,该示例代码仅供参考,实际应用中需要根据具体的单片机和需求进行修改和优化。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bill66

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值