F103 I2c eeprom

Wszystko o naszych nuklejkach od STM
ODPOWIEDZ
Pawel5
Użytkownik
Posty: 15
Rejestracja: 19 lut 2018, 17:13

F103 I2c eeprom

Post autor: Pawel5 » 10 mar 2018, 23:27

Witam.
Posiada ktoś kod do obsługi eeprom po i2c napisanego na rejestrach?
Posiadam kostki eeprom 24LC128, 24C02, 24C08A oczywiście przykładowy kod możne być na inne eeprom ;)

Awatar użytkownika
squeez
Użytkownik
Posty: 76
Rejestracja: 16 paź 2017, 23:52

Re: F103 I2c eeprom

Post autor: squeez » 11 mar 2018, 9:34

kiedys na poczatku zabawy z STM32 napisałem to na F103

Kod: Zaznacz cały

void I2C_Init(void)
{
   // I2C GPIO CONFIG
   GPIOB->CRL |= GPIO_CRL_CNF6 | GPIO_CRL_CNF7 | GPIO_CRL_MODE6 | GPIO_CRL_MODE7;

   // Software reset I2C
   I2C1->CR1 |= I2C_CR1_SWRST;
   I2C1->CR1 &= ~I2C_CR1_SWRST;

   I2C1->CR1 &= ~I2C_CR1_PE;
   I2C1->CR2 = I2C_CR2_FREQ_3;
   I2C1->TRISE = 9;
   I2C1->CCR = 0x24;

   // Wlaczenie I2C
   I2C1->CR1 |= I2C_CR1_PE | I2C_CR1_ACK;
   I2C1->OAR1 = (1 << 14);
}


void I2C_Start(void)
{
   I2C1->CR1 |= I2C_CR1_START;
   while( !(I2C1->SR1 & I2C_SR1_SB) );
   uint32_t tmp = I2C1->SR1;
}

void I2C_Stop(void)
{
   while( !(I2C1->SR1 & I2C_SR1_BTF) );
   I2C1->CR1 |= I2C_CR1_STOP;
}

void I2C_SendAddr(uint8_t address)
{
   I2C1->DR = address;
   while( !(I2C1->SR1 & I2C_SR1_ADDR) );
   uint32_t dummy = I2C1->SR1;
   dummy = I2C1->SR2;
}

void I2C_SendByte(uint8_t byte)
{
   while( !(I2C1->SR1 & I2C_SR1_TXE) );
   I2C1->DR = byte;
}
prymitywna wersja działa w pollingu, napisałem też na przerwania i DMA. do I2C trzeba przeczytac errate

Pawel5
Użytkownik
Posty: 15
Rejestracja: 19 lut 2018, 17:13

Re: F103 I2c eeprom

Post autor: Pawel5 » 12 mar 2018, 17:43

Cześć ;)
Zrobiłem zapis w ten sposób:

Kod: Zaznacz cały

void zapisi2c(uint8_t adresx, uint16_t subAddr, uint16_t dlugosc, uint8_t *buf) {

	while (dlugosc--) {
		I2C_Start();

		I2C_SendAddr( adresx );
		I2C_SendByte(subAddr);

		I2C_SendByte(*buf++);

		I2C_Stop();
		delay_ms2(5);
		subAddr++;
	}
}
robię zapis napisu "test2"
uint8_t tekst[] = "test2";

Kod: Zaznacz cały

zapisi2c( adres, 200, sizeof(tekst), tekst );
Oto wynik:
Obrazek
Problem mam z odczytem, oto jak go wykonałem:

Kod: Zaznacz cały

void odczyti2c(uint8_t adresx, uint16_t subAddr, uint16_t len, uint8_t *buf) {

	while (len--) {
		I2C_Start();
		I2C_SendAddr(adresx );
		I2C_SendByte(subAddr);
		I2C_Start();
		I2C_SendAddr(adresx + 1);
		*buf++ = I2C_ReadByte( 0 );
		I2C_Stop();
		subAddr++;
	}


}

Kod: Zaznacz cały

I2C_ReadByte(uint8_t byte)
{
   while( !(I2C1->SR1 & I2C_SR1_RXNE) );
   byte = I2C1->DR ;
   return byte;
}
Nie wyświetla mi danych odczytanych po czym zawiesza i2c i muszę resetować zasilanie
Oto jak to wygląda
Obrazek

Cały kod:

Kod: Zaznacz cały

#include "stm32f1xx.h"
#include "LCD/hd44780.h"
			
void I2C_Start(void);
void I2C_Stop(void);
I2C_ReadByte(uint8_t byte);
void I2C_SendAddr(uint8_t address);
void I2C_SendByte(uint8_t byte);

void zapisi2c(uint8_t adresx, uint16_t subAddr, uint16_t dlugosc, uint8_t *buf);
void odczyti2c(uint8_t adresx, uint16_t subAddr, uint16_t len, uint8_t *buf);

void delay_ms2(int ms);

uint8_t tekst[] = "test2";
uint8_t bo[ 6 ];


#define adres 0xAC
int main(void)
{


	RCC->APB2ENR =  RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN ;
	RCC->APB1ENR = RCC_APB1ENR_I2C1EN;


	lcd_init();

	lcd_cls();
		lcd_locate(0,0);
		lcd_str( "Uruchamianie ");



		// I2C GPIO CONFIG
		   GPIOB->CRL |= GPIO_CRL_CNF6 | GPIO_CRL_CNF7 | GPIO_CRL_MODE6 | GPIO_CRL_MODE7;

		   // Software reset I2C
		   I2C1->CR1 |= I2C_CR1_SWRST;
		   I2C1->CR1 &= ~I2C_CR1_SWRST;

		   I2C1->CR1 &= ~I2C_CR1_PE;
		   I2C1->CR2 = I2C_CR2_FREQ_3;
		   I2C1->TRISE = 9;
		   I2C1->CCR = 0x24;

		   // Wlaczenie I2C
		   I2C1->CR1 |= I2C_CR1_PE | I2C_CR1_ACK;
		   I2C1->OAR1 = (1 << 14);






	//	zapisi2c( adres, 200, sizeof(tekst), tekst );
		   odczyti2c( adres, 200, sizeof(tekst), bo );

		  lcd_locate(2, 0);
		  			lcd_str( (char*)bo );
	while(1){


	}
}






void zapisi2c(uint8_t adresx, uint16_t subAddr, uint16_t dlugosc, uint8_t *buf) {

	while (dlugosc--) {
		I2C_Start();

		I2C_SendAddr( adresx );
		I2C_SendByte(subAddr);

		I2C_SendByte(*buf++);

		I2C_Stop();
		delay_ms2(5);
		subAddr++;
	}
}

// odczyt danych z pamięci EEPROM
void odczyti2c(uint8_t adresx, uint16_t subAddr, uint16_t len, uint8_t *buf) {

	while (len--) {
		I2C_Start();
		I2C_SendAddr(adresx  );
		I2C_SendByte(subAddr);
		I2C_Start();
		I2C_SendAddr(adresx + 1);
		*buf++ = I2C_ReadByte( 0 );
		I2C_Stop();
		subAddr++;
	}


}

void I2C_Start(void)
{
   I2C1->CR1 |= I2C_CR1_START;
   while( !(I2C1->SR1 & I2C_SR1_SB) );
   uint32_t tmp = I2C1->SR1;
}

void I2C_Stop(void)
{
   while( !(I2C1->SR1 & I2C_SR1_BTF) );
   I2C1->CR1 |= I2C_CR1_STOP;
}

void I2C_SendAddr(uint8_t address)
{
   I2C1->DR = address;
   while( !(I2C1->SR1 & I2C_SR1_ADDR) );
   uint32_t dummy = I2C1->SR1;
   dummy = I2C1->SR2;
}

void I2C_SendByte(uint8_t byte)
{
   while( !(I2C1->SR1 & I2C_SR1_TXE) );
   I2C1->DR = byte;
}
I2C_ReadByte(uint8_t byte)
{
   while( !(I2C1->SR1 & I2C_SR1_RXNE) );
   byte = I2C1->DR ;
   return byte;
}
void delay_ms2(int ms) {
	int c = 0;
	SysTick->LOAD = 8000000 / 1000 - 1;

	SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
	SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk;
	while (c < ms) {
		while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk))
			;
		c++;
	}
	SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
}
Już nie mam pomysłu jak ugryźć i2c na stm32 spędziłem sporo czasu a efekt jest slaby.
eeprom 24C02 zasilany 5v

Awatar użytkownika
SunRiver
Administrator
Posty: 361
Rejestracja: 08 paź 2017, 11:27
Lokalizacja: Opole
Kontakt:

Re: F103 I2c eeprom

Post autor: SunRiver » 12 mar 2018, 17:55

Oczywiście sprawdziłeś w nocie jakie masz adresy zapisu i odczytu ??
bo ... zapis ma swój adres , a odczyt ma swój adres :)

zaglądałeś do noty układu ??
wiesz że ma zasilanie od 1.8V do 5,5V :P
że prędkość magistrali jest musi byś ustawiona .... 1MHz dla 5V , 400KHz dla 1,8 , 2,5 , 2.7V
czy pinami A0 - A2 ustawiłeś adres ??
Czy pamiętałeś o pullupach dla SDA i SCL 4K7
Czy czekasz właściwą ilość cykli na zakończenie zapisu i odczyt ?? średnio 9 cykli
.... z każdym bitem serca ....
💫SunDUINO
💦Google+
💦Kanał Youtube
💦Sotton

Awatar użytkownika
SunRiver
Administrator
Posty: 361
Rejestracja: 08 paź 2017, 11:27
Lokalizacja: Opole
Kontakt:

Re: F103 I2c eeprom

Post autor: SunRiver » 12 mar 2018, 18:04

https://community.st.com/thread/34622-i ... om-example

to że wolisz rejestry nie zmienia faktu że możesz sprawdzić komunikację nawet na CMSIS HAL czy STD

Przemyśl to i zapoznaj się :P
.... z każdym bitem serca ....
💫SunDUINO
💦Google+
💦Kanał Youtube
💦Sotton

Pawel5
Użytkownik
Posty: 15
Rejestracja: 19 lut 2018, 17:13

Re: F103 I2c eeprom

Post autor: Pawel5 » 12 mar 2018, 18:05

O zasilaniu wiem dlatego jest na 5v ;)
Adres zapisu 172 a odczytu 173 i tak mam ustawione piny Ax.
Pullupy są.
Teraz jak patrzę w nocie to minimum prędkość magistrali to 2MHz? W tym może być problem.
Po zapisie czekam 5ms. Przy odczycie nie czekam. 9 cykli czy ile, nie bardzo rozumiem.

Awatar użytkownika
SunRiver
Administrator
Posty: 361
Rejestracja: 08 paź 2017, 11:27
Lokalizacja: Opole
Kontakt:

Re: F103 I2c eeprom

Post autor: SunRiver » 12 mar 2018, 18:11

min 10ms jest układ zajęty ...
Napięcia przytoczyłem dlatego że jak widzisz moęsz zasilać eeprom 3,3V nawet ..
zwolnij magistralę i wydłuż oczekiwanie
.... z każdym bitem serca ....
💫SunDUINO
💦Google+
💦Kanał Youtube
💦Sotton

Pawel5
Użytkownik
Posty: 15
Rejestracja: 19 lut 2018, 17:13

Re: F103 I2c eeprom

Post autor: Pawel5 » 12 mar 2018, 20:06

Ustawiłem I2C1->CCR = 0x4; lecz jest gorzej. Może z któryś kolegów podpowie jak zmniejszyć częstotliwość i2c.

ODPOWIEDZ

Wróć do „STM32-Nucleo”