TI中文支持网
TI专业的中文技术问题搜集分享网站

ADS1292R: 使用STM32H723采集ADS1292R信号SCLK没有信号

Part Number:ADS1292ROther Parts Discussed in Thread: ADS1292

  您好!本人在使用STM32H723系列进行HAL库开发时,发现单片机始终无法采集ADS1292R模块的信息,就连正常的读取ADS1292R的寄存器功能也无法实现,困扰了好几天。为了排除是模块的问题,我使用C8T6的例程在C8T6上测试了一遍,发现能够正常读取寄存器,说明模块是正常工作的,只能是软件方面的问题。我的软件配置如下:

我检查过原理图,SPI4的几个引脚并没有被其他SPI外设占用。ADS1292R的供电为3.3V,SCLK周期没有低于最小值50ns。以下是我的寄存器读取代码:

	void ADS1292_Init(void) 
{		
		// 屏蔽外部中断线10
		HAL_NVIC_DisableIRQ(EXTI9_5_IRQn);
	
		ADS_CS_H; // 设置引脚状态为1		
		//__HAL_SPI_ENABLE(&hspi4);//使能SPI2
		//SPI2_ReadWriteByte(0X00); 
		ADS1292_PowerOnInit();//上电复位,进入待机模式	
		
		while(Set_ADS1292_Collect(0))//0 正常采集  //1 1mV1Hz内部侧试信号 //2 内部短接噪声测试
		{	
				printf("1292寄存器设置失败\r\n");
				HAL_Delay(1000);			
		}	
		printf("寄存器设置成功\r\n");
		HAL_Delay(1000);	
		HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);//开DRDY中断	
}



void ADS1292_SET_REGBUFF(void)
{
	ADS1292_REG[ID] =	ADS1292_DEVICE;//ID只读
	ADS1292_REG[CONFIG1] =	0x00;		//0000 0aaa	[7] 0连续转换模式  [6:3] 必须为0 
	ADS1292_REG[CONFIG1] |=	Ads1292_Config1.Data_Rate;//[2:0] aaa 采样率设置采样率

	ADS1292_REG[CONFIG2] =	0x00;		//1abc d0e1	[7] 必须为1  [2] 必须为0  [0] 设置测试信号为1HZ、±1mV方波 
	ADS1292_REG[CONFIG2] |=	Ads1292_Config2.Pdb_Loff_Comp<<6;	//[6]a 导联脱落比较器是否掉电
	ADS1292_REG[CONFIG2] |=	Ads1292_Config2.Pdb_Refbuf<<5;		//[5]b 内部参考缓冲器是否掉电
	ADS1292_REG[CONFIG2] |=	Ads1292_Config2.Vref<<4;					//[4]c 内部参考电压设置,默认2.42V
	ADS1292_REG[CONFIG2] |=	Ads1292_Config2.Clk_EN<<3;				//[3]d CLK引脚输出时钟脉冲?
	ADS1292_REG[CONFIG2] |=	Ads1292_Config2.Int_Test<<1;			//[1]e 是否打开内部测试信号,
	ADS1292_REG[CONFIG2] |=	0x81;//设置默认位
	
	ADS1292_REG[LOFF] =	0x10;//[7:5]	设置导联脱落比较器阈值 [4]	必须为1 		[3:2] 导联脱落电流幅值		[1]	必须为0	[0]	导联脱落检测方式 0 DC 1 AC 

	ADS1292_REG[CH1SET] =	0x00;	 //abbb cccc
	ADS1292_REG[CH1SET] |=Ads1292_Ch1set.PD<<7;		//[7]  a 		通道1断电?
	ADS1292_REG[CH1SET] |=Ads1292_Ch1set.GAIN<<4;	//[6:4]bbb	设置PGA增益
	ADS1292_REG[CH1SET] |=Ads1292_Ch1set.MUX;			//[3:0]cccc	设置通道1输入方式

	ADS1292_REG[CH2SET] =	0x00;	//abbb cccc
	ADS1292_REG[CH2SET] |=Ads1292_Ch2set.PD<<7;		//[7]  a 		通道2断电?
	ADS1292_REG[CH2SET] |=Ads1292_Ch2set.GAIN<<4;	//[6:4]bbb	设置PGA增益
	ADS1292_REG[CH2SET] |=Ads1292_Ch2set.MUX;			//[3:0]cccc	设置通道2输入方式
	
	ADS1292_REG[RLD_SENS] = 0X00; //11ab cdef	[7:6] 11 PGA斩波频率	fMOD/4 
	ADS1292_REG[RLD_SENS] |=Ads1292_Rld_Sens.Pdb_Rld<<5;					//[5]a	该位决定RLD缓冲电源状态
	ADS1292_REG[RLD_SENS] |=Ads1292_Rld_Sens.Rld_Loff_Sense<<4;	//[4]b	该位使能RLD导联脱落检测功能
	ADS1292_REG[RLD_SENS] |=Ads1292_Rld_Sens.Rld2N<<3;						//[3]c	这个位控制通道2负输入	用于右腿驱动的输出
	ADS1292_REG[RLD_SENS] |=Ads1292_Rld_Sens.Rld2P<<2;						//[2]d	该位控制通道2正输入		用于右腿驱动的输出
	ADS1292_REG[RLD_SENS] |=Ads1292_Rld_Sens.Rld1N<<1;						//[1]e	这个位控制通道1负输入	用于右腿驱动的输出
	ADS1292_REG[RLD_SENS] |=Ads1292_Rld_Sens.Rld1P;							//[0]f	该位控制通道1正输入		用于右腿驱动的输出	
	ADS1292_REG[RLD_SENS] |=	0xc0;//设置默认位

	ADS1292_REG[LOFF_SENS] = 0X00;  //00ab cdef	[7:6] 必须为0
	ADS1292_REG[LOFF_SENS] |=Ads1292_Loff_Sens.Flip2<<5;		//[5]a	这个位用于控制导联脱落检测通道2的电流的方向
	ADS1292_REG[LOFF_SENS] |=Ads1292_Loff_Sens.Flip1<<4;		//[4]b	这个位控制用于导联脱落检测通道1的电流的方向
	ADS1292_REG[LOFF_SENS] |=Ads1292_Loff_Sens.Loff2N<<3;	//[3]c	该位控制通道2负输入端的导联脱落检测
	ADS1292_REG[LOFF_SENS] |=Ads1292_Loff_Sens.Loff2P<<2;	//[2]d	该位控制通道2正输入端的导联脱落检测
	ADS1292_REG[LOFF_SENS] |=Ads1292_Loff_Sens.Loff1N<<1;	//[1]e	该位控制通道1负输入端的导联脱落检测
	ADS1292_REG[LOFF_SENS] |=Ads1292_Loff_Sens.Loff1P;			//[0]f	该位控制通道1正输入端的导联脱落检测
	
	ADS1292_REG[LOFF_STAT] =	0x00;		//[6]0 设置fCLK和fMOD之间的模分频比 fCLK=fMOD/4  [4:0]只读,导联脱落和电极连接状态
	
	ADS1292_REG[RESP1] = 0X00;//abcc cc1d
	ADS1292_REG[RESP1] |=Ads1292_Resp1.RESP_DemodEN<<7;//[7]a		这个位启用和禁用通道1上的解调电路		
	ADS1292_REG[RESP1] |=Ads1292_Resp1.RESP_modEN<<6;	//[6]b		这个位启用和禁用通道1上的调制电路	
	ADS1292_REG[RESP1] |=Ads1292_Resp1.RESP_ph<<2;			//[5:2]c	这些位控制呼吸解调控制信号的相位	
	ADS1292_REG[RESP1] |=Ads1292_Resp1.RESP_Ctrl;			//[0]d		这个位设置呼吸回路的模式
	ADS1292_REG[RESP1] |=	0x02;//设置默认位	
	
	ADS1292_REG[RESP2] = 0x00; //a000 0bc1	[6:3]必须为0 [0]必须为1
	ADS1292_REG[RESP2] |=	Ads1292_Resp2.Calib<<7;				//[7]a 启动通道偏移校正?
	ADS1292_REG[RESP2] |=	Ads1292_Resp2.freq<<2;				//[2]b 呼吸频率设置
	ADS1292_REG[RESP2] |=	Ads1292_Resp2.Rldref_Int<<1;	//[1]c RLDREF信号源外部馈电?
	ADS1292_REG[RESP2] |= 0X01;//设置默认位
	ADS1292_REG[GPIO] =	0x0C;			//GPIO设为输入		[7:4]必须为0	 [3:2]11 GPIO为输入 [1:0] 设置输入时,指示引脚电平,设置输出时控制引脚电平
}

//通过SPI总线与ADS1292通信
u8 ADS1292_SPI(u8 com)
{	
		return SPI2_ReadWriteByte(com);
}
//写命令
void ADS1292_Send_CMD(u8 data)
{
		ADS_CS_L;
		HAL_Delay(1);
		ADS1292_SPI(data);		
		HAL_Delay(1);	
		ADS_CS_H;
}


/*ADS1291、ADS1292和ADS1292R串行接口以字节形式解码命令,需要4个tCLK周期来解码和执行.
因此,在发送多字节命令时,4 tCLK周期必须将一个字节(或操作码)的结束与下一个字节(或操作码)分开。
假设CLK(时钟)为512 kHz,则tSDECODE (4 tCLK)为7.8125 us。
当SCLK(数据速率)为16mhz时,一个字节可以在500ns中传输,此字节传输时间不符合tSDECODE规范;
因此,必须插入一个延迟,以便第二个字节的末尾晚于7.3125us到达。
如果SCLK为1 MHz,则在8u秒内传输一个字节。由于此传输时间超过tSDECODE规范,处理器可以不延迟地发送后续字节。
在后面的场景中,可以对串行端口进行编程,使其从每个循环的单字节传输转移到多个字节*/

//读写多个寄存器
void ADS1292_WR_REGS(u8 reg,u8 len,u8 *data)
{
		u8 i;
		ADS_CS_L;	
		HAL_Delay(1);
		ADS1292_SPI(reg);
		HAL_Delay(1);
		ADS1292_SPI(len-1);
		if(reg&0x40) //写
		{
				for(i=0;i<len;i++)
				{
						HAL_Delay(1);		
						ADS1292_SPI(*data);
						data++;				
				}			
		}
		else //读		
		{
				for(i=0;i<len;i++)
				{
						HAL_Delay(1);		
						*data = ADS1292_SPI(0);
						data++;
				}
		}			
		HAL_Delay(1);	
		ADS_CS_H;
}


//寄存器数组写入寄存器
u8 ADS1292_WRITE_REGBUFF(void)
{
		u8 i,res=0;
		u8 REG_Cache[12];	//存储寄存器数据
		ADS1292_SET_REGBUFF();//设置寄存器数组		
		ADS1292_WR_REGS(WREG|CONFIG1,11,ADS1292_REG+1);//数组变量写入寄存器
		HAL_Delay(10);		
		ADS1292_WR_REGS(RREG|ID,12,REG_Cache);//读寄存器
		HAL_Delay(10);	
		
		for(i=0;i<12;i++	)	//检查寄存器	
		{		
				//printf("1111 device_id value: 0x%02X\r\n", REG_Cache[i]);
				//printf("Write: 0x%02X, Read: 0x%02X\r\n", ADS1292_REG[i], REG_Cache[i]);
				if(ADS1292_REG[i] != REG_Cache[i])
				{
						if(i!= 0 && i!=8 && i != 11)	//0 8 和11是ID 导联脱落和GPIO相关
								res=1;
						else
								continue;
				}					
		}	

		return res;				
}


void ADS1292_PowerOnInit(void)
{	
		//u8 i;
		//u8 REG_Cache[12];	
	
		ADS1292_Send_CMD(SDATAC);//发送停止连续读取数据命令
		HAL_Delay(100);	
		ADS1292_Send_CMD(RESET);//复位
		HAL_Delay(1000);		
		ADS1292_Send_CMD(SDATAC);//发送停止连续读取数据命令
		HAL_Delay(100);		
}



//设置通道1内部1mV测试信号
u8 ADS1292_Single_Test(void) //注意1292R开了呼吸解调,会对通道一的内部测试信号波形造成影响,这里只参考通道2即可,1292不受影响
{
		u8 res=0;
		Ads1292_Config2.Int_Test = INT_TEST_ON;//打开内部测试信号
		Ads1292_Ch1set.MUX=MUX_Test_signal;//测试信号输入	
		Ads1292_Ch2set.MUX=MUX_Test_signal;//测试信号输入	
		
		if(ADS1292_WRITE_REGBUFF())//写入寄存器
				res=1;	
		HAL_Delay(10);			
		return res;		
}
//设置内部噪声测试
u8 ADS1292_Noise_Test(void)
{
		u8 res=0;
		Ads1292_Config2.Int_Test = INT_TEST_OFF;//关内部测试信号
		Ads1292_Ch1set.MUX = MUX_input_shorted;//输入短路	
		Ads1292_Ch2set.MUX = MUX_input_shorted;//输入短路	

		if(ADS1292_WRITE_REGBUFF())//写入寄存器
				res=1;	
		HAL_Delay(10);			
		return res;			
}

//正常信号采集模式
u8 ADS1292_Single_Read(void)
{
		u8 res=0;
		Ads1292_Config2.Int_Test = INT_TEST_OFF;//关内部测试信号
		Ads1292_Ch1set.MUX = MUX_Normal_input;//普通电极输入
		Ads1292_Ch2set.MUX = MUX_Normal_input;//普通电极输入
	
		if(ADS1292_WRITE_REGBUFF())//写入寄存器
				res=1;
		HAL_Delay(10);		
		return res;		
}	

//配置ads1292采集方式
u8 Set_ADS1292_Collect(u8 mode)
{
		u8 res;
		
		HAL_Delay(10);	
		switch(mode)//设置采集方式
		{
				case 0:
					res =ADS1292_Single_Read();												
				break;
				case 1:
					res =ADS1292_Single_Test();											
				break;
				case 2:
					res =ADS1292_Noise_Test();											
				break;
		}		
		if(res)return 1;//寄存器设置失败		
		ADS1292_Send_CMD(RDATAC); //启动连续模式
		HAL_Delay(10);		
		ADS1292_Send_CMD(START);	//发送开始数据转换(等效于拉高START引脚)	
		HAL_Delay(10);		
		return 0;
}



uint8_t SPI2_ReadWriteByte(uint8_t TxData)
{		
	uint8_t retry=0;
	uint8_t RxData=0;	
	while (__HAL_SPI_GET_FLAG(&hspi4, SPI_FLAG_TXE) == RESET) //检查指定的SPI标志位设置与否:发送缓存空标志位
		{
		retry++;
			printf("1111 device_id value: 0x%02X\r\n", RxData);
		if(retry>200)return 0;
		}
	HAL_SPI_Transmit(&hspi4, &TxData, 1, HAL_MAX_DELAY); //通过外设SPIx发送一个数据
	retry=0;

	while (__HAL_SPI_GET_FLAG(&hspi4, SPI_FLAG_RXNE) == RESET) //检查指定的SPI标志位设置与否:接受缓存非空标志位
		{
			//printf("1111 device_id value: 0x%02X\r\n", RxData);
			printf("SPI State: %d\n", hspi4.State);

		retry++;
		if(retry>200)return 0;
		}
	HAL_SPI_Receive(&hspi4, &RxData, 1, HAL_MAX_DELAY);
		//printf("1111 device_id value: 0x%02X\r\n", RxData);
		
	return RxData; //返回通过SPIx最近接收的数据
}  

经过调试,发现是卡在SPI2_ReadWriteByte(uint8_t TxData)函数的第二个循环里了,也就是说标志位__HAL_SPI_GET_FLAG(&hspi4, SPI_FLAG_RXNE) == RESET一直没有置位,说明接收缓存区始终为空。我自己xiel一个ADC采集,来采集SCLK的电压,发现SCLK一直没有波形,而在C8T6上SCLK是有波形的。这到底是为什么?求解答!

Amy Luo:

您好,

对于STM32H723 软件方面的问题建议你咨询ST 公司的技术支持。

对 ADS1292R 若有什么问题或疑问,你可以在此论坛发帖我们一起讨论。

赞(0)
未经允许不得转载:TI中文支持网 » ADS1292R: 使用STM32H723采集ADS1292R信号SCLK没有信号
分享到: 更多 (0)

© 2024 TI中文支持网   网站地图 鲁ICP备2022002796号-1