Przeszukaj forum
Pokazywanie wyników dla tagów 'HAL'.
Znaleziono 3 wyniki
-
Potrzebowałem na szybko biblioteki dla wyświetlacza OLED 1.5" Wziąłem pierwszą z brzegu: https://github.com/hexaguin/SSD1327 i przystosowałem ją aby działała na mikrokontroler STM32L476 z HAL: .h #ifndef SSD1327_SSD1327_H_ #define SSD1327_SSD1327_H_ #include "main.h" #include "stdbool.h" #include "spi.h" // Scroll rate constants. See datasheet page 40. #define SSD1327_SCROLL_2 0b111 #define SSD1327_SCROLL_3 0b100 #define SSD1327_SCROLL_4 0b101 #define SSD1327_SCROLL_5 0b110 #define SSD1327_SCROLL_6 0b000 #define SSD1327_SCROLL_32 0b001 #define SSD1327_SCROLL_64 0b010 #define SSD1327_SCROLL_256 0b011 // void writeCmd(uint8_t reg); void writeData(uint8_t data); void setWriteZone(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2); uint16_t coordsToAddress(uint8_t x, uint8_t y); void setPixelChanged(uint8_t x, uint8_t y, bool changed); void SSD1327drawPixel(uint8_t x, uint8_t y, uint8_t color, bool display); void SSD1327drawRect(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t color, bool display); void SSD1327drawHLine(int x, int y, int length, uint8_t color, bool display); void SSD1327drawVLine(int x, int y, int length, uint8_t color, bool display); void SSD1327drawLine(int x1, int y1, int x2, int y2, uint8_t color, bool display); void SSD1327drawByteAsRow(uint8_t x, uint8_t y, uint8_t byte, uint8_t color); void SSD1327drawChar(uint8_t x, uint8_t y, char thisChar, uint8_t color); void SSD1327drawChar16(uint8_t x, uint8_t y, char thisChar, uint8_t color); void SSD1327drawChar32(uint8_t x, uint8_t y, char thisChar, uint8_t color); void SSD1327drawCharArray(uint8_t x, uint8_t y, char text[], uint8_t color, int size); void SSD1327drawString(uint8_t x, uint8_t y, char * textString, uint8_t color, int size); void setupScrolling(uint8_t startRow, uint8_t endRow, uint8_t startCol, uint8_t endCol, uint8_t scrollSpeed, bool right); void startScrolling(); void stopScrolling(); void scrollStep(uint8_t startRow, uint8_t endRow, uint8_t startCol, uint8_t endCol, bool right); void fillStripes(uint8_t offset); void SSD1327clearBuffer(); void SSD1327writeFullBuffer(); void writeUpdates(); void SSD1327setContrast(uint8_t contrast); void SSD1327initRegs(); void SSD1327init(SPI_HandleTypeDef * hspi); extern uint8_t frameBuffer[8192]; // Should mirror the display's own frameBuffer. extern uint8_t changedPixels[1024]; // Each bit of this array represets whether a given byte of frameBuffer (e.g. a pair of pixels) is not up to date. #endif /* SSD1327_SSD1327_H_ */ .c /* * ssd1327.c * * Created on: Apr 22, 2022 * Author: dell */ #include "main.h" #include "spi.h" #include "dma.h" #include "ssd1327.h" #include "stdbool.h" #include "stdlib.h" #include "math.h" #include "font8x8_basic.h" #include "font16x16.h" #include "font16x32.h" #define CS_SET HAL_GPIO_WritePin(SSD_CS_GPIO_Port, SSD_CS_Pin,GPIO_PIN_SET) #define CS_RESET HAL_GPIO_WritePin(SSD_CS_GPIO_Port, SSD_CS_Pin,GPIO_PIN_RESET) #define DC_SET HAL_GPIO_WritePin(SSD_DC_GPIO_Port,SSD_DC_Pin,GPIO_PIN_SET) #define DC_RESET HAL_GPIO_WritePin(SSD_DC_GPIO_Port,SSD_DC_Pin,GPIO_PIN_RESET) #define RST_SET HAL_GPIO_WritePin(SSD_RST_GPIO_Port,SSD_RST_Pin,GPIO_PIN_SET) #define RST_RESET HAL_GPIO_WritePin(SSD_RST_GPIO_Port,SSD_RST_Pin,GPIO_PIN_RESET) #define MAX(x, y) (((x) > (y)) ? (x) : (y)) #define MIN(x, y) (((x) < (y)) ? (x) : (y)) uint8_t frameBuffer[8192]; // Should mirror the display's own frameBuffer. uint8_t changedPixels[1024]; SPI_HandleTypeDef * spix; static void bitWrite(uint8_t * x, uint8_t n, bool b); static uint8_t bitRead(uint8_t x,uint8_t n) { return(x & (1<<n)); } // bitWrite(x, 0, 1); // write 1 to the first bit of x static void ssdDelay(uint32_t d); static void SSD1327writeCmd(uint8_t reg); static void bitWrite(uint8_t * x, uint8_t n, bool b) { b ? (*x|= (1 << n)):(*x&=~(1 << n)); } //void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState) //TODO: Find a way to handle the write commands without toggling CS and DC every time void SSD1327writeCmd(uint8_t reg){//Writes a command byte to the driver DC_RESET; // digitalWrite(_dc, LOW); CS_RESET; // SPI.transfer(reg); HAL_SPI_Transmit(spix,®,1,500); CS_SET; // digitalWrite(_cs, HIGH); } void SSD1327writeData(uint8_t data){//Writes 1 byte to the display's memory DC_SET; CS_RESET; HAL_SPI_Transmit(spix,&data,1,100); CS_SET; } void SSD1327setWriteZone(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) { //defines a rectangular area of memory which the driver will itterate through. This function takes memory locations, meaning a 64x128 space SSD1327writeCmd(0x15); //Set Column Address SSD1327writeCmd(x1); //Beginning. Note that you must divide the column by 2, since 1 byte in memory is 2 pixels SSD1327writeCmd(x2); //End SSD1327writeCmd(0x75); //Set Row Address SSD1327writeCmd(y1); //Beginning SSD1327writeCmd(y2); //End } uint16_t SSD1327coordsToAddress(uint8_t x, uint8_t y){ //Converts a pixel location to a linear memory address return (x/2)+(y*64); } void SSD1327setPixelChanged(uint8_t x, uint8_t y, bool changed){ uint16_t targetByte = SSD1327coordsToAddress(x, y)/8; bitWrite(&changedPixels[targetByte], SSD1327coordsToAddress(x, y) % 8, changed); } void SSD1327drawPixel(uint8_t x, uint8_t y, uint8_t color, bool display){//pixel xy coordinates 0-127, color 0-15, and whether to immediately output it to the display or buffer it int address = SSD1327coordsToAddress(x,y); if((x%2) == 0){//If this is an even pixel, and therefore needs shifting to the more significant nibble frameBuffer[address] = (frameBuffer[address] & 0x0f) | (color<<4); } else { frameBuffer[address] = (frameBuffer[address] & 0xf0) | (color); } if(display){ SSD1327setWriteZone(x/2,y,x/2,y); SSD1327writeData(frameBuffer[address]); SSD1327setPixelChanged(x, y, false); // We've now synced the display with this byte of the buffer, no need to write it again } else { SSD1327setPixelChanged(x, y, true); // This pixel is due for an update next refresh } } void SSD1327drawRect(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint8_t color, bool display){//Draws a rectangle from x1,y1 to x2,y2. uint8_t xMin = MIN(x1, x2); // TODO: double performance by writing whole bytes at a time uint8_t xMax = MAX(x1, x2); uint8_t yMin = MIN(y1, y2); uint8_t yMax = MAX(y1, y2); for (uint8_t x = xMin; x <= xMax; x++) { for (uint8_t y = yMin; y <= yMax; y++) { SSD1327drawPixel(x, y, color, display); } } } void SSD1327drawHLine(int x, int y, int length, uint8_t color, bool display){ for (uint8_t i = x; i < x+length; i++) { SSD1327drawPixel(i, y, color, display); } } void SSD1327drawVLine(int x, int y, int length, uint8_t color, bool display){ for (uint8_t i = y; i < y+length; i++) { SSD1327drawPixel(x, i, color, display); } } void SSD1327drawLine(int x0, int y0, int x1, int y1, uint8_t color, bool display){ //Bresenham's line algorithm int deltaX = abs(x1-x0); int deltaY = abs(y1-y0); int signX = x0<x1 ? 1 : -1; int signY = y0<y1 ? 1 : -1; int error = (deltaX>deltaY ? deltaX : -deltaY)/2, error2; while (true) { SSD1327drawPixel(x0, y0, color, display); if (x0==x1 && y0==y1) break; error2 = error; if (error2 >-deltaX) { error -= deltaY; x0 += signX; } if (error2 < deltaY) { error += deltaX; y0 += signY; } } } void SSD1327drawByteAsRow(uint8_t x, uint8_t y, uint8_t byte, uint8_t color){//Draws a byte as an 8 pixel row for (int i = 0; i < 8; i++) { if(bitRead(byte, i)){ SSD1327drawPixel(x+i, y, color, false); } } } void SSD1327drawChar(uint8_t x, uint8_t y, char thisChar, uint8_t color){ for (size_t i = 0; i < 8; i++) { SSD1327drawByteAsRow(x, y+i, font8x8_basic[(unsigned char)thisChar][i], color); } } void SSD1327drawCharArray(uint8_t x, uint8_t y, char text[], uint8_t color, int size){ const char* thisChar; uint8_t xOffset = 0; if(size==16){ for (thisChar = text; *thisChar != '\0'; thisChar++) { SSD1327drawChar16(x+xOffset, y, *thisChar, color); xOffset += 8; } } else if(size==32){ for (thisChar = text; *thisChar != '\0'; thisChar++) { SSD1327drawChar32(x+xOffset, y, *thisChar, color); xOffset += 16; } } else { for (thisChar = text; *thisChar != '\0'; thisChar++) { SSD1327drawChar(x+xOffset, y, *thisChar, color); xOffset += 8; } } } void SSD1327drawString(uint8_t x, uint8_t y, char * textString, uint8_t color, int size){ // char text[64]; // textString.toCharArray(text, 64); SSD1327drawCharArray(x,y, textString, color, size); } void SSD1327drawChar16(uint8_t x, uint8_t y, char thisChar, uint8_t color){ for (size_t row = 0; row < 16; row++) { SSD1327drawByteAsRow(x, y+row, font16x16[(unsigned char)thisChar][row*2], color); SSD1327drawByteAsRow(x+8, y+row, font16x16[(unsigned char)thisChar][(row*2)+1], color); } } void SSD1327drawChar32(uint8_t x, uint8_t y, char thisChar, uint8_t color){ for (size_t row = 0; row < 32; row++) { SSD1327drawByteAsRow(x, y+row, font16x32[(unsigned char)thisChar][row*2], color); SSD1327drawByteAsRow(x+8, y+row, font16x32[(unsigned char)thisChar][(row*2)+1], color); } } void SSD1327fillStripes(uint8_t offset){ //gradient test pattern for(int i = 0; i < 8192; i++){ uint8_t color = ((i+offset) & 0xF) | (((i+offset) & 0xF)<<4); frameBuffer[i] = color; } for (uint16_t i = 0; i < 1024; i++) { changedPixels[i] = 0xFF; // Set all pixels to be updated next frame. fillStripes should not be used without a full write anyways, but just in case } } void SSD1327setupScrolling(uint8_t startRow, uint8_t endRow, uint8_t startCol, uint8_t endCol, uint8_t scrollSpeed, bool right){ uint8_t swap; if (startRow > endRow) { // Ensure start row is before end swap = startRow; startRow = endRow; endRow = swap; } if (startCol > endCol) { // Ditto for columns swap = startCol; startCol = endCol; endCol = swap; } SSD1327writeCmd(0x2E); // Deactivate scrolling before changing anything if (right) { SSD1327writeCmd(0x26); // Scroll right } else { SSD1327writeCmd(0x27); // Scroll left } SSD1327writeCmd(0); // Dummy byte SSD1327writeCmd(startRow); SSD1327writeCmd(scrollSpeed); SSD1327writeCmd(endRow); SSD1327writeCmd(startCol); SSD1327writeCmd(endCol); SSD1327writeCmd(0); // Dummy byte }; void SSD1327startScrolling(){ SSD1327writeCmd(0x2F); } void SSD1327stopScrolling(){ SSD1327writeCmd(0x2E); } void SSD1327scrollStep(uint8_t startRow, uint8_t endRow, uint8_t startCol, uint8_t endCol, bool right){ setupScrolling(startRow, endRow, startCol, endCol, SSD1327_SCROLL_2, right); startScrolling(); ssdDelay(15); stopScrolling(); } void SSD1327clearBuffer(){// for(int i = 0; i < 8192; i++){ if (frameBuffer[i]) { // If there is a non-zero (non-black) byte here, make sure it gets updated frameBuffer[i] = 0; bitWrite(&changedPixels[i/8], i%8, 1); // Mark this pixel as needing an update } } } void SSD1327writeFullBuffer(){ //Outputs the full framebuffer to the display SSD1327setWriteZone(0,0,63,127); //Full display for(int i = 0; i < 8192; i++){ SSD1327writeData(frameBuffer[i]); } for (uint16_t i = 0; i < 1024; i++) { changedPixels[i] = 0; // Set all pixels as up to date. } } void SSD1327writeUpdates(){ // Writes only the pixels that have changed to the display for (size_t y = 0; y < 128; y++) { bool continued = false; // If we can continue with the write zone we're using for (size_t x = 0; x < 128; x++) { uint16_t address = coordsToAddress(x, y); if ( bitRead(changedPixels[address/8], address % 8) ) { // If we need an update here if (!continued) { // Just write the byte, no new write zone needed continued = true; setWriteZone(x/2, y, 63, 127); // Set the write zone for this new byte and any subsequent ones } writeData(frameBuffer[address]); bitWrite(&changedPixels[address/8], address % 8, 0); } else { continued = false; // The chain of pixels is broken } } } } void SSD1327setContrast(uint8_t contrast){ SSD1327writeCmd(0x81); //set contrast control SSD1327writeCmd(contrast); //Contrast byte } void SSD1327initRegs(){ //Sends all the boilerplate startup and config commands to the driver SSD1327writeCmd(0xae);//--turn off oled panel SSD1327writeCmd(0x15); //set column addresses SSD1327writeCmd(0x00); //start column 0 SSD1327writeCmd(0x7f); //end column 127 SSD1327writeCmd(0x75); //set row addresses SSD1327writeCmd(0x00); //start row 0 SSD1327writeCmd(0x7f); //end row 127 SSD1327writeCmd(0x81); //set contrast control SSD1327writeCmd(0x80); //50% (128/255) SSD1327writeCmd(0xa0); //gment remap SSD1327writeCmd(0x51); //51 (To my understanding, this is orientation SSD1327writeCmd(0xa1); //start line SSD1327writeCmd(0x00); SSD1327writeCmd(0xa2); //display offset SSD1327writeCmd(0x00); SSD1327writeCmd(0xa4); //rmal display SSD1327writeCmd(0xa8); //set multiplex ratio SSD1327writeCmd(0x7f); SSD1327writeCmd(0xb1); //set phase leghth SSD1327writeCmd(0xf1); SSD1327writeCmd(0xb3); //set dclk SSD1327writeCmd(0x00); //80Hz:0xc1 90Hz:0xe1 100Hz:0x00 110Hz:0x30 120Hz:0x50 130Hz:0x70 01 SSD1327writeCmd(0xab); //Enable vReg SSD1327writeCmd(0x01); SSD1327writeCmd(0xb6); //set phase leghth SSD1327writeCmd(0x0f); SSD1327writeCmd(0xbe); //Set vcomh voltage SSD1327writeCmd(0x0f); SSD1327writeCmd(0xbc); //set pre-charge voltage SSD1327writeCmd(0x08); SSD1327writeCmd(0xd5); //second precharge period SSD1327writeCmd(0x62); SSD1327writeCmd(0xfd); //Unlock commands SSD1327writeCmd(0x12); SSD1327writeCmd(0xAF); ssdDelay(100); } void SSD1327init(SPI_HandleTypeDef * hspi){ spix = hspi; RST_SET; ssdDelay(10); // digitalWrite(_rst, LOW); RST_RESET; //delay(100); ssdDelay(10); RST_SET; ssdDelay(10); SSD1327initRegs(); } static void ssdDelay(uint32_t d) { HAL_Delay(d); }; bibliotekę uruchomiłem, działa, ale widzę że jest sporo bajtów kopiowanych z ram do wyświetlacza, próbowałem to zrobić za pomocą DMA, ja używam SPI2 więc DMA pracuje na kanale 5 tryb normal. W pierszej kolejności próbowałem podmienić zawartość funkcji void SSD1327writeFullBuffer(){ //Outputs the full framebuffer to the display SSD1327setWriteZone(0,0,63,127); //Full display for(int i = 0; i < 8192; i++){ SSD1327writeData(frameBuffer[i]); } for (uint16_t i = 0; i < 1024; i++) { changedPixels[i] = 0; // Set all pixels as up to date. } } W taki sposób: void SSD1327writeFullBuffer(){ //Outputs the full framebuffer to the display SSD1327setWriteZone(0,0,63,127); //Full display // for(int i = 0; i < 8192; i++){ // SSD1327writeData(frameBuffer[i]); // } DC_SET; CS_RESET; HAL_SPI_Transmit_DMA(&spi2,frameBuffer,8192); CS_SET; for (uint16_t i = 0; i < 1024; i++) { changedPixels[i] = 0; // Set all pixels as up to date. } } W main jest przykładowy kod z biblioteki while (1) { static uint32_t lastTimer = 0; if(HAL_GetTick() > lastTimer) { HAL_GPIO_TogglePin(LD2_GPIO_Port,LD2_Pin); lastTimer = HAL_GetTick() + 200; // SSD1327clearBuffer(); // SSD1327drawString(16, 16, "Oled", 0x1, 32); // SSD1327drawString(16, 48, "TEST 1", 0x2, 32); // SSD1327drawString(20, 48+48, "16:32:55", 0xF, 16); // SSD1327setContrast(50); // SSD1327writeFullBuffer(); framecount++; SSD1327clearBuffer(); for (int x = 0; x < 128; x++) { for (int y = (sin(((float)x+framecount)/16)*32)+64; y < 128; y++) { SSD1327drawPixel(x, y, 3, false); } } SSD1327drawCharArray(24, 0, timeText, 0xF, 32); SSD1327drawString(0, 112, "-12.5C", 0xF, 16); SSD1327drawString(84, 112, "52.1%", 0xF, 16); SSD1327writeFullBuffer(); } /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } Tyle że zamiast delay, użyłem timera programowego. Niestety DMA nie wysyła danych na SPI. Czy jeśli SPI jest skonfigurowane do pracy z DMA to mogę używać go też "normalnie" tj: część danych np ustawienia wysyłać z funkcji a część za pomocą DMA?
-
Piszę sobie takiego małego libsa do obsługi enkodera, do testów używam najzwyklejszego impulsowego oraz płytki nucleo L476. Problem polega na tym że po pewnym czasie kręcenia, funkcja enkodera zacina się. Ponieważ nie mam pomysłu jak to dalej debugować przedstawiam kod testowy. Użyłem timera4 w trybie encodera i pracuje on w pełnej swojej pojemności zliczania. Podejrzewam że problem tkwi w maszynie stanów, być może ktoś zauważy miejsce błędu. #include "main.h" #include "tim.h" #include "stm32l4xx_hal.h" #include "enco.h" typedef enum {idle, count, runf,end}encoState_t; static uint8_t encodir = 0; static uint16_t encoInterval = 50; static void(*enc_event_callback)(void); void enco_init(const uint16_t interval) { encoInterval = interval; } void register_enc_event_callback(void(*callback)(void)){ if(callback)enc_event_callback = callback; } void ENCODER_EVENT() { static uint16_t encoval = 0; static uint32_t tickStart = 0; static encoState_t enc = idle; static uint16_t roznicaPlus, roznicaMinus; if (encoval != __HAL_TIM_GET_COUNTER(&htim4) && enc == idle) { // zaczeto krecic enc = count; // liczenie encoval = __HAL_TIM_GET_COUNTER(&htim4); // roznicaPlus = __HAL_TIM_GET_COUNTER(&htim4) + (ENCO_STEP - 1); roznicaMinus = __HAL_TIM_GET_COUNTER(&htim4) - (ENCO_STEP - 1); tickStart = HAL_GetTick() + encoInterval; // timeout return; } if (enc == count) { if (roznicaPlus == __HAL_TIM_GET_COUNTER(&htim4)) { encodir = encoRight; encoval = __HAL_TIM_GET_COUNTER(&htim4); enc = idle; if (enc_event_callback)enc_event_callback(); }else if (roznicaMinus == __HAL_TIM_GET_COUNTER(&htim4)) { encodir = encoLeft; encoval = __HAL_TIM_GET_COUNTER(&htim4); enc = idle; if (enc_event_callback)enc_event_callback(); // wykonanie przypisanej f } } else if (enc == count && HAL_GetTick() > tickStart) { // timeout encoval = __HAL_TIM_GET_COUNTER(&htim4); // przypisanie aby nie zmenial statusu bez potrzeby enc = idle; } } encoDir getEncoDir(void){ return encodir; // zwraca kierunek obracania } .h #ifndef INC_ENCO_H_ #define INC_ENCO_H_ #define ENCO_STEP 4 //4 or 2 typedef enum{encoLeft = 16,encoRight = 32}encoDir; encoDir getEncoDir(void); void enco_init(const uint16_t interval); void ENCODER_EVENT(); void register_enc_event_callback(void(*callback)(void)); #endif /* INC_ENCO_H_ */ main.c /* USER CODE BEGIN 2 */ enco_init(500); register_enc_event_callback(encoclb); HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_1); HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_2); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { ENCODER_EVENT(); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ } Oraz zarejestrowana funkcja obsługi callbacka: void encoclb(){ HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); }
-
STM32 + CubeMX + LIS3DHH - brak odbioru danych przez SPI
przemof-s opublikował temat w Mikrokontrolery
Witam, próbuję uruchomić akcelerometr LIS3DHH ( https://www.st.com/en/mems-and-sensors/lis3dhh.html) na zestawie Nucleo F411RE (https://www.st.com/en/evaluation-tools/nucleo-f411re.html). Czujnik mam w postaci adaptera STEVAL-MKI180V1 (https://www.st.com/en/evaluation-tools/steval-mki180v1.html). Konfigurację dla mikrokontrolera generuję za pomocą CubeMX 5.0.1 z bibliotekami HAL dla rodziny STM32F4, w wersji 1.23.0. Próbę uruchomienia czujnika rozpocząłem od wykorzystania bibliotek: https://github.com/STMicroelectronics/STMems_Standard_C_drivers/tree/master/lis3dhh_STdC, a dokładnie od przykładu: read_data_simple.c. Po dużej liczbie nieudanych prób komunikacji, maksymalnie uprościłem przykład. Aktualnie próbuję odczytać wartość rejestru WHO_AM_I. Adres rejestru to: 0x0F. Podczas odczytu danych, bit SMB adresu powinien mieć wartość 1, więc modyfikuję adres rejestru do wartości 0x8F. Wartość rejestru WHO_AM_I powinna wynosić 0x11, a ja otrzymuję wartość 0x00. Wszystkie linie SPI są sprzętowo podciągnięte do plusa zasilania, za pomocą wewnętrznych rezystorów mikrokontrolera. Korzystam z SPI2. Jego konfiguracja to: CPOL = High, CPHA = 2 Edge, prędkość: 1.3125 Mbits/s. Sygnał CS jest generowany programowo. Poniżej przedstawiam fragment kodu źródłowego odpowiedzialnego za inicjalizację SPI oraz próbę odczytania rejestru WHO_AM_I. Inicjalizacja SPI: void MX_SPI2_Init(void) { 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_32; 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(); } } [Próba odczytu zawartości rejestru WHO_AM_I (zawarte w funkcji main): MX_GPIO_Init(); MX_SPI2_Init(); HAL_Delay(10); HAL_StatusTypeDef status; uint8_t reg = 0x0F; // Adres rejestru WHO_AM_I uint8_t bufp[3]; uint16_t len = 1; reg |= 0x80; // Informacja, ze przeprowadzany bedzie odczyt danych HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_RESET); // Aktywacja SPI status = HAL_SPI_Transmit(&LIS3DHH_HANDLE, ®, 1, 1000); // Wyslanie adresu do odczytu status = HAL_SPI_Receive(&LIS3DHH_HANDLE, bufp, len, 1000); // Odbior zawartosci adresu HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, GPIO_PIN_SET); // Dezaktywacja SPI W załączniku przedstawiam przebiegi uzyskane z analizatora stanów logicznych, plik konfiguracyjny dla CubeMX oraz kod źródłowy programu testowego. Dodam, że testy przeprowadzałem na dwóch czujnikach, oraz dodatkowo na zestawie z mikrokontrolerem STM32F103 (blue PCB). Modyfikowałem na wiele sposobów konfigurację SPI oraz odczyt rejestrów. Efekt za każdym razem taki sam. Czy ktoś ma pomysł co robię nie tak, że za każdym razem otrzymuję wartość zero z rejestru WHO_AM_I? Test_LIS3DHH_F4.zip