Skocz do zawartości

Kurs STM32 - #11 - I2C w praktyce, pamięć eeprom


Komentator

Pomocna odpowiedź

Dlaczego w przykladzie ,gdzie odczytujemy wartosci, blok STOP wysyłamy przed ostatnim blokiem danych a nie po nim?

Mógłby to ktoś wyjaśnić?

[ Dodano: 17-06-2017, 20:16 ]

Dlaczego w przykladzie z odczytywaniem danych, blok STOP wysyalmy przed ostatnim blokiem dancych a nie po nim?

Moze te jest blok STOPu po pierszym bloku danych, ale w takim razie gdzie jest blok STOPu po drugim bloku ?

Link do komentarza
Share on other sites

Sygnał stop jest wysyłany prawidłowo - tak działa i2c w STM32, trzeba flagę stopu ustawić wcześniej, a sprzęt wygeneruje odpowiednią sekwencję po odebraniu kolejnej danej. Wszystko jest opisane dokładnie w dokumentacji procesora. Niestety nie jest to do końca intuicyjne, więc warto uzbroić się w analizator stanów logicznych.

  • Lubię! 1
Link do komentarza
Share on other sites

Witam.

Właśnie przesiadłem się a AVR na STM. Doszedłem do tej lekcji i wszystko działa ok, tylko chciałbym by program rejestrował nie ilość uruchomień, tylko działał w pętli głównej programu i co 1 sekundę zapisywał i odczytywał counter. pętla główna programu wyglądałaby tak:

while (1) {

  eeprom_read(0x10, &counter, sizeof(counter));
  printf("Uruchomenie numer %ld\n", counter);
  counter++;
  eeprom_write(0x10, &counter, sizeof(counter));
  delay( 1000 );

}

I tu zong!!!, nic nie działa, ani usart nic nie wysyła, ani i2c nic nie odczytuje i zapisuje w pamięci.

[ Dodano: 25-04-2018, 10:49 ]

Ok. Wszystko działa. Musiałem wcześniej jakiś czeski błąd zrobić. Sorry

Link do komentarza
Share on other sites

Witam ponownie.

Zastanawia mnie ten program

while (1) {

     eeprom_read(0x10, &counter, sizeof(counter));
     send_string( "Uruchomenie numer " );
     send_int( counter );
     send_string( "\r\n" );
     counter++;
     eeprom_write(0x10, &counter, sizeof(counter));
     delay( 1000 );

Choć program pracije dobrze, bo oblicza w pętli ilość uruchomień. Zapisuje tą ilość do pamięci, odczytuje ją z pamięci, tylko my operujemy na zmiennej COUNTER i nie wyświetla nam faktycznej liczby odczytanej z pamięci.

Jeśli chcielibyśmy odczytać ją to w we funkcji eeprom_read(0x10, &counter, sizeof(counter));.


send_string( "Uruchomenie numer " );

for( i = 0; i < size - 1; i++ ) {
	while( I2C_CheckEvent( I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED ) != SUCCESS );
	buffer[ i ] = I2C_ReceiveData( I2C1 );

	send_int( buffer[ i ]);
}
send_string( "\r\n" );

Myślę, że tak powinno wyglądać albo w pętli zmniejszającej. Jutro to sprawdzę i potwierdzę.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

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

Cześć,

mam problem z drugim przykładem (czyli odczytem wartości). Po pierwsze kod pod akapitem "Całość wygląda następująco:" jest niekompletny tzn. zawiera tylko instrukcje opisujące odczyt bez zapisu. Mój problem polega na tym, że starałem się skleić wszystko co jest opisane w artykule w spójną całość i program się zawiesza po wygenerowaniu stopu oraz oczekiwaniu na event I2C_EVENT_MASTER_BYTE_RECEIVED na końcu programu. Jeśli jednak odczytam drugą wartość przed stopem i się pozbędę oczekiwania na event program działa, aczkolwiek to jest raczej hack aniżeli rozwiązanie. Czy jest ktoś kto może pomóc?

Link do komentarza
Share on other sites

Ja tylko wspomnę, że kod jest jak najbardziej kompletny. Takie było założenie tego przykładu, że zawiera tylko odczyt - wcześniej został opisany zapis i jeśli ten program był uruchomiony, dane są już w pamięci eeprom. Właśnie to chciałem pokazać - że raz zapisane dane "przetrwają" odłączenie zasilania, a nawet zmianę programu.

O ile rozumiem oryginalny kod działa poprawnie, ale Loled, próbuje napisać własny program z zapisem i odczytem. Pewnie błąd jest gdzieś w tych "własnych" zmianach, ale nie widząc kodu ciężko pomóc.

Link do komentarza
Share on other sites

Cześć, dzięki za odpowiedzi. Przywitałem się w załączonym linku 🙂. Co do kodu zacząłem kombinować ponieważ przeklejenie przykładu pierwszego (zapis) i uruchomienie go działa bez zarzutu. Problem miałem z przykładem drugim (odczyt) gdzie kod po prostu się zawiesza na końcu przed linijką data2=I2C_ReceiveData(I2C1) stąd moje mniemanie, że coś jest nie tak. Kodu nie wklejam bo tak jak mówię, oryginalny z przykładu mi nie działa 🙁 czy jest ktoś w stanie zweryfikować, czy nie ma tam błędu? Treker co do HALa z chęcią przejdę przez wszystkie przykłady z tego kursu aczkolwiek chciałbym dokończyć najpierw ten skoro zaszedłem już tak daleko 😋

Link do komentarza
Share on other sites

Problem rozwiązany, błędu w kodzie oczywiście nie ma. Pojawiał się problem tylko jeśli przeskakiwałem przez kod z linijki na linijkę, a dokładnie na I2C_GenerateSTOP(I2C1, ENABLE); wduszenie f6 w Eclipsie na tej linii powoduje zawieszenie programu.

  • Lubię! 1
Link do komentarza
Share on other sites

Hej.

Uznałem, że zrobię sobie "własną" pracę domową i postanowiłem wyświetlić zawartość pamięci pod podanym adresem w terminalu. Problem polega na tym, że po wykonaniu funkcji jak na przykład eeprom_set_addr(0x00); niemożliwe staje się wyświetlenie czegokolwiek z użyciem funkcji printf. Wygląda jakby nagle funkcja wyświetlająca napisy przestawała działać. Program kompiluje się, oraz napis z liczbą uruchomienia MCU działa poprawnie. Macie jakieś pomysły? 🙂

	printf("Uruchomienie numer %ld\n", counter); // wyświetla

	eeprom_write(0x10, &counter, sizeof(counter));

	eeprom_set_addr(0x00);

	printf("cokolwiek\n"); //już nie wyświetla

 

Link do komentarza
Share on other sites

32 minuty temu, Treker napisał:

Standardowa prośba - wklej proszę cały program, bez tego można tylko zgadywać 😉

/**
  ******************************************************************************
  * @file    main.c
  * @author  Ac6
  * @version V1.0
  * @date    01-December-2013
  * @brief   Default main function.
  ******************************************************************************
*/


#include "stm32f10x.h"
#include "stdio.h"
#include "delay.h"

void send_char(char c)
{
	while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
 	USART_SendData(USART2, c);
}

int __io_putchar(int c)
{
	if (c=='\n')
	send_char('\r');
 	send_char(c);
 	return c;
}


void eeprom_set_addr(uint32_t addr)
{
	I2C_GenerateSTART(I2C1, ENABLE);
	while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);
	I2C_Send7bitAddress(I2C1, 0xa0, I2C_Direction_Transmitter);
	while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS);

	I2C_SendData(I2C1, addr);
	while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS);
}

void eeprom_write(uint32_t addr, const void* data, int size)
{
	int i;
	const uint8_t* buffer = (uint8_t*)data;

	eeprom_set_addr(addr);
	for (i=0; i<size; i++)
	{
		I2C_SendData(I2C1, buffer[i]);
		while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS);
	}
	I2C_GenerateSTOP(I2C1, ENABLE);
}

void eeprom_read(uint32_t addr, void* data, int size)
{
	int i;
	uint8_t* buffer = (uint8_t*)data;

	eeprom_set_addr(addr);

	I2C_GenerateSTART(I2C1, ENABLE);
	while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);

	I2C_AcknowledgeConfig(I2C1, ENABLE);
	I2C_Send7bitAddress(I2C1, 0xa0, I2C_Direction_Receiver);
	while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) != SUCCESS);

	for (i=0; i<size-1; i++)
	{
		while(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS);
		buffer[i] = I2C_ReceiveData(I2C1);
	}
	I2C_AcknowledgeConfig(I2C1, DISABLE);
		I2C_GenerateSTOP(I2C1, ENABLE);
		while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS);
		buffer[i] = I2C_ReceiveData(I2C1);
}

int main(void)
{
	uint32_t counter = 0;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

	GPIO_InitTypeDef gpio;

	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);

	GPIO_StructInit(&gpio);
	gpio.GPIO_Pin = GPIO_Pin_2;
	gpio.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOA, &gpio);

	gpio.GPIO_Pin = GPIO_Pin_3;
	gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA, &gpio);

	USART_InitTypeDef uart;

	USART_StructInit(&uart);
	uart.USART_BaudRate = 115200;
	USART_Init(USART2, &uart);
	USART_Cmd(USART2, ENABLE);

	I2C_InitTypeDef i2c;

	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);

	eeprom_read(0x10, &counter, sizeof(counter));

	counter++;

	printf("Uruchomienie numer %ld\n", counter); // wyświetla

	eeprom_write(0x10, &counter, sizeof(counter));

	eeprom_set_addr(0x00);

	printf("cokolwiek\n"); //już nie wyświetla

	I2C_GenerateSTART(I2C1, ENABLE);
	while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);

	I2C_AcknowledgeConfig(I2C1, ENABLE);
	I2C_Send7bitAddress(I2C1, 0xa0, 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 data1 = I2C_ReceiveData(I2C1);

	I2C_AcknowledgeConfig(I2C1, DISABLE);
	I2C_GenerateSTOP(I2C1, ENABLE);
	while(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS);
	uint8_t data2 = I2C_ReceiveData(I2C1);
	
	printf("data1: %x/n", data1); //chcę aby wypisywało wartość przez uart
	printf("data2: %x/n", data2);

	while(1)
	{

	}
}

Proszę. 🙂

Link do komentarza
Share on other sites

Dnia 5.01.2019 o 17:22, Elvis napisał:

Usuń:


eeprom_set_addr(0x00);

Usunąłem i napis został wyświetlony, lecz po wykonaniu kolejnych komend dalej nie działa printf.

/**
  ******************************************************************************
  * @file    main.c
  * @author  Ac6
  * @version V1.0
  * @date    01-December-2013
  * @brief   Default main function.
  ******************************************************************************
*/


#include "stm32f10x.h"
#include "stdio.h"
#include "delay.h"

void send_char(char c)
{
	while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
 	USART_SendData(USART2, c);
}

int __io_putchar(int c)
{
	if (c=='\n')
	send_char('\r');
 	send_char(c);
 	return c;
}


void eeprom_set_addr(uint32_t addr)
{
	I2C_GenerateSTART(I2C1, ENABLE);
	while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);
	I2C_Send7bitAddress(I2C1, 0xa0, I2C_Direction_Transmitter);
	while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) != SUCCESS);

	I2C_SendData(I2C1, addr);
	while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS);
}

void eeprom_write(uint32_t addr, const void* data, int size)
{
	int i;
	const uint8_t* buffer = (uint8_t*)data;

	eeprom_set_addr(addr);
	for (i=0; i<size; i++)
	{
		I2C_SendData(I2C1, buffer[i]);
		while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTING) != SUCCESS);
	}
	I2C_GenerateSTOP(I2C1, ENABLE);
}

void eeprom_read(uint32_t addr, void* data, int size)
{
	int i;
	uint8_t* buffer = (uint8_t*)data;

	eeprom_set_addr(addr);

	I2C_GenerateSTART(I2C1, ENABLE);
	while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);

	I2C_AcknowledgeConfig(I2C1, ENABLE);
	I2C_Send7bitAddress(I2C1, 0xa0, I2C_Direction_Receiver);
	while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) != SUCCESS);

	for (i=0; i<size-1; i++)
	{
		while(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS);
		buffer[i] = I2C_ReceiveData(I2C1);
	}
	I2C_AcknowledgeConfig(I2C1, DISABLE);
		I2C_GenerateSTOP(I2C1, ENABLE);
		while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS);
		buffer[i] = I2C_ReceiveData(I2C1);
}

int main(void)
{
	uint32_t counter = 0;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD, ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

	GPIO_InitTypeDef gpio;

	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);

	GPIO_StructInit(&gpio);
	gpio.GPIO_Pin = GPIO_Pin_2;
	gpio.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOA, &gpio);

	gpio.GPIO_Pin = GPIO_Pin_3;
	gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA, &gpio);

	USART_InitTypeDef uart;

	USART_StructInit(&uart);
	uart.USART_BaudRate = 115200;
	USART_Init(USART2, &uart);
	USART_Cmd(USART2, ENABLE);

	I2C_InitTypeDef i2c;

	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);

	eeprom_read(0x10, &counter, sizeof(counter));

	counter++;

	printf("Uruchomienie numer %ld\n", counter); // wyświetla

	eeprom_write(0x10, &counter, sizeof(counter));

	I2C_GenerateSTART(I2C1, ENABLE);
	while (I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT) != SUCCESS);

	I2C_AcknowledgeConfig(I2C1, ENABLE);
	I2C_Send7bitAddress(I2C1, 0xa0, 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 data1 = I2C_ReceiveData(I2C1);

	I2C_AcknowledgeConfig(I2C1, DISABLE);
	I2C_GenerateSTOP(I2C1, ENABLE);
	while(I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED) != SUCCESS);
	uint8_t data2 = I2C_ReceiveData(I2C1);

	printf("data1: %x/n", data1);
	printf("data2: %x/n", data2);
	
	printf("cokolwiek\n"); //nie wyświetla

	while(1)
	{

	}
}

 

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.