ADC芯片CS1238,CS1237介绍和代码

一.芯片介绍

CS1238是一款高精度、低功耗 模数转换芯片,两路差分输入通道,内置温度传感器和高精度振荡器。MCU可以通过2线的SPI 接口SCLK、DRDY与CS1237进行通信,对其进行配置,例如通道选择、PGA选择、输出速率选择等。下面是CS1238和CS1237的一些特点。
在这里插入图片描述

二.硬件设计

CS1238的管脚定义如下

在这里插入图片描述
结合框架图,可以看出CS1238的使用方法比较简单,除去电源口就只有4个输入脚,CS1238和MCU的通信只要2个IO口模拟SPI。
在这里插入图片描述

三,程序设计

CS1238的程序设计比较简单,按照步骤为配置IO,写寄存器配置模式,读取ADC数据。一般只要配置两个IO口为输入和输出模式就可以。

在这里插入图片描述

//IO初始化
void CS1238_IO_Init(void)
{
	
	GPIO_InitTypeDef  GPIO_InitStructure;						
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;     
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	GPIO_SetBits(GPIOA, GPIO_Pin_12);	
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;   
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 	   
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		
	GPIO_Init(GPIOA, &GPIO_InitStructure);	
	GPIO_SetBits(GPIOA, GPIO_Pin_11);	
}

CS1238的程序重点在于他的读写时序,首先看下时序图。
在这里插入图片描述
在这里插入图片描述
CS1238一次完整的周期有48个时钟信号。每一个时钟的都有特定的作用,下面我们结合程序来看。首先写一个时钟周期。

//一个时钟周期
//高电平不能超过100uS,否则进入powerdown的休眠模式.
void cs1238_clock(void) 
{
    GPIO_SetBits(GPIOA, GPIO_Pin_12);
    delay_us(10);//延时10us
    GPIO_ResetBits(GPIOA, GPIO_Pin_12);
    delay_us(10);//延时10us
}

这里要注意到高电平的时间不可以超过100us,不然就会进入到睡眠模式。

在这里插入图片描述
我们1到24个时钟信号为读ADC数值,代码如下。

//CS1238读数据
int32_t read_cs1238_data(void)
{
	int i=0;
	uint32_t dat=0;//读取到的数据
	int32_t temp;

	//DOUT由高变低之后开始读取数据
	CS1238_OUT();
	GPIO_SetBits(GPIOA, GPIO_Pin_11);
	CS1238_IN();
	GPIO_ResetBits(GPIOA, GPIO_Pin_11);
	
	//等待芯片准备好,低电平准备好
	while(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11))
	{
     delay_ms(1);
	 i++;
		 if(i>100)//检测100ms
		 {
		    u2_printf("CS1238 Data error \r\n");
		    return 0;
		 }

	}
	
/* 1: clk1 ~ clk24 ADC数据*/
	for(i=0;i<24;i++)//获取24位有效转换
	{
		dat <<= 1;
		cs1238_clock();
		if(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11)==1)
		 {
			 dat |= 0x01; 
	 	 }
	} 
	
	
/* 1: clk25 ~ clk27 读取寄存器写操作状态*/	
	for(i=0;i<3;i++)
	{
     cs1238_clock();
	}	

	
	if(dat&0x00800000)// 判断是负数 最高位24位是符号位
	{
	  temp=(((~dat)&0x007FFFFF) + 1);// 补码变源码
		u2_printf("CS1238_data=  %x  \r\n", temp);
		return temp;

	} else temp=dat;// 正数的补码就是源码
	
	u2_printf("CS1238_data=  %x  \r\n", dat);
	return temp;
	
}

然后CS1238只有一个7位寄存器,功能为设置ADC的放大倍数和输出数据频率等。并且CS1238只有两个7bit的指令,为写寄存器和读寄存器的指令。
在这里插入图片描述

在这里插入图片描述
相对应的代码如下。

//写CS1238的寄存器,ad_reg为写入的寄存器数值
void	Write_AdReg(u8 ad_reg)
{
	int i;
	u8 Write_AdReg=0x00;
	
	 //DOUT由高变低之后开始读取数据
	CS1238_OUT();
	GPIO_SetBits(GPIOA, GPIO_Pin_11);
	CS1238_IN();
	GPIO_ResetBits(GPIOA, GPIO_Pin_11);
	
	//1-29,读ADC数值
	for(i=0;i<29;i++)
	{
	  cs1238_clock();
	}
	
	CS1238_OUT();
	Write_AdReg=0xCA;  //0X56为写命令,因为只有7个时钟,所以左移一位
	
/* 1: clk30 ~ clk36  写入写命令*/
	for(i=0;i<7;i++)   //30-36
	{
		if(Write_AdReg & 0x80)
		  {
		    GPIO_SetBits(GPIOA, GPIO_Pin_11);	// DATA=1
		  }
		else
		  {
				GPIO_ResetBits(GPIOA, GPIO_Pin_11);	// DATA=0;
		  }
	
		Write_AdReg = Write_AdReg << 1;
		cs1238_clock();  
	}
	
	//clk37切换写入写出方向
	cs1238_clock();   //37
  CS1238_OUT();
	
/* 1: clk38 ~ clk45  写入寄存器配置*/	
	Write_AdReg=ad_reg; //寄存器配置
	for(i=0;i<8;i++)    
	 {
	   if(Write_AdReg&0x80)
		  {
				GPIO_SetBits(GPIOA, GPIO_Pin_11);	// DATA=1
		  }
			else
			{
				GPIO_ResetBits(GPIOA, GPIO_Pin_11);	// DATA=0;
			}
			Write_AdReg = Write_AdReg << 1;
		  cs1238_clock();   
	 }
	
	GPIO_SetBits(GPIOA, GPIO_Pin_11);
	//clk46
	cs1238_clock();

}
//读CS1238寄存器
uchar_t Rd_AdReg(void) 
{
  int i;
	u8 RD_AdReg=0x00;
	
 //DOUT由高变低之后开始读取数据
	CS1238_OUT();
	GPIO_SetBits(GPIOA, GPIO_Pin_11);
	CS1238_IN();
	GPIO_ResetBits(GPIOA, GPIO_Pin_11);
	
	//1-29,读ADC数值
	for(i=0;i<29;i++)
	{
	  cs1238_clock();
	}
	
	CS1238_OUT();
	RD_AdReg = 0xAC;  //0X56为读命令,因为只有7个时钟,所以左移一位
	
/* 1: clk30 ~ clk36  写入读命令*/	
	for(i=0;i<7;i++)  
	{
		
	 if((RD_AdReg & 0x80)!=0)
	   {
       GPIO_SetBits(GPIOA, GPIO_Pin_11);	// DATA=1;
	   }
	 else
		 {
		   GPIO_ResetBits(GPIOA, GPIO_Pin_11);	// DATA=0;
	   }
	
	 RD_AdReg<<=1;
	 cs1238_clock();   
	}
	
  //clk37切换写入写出方向
	cs1238_clock();
	CS1238_IN()
	
/* 1: clk38 ~ clk45 输出寄存器配置*/
	RD_AdReg=0x00;
	for(i=0;i<8;i++)   
	{
		RD_AdReg<<=1;
		cs1238_clock();
		if((GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_11)==1))
		 {
			  RD_AdReg |= 0x01;  //为了保证前面输入的数据不变新输入的数据为高电平1时可以传进来
		 }
	}
		GPIO_SetBits(GPIOA, GPIO_Pin_11);
	  cs1238_clock();   //第46CLK
	  return RD_AdReg;	
}

最后是CS1238的初始化。

//CS1238初始化
void	CS1238_Init(void)
{
   CS1238_IO_Init();
	 //关闭REF输出,ADC输出640HZ,PGA1,通道选择A
	 Write_AdReg(0x60);
   Rd_AdReg();
}

然后调用CS1238读ADC的函数是返回一个24bit的数据,一般我习惯把他换算成mV的单位。

//计算CS1238的输入电压
float Get_CS1238_Voltage(void)
{
     CS1238_DATA=read_cs1238_data();   //获取cs1238的AD数值
     CS1238_IN=(CS1238_DATA/8388607)*CS1238_REF;   //计算差分输入的电压,8388607位满载
	 CS1238_AINP1=CS1238_IN/2+CS1238_AINN1;       //计算CS1238的+输入
	 u2_printf("CS1238_IN=%.0fmV  \r\n",CS1238_IN);
	 u2_printf("CS1238_AINP1=%.0f mV  \r\n",CS1238_AINP1);
	 u2_printf("CS1238_AINN1=%.0f mV  \r\n",CS1238_AINN1);
}

CS1237和CS1238的用法一样,只不过CS1237的输入只有一组差分输入。最后附上工程代码和资料,需要的可以联系我(不是白嫖的)。
在这里插入图片描述

  • 6
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

爱学习的王大胖子

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

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

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

打赏作者

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

抵扣说明:

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

余额充值