Hallo Chris und Moppi,
danke für euer Reindenken. Hier die benötigten Informationen:
@Chris:
Der STM32 läuft mit 16MHz. Das reicht erstmal aus, um auch bei einer SCLK-Rate von 1MHz noch den einen Sensor erfolgreich auszulesen - wenn nichts anderes angeschlossen ist. Wie gesagt: neuerdings auf 500kHz reduziert.
Der Code ist unten. Ich habe ihn mal auf die SPI- und IMU-relevanten Sachen beschnitten. Dann müsst ihr nicht die ganzen 900 Zeilen Code durchschauen.
Ich gestalte lediglich die SS-Initialisierung mit:
SS auf high (Zeile 103)
Die anderen Leitungen stimmen zumindest zwischen den einzelnen SPI-Übertragung in der Polarität.
Wenn der Sensor positiv mit WHO_AM_I antwortet, aber noch nicht richtig konfiguriert ist, dann wird er erneut konfiguriert (Zeile 196). Dass das ab und zu passiert, sehe ich an einer LED, die in dann immer schalten lasse.
@Moppi:
Den Schaltplan habe ich angehangen. Auch reduziert auf's Wesentliche. Der Schaltplan vom IMU-Breakout-Board ist hier:https://cdn.sparkfun.com/datasheets/...eakout_v10.pdf
Ohne 100Ohm in Serie hatte ich es am Anfang des Jahres probiert. Diese Wiederstände bügeln etwas die steigenden und fallenden Flanken. Gerade bei langen Leitungen bekommt man die übertragenen Bits wieder etwas den Rechteck-Verläufen angenähert. Ansonsten kommt es zu teils recht starken Über- und Unterschwingern auf den Zielspannungsniveaus. Dann muss man allerdings mit der SCLK-Frequenz aufpassen, dass die nicht zu hoch gewählt wird, da sonst die Spannungsniveaus nicht mehr erreicht werden. Bei 500kHz ist das Verhalten aber ohnehin vernachlässigbar. Aber durchaus gängige Praxis, siehe
hier: https://www.first-sensor.com/cms/upl...CE_D_11156.pdf (S. 10)
oder hier: https://www.edaboard.com/threads/spi-serial-resistor.345440/
Wenn ihr noch etwas braucht, gebt Bescheid!
Vielen Dank euch!
Grüß, NRicola
Code:
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stdbool.h"
#include "math.h"
#include "../Peripherals/LSM6DS3.h" // Funktionen sind hier angehangen (siehe unten)
#include "../Peripherals/OLED_128x32.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c3;
SPI_HandleTypeDef hspi2;
UART_HandleTypeDef huart2;
DMA_HandleTypeDef hdma_usart2_rx;
/* USER CODE BEGIN PV */
const uint8_t IMU_datlength = 8; // die letzten x Messwerte werden mitgespeichert
struct IMU_Struct IMU1; // besteht aus IMU1.status, sowie 6 Arrays [0:IMU_datlength-1] für acc und gyr in x,y,z
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_SPI2_Init(void);
static void MX_I2C3_Init(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART2_UART_Init();
MX_SPI2_Init();
MX_I2C3_Init();
/* USER CODE BEGIN 2 */
IMU1.status=0;
for(uint8_t i=0;i<IMU_datlength-1;i++){
IMU1.acc_x[i] = 0;
IMU1.acc_y[i] = 0;
IMU1.acc_z[i] = 0;
IMU1.gyr_x[i] = 0;
IMU1.gyr_y[i] = 0;
IMU1.gyr_z[i] = 0;
}
//--------------------------------
IMU1_SS_Disable(); // SS auf high
HAL_Delay(20); // 20ms start-up time für IMUs
// OLED-Display
uint16_t OLED_refresh_cntr=0;
uint16_t OLED_refresh_max=5;
OLED_Init();
OLED_Clear_Screen();
OLED_IMU1_vars();
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
IMU1 = IMU1_Read_Values();
if(OLED_refresh_cntr>=OLED_refresh_max){ OLED_refresh_cntr=0; OLED_IMU1_vars(); // Messwerte des IMU1 anzeigen
}else{ OLED_refresh_cntr++;
}
}
/* USER CODE END 3 */
}
/**
* @brief SPI2 Initialization Function
* @param None
* @retval None
*/
static void MX_SPI2_Init(void)
{
/* USER CODE BEGIN SPI2_Init 0 */
/* USER CODE END SPI2_Init 0 */
/* USER CODE BEGIN SPI2_Init 1 */
/* USER CODE END SPI2_Init 1 */
/* SPI2 parameter configuration*/
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;
hspi2.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi2.Init.NSS = SPI_NSS_SOFT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI2_Init 2 */
/* USER CODE END SPI2_Init 2 */
}
//-------------------------------------------------------------------------------
//---------- Inhalt LSM6DS3.c ---------------------------------------------------
//-------------------------------------------------------------------------------
void IMU1_config(void){
const uint8_t CTRL1_XL_addr = 0x10;
const uint8_t CTRL1_XL_write = 0x3B; // 0011_10_11
const uint8_t CTRL2_G_addr = 0x11;
const uint8_t CTRL2_G_write = 0x34; // 0011_01_0_0
Send_2Bytes_IMU1(CTRL1_XL_addr,CTRL1_XL_write);
Send_2Bytes_IMU1(CTRL2_G_addr,CTRL2_G_write);
}
struct IMU_Struct IMU1_Read_Values(void){
const uint8_t WHO_AM_I = 0x69; // ist die korrekte Antwort, falls der Sensor da ist
const uint8_t addr_WHO_AM_I_read = 0x8F;
const uint8_t addr_CTRL1_XL_read = 0x90;
const uint8_t addr_acc_x_l_read = 0xA8;
const uint8_t addr_acc_x_h_read = 0xA9;
//------------------------------
//--------------------------------------------------
if (Read_1Byte_IMU1(addr_WHO_AM_I_read) == WHO_AM_I){ // Wenn IMU1 auf WHO_AM_I reagiert,
IMU1.status=1; //
if (Read_1Byte_IMU1(addr_CTRL1_XL_read) == 0){ IMU1_config(); // Falls der Accelerometer im Sensor nicht korrekt konfiguriert ist, konfiguriere nochmal neu
HAL_GPIO_TogglePin(LED_GN_GPIO_Port, LED_GN_Pin);
}
}else{
IMU1.status=0; // Status: Sensor ist nicht angeschlossen
}
if(IMU1.status==1){ // Wenn IMU1 erkannt,
IMU1_Status_SET(); // dann Status-LED anschalten
}else{
IMU1_Status_RESET(); // ansonsten Status-LED ausschalten
}
IMU1.acc_x[IMU_datlength-1]=Read_1Byte_IMU1(addr_acc_x_l_read); // einen Messwert lesen
return IMU1;
}
void Send_2Bytes_IMU1(uint8_t Byte1,uint8_t Byte2){
const uint8_t timeout = 10;
uint8_t TxBuffer[2];
TxBuffer[0]=Byte1;
TxBuffer[1]=Byte2;
IMU1_SS_Enable(); // SS auf low
HAL_SPI_Transmit(&hspi2, TxBuffer, 2, timeout);
IMU1_SS_Disable(); // SS auf high
}
uint8_t Read_1Byte_IMU1(uint8_t Byte){
const uint8_t timeout = 10;
uint8_t TxBuffer[2];
TxBuffer[0]=Byte; // Adresse des Read-Bytes
TxBuffer[1]=0;
uint8_t RxBuffer[2];
IMU1_SS_Enable(); // SS auf low
HAL_SPI_TransmitReceive(&hspi2, TxBuffer, RxBuffer, 2, timeout);
IMU1_SS_Disable(); // SS auf high
return RxBuffer[1];
}
Lesezeichen