This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TM4C1294NCPDT -在从其读取数据时移除 SSI 器件会产生环路问题

Guru**** 2539500 points
Other Parts Discussed in Thread: TM4C1294NCPDT

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/interface-group/interface/f/interface-forum/1133552/tm4c1294ncpdt---removing-ssi-device-while-reading-data-from-it-generates-loop-issue

主题中讨论的其他器件:TM4C1294NCPDT

大家好、

我的 SSI 通信有问题、我需要获得指导以更好地理解或处理代码生成的异常。  

-我有一个带有 tm4c1294ncpdt Tiva C 处理器的定制板  
-我有4个数字传感器( icm20602 ),我从这些传感器读取这些传感器,并通过 USB-c 连接到定制板
-这些传感器可以在运行时移除、当移除传感器时、数据收集停止、并在 Tiva 上触发软件复位、以从头开始。

有时、该 序列不会发生、它进入一个循环、然后在10s 后执行复位、一切都正常  

我怀疑在 我从传感器中簧入数据的确切时间移除传感器时、传感器会进入延迟环路

代码、 用于将传感器数据红色化为缓冲器、然后交换 ACC 和陀螺仪的字节

uint8_t read_icm20602_sensor(uint8_t sensor_id, uint8_t timeout, uint8_t *buffer) {
	uint8_t drdy_data;
	uint8_t whoamy_data;

	uint8_t icm_buff[14];

	select_digi_sensor(sensor_id);

//	SSI1_device_read(WHO_AM_I, 1, &whoamy_data);
//	if(whoamy_data != WHO_AM_I_DATA_OK) return 0;

	uint16_t buffer_index = ICM20602_DATA_SIZE * (sensor_id -1);

	while(timeout--){
		SSI1_device_read(INT_STATUS, 1, &drdy_data);
		if ((drdy_data & 0x01) == 0x01){

			SSI1_device_read(ACCEL_XOUT_H, 14, icm_buff);
			icm20602_buffer_byte_swap(&buffer[buffer_index], icm_buff);
			return 1;
		}
	}
	return 0;
}

执行 SSI 读取和发送的函数

unsigned char SSI1_transmit_data(unsigned char data) {
	uint32_t rx_buffer;

	while(SSIDataGetNonBlocking(SSI1_BASE, &rx_buffer));
	SSIDataPut(SSI1_BASE, data);

	while(SSIBusy(SSI1_BASE));
	SSIDataGet(SSI1_BASE, &rx_buffer);

//	while(SSIBusy(SSI1_BASE));// added for testing purpose, this waits till the buffer is full.

	return rx_buffer & 0x00FF;
}

void SSI1_device_read(uint8_t address, uint8_t size, uint8_t *buffer) {

	uint32_t i = 0;

	SSI1_cs_on();

	address |= 0x80;

	SSI1_transmit_data(address);

	for(i = 0; i < size; i++){
		buffer[i] = SSI1_transmit_data(0xFF);
	}

	SSI1_cs_off();
}

我是否监督代码中的内容或这些功能的处理

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    void read_4_sensor_device(uint8_t sensorId, uint8_t *buffer) {
    
    	if(sensorId == 1){
    		// ICM20602 1 if device is available read data from it
    		if (digi_sensor_status1){
    			digi_sensor_status1 = read_icm20602_sensor(SENSOR_ID_1, READ_TIMEOUT, &digi_sensor_buffer);
    		}
    		else{
    			if(isavailable_icm20602(SENSOR_ID_1)){
    				if (check_digi_byte() == 1){
    					digi_sensor_status1 = 1;
    					// no restart
    				}else{
    					// restart indicated
    					digi_sensor_current |= SENSOR_ACTIVE_1;
    				}
    			}
    			else{
    				digi_sensor_current &= ~SENSOR_ACTIVE_1;
    			}
    
    		}
    	}
    	if(sensorId == 1){
    		// ICM20602 2 if device is available read data from it
    		if (digi_sensor_status2){
    			digi_sensor_status2 = read_icm20602_sensor(SENSOR_ID_2, READ_TIMEOUT, &digi_sensor_buffer);
    		}
    		else{
    			if(isavailable_icm20602(SENSOR_ID_2)){
    				if (check_digi_byte() == 1){
    					digi_sensor_status2 = 1;
    					// no restart
    				}else{
    					// restart indicated
    					digi_sensor_current |= SENSOR_ACTIVE_2;
    				}
    			}
    			else{
    				digi_sensor_current &= ~SENSOR_ACTIVE_2;
    			}
    
    		}
    	}
    	if(sensorId == 2){
    		// ICM20602 3 if device is available read data from it
    		if (digi_sensor_status3){
    			digi_sensor_status3 = read_icm20602_sensor(SENSOR_ID_3, READ_TIMEOUT, &digi_sensor_buffer);
    		}
    		else{
    			if(isavailable_icm20602(SENSOR_ID_3)){
    				if (check_digi_byte() == 1){
    					digi_sensor_status3 = 1;
    					// no restart
    				}else{
    					// restart indicated
    					digi_sensor_current |= SENSOR_ACTIVE_3;
    				}
    			}
    			else{
    				digi_sensor_current &= ~SENSOR_ACTIVE_3;
    			}
    		}
    	}
    	if(sensorId == 2){
    		// ICM20602 4 if device is available read data from it
    		if (digi_sensor_status4){
    			digi_sensor_status4 = read_icm20602_sensor(SENSOR_ID_4, READ_TIMEOUT, &digi_sensor_buffer);
    		}
    		else{
    			if(isavailable_icm20602(SENSOR_ID_4)){
    				if (check_digi_byte() == 1){
    					digi_sensor_status4 = 1;
    					//				 no restart/
    				}else{
    					// restart indicated
    					digi_sensor_current |= SENSOR_ACTIVE_4;
    				}
    
    			}
    			else{
    				digi_sensor_current &= ~SENSOR_ACTIVE_4;
    			}
    		}
    	}
    	//Update the digital sensor statuses
    	digi_sensor_status &= 0x00;
    	digi_sensor_status = digi_sensor_status1 << DIGI_SENSOR_INDEX_1 | digi_sensor_status2 << DIGI_SENSOR_INDEX_2 | digi_sensor_status3<< DIGI_SENSOR_INDEX_3 | digi_sensor_status4 << DIGI_SENSOR_INDEX_4;
    
    	// TODO: Debug current digital sensor status
    	current_state = digi_sensor_status;
    
    
    	// TODO: Restart Handler
    	if(DIGI_SENSOR_AUTO_RESET){
    
    		// Currently running configuration
    		if(digi_sensor_status != digi_sensor_current && restart_timeout < 2){
    			// LEDs
    			GPIO_write(Board_LED1,1);
    			GPIO_write(Board_LEDS5,1);
    
    			restart_timeout = 1; // start counter - Enable the resetting variable and function
    		}
    		if (restart_timeout>0) // increment after once the restart_timeout=1
    			restart_timeout++;
    
    		if (restart_timeout>RESTART_TIMEOUT){
    			// Maybe to send the restart sequence as a semaphore
    			Semaphore_post(sw_simulated_reset_sem_handle);
    		}
    
    	}else{
    		if( digi_sensor_status != sensors_frozen_stats){ // Default frozen state  removed
    
    			// start reconfiguration procedure
    			Semaphore_post(hot_digi_reconfigure_sem_handle);
    			// hot_digi_reconfigure(); // update: digi_sensor_status
    
    			if(digi_sensor_status == sensors_frozen_stats){
    				GPIO_write(Board_LED1, 0);
    				GPIO_write(Board_LEDS5,0);
    			}
    			else{
    				GPIO_write(Board_LED1, 1);
    				GPIO_write(Board_LEDS5,1);
    			}
    		}
    		else{
    			GPIO_write(Board_LED1,0);
    			GPIO_write(Board_LEDS5,0);		// DS4 LED
    		}
    	}
    
    }

    RTOS 用于 Tiva。

    在测试了更多之后、我看到代码继续执行、但它仍然没有设置 LED、就像它从未进入第98行一样。 但是、当我签入调试时、我看到它正在收集数字数据、被删除的通道中有-1。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

     我不熟悉  icm20602。 我无法真正调试您的长代码行、因为我不知道您的应用是什么。 当您卸下传感器时、处理器的什么输入将指示传感器已卸下? 您必须有一种方法来检测并通知传感器已被移除、对吧?  icm20602中的 INT/DRDY 是否存在可用于检测传感器拆卸情况的信号? 如果 INT 是要使用的正确信号、则可以使用生成处理器的中断。 当处理器检测到中断时、在 ISR 中 、您可以将信标发布到挂起的任务、以生成软件复位。   据我所知、如果拆下传感器、则会切断处理器和传感器之间的 SPI 接口。 我认为您不能依赖读取一些状态来了解传感器是否已被移除。 这只是我的看法。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    我没有任何物理连接来确定传感器是否已连接。 我仅使用 SPI 线路和通信来确定是否连接了传感器。
    我读取 ICM 的 drdy 寄存器、如果数据准备就绪、则传感器已连接、并且我可以从中读取数据。 如果它为零、则处理器会将其注册为缺失的传感器。  我从传感器读取的数据速率为1kHz。
    由于该解决方案、我使用8kHz 采样率的数字传感器来始终提供数据。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    对于这个数字传感器、器件、有可能会使用计数信标、并且在某种程度上、一个引脚中断被禁用与代码的其它部分相关。

    现在没有计数信标并且中断也被禁用、这是否进入 RTOS 使用的 IDLE_LOOP 中。

    如果是,如何在永远 idle_loop 的情况下设置触发器,以便从该触发器中退出,可能需要进行软件复位

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="448168" URL"~/support/interface-group/interface/f/interface-forum/1133552/tm4c1294ncpdt---removing-ssi-device-while-reading-data-from-it-generates-loop-issue/4207818 #4207818")我读取 ICM 的 drdy 寄存器,如果数据准备就绪,而传感器已连接,我可以从中读取数据。 如果它为零、则处理器会将其注册为缺失的传感器。  [/报价]

    当 SPI 接口断开连接时、如何确保读数为零? SSI 主设备仍然驱动 SPICLK 和 CS、并希望从 RX 输入进行读取。 如果 RX 断开连接、则很可能是处于高电平或低电平或中间状态的浮动信号。 RX 上是否有下拉电阻器?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这是真的,我真的不知道,但在第二次尝试后应该清楚,还是不清楚? 是我们的假设。

    正如您所写的那样,我们真的不知道。 在调试后、我们发现当我们进入 这个延迟的复位序列时。 读取 INT_STATUS 寄存器时、移除的传感器仍会接收1、并接收传感器数据的0xFF。

    我们尝试的第一个解决方案是检查缓冲区的0xFF,如果0xFF 是复位的14倍,则继续。

    第二种解决方案是只读取传感器的世卫组织_AM_I 寄存器、而不是先读取 int_status 寄存器、然后读取数据。 这个解决了这个问题,第一个也是一个可能的解决办法,第二个更干净。