|
avr155, Вопрос |
|
|
|
Jul 19 2007, 11:07
|
Знающий
   
Группа: Свой
Сообщений: 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
|
|
|
|
|
Jul 19 2007, 15:18
|

кекс
     
Группа: Свой
Сообщений: 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); Это оригинал? Тут только два варианта: 1. специально сделанная ошибка, 2. китайцы, которые это написали - в работе это не проверяли. Либо проверяли, но для устройства с которым они работали было некритично наличие последнего NACK'a.
|
|
|
|
|
Jul 20 2007, 06:03
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Цитата(defunct @ Jul 19 2007, 18:18)  Это оригинал? Тут только два варианта: 1. специально сделанная ошибка, 2. китайцы, которые это написали - в работе это не проверяли. Либо проверяли, но для устройства с которым они работали было некритично наличие последнего NACK'a. Да, оригинал. Правильно ли будет с моей поправкой? for(j=data_pack.size;((j)&&(state == SUCCESS));j--) state = Get_byte(data_pack.data_ptr++,j); Для разрабатываемого устройства важна надежность работы TWI. Сейчас думаю перейти на TWI с прерываниями (avr315). Есть ли там какие-нибудь подводные камни. И надежней ли так будет?
|
|
|
|
|
Jul 20 2007, 12:10
|

кекс
     
Группа: Свой
Сообщений: 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; }
|
|
|
|
|
Jul 20 2007, 15:13
|
Знающий
   
Группа: Свой
Сообщений: 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 байт...
|
|
|
|
|
Jul 20 2007, 18:23
|

кекс
     
Группа: Свой
Сообщений: 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?
|
|
|
|
|
Jul 20 2007, 18:30
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Цитата(defunct @ Jul 20 2007, 21:23)  Вы с каким устройством собираетесь работать через i2c? LCD(TIC154), DS1388(rtc), FOSP-01A(цифровой барометр) Сейчас вот думаю , как отправить картинку (массив[1064] во флеше) в LCD. Покажите, пожалуста, на примере с использованием аппаратного twi с прерываниями.
|
|
|
|
|
Jul 20 2007, 21:15
|

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

|
Цитата(alux @ Jul 20 2007, 23:33)  я имел в виду пример кода, как отправить большой массив частями по 32 байта по аппаратному TWI. В рамках предыдущего примера - вызвать функцию I2C_TRANSFER n/32 раз с требуемыми параметрами в цикле... где n - объем данных в байтах который надо переслать.. Или Вам надо обязательно за одну транзакцию 1024 байта перегонять? Цитата Только не понятно как быть, если размер массива не кратный 32? Т.е. последняя отправка неполного буфера. При отправке порции отнимайте 32 байта от суммарной длины. Когда остается меньше 32х байт, то отправляйте все что осталось и на этом собсно все.. Зачем там еще операции деления использовать?!
|
|
|
|
|
Jul 21 2007, 17:51
|
Знающий
   
Группа: Свой
Сообщений: 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++.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|