реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> STM32F0 и I2C, передача/прием нескольких байт
toweroff
сообщение Sep 23 2015, 08:45
Сообщение #1


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Добрый день

Во всех примерах, какие находились на просторах, чтение/запись осуществляется по одному байту.
Теоретически, ничего сложного - "задвинуть" количество байт в CR2 и потом пиши/читай
Но что-то не сходится. После записи байта никакие флаги не возводятся, как определить готовность к следующему байту? Да и с чтением та же петрушка
Как вообще это нужно делать?

Спасибо
Go to the top of the page
 
+Quote Post
smalcom
сообщение Sep 23 2015, 10:25
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 292
Регистрация: 26-06-07
Пользователь №: 28 718



там весёлый I2C. Тут недавно проскакивала тема про это, в ней и исходники есть.
Суть в том, что правильно(по рек.произв.) алгоритм отправки состоит из трёх ветвей: отправить один байт, отправить два, отправить больше двух.
Go to the top of the page
 
+Quote Post
toweroff
сообщение Sep 23 2015, 10:46
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



В общем у меня вот такое родилось, работает. На шине одновременно висят EEPROM 24LC16 и LIS3DH

CODE

// ==================================================
void I2C_Start_Direction_Adress_Size (I2C_TypeDef* Port, uint32_t Direction, uint8_t Adress, uint8_t Size)
{
Port->CR2 &= ~I2C_CR2_AUTOEND; // Stop by siftware
Port->CR2 &= ~I2C_CR2_RELOAD; // No reload
if (Direction == I2C_CR2_RD_WRN) Port->CR2 |= I2C_CR2_RD_WRN; // receive mode
else Port->CR2 &= ~I2C_CR2_RD_WRN; // transmit mode
Port->CR2 &= ~I2C_CR2_NBYTES; // clear NBYTES field
Port->CR2 |= Size<<16; // Set NBYTES
Port->CR2 &= ~I2C_CR2_SADD; // clear slave address field
Port->CR2 |= Adress; // Set slave address
Port->CR2 |= I2C_CR2_START; // Transmit START bit
while ((Port->ISR & I2C_ISR_BUSY)==0) {}; // Wait for done
}
// ==================================================


// ==================================================
void I2C_Stop (I2C_TypeDef* Port)
{
Port->CR2 |= I2C_CR2_STOP; // Stop to bus
while (Port->ISR & I2C_ISR_BUSY) {}; // wait for stop transmitted
// Clear flags
Port->ICR |= I2C_ICR_STOPCF;
Port->ICR |= I2C_ICR_NACKCF;
// Clear errors flags
if (Port->ISR & (I2C_ISR_ARLO | I2C_ISR_BERR))
{
Port->ICR |= I2C_ICR_ARLOCF;
Port->ICR |= I2C_ICR_BERRCF;
}
}
// ==================================================



i2c_operate_t I2C_Operate(I2C_TypeDef* Port, uint8_t addr, void* trsm, uint8_t tcount, void* rcv, uint8_t rcount)
{
uint8_t *u8_ptr;
uint32_t status;

if (((tcount==0) && (rcount==0)) || (tcount)) // tcount== 0 and rcount==0 for device presence check
{
I2C_Start_Direction_Adress_Size(Port, 0, addr, tcount);
// Check for status
while (!(Port->ISR & (I2C_ISR_TC | I2C_ISR_TXIS | I2C_ISR_NACKF) && (Port->ISR & I2C_ISR_BUSY))) {};

if (Port->ISR & I2C_ISR_NACKF)
{
I2C_Stop(Port);
return I2C_OPERATE_NO_DEVICE;
}
}

// Transmit part
if (tcount)
{
u8_ptr = (uint8_t*)trsm;
while ((((Port->ISR & I2C_ISR_TC)==0) && ((Port->ISR & I2C_ISR_NACKF)==0)) && (Port->ISR & I2C_ISR_BUSY))
{
if (Port->ISR & I2C_ISR_TXIS) Port->TXDR = *u8_ptr++; // Send data
}

status = Port->ISR;
if (status & (I2C_ICR_ARLOCF | I2C_ICR_BERRCF | I2C_ISR_NACKF)) // some errors
{
I2C_Stop(Port);
if (status & (I2C_ICR_ARLOCF | I2C_ICR_BERRCF)) return I2C_BUS_ERROR;
if (status & I2C_ISR_NACKF) return I2C_OPERATE_WRITE_NACK;
}
}

// Receive part
if (rcount)
{
u8_ptr = (uint8_t*)rcv;

I2C_Start_Direction_Adress_Size (Port, I2C_CR2_RD_WRN, addr, rcount);
if (Port->ISR & I2C_ISR_NACKF)
{
I2C_Stop(Port);
return I2C_OPERATE_NO_DEVICE;
}
u8_ptr = (uint8_t*)rcv;
while (!(Port->ISR & (I2C_ISR_TC | I2C_ISR_NACKF)) && (Port->ISR & I2C_ISR_BUSY))
{
if (Port->ISR & I2C_ISR_RXNE) *u8_ptr++ = Port->RXDR; // Receive data
}
}
status = Port->ISR;

I2C_Stop(Port);

if (status & (I2C_ICR_ARLOCF | I2C_ICR_BERRCF | I2C_ISR_NACKF)) // some errors
{
I2C_Stop(Port);
if (status & (I2C_ICR_ARLOCF | I2C_ICR_BERRCF)) return I2C_BUS_ERROR;
if (status & I2C_ISR_NACKF) return I2C_OPERATE_READ_NACK;
}

return I2C_OPERATE_OK;
}
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Sep 24 2015, 07:01
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



А в чем идея передачи tcount в I2C_Operate? Что-то он там только на ноль/не-ноль проверяется... Или так и задумано? Пока устройство не начнет в ответ что=то слать, передаем ему данные...
ps: давно пытаюсь сделать работающий модуль I2C для stm32f4xxx и для остальных. Пока не очень успешно - в работающих изделиях стоит программная реализация.
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Sep 24 2015, 13:25
Сообщение #5


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Добавлю ссылочку на хорошую реализацию i2c на STM32 : тынц. Там всё подробно описано в комментариях.


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
toweroff
сообщение Sep 24 2015, 21:11
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Цитата(Genadi Zawidowski @ Sep 24 2015, 10:01) *
А в чем идея передачи tcount в I2C_Operate? Что-то он там только на ноль/не-ноль проверяется... Или так и задумано? Пока устройство не начнет в ответ что=то слать, передаем ему данные...

ну здрасте!
Код
I2C_Start_Direction_Adress_Size(Port, 0, addr, tcount);

если 0, то просто проверится ACK от устройства на шине, а если не 0, так данные и будут вгоняться в соответствии с этим количеством (пока флаг TC не поднимется, а поднимется он после передачи tcount байт)
Go to the top of the page
 
+Quote Post
Genadi Zawidowsk...
сообщение Sep 25 2015, 05:57
Сообщение #7


Профессионал
*****

Группа: Участник
Сообщений: 1 620
Регистрация: 22-06-07
Из: Санкт-Петербург, Россия
Пользователь №: 28 634



"в соответствии с количеством" не получится - tcount только на ноль/не ноль проверяется вTransmit part... Или тут надежда на то, что контроллер отсчитает нужное количество сам?

Сообщение отредактировал Genadi Zawidowski - Sep 25 2015, 05:59
Go to the top of the page
 
+Quote Post
toweroff
сообщение Sep 25 2015, 10:46
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514



Цитата(Genadi Zawidowski @ Sep 25 2015, 08:57) *
"в соответствии с количеством" не получится - tcount только на ноль/не ноль проверяется вTransmit part...

проверяется. Именно для того, чтобы дать стартовую посылку

Цитата(Genadi Zawidowski @ Sep 25 2015, 08:57) *
Или тут надежда на то, что контроллер отсчитает нужное количество сам?

Прикрепленное изображение
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st August 2025 - 20:45
Рейтинг@Mail.ru


Страница сгенерированна за 0.01423 секунд с 7
ELECTRONIX ©2004-2016