STM32硬件SPI驱动ADS1118采集数据

1.SPI就不介绍了,能搜这个题目的人,如果不了解SPI的话,那么说明还需要去看一下SPI的协议。

2.ADS1118,就在CSDN关于这个芯片的解释很多,其中有几篇就写的不错。看这个博主写的就能明白大概:ADS1118笔记_路人丙&的博客-CSDN博客。我这篇呢也是记录一下一个折磨了我好几天的问题。32收到的数据总是移位,甚至不对劲。所以我写出来,如果有能帮到你,请点个小赞谢谢。也包含一些我的疑惑。

首先,这个芯片有两种数据长度格式,32位和16位模式。这两个模式的配置不是通过直接配置寄存器而设置的。而是通过初始化的时候,主设备往从设备传输的配置指令格式来自动设置的,比如你在一个初始化函数中。拉低了CS信号后连续发送两个16位的初始化指令或者先发送16位配置指令再发送16位0或者1,期间只要CS保持低,并且以后CS都保持低,那么这个芯片就会工作在32位的模式,而ADS返回的32位数据,前16位表示转换寄存器中的数据,后16位就表示配置寄存器中的数据。记住以后你只要想读取一次转换寄存器中的数据,你必须每次都发送32比特的任意数据,来触发32次的接收。STM32的HAL库中我配置SPI是8bit每次传输,所以我就要连续发送4次数据,那我就可以收到四次数据。我再组合一下就得到了我想要的两个数据。代码如下

//SPI1 读写一个字节
u8 SPI1_ReadWriteByte(u8 TxData)
{
	u8 Rxdata;
	volatile HAL_StatusTypeDef	ret;
    ret = HAL_SPI_TransmitReceive(&SPI1_Handler,&TxData,&Rxdata,1, 1000);       
 	return Rxdata;          		    //返回收到的数据		
}
//这下面这个函数就是为了方便,你也可以自己在初始化函数中调用两次上面这
//个SPI1_ReadWriteByte函数
uint16_t    ADS_Config[2]={0}; 
uint16_t     ADS_Vol_Data;
uint16_t Read_ADS_Data(uint8_t MSB,uint8_t LSB,uint16_t *config)
{
    uint16_t ADS_Data;
    //delay_us(2);        //拉低后等待2us
    ADS_Data=ADS1118_Send_Data(MSB,LSB);        //读取一次数据
    *config=ADS1118_Send_Data(0,0);
    return ADS_Data ;        //返回读到的数据
}


//初始化ADS118
void ADS1118_Config()
{
	PAout(4)=1;
    delay_us(1000);
	PAout(4)=0;
    ADS_Vol_Data=Read_ADS_Data(0x52,0x4a,ADS_Config);
	
}


//下面是主函数中的
while(1)
		{
			if(ADS1118_MISO_ReadPin==0)
			{
				delay_us(1);
		        ads_data= SPI1_ReadWriteByte(0x00)<<8;
				ads_data|=SPI1_ReadWriteByte(0x00);
				register_InitData=SPI1_ReadWriteByte(0x00)<<8;
				register_InitData|=SPI1_ReadWriteByte(0x00);
				
				ADC_Value=ads_data*4.096/32768;
				printf("ads_data=%x\n",ads_data);
				printf("register_InitData=%x\n",register_InitData);
				printf("ADC_VAlue=%.4f\n",ADC_Value);
				ads_data=0;
				register_InitData=0;
			} 
			while(ADS1118_MISO_ReadPin==0);
			
		}

16位的道理就是:你要控制CS片选信号,在配置的时候,拉低片选,然后发送16位配置数据,然后拉高片选CS,然后在主函数中,你每次读取数据都要拉低片选然后拉高片选。我没有配置16位的,不想去搞了累了,但是好像在配置16位的时候,要注意片选的问题,因为当片选为低的时候ADS1118不会工作。

下面讲重点:比如我采用32位模式,我写入ADS配置寄存器的指令原本是0x524a。按照ADS的手册来讲,第15位永远读取为0,最低位永远读取为1。其他位置就是你配置多少就是多少。那么当我配置这个0x524a的时候,按道理之后如果进行32bit的数据传输,那么就应该返回一个16位的转换寄存器数据,加上一个16位的配置寄存器数据。这16位的配置寄存器的数据应该是524b才对。但是传回的数据要么是a925,要么就是2925。

524A:0101 0010 0100 1010

A925:  1010  1001 0010 0101

2925: 0010 1001 0010 0101

还有其他的数据就不赘述了,反正都是错的。当我看到这个规律的时候,我上网一搜,喔这是发生了数据移位,有说要改时钟极性的,啥都有说。我都试了都没解决问题。

最后通过观察示波器,发现当ADS1118传输完一次数据之后会将DOUT数据线拉高,但是这个拉高有一定的时间,如下图所示。n表示拉高的时间段,懒得接示波器了我的芯片都拆了放好了才写的这个。如果我们在主函数的while循环中只是通过判断DOUT是否拉低就进行数据采集的话,那么问题就出现了:我ADS1118传输完数据之后,准备拉高DOUT,但是我的主函数中只判断这时候DOUT是不是低电平,如果恰好我们采集完一次数据之后又判断DOUT是不是低,而这时候刚好判断到第一个拉高箭头处的电平,此时电平还较小,那么系统就会将其判定为低电平,那么就会继续对该数据进行采样。而这并不是我们要的数据,所以就导致了各种各样的数据错误。我的解决办法就是,在采集完一帧数据之后,加一个while循环判断DOUT有没有拉高,等拉高之后再进行下一次判断。这就在上面也有。

while(ADS1118_MISO_ReadPin==0);

 加上这行代码之后,数据就接收正常了。就可以进行通信了。新手,有问题勿喷,这只是一个分享,旨在帮助遇到这个问题的人,因为我要是也能提前就有这个文章,我也不至于郁闷几天。我一直以为是我的时序有问题。下面是源代码的连接,里面还有三重ADC的配置文件,DMA配置文件,链接:https://pan.baidu.com/s/11g9hurf5X8RlCohgr8jwLg 
提取码:szb8 
--来自百度网盘超级会员V5的分享

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

出淤泥而半染

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

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

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

打赏作者

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

抵扣说明:

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

余额充值