-
Data: 2016-07-03 21:46:11
Temat: I2C/TWI - poddaję się...
Od: badworm <n...@p...pl> szukaj wiadomości tego autora
[ pokaż wszystkie nagłówki ]Czołem!
Wracam do tematu, który tu poruszałem na początku kwietnia, a mianowicie
komunikacji pomiędzy AVRem (Mega 8, docelowo Mega 324) a wyświetlaczem
OLED z kontrolerem SSD1308. O ile komunikacja po I2C zrealizowanym
programowo działa prawidłowo, choć z niewiadomych przyczyn po
skompilowaniu programu nowszą wersją GCC prędkość transmisji spada
kilkunastokrotnie (częstotliwość zegara na SCL obniża się z 80kHz do
zaledwie 5kHz), o tyle z komunikacją za pośrednictwem sprzętowego I2C
jest jakiś grubszy problem. Kod wysyłający dane na sprzętowe I2C sam w
sobie jest dobry. Prosty program, wysyłający dane do układu PCF8574
(ekspander portu I2C) działa aż miło, w przebiegach praktycznie nie
widać różnicy czy to programowe czy sprzętowe I2C. Podmiana procedur
obsługi I2C w docelowym kodzie z obsługą OLED kończy się porażką. Sam
program jako całość żyje, bo diodka podpięta pod PB3 i taktowana
przerwaniem timera mruga prawidłowo. Jeśli wyświetlacz jest już
podłączony w momencie załączania zasilania, to efekt jest taki, że coś
idzie nie tak w programie, bo nie pojawia się stan wysoki na PB0, mający
za zadanie potrzymywać pracę stabilizatora zasilającego cały układ.
Muszę więc cały czas trzymać wciśnięty przycisk "power on", podczas gdy
normalnie wystarcza naciśnięcie go na chwilę a potem jego rolę przejmuje
właśnie PB0. Jeśli natomiast spróbuję podłączyć moduł z wyświetlaczem do
pracującego już procesora, to z tego co pokazuje oscyloskop, momentalnie
na pysk leci sygnał na SCL.
Jakieś pomysły co z tym fantem zrobić? :(
Przebieg I2C sprzętowego dla PCF8574:
http://transport.prohost.pl/kolejowy/pliki/tek00031.
png
Przebieg dla I2C programowego dla PCF8574:
http://transport.prohost.pl/kolejowy/pliki/tek00029.
png
Przebieg dla I2C programowego dla OLED:
http://transport.prohost.pl/kolejowy/pliki/tek00026.
png
Przebieg dla I2C sprzętowego dla OLED ale bez podłączonego wyświetlacza:
http://transport.prohost.pl/kolejowy/pliki/tek00019.
png
Najśmieszniejsze w tym wszystkim jest to, że to właśnie SSD1308
oficjalnie obsługuje I2C, a Atmel tę magistralę nazywa (ze względów
licencyjnych) TWI, więc prędzej możnaby się spodziewać odstępstw od
wzorcowego I2C ze strony procka niż kontrolera w wyświetlaczu...
Funkcje obsługujące I2C sprzętowe:
//TEST I2C SPRZĘTOWEGO
void twiinit(void)
{
//set SCL to 400kHz
TWSR = 0x00;
TWBR = 0x0C;
//enable TWI
TWCR = (1<<TWEN);
}
void twistart(void)
{
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while ((TWCR & (1<<TWINT)) == 0);
}
void twistop(void)
{
TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);
}
void twiwrite(uint8_t u8data)
{
TWDR = u8data;
TWCR = (1<<TWINT)|(1<<TWEN);
while ((TWCR & (1<<TWINT)) == 0);
}
Funkcje obsługi I2C programowego:
// Wyliczenie czasu opóźnienia połówkowego i ćwiartkowego (cykle)
#define I2C_nhalf (F_CPU/I2C_SPEED/2)
// Funkcja dłuższych opóźnień
#if I2C_nhalf < 3
// Nic
#elif I2C_nhalf < 8
static void i2c_xdelay(void)
{
NOP();
}
#else
#define I2C_delayloops (1+(I2C_nhalf-8)/3)
#if I2C_delayloops > 255
#error Przyspiesz - bo sie nie wyrabiam ;)
#endif
static void i2c_xdelay(void)
{
asm volatile( \
"delayus8_loop%=: \n\t"\
"dec %[ticks] \n\t"\
"brne delayus8_loop%= \n\t"\
: :[ticks]"r"(I2C_delayloops) );
}
#endif //I2C_nhalf >= 3
// Opóźnienia dla I2C
static inline void i2c_hdelay(void)
{
#if I2C_nhalf < 1
return; // To jest funkcja inline, jeśli składa się tylko z "return"
jest usuwana podczas optymalizacji
#elif I2C_nhalf < 2
NOP();
#elif I2C_nhalf < 3
asm volatile(
"rjmp exit%=\n\t"
"exit%=:\n\t"::);
#else
i2c_xdelay();
#endif
}
// Ustawienie i zerowanie wyjścia
static inline void i2c_sdaset(void)
{
DDR(I2C_PORT) &= ~(1<<I2C_SDA);
PORT(I2C_PORT) |= 1<<I2C_SDA;
}
static inline void i2c_sdaclear(void)
{
PORT(I2C_PORT) &= ~(1<<I2C_SDA);
DDR(I2C_PORT) |= 1<<I2C_SDA;
}
// Pobieranie danej z wyprowadzenia portu
// Zwraca: bajt będący odpowiednikiem fizycznego stanu portu, z
wyzerowanaymi wszystkimi bitami poza sda
static inline uint8_t i2c_sdaget(void)
{
return PIN(I2C_PORT) & (1<<I2C_SDA);
}
// Zerowanie i ustawianie zegara
static inline void i2c_sclset(void)
{
PORT(I2C_PORT) |= 1<<I2C_SCL;
}
static inline void i2c_sclclear(void)
{
PORT(I2C_PORT) &= ~(1<<I2C_SCL);
}
// Warunek startu
void i2c_start(void)
{
// Konieczne jeśli chcę użyć start bez stop
i2c_sdaset();
i2c_hdelay();
i2c_sclset();
i2c_hdelay();
// Normalna sekwencja startu
i2c_sdaclear();
i2c_hdelay();
i2c_sclclear();
//TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
//while (!(TWCR & (1<<TWINT)));
}
// Warunek stop
void i2c_stop(void)
{
i2c_sdaclear();
i2c_hdelay();
i2c_sclset();
i2c_hdelay();
i2c_sdaset();
i2c_hdelay();
//TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
//while ((TWCR & (1<<TWSTO)));
}
// Transmisja bajtu
// Zwraca: 0 jeśli było ack, wartość 1<<I2C_SDA jeśli nie było ACK
uint8_t i2c_send(uint8_t data)
{
uint8_t n;
for(n=8; n>0; --n)
{
if(data & 0x80)
i2c_sdaset();
else
i2c_sdaclear();
data <<= 1;
i2c_hdelay();
i2c_sclset();
i2c_hdelay();
i2c_sclclear();
}
// ack
i2c_sdaset();
i2c_hdelay();
i2c_sclset();
i2c_hdelay();
n = i2c_sdaget();
i2c_sclclear();
return n;
}
// Pobranie bajtu
uint8_t i2c_get(uint8_t ack)
{
uint8_t n, temp=0;
i2c_sdaset();
for(n=8; n>0; --n)
{
i2c_hdelay();
i2c_sclset();
i2c_hdelay();
temp<<=1;
if(i2c_sdaget())
temp++;
i2c_sclclear();
}
// ack
if(ack == I2C_ACK)
i2c_sdaclear();
else
i2c_sdaset();
i2c_hdelay();
i2c_sclset();
i2c_hdelay();
i2c_sclclear();
return temp;
}
--
Pozdrawiam Bad Worm badworm[maupa]post{kropek}pl
GG#2400455 ICQ#320399066
Następne wpisy z tego wątku
- 03.07.16 22:08 janusz_k
Najnowsze wątki z tej grupy
- Fejk muzyczny czy nie fejk
- Raspberry Pi 3 Model B+
- Kuchenka elektryczna
- test
- Cewka elektrozaworu
- zapytanie o chip r5f21275nfp
- nie naprawiam więcej telewizorów
- Zrobił TV OLED z TV LCD
- Zasilacz USB na ścianę.
- Gniazdo + wtyk
- Aliexpress zaczął oszukiwać na bezczelnego.
- OpenPnP
- taka skrzynka do kablowki
- e-paper
- 60 mA dużo czy spoko?
Najnowsze wątki
- 2025-03-15 kraje nieprzyjazne samochodom
- 2025-03-15 parking Auchan
- 2025-03-15 Art. 19.1 ustawy o ochronie praw autorskich
- 2025-03-15 przegląd za mną
- 2025-03-15 Na co komu okna
- 2025-03-15 Mój elektryk
- 2025-03-15 Fejk muzyczny czy nie fejk
- 2025-03-15 China-Kraków => Senior PHP Symfony Developer <=
- 2025-03-15 Wrocław => Konsultant wdrożeniowy Comarch XL (Logistyka, WMS, Produk
- 2025-03-15 Błonie => Analityk Systemów Informatycznych (TMS SPEED) <=
- 2025-03-15 Warszawa => Senior Frontend Developer (React + React Native) <=
- 2025-03-15 Warszawa => Java Full Stack Developer (Angular2+ experience) <=
- 2025-03-15 Warszawa => Java Full Stack Developer (Angular2+) <=
- 2025-03-15 KOMU w RP3 pasuje "Rumuńska łatwość gmerania w wyborach" i dlaczego nie PO-Trzaskanym?
- 2025-03-15 China-Kraków => Key Account Manager IT <=