Komentator Napisano Grudzień 22, 2015 Udostępnij Napisano Grudzień 22, 2015 Wcześniej poznaliśmy dwa interfejsy szeregowe: UART i SPI. Pierwszy wymagał tylko dwóch linii, ale był dość powolny. Drugi działał bardzo szybko wykorzystując więcej wyprowadzeń.Teraz zajmiemy się I2C, który kwalifikuje się gdzieś pomiędzy wcześniejszymi interfejsami. UWAGA, to tylko wstęp! Dalsza część artykułu dostępna jest na blogu.Przeczytaj całość »Poniżej znajdują się komentarze powiązane z tym wpisem. 1 Link do komentarza Share on other sites More sharing options...
mareq Styczeń 4, 2016 Udostępnij Styczeń 4, 2016 Witam. Osobiście przerabiam ten kurs na stm32f0 discovery. Do tej pory większość zmian to była kosmetyka. Teraz utknąłem na: i2c.I2C_ClockSpeed = 100000 SPL dla F0 nie przewiduje tej opcji. Jak to obejść? Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Styczeń 4, 2016 Udostępnij Styczeń 4, 2016 mareq, witam na forum. Kurs dotyczy rodziny F1, więc jeśli masz problem z innym układem stwórz proszę osobny temat i opisz tam swój problem. Nie dyskutujmy o innych układach w kursie, aby nie robić początkującym zbędnego zamieszania. Link do komentarza Share on other sites More sharing options...
kubavit Luty 10, 2016 Udostępnij Luty 10, 2016 Hej kończę przerabiać ten świetny kurs i mam problem z I2C. Zawiesza sie na drugim odczycie nie wiadomo dlaczego. Problem opisałem tutaj: http://forum.atnel.pl/topic14484.html . Jeśli jest ktoś w stanie rzucić okiem i pomóc będę wdzięczny. Pozdrawiam Link do komentarza Share on other sites More sharing options...
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Produkcja i montaż PCB - wybierz sprawdzone PCBWay! • Darmowe płytki dla studentów i projektów non-profit • Tylko 5$ za 10 prototypów PCB w 24 godziny • Usługa projektowania PCB na zlecenie • Montaż PCB od 30$ + bezpłatna dostawa i szablony • Darmowe narzędzie do podglądu plików Gerber Zobacz również » Film z fabryki PCBWay
marek1707 Luty 10, 2016 Udostępnij Luty 10, 2016 Ale tam trzeba się zalogować by zobaczyć Twoje programy. To celowe? 1 Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Luty 10, 2016 Udostępnij Luty 10, 2016 kubavit, jeśli oczekujesz pomocy na naszym forum, to miło by było, gdybyś opisał tutaj problem. Nie każdy ma konto na linkowanej przez Ciebie stronie 🙂 Link do komentarza Share on other sites More sharing options...
kubavit Luty 10, 2016 Udostępnij Luty 10, 2016 Przepraszam, zapomniałem że bez konta nie zobzczycie posta. A więc tak: Przenoszę obsługę czujnika HIH6030 z AVR na STM32. Na Atmedze działał poprawnie, więc adresy i wysyłane sekwencje są w odpowiedniej kolejności. Problem polega na tym, że po ponownym wysłaniu bitu startu i próbie zapisu (i2c_write_byte( (HIH6030_ADDR<< 1) | 0x01)) program się zawiesza i czeka na odpowiednią flagę w pętli while. Załączam kod i schemat podłączonego układu. PLIK I2C.C #include "main.h" /* I2C init */ void I2Cinit(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB); /* Enable clock for alternative functions */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); /* Enable clock for I2C1 */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); GPIO_InitTypeDef gpio; I2C_InitTypeDef i2c; /* init GPIO stricture for SDA & SCL */ GPIO_StructInit(&gpio); gpio.GPIO_Pin = I2C1_SDA_PINx | I2C1_SCL_PINx; /* Outputs must be Open Drain - no pullup ! */ gpio.GPIO_Mode = GPIO_Mode_AF_OD; gpio.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(I2C1_REGx, &gpio); /* init I2C structure */ I2C_StructInit(&i2c); i2c.I2C_Mode = I2C_Mode_I2C; /* 100 kHz speed - max 400 kHz but depends on wire's length */ /* the longer wires are, the lowest speed shuold be used */ /* to avoid transmission errors */ i2c.I2C_ClockSpeed = 100000; I2C_Init(I2C1, &i2c); I2C_Cmd(I2C1, ENABLE); } /* I2C start */ void i2c(void) { I2C_GenerateSTOP(I2C1, ENABLE); } PLIK I2C.H #ifndef I2C_H_ #define I2C_H_ #define I2C1_SDA_PINx (GPIO_Pin_7) #define I2C1_SCL_PINx (GPIO_Pin_6) #define I2C1_REGx (GPIOB) typedef enum I2C_Dir_Tag { I2C_WriteData, I2C_ReadData } I2C_Dir_T; void I2Cinit(void); void i2c(void); uint8_t i2c_read_byte(void); void i2c_write_byte(uint8_t data); void i2c_write_addr(uint8_t addr, I2C_Dir_T mode); #endif /* I2C_H_ */ HIH6030.C #include "main.h" uint8_t buffer[2]; static void _hih_request_measurement(void) { i2c(); _delay_ms(50); } void hih_read_temp(void) { uint16_t HumidBuffer[2]; uint16_t TemperatureBuffer[2]; uint8_t lsbHumid, msbHumid, lsbTemp, msbTemp; long temperature, humidity; long conv_temp, conv_humid; /* request measurement */ _hih_request_measurement(); i2c(); /* humidity conversion */ msbHumid = (HumidBuffer[0] & 0x3F); lsbHumid = HumidBuffer[1]; humidity = (msbHumid << 8) | lsbHumid; conv_humid = (humidity * 100) >> 14; /* temperature conversion */ msbTemp = TemperatureBuffer[0]; lsbTemp = TemperatureBuffer[1]; temperature = ( (msbTemp << 6) | (lsbTemp >> 2) ); conv_temp = ( (temperature * 165) >> 14 ) - 40; } HIH6030.H #ifndef BMP180_H_ #define BMP180_H_ #define HIH6030_ADDR (0x27) void hih_read_temp(void); #endif /* HIH6030_H_ */ Schemat realizowanego układu: Z góry dziękuję za pomoc [ Dodano: 10-02-2016, 17:20 ] Na AVR powyższy układ działał bez problemu, więc błędy w schemacie i połączeniach odrzucam. Gdzieś w programie sie walnąłem i nie mogę znależć gdzie. [ Dodano: 10-02-2016, 17:33 ] Rzuciłem okiem na ERRATE i używam jednocześnie SPI1 i I2C1.. Conditions • I2C1 and SPI1 are clocked. • SPI1 is remapped. • I/O port pin PB5 is configured as an alternate function output. Description Conflict between the SPI1 MOSI signal and the I2C1 SMBA signal (even if SMBA is not used). Workaround Do not use SPI1 remapped in master mode and I2C1 together. When using SPI1 remapped, the I2C1 clock must be disabled. [ Dodano: 10-02-2016, 17:35 ] Ale możliwe, że nie tylko o to chodzi więc proszę o przejrzenie kodu, gdyż dopiero jutro wieczorem będe mógł to sprawdzić Link do komentarza Share on other sites More sharing options...
Elvis Luty 10, 2016 Udostępnij Luty 10, 2016 Ciężko jest czytając sam program "zgadnąć" gdzie jest błąd. Tak na oko widzę jedną ciekawostkę - nigdzie nie ma wywołania funkcji i2c_write_addr. Wiem że adres wysyłasz jako dane, ale nie wiem jak na to maszyna stanowa i2c reaguje. [ Dodano: 10-02-2016, 17:46 ] Nie wiem jak dokładnie działa czujnik, który wykorzystujesz, ale wygląda że jest podobny do LSM303D - więc może wykorzystaj program z kolejnej części kursu: https://forbot.pl/blog/artykuly/programowanie/kurs-stm32-12-i2c-w-praktyce-akcelerometr-id10644 Po zmianie adresów powinno działać. Link do komentarza Share on other sites More sharing options...
kubavit Luty 10, 2016 Udostępnij Luty 10, 2016 Wrzuce jutro i2c_write_addr, zamiast wysyłać w funkcji i2c_write oraz wyłącze na chwile SPI1 i inne peryferia. Zobacze po przedebugowaniu czy dalej sie zawiesza czy w końcu ruszy 🙂 [ Dodano: 10-02-2016, 17:49 ] jak pisałem wcześniej na kilku AVR'ach czujnik działał. Zmienione zostały tylko funkcje niższego poziomu obsługujące I2C Link do komentarza Share on other sites More sharing options...
Elvis Luty 10, 2016 Udostępnij Luty 10, 2016 Skoro wiesz najlepiej to po co pytasz? W programie na oko widać sporo błędów - dlatego proponowałem zacząć od czegoś co jest sprawdzone. Może i ten program działał na AVR, ale lepiej zacząć od czegoś co działa na STM32. Na pewno masz niepoprawne kończenie komunikacji po odebraniu danych. Flaga Stop i wyłączenie potwierdzenia powinno być ustawione przed odebraniem ostatniego bajtu. Jest to błąd, ale możliwe że będzie z nim działał - jednak jeśli podłączysz analizator i2c zobaczysz, że transmisja nie jest w pełni poprawna. Link do komentarza Share on other sites More sharing options...
kubavit Luty 10, 2016 Udostępnij Luty 10, 2016 Bede starał się to poprawić w miare czasu i w razie błędów będe wrzucał poprawiony kod i zapytania Link do komentarza Share on other sites More sharing options...
Bielku Czerwiec 2, 2016 Udostępnij Czerwiec 2, 2016 Cześć Próbuję skomunikować się z układem DS3231. Poniżej zamieszczam model komunikacji z noty układu. Posiadam zestaw NUCLEO F103RB, pracuje na ac6 system workbench, najnowsza wersja, najnowsze firmware w zestawie. Oto mój kod: #include "stm32f10x.h" int main(void) { GPIO_InitTypeDef gpio; I2C_InitTypeDef i2c; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); GPIO_StructInit(&gpio); gpio.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7; // SCL, SDA gpio.GPIO_Mode = GPIO_Mode_AF_OD; gpio.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &gpio); I2C_StructInit(&i2c); i2c.I2C_Mode = I2C_Mode_I2C; i2c.I2C_Ack = I2C_Ack_Enable; i2c.I2C_ClockSpeed = 100000; I2C_Init(I2C1, &i2c); I2C_Cmd(I2C1, ENABLE); while (1) { I2C_GenerateSTART(I2C1, ENABLE); while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS); I2C_AcknowledgeConfig(I2C1, ENABLE); I2C_Send7bitAddress(I2C1, 0xd0, I2C_Direction_Receiver); while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) != SUCCESS); while(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS); uint8_t sekundy = I2C_ReceiveData(I2C1); I2C_AcknowledgeConfig(I2C1, DISABLE); I2C_GenerateSTOP(I2C1, ENABLE); } } Moim celem jest odczytanie pierwszego adresu 0x00 gdzie przechowywane są sekundy i zakończenie transmisji. W trybie debug program zawiesza się w pętli while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS); ale czasami odczyta poprawnie pierwszą wartość i dalej wisi na powyższej pętli, bywa też, że zawiesza się na kolejnych pętlach. Debugger zatrzymuje się w tej funkcji wewnątrz stm32f10x_i2c.c ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT) { uint32_t lastevent = 0; uint32_t flag1 = 0, flag2 = 0; ErrorStatus status = ERROR; /* Check the parameters */ assert_param(IS_I2C_ALL_PERIPH(I2Cx)); assert_param(IS_I2C_EVENT(I2C_EVENT)); /* Read the I2Cx status register */ flag1 = I2Cx->SR1; flag2 = I2Cx->SR2; flag2 = flag2 << 16; /* Get the last event value from I2C status register */ lastevent = (flag1 | flag2) & FLAG_Mask; /* Check whether the last event contains the I2C_EVENT */ if ((lastevent & I2C_EVENT) == I2C_EVENT) { /* SUCCESS: last event is equal to I2C_EVENT */ status = SUCCESS; } else { /* ERROR: last event is different from I2C_EVENT */ status = ERROR; } /* Return status */ return status; } Sprawdzałem to na 2 układach DS3231, one są na pewno sprawne, na ATMega działają prawidłowo. Ja coś robię źle, czy jest problem w bibliotekach od producenta? Link do komentarza Share on other sites More sharing options...
natrov Czerwiec 5, 2016 Udostępnij Czerwiec 5, 2016 Stm32 F0 nie ma w pliku nagłówkowym czegoś takiego jak: I2C_ClockSpeed, na co to zamienić? 🙂 Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Czerwiec 5, 2016 Udostępnij Czerwiec 5, 2016 natrov, w komentarzach do artykułów rozmawiamy wyłącznie o konfiguracji sprzętowej omawianej w kursie. Inaczej wprowadzi to duże zamieszanie 🙂 Jeśli masz problem z inną płytką, to załóż osobny temat w odpowiednim dziale. Link do komentarza Share on other sites More sharing options...
lewander Maj 26, 2017 Udostępnij Maj 26, 2017 Po przerobieniu lekcji z dołączoną pamięcią postanowiłem spróbować z AT34C02C. Odczyt działa dla pierwszych 128 pozycji. Dla adresów powyżej 0x80 dane które wyświetlane są w debuggerze nie zgadzają się z wartościami zapisanymi w pamięci. Czy adresowanie rekordów 128-255 powinno wyglądać inaczej? Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Bądź aktywny - zaloguj się lub utwórz konto!
Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony
Utwórz konto w ~20 sekund!
Zarejestruj nowe konto, to proste!
Zarejestruj się »Zaloguj się
Posiadasz własne konto? Użyj go!
Zaloguj się »