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

 
 
2 страниц V   1 2 >  
Reply to this topicStart new topic
> avr155, Вопрос
alux
сообщение Jul 19 2007, 11:07
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Разбираюсь с этим апнотом. Не понятно, каким образом в функции Get_byte() происходит обнаружение приема последнего байта? Ведь переменная j, которая передается в качестве второго аргумента этой функции, и которая сравнивается с нулем, инкрементируется data_pack.size раз и по идее не станет равной нулю ни при каких условиях. Ну, разве что размер получаемых данных превысит 255. Или я чего-то не доганяю?
На всякий случай прилагаю апнот.

Может быть правильней было бы сделать так:
for(j=data_pack.size;((j)&&(state == SUCCESS));j--)
state = Get_byte(data_pack.data_ptr++,j);
Прикрепленные файлы
Прикрепленный файл  AVR155.zip ( 10.02 килобайт ) Кол-во скачиваний: 50
 
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 19 2007, 15:18
Сообщение #2


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(alux @ Jul 19 2007, 14:07) *
Разбираюсь с этим апнотом. Не понятно, каким образом в функции Get_byte() происходит обнаружение приема последнего байта?

У функции Get_Byte - last_byte - это параметр, он из-вне задается.
Смысл конечно искажен немного, т.к. судя по отправке ACK/NACK - last_byte == 0 - означает последний принимаемый байт.

Цитата
for(j=0;((j<data_pack[i].size)&&(state == SUCCESS));j++)
state = Get_byte(data_pack[i].data_ptr++,j);

Это оригинал? smile.gif
Тут только два варианта:
1. специально сделанная ошибка,
2. китайцы, которые это написали - в работе это не проверяли. Либо проверяли, но для устройства с которым они работали было некритично наличие последнего NACK'a.
Go to the top of the page
 
+Quote Post
alux
сообщение Jul 20 2007, 06:03
Сообщение #3


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Цитата(defunct @ Jul 19 2007, 18:18) *
Это оригинал? smile.gif
Тут только два варианта:
1. специально сделанная ошибка,
2. китайцы, которые это написали - в работе это не проверяли. Либо проверяли, но для устройства с которым они работали было некритично наличие последнего NACK'a.

Да, оригинал. Правильно ли будет с моей поправкой?
for(j=data_pack.size;((j)&&(state == SUCCESS));j--)
state = Get_byte(data_pack.data_ptr++,j);
Для разрабатываемого устройства важна надежность работы TWI. Сейчас думаю перейти на TWI с прерываниями (avr315). Есть ли там какие-нибудь подводные камни. И надежней ли так будет?
Go to the top of the page
 
+Quote Post
WHALE
сообщение Jul 20 2007, 08:33
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 902
Регистрация: 2-01-06
Из: Краснодар
Пользователь №: 12 768



я уже года 2 работаю с AVR315,глюков не замечал(кроме собственных :-))


--------------------
"Hello, word!" - 17 errors 56 warnings
Go to the top of the page
 
+Quote Post
alux
сообщение Jul 20 2007, 11:53
Сообщение #5


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Если использовать avr315, как просто получить и/или принять один байт без применения буфера?
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 20 2007, 12:10
Сообщение #6


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(alux @ Jul 20 2007, 14:53) *
Если использовать avr315, как просто получить и/или принять один байт без применения буфера?

Никак - буфер должен быть обязательно. И упр. структура.
Но это не должно Вас пугать. Это есть правильный подход.

Цитата(alux @ Jul 20 2007, 09:03) *
Правильно ли будет с моей поправкой?

Думаю что нет.
условие (j) равносильно (j > 0), вы используете пост декремент, а это значит, что 0 в теле цикла никогда не появится.

Я бы сделал функцию чтения блока, т.к. все равно побайтовый I2C обмен практически не нужен:
Код
U8 Get_Block( <Тип записи> *pDataPkt )
{
     U8 size = pDataPkt->size;
     U8 state = ACK;
     while( size-- &&  state == ACK)
     {
          state = Get_byte(pDataPkt->data_ptr++, size);
     }
     return state;
}
Go to the top of the page
 
+Quote Post
alux
сообщение Jul 20 2007, 15:13
Сообщение #7


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Цитата(defunct @ Jul 20 2007, 15:10) *
условие (j) равносильно (j > 0), вы используете пост декремент, а это значит, что 0 в теле цикла никогда не появится.

Значит нужно сделать предекремент?

Цитата(defunct @ Jul 20 2007, 15:10) *
Я бы сделал функцию чтения блока...

Я бы предпочел использовать функцию Send_to_TWI , как в avr155. Только с поправкой (с предекрементом для receive data).

Как отправить по TWI (avr315) массив из 1000 байт? Не инициализировать же буфер из 1000 байт...
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 20 2007, 18:23
Сообщение #8


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(alux @ Jul 20 2007, 18:13) *
Значит нужно сделать предекремент?

нет, нужно менять либо условие (т.к. проверка условия в цикле for делается до модификации),
либо параметр функции:
Get_Byte( xx, j - 1);

либо саму функцию..

Цитата
Я бы предпочел использовать функцию Send_to_TWI , как в avr155. Только с поправкой (с предекрементом для receive data).

я предпочитаю пользоваться функцией блочной записи/чтения:

/***********************************************
* i2c_MemTransfer() *
* begin interrupt handled transfer *
* ---> I2CAddr - address of the target device *
* if even - Master to slave direction *
* if odd - Slave to Master direction *
* ---> memAddr - address of memory cell *
* ---> count - number of bytes to transfer *
* ---> pData - data to write, or pointer to *
* buffer (if receiving) *
* <--- ничего не возвращает *
***********************************************/
void i2c_MemTransfer(U8 I2CAddr, U16 memAddr, U8 count, U8 *pData)

Цитата
Как отправить по TWI (avr315) массив из 1000 байт? Не инициализировать же буфер из 1000 байт...

Блоками например по 32 байта. И буфер сделать 32 байта.
Обычно объем буфера зависит от слейва.
Вы с каким устройством собираетесь работать через i2c?
Go to the top of the page
 
+Quote Post
alux
сообщение Jul 20 2007, 18:30
Сообщение #9


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Цитата(defunct @ Jul 20 2007, 21:23) *
Вы с каким устройством собираетесь работать через i2c?

LCD(TIC154), DS1388(rtc), FOSP-01A(цифровой барометр)
Сейчас вот думаю , как отправить картинку (массив[1064] во флеше) в LCD.
Покажите, пожалуста, на примере с использованием аппаратного twi с прерываниями.
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 20 2007, 19:18
Сообщение #10


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(alux @ Jul 20 2007, 21:30) *
Покажите, пожалуста, на примере с использованием аппаратного twi с прерываниями.

Рабочий пример под ARM. Надо будет поменять имена регистров на соответвующие из TWI модуля. Немного подрихтовать напильником, и можно использовать для AVR.

PS: I2C модуль ARM практически ничем (кроме имен регистров) не отличается от TWI модуля AVR
Прикрепленные файлы
Прикрепленный файл  ex21_i2c.rar ( 28.93 килобайт ) Кол-во скачиваний: 44
 
Go to the top of the page
 
+Quote Post
alux
сообщение Jul 20 2007, 20:33
Сообщение #11


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



я имел в виду пример кода, как отправить большой массив частями по 32 байта по аппаратному TWI. Ну да ладно. Наверно я изобретаю велосипед:
static const unsigned char __flash logo[]={....};
#define COUNT(logo) (sizeof(logo)/sizeof((logo)[0]))
const unsigned char __flash *pic;
unsigned int max;
unsigned char messageBuf[32];
pic = logo;
max=COUNT(logo);

for(unsigned int cnt = 0; cnt < (max/32); cnt++)
{
messageBuf[0] = (TWI_targetSlaveAddress<<TWI_ADR_BITS)|(FALSE<<TWI_READ_BIT);
for(unsigned char i=1;i<32;i++)
messageBuf[i] = *pic++;
TWI_Start_Transceiver_With_Data(messageBuf,32);
}
Только не понятно как быть, если размер массива не кратный 32? Т.е. последняя отправка неполного буфера.
...пока спрашивал, пришла мысль. Можно так?
messageBuf[0] = (TWI_targetSlaveAddress<<TWI_ADR_BITS)|(FALSE<<TWI_READ_BIT);
for(unsigned char i=1;i<(max%32);i++)
messageBuf[i] = *pic++;
TWI_Start_Transceiver_With_Data(messageBuf,(max%32));
...И еще. Первый элемент messageBuf всегда должен быть (TWI_targetSlaveAddress<<TWI_ADR_BITS)|(FALSE<<TWI_READ_BIT); в случае отправки.
Правильно ли я делаю?
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 20 2007, 21:15
Сообщение #12


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(alux @ Jul 20 2007, 23:33) *
я имел в виду пример кода, как отправить большой массив частями по 32 байта по аппаратному TWI.

В рамках предыдущего примера - вызвать функцию I2C_TRANSFER n/32 раз с требуемыми параметрами в цикле... где n - объем данных в байтах который надо переслать..

Или Вам надо обязательно за одну транзакцию 1024 байта перегонять?

Цитата
Только не понятно как быть, если размер массива не кратный 32? Т.е. последняя отправка неполного буфера.

При отправке порции отнимайте 32 байта от суммарной длины. Когда остается меньше 32х байт, то отправляйте все что осталось и на этом собсно все.. Зачем там еще операции деления использовать?!
Go to the top of the page
 
+Quote Post
alux
сообщение Jul 20 2007, 21:53
Сообщение #13


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Цитата(defunct @ Jul 21 2007, 00:15) *
При отправке порции отнимайте 32 байта от суммарной длины. Когда остается меньше 32х байт, то отправляйте все что осталось и на этом собсно все.. Зачем там еще операции деления использовать?!

Как узнать, что остается меньше 32х байт? А в моем варианте, допустим надо переслать 1064 байт. Первый раз отправляем 1064/32=33 раз. Остаток отправляем 1064%32=8 байт. А что Вас смущает?
Go to the top of the page
 
+Quote Post
defunct
сообщение Jul 20 2007, 23:54
Сообщение #14


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(alux @ Jul 21 2007, 00:53) *
Как узнать, что остается меньше 32х байт? А в моем варианте, допустим надо переслать 1064 байт. Первый раз отправляем 1064/32=33 раз. Остаток отправляем 1064%32=8 байт. А что Вас смущает?


Код
while(size)
{
   BytesToSend = (size > 32) ? 32 : size;
   i2c_transfer( devaddr, memaddr, BytesToSend, pData);
   pData += BytesToSend;
   memaddr += BytesToSend;
   size -= BytesToSend;
}
Go to the top of the page
 
+Quote Post
alux
сообщение Jul 21 2007, 17:51
Сообщение #15


Знающий
****

Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447



Вот, немного подрихтовал:
Код
static const unsigned char __flash logo[]={....};
#define COUNT(logo) (sizeof(logo)/sizeof((logo)[0]))
const unsigned char __flash *pic;
unsigned int size;
unsigned char messageBuf[32];
pic = logo;
size=COUNT(logo);
  while(size)
  {
    BytesToSend=(size > 32) ? 32 : size;
    for(unsigned char i=1;i<BytesToSend;i++)
    {
      messageBuf[0] = (TWI_targetSlaveAddress<<TWI_ADR_BITS)|(FALSE<<TWI_READ_BIT);
      messageBuf[i] = *pic++;
    }
    TWI_Start_Transceiver_With_Data(messageBuf,BytesToSend);
    size -= BytesToSend;
  }

Если имя массива использовать в качестве указателя на первый элемент, можно ли использовать его вместо указателя *pic? Т.е. написать *(logo++) вместо *pic++.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 7th July 2025 - 16:28
Рейтинг@Mail.ru


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