清晰提问,多图。ADS1118问题。经验者请进。DOUT/DRDY引脚为什么始终高电平?
题主新手,已经调了1周多了,还是没通。望经验者赐教。
一:
因为是新手,所以就说明书一些概念先提出并于答主先确认,如下。
1. SPS是ADC采样速率,与SPI通讯时的SCLK频率无关。
2.SCLK最小周期为250纳秒.(datasheet page 8),也就是说SPI的SCLK频率必须小于4MHZ。
3.在CS片选信号为高电平并且使能ADS1118的寄存器的PULL_UP_EN位(datasheet page 26)的情况下,则DOUT/DRDY引脚为高阻态。再者由datasheet page 22的9.5.2小节所述。得出,CS为高电平时,DOUT/DRDY引脚不能标记模数转换的结果就绪。也就是说必须在CS拉低的情况下,再根据DOUT/DRDY的引脚电平来判断数据是否就绪。
4.单次转换模式初始化伪代码如下,关键是流程所以许多细节省略,真实代码无编译和语法问题,请关注流程。控制器为stm32F746 discovery。时钟cube生成工程和固件库函数。时钟32位传输周期,单次转换模式。
/*配置ADS1118*/
//主控端各种初始化,GPIO,SPI,中断等等
InitFunc();
//ADS1118配置寄存器的参数
adsCfg.RESERVED = 1;
adsCfg.NOP = 1;
adsCfg.PULL_UP_EN = 1;
adsCfg.TS_MODE = 0;
adsCfg.DR = 7;
adsCfg.MODE = 1;
adsCfg.PGA = 1; //
adsCfg.MUX = 4;
adsCfg.SS = 0;
//
adsCfgHighByte = (uint_8)adsCfg>>8;
adsCfgLowByte = (uint_8)adsCfg;
//拉低CS后传出配置字,传完后拉高CS
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,GPIO_PIN_RESET); //拉低CS
retFunc = HAL_SPI_TransmitReceive(&hspi2, &adsCfgHighByte, (uint8_t *)&aRxBuffer1, 1, 5000); //发送配置的高8位
retFunc = HAL_SPI_TransmitReceive(&hspi2, &adsCfgLowByte, (uint8_t *)&aRxBuffer2, 1, 5000); //发送配置的低8位
retFunc = HAL_SPI_TransmitReceive(&hspi2, &adsCfgHighByte, (uint8_t *)&aRxBuffer3, 1, 5000); //再次发送配置的高8位
retFunc = HAL_SPI_TransmitReceive(&hspi2, &adsCfgLowByte, (uint8_t *)&aRxBuffer4, 1, 5000); //再次发送配置的低8位
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,GPIO_PIN_RESET); //拉高CS
/*至此配置结束*/
5.读转换结果代码如下,紧接上面代码
/*读取结果开始*/
while(1)
{
//更新读取结果时的寄存器配置
adsCfg.SS = 1;//配置寄存器的bit15置1,意图为启动转换。
adsCfgHighByte = (uint_8)adsCfg>>8;
adsCfgLowByte = (uint_8)adsCfg;
//拉低CS后传出配置字,该配置字SS位置1,也就是说将启动AD转换。传完后拉高CS
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,GPIO_PIN_RESET); //拉低CS
retFunc = HAL_SPI_TransmitReceive(&hspi2, &adsCfgHighByte, (uint8_t *)&aRxBuffer1, 1, 5000); //发送配置的高8位
retFunc = HAL_SPI_TransmitReceive(&hspi2, &adsCfgLowByte, (uint8_t *)&aRxBuffer2, 1, 5000); //发送配置的低8位
retFunc = HAL_SPI_TransmitReceive(&hspi2, &adsCfgHighByte, (uint8_t *)&aRxBuffer3, 1, 5000); //再次发送配置的高8位
retFunc = HAL_SPI_TransmitReceive(&hspi2, &adsCfgLowByte, (uint8_t *)&aRxBuffer4, 1, 5000); //再次发送配置的低8位
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,GPIO_PIN_RESET); //拉高CS
HAL_Delay(1); //延时1毫秒
//关键问题,循环等待DOUT/DRDY引脚变为低电平,该引脚若跳变到低电平则说明转换完成.
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,GPIO_PIN_RESET); //拉低CS
do
{
rdyStat = HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_14); //UNREADY为高电平,也就是未准备就绪.GPIO_PIN_14就是DOUT/DRDY引脚
}while( rdyStat == UNREADY) //循环等待直至准备就绪才离开循环。既DRDY引脚为低电平.
//再次配置寄存器
adsCfg.SS = 0;//配置寄存器的bit15置0,因为单次转换所以每次都必须配置寄存器(我也不确定,论坛里的ADS1118代码都是如此)。
adsCfgHighByte = (uint_8)adsCfg>>8;
adsCfgLowByte = (uint_8)adsCfg;
//刚才循环处已经拉低CS,不再拉低
retFunc = HAL_SPI_TransmitReceive(&hspi2, &adsCfgHighByte, (uint8_t *)&aRxBuffer1, 1, 5000); //发送配置的高8位
retFunc = HAL_SPI_TransmitReceive(&hspi2, &adsCfgLowByte, (uint8_t *)&aRxBuffer2, 1, 5000); //发送配置的低8位
retFunc = HAL_SPI_TransmitReceive(&hspi2, &adsCfgHighByte, (uint8_t *)&aRxBuffer3, 1, 5000); //再次发送配置的高8位
retFunc = HAL_SPI_TransmitReceive(&hspi2, &adsCfgLowByte, (uint8_t *)&aRxBuffer4, 1, 5000); //再次发送配置的低8位
HAL_GPIO_WritePin(GPIOA,GPIO_PIN_8,GPIO_PIN_RESET); //拉高CS
}
6.时钟极性闲置时为低电平,第二个边沿捕获数据。datasheet page 22的9.5.4。
二. 总结问题:
若上文中有概念说的不对,或者写的不对(语法省略了很多,只留下主要流程)的话,请帮忙指出。
我现在的程序无论如何都跑不出红色处的循环,也就是说,DRDY引脚始终为高电平。
我把发送的代码单独提出来,用分析仪抓了下波形。根据极性和捕获边沿的设置,发送的数据是没错的。如下,上面是MOSI,下面是SCLK。
现在就是不能正常工作,请问是不是还有哪里需要注意,或者流程哪做的不对?
而且直接读取其默认配置字,也不能读出0X058B,非常不解。
排过版的,一发全乱了,请点击题主顶层里(就是提问题的那层楼)的回复按钮,排版就会恢复。。
排过版,一发就乱了,请诸位点题主提问层的恢复按钮,就会恢复排版了。。
1. 采样率跟SPI时钟没有直接关系,但是采样率越高,SPI的读取速率也需要更快,相比的话SPI时钟也需要这么高。
2. 是的,时钟有一个最高的限制。
3.片选拉为低以后,等到ready信号有效后读取。
4.建议先使用I/O模拟SPI来读写,再使用芯片自带的SPI设置。MCU自带的SPI如果之前用过,比较熟悉,那么使用这个SPI也是可以的。但是I/O模拟的SPI会相对比较灵活一点。
5.首先保证配置寄存器可以正常读写,再试图读取转换数据。
谢谢解答,问题已经找到,是硬件接线问题。供电电压给了5V,而ARDUINO接口为3.3V,导致逻辑电平错误。