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

 
 
> WinAVR: оптимизация
Arlleex
сообщение Feb 6 2012, 10:57
Сообщение #1


Местный
***

Группа: Участник
Сообщений: 492
Регистрация: 12-11-11
Пользователь №: 68 264



Добрый день. Столкнулся с проблемой оптимизации программы для микроконтроллера ATTiny2313. В Makefile выбрал оптимизацию "s", что означает "по размеру".
Вот эту функцию он выполняет не верно. Возвращаемое значение функции (байт) сдвинуто на 1 влево. В принципе есть определенные догадки, как рассуждает оптимизатор при оптимизации, но по другому нельзя, интерфейс требует установить линию данных в Hi-Z состояние, т.е. судя по логике оптимизатора можно просто спалить линию микроконтроллера и/или ведомой микросхемы (в моем случае это RTC DS1305 3-Wire). Но! При установке оптимизации уровня 1 все работает как задумано (в чем, собственно, я и не сомневался).
Функцию привожу:
Цитата
uint8_t rtc_read_byte(uint8_t address)
{
uint8_t i; // промежуточный счетчик бит
uint8_t buffer; // промежуточный буффер данных
uint8_t rtc_data; // данные
rtc_data=0x0; // запись данных
PORTD=PORTD | (1<<CS); // выбор периферийного устройства
for(i=0; i<8; ++i)
{
buffer=address; // копирование данных
buffer=buffer & 0x1; // выделение младшего бита
if (buffer==0x1)
{
PORTD=PORTD | (1<<DATA); // установка DATA
}
else
{
PORTD=PORTD & (~(1<<DATA)); // сброс DATA
}
PORTD=PORTD | (1<<CLK); // установка CLK
if (i<7)
{
PORTD=PORTD & (~(1<<CLK)); // сброс CLK
}
address=address>>1; // сдвиг вправо
}
PORTD=PORTD & (~(1<<DATA)); // настройка подтягивающего резистора линии DATA порта D
DDRD=DDRD & (~(1<<DATA)); // настройка линии DATA порта D
for(i=0; i<8; ++i)
{
PORTD=PORTD & (~(1<<CLK)); // сброс CLK
buffer=PIND & (1<<DATA); // чтение данных
if (buffer!=0)
{
rtc_data=rtc_data | (1<<i); // установка бита
}
PORTD=PORTD | (1<<CLK); // установка CLK
}
PORTD=PORTD & (~(1<<CS)); // сброс CS
DDRD=DDRD | (1<<DATA); // настройка линии DATA порта D
PORTD=PORTD & (~((1<<DATA) | (1<<CLK) | (1<<CS))); // сброс DATA, CLK, CS
return rtc_data; // выход из функции
}


Сообщение отредактировал Arlleex - Feb 6 2012, 11:00
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
Палыч
сообщение Feb 6 2012, 11:52
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Уж не знаю: как у Вас получается принимать правильно при другом уровне оптимизации...
Насколько я понял: у Вас CPOL=0. При этом DS1305 выставит очередной бит для считывания его МК при установки высокого уровня на CLK. Вы же его считываете при низком уровне на CLK, т.е. "забегаете вперед" на один бит. Вот результат и получается сдвинутым...
Go to the top of the page
 
+Quote Post
Arlleex
сообщение Feb 6 2012, 12:33
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 492
Регистрация: 12-11-11
Пользователь №: 68 264



Цитата(Палыч @ Feb 6 2012, 15:52) *
Уж не знаю: как у Вас получается принимать правильно при другом уровне оптимизации...
Насколько я понял: у Вас CPOL=0. При этом DS1305 выставит очередной бит для считывания его МК при установки высокого уровня на CLK. Вы же его считываете при низком уровне на CLK, т.е. "забегаете вперед" на один бит. Вот результат и получается сдвинутым...

У меня 3-Wire подключение.
Цитата
PORTD=PORTD | (1<<CS); // выбор периферийного устройства
for(i=0; i<8; ++i)
{
buffer=address; // копирование данных
buffer=buffer & 0x1; // выделение младшего бита
if (buffer==0x1)
{
PORTD=PORTD | (1<<DATA); // установка DATA
}
else
{
PORTD=PORTD & (~(1<<DATA)); // сброс DATA
}
PORTD=PORTD | (1<<CLK); // установка CLK
if (i<7)
{
PORTD=PORTD & (~(1<<CLK)); // сброс CLK
}
address=address>>1; // сдвиг вправо
}

Вот это выполняется правильно, адрес записывается.
Строки PORTD=PORTD | (1<<CLK); // установка CLK
if (i<7)
{
PORTD=PORTD & (~(1<<CLK)); // сброс CLK
}
указывают, что как только мы передали 8-й бит слова адреса, мы линию CLK не сбрасываем в 0, а сбрасываем ее тут:
Цитата
for(i=0; i<8; ++i)
{
PORTD=PORTD & (~(1<<CLK)); // сброс CLK
buffer=PIND & (1<<DATA); // чтение данных
if (buffer!=0)
{
rtc_data=rtc_data | (1<<i); // установка бита
}
PORTD=PORTD | (1<<CLK); // установка CLK
}

, поскольку при заднем фронте CLK произойдет вывод данных из RTC. Если бы мы это сделали раньше, чем написали бы строки
Цитата
PORTD=PORTD & (~(1<<DATA)); // настройка подтягивающего резистора линии DATA порта D
DDRD=DDRD & (~(1<<DATA)); // настройка линии DATA порта D

RTC выставил бы данные, и МК не переопределя линию на вход, спалил бы и себе линию, и возможно RTC.
Насчет таймингов. У меня частота микроконтроллера остается стандартной и поэтому время выполнения даже самой короткой операции не превышает 1мкс.
Go to the top of the page
 
+Quote Post
Палыч
сообщение Feb 6 2012, 13:03
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(Arlleex @ Feb 6 2012, 16:33) *
указывают, что как только мы передали 8-й бит слова адреса, мы линию CLK не сбрасываем в 0, а сбрасываем ее тут:
....
, поскольку при заднем фронте CLK произойдет вывод данных из RTC. Если бы мы это сделали раньше, чем написали бы строки
...
RTC выставил бы данные, и МК не переопределя линию на вход, спалил бы и себе линию, и возможно RTC.

Не-а...
Еще раз: вывод данных из RTC - по переднему фронту (из низкого в высокий). Т.е. линию CLK "опустить" после вывода последнего бита адреса (if с проверкой i<7 - убрать); настрока на ввод DATA; данные забирать при высоком уровне на CLK (высокий CLK - чтение DATA - низкий CLK), у Вас сейчас - наоборот.

PS. Посмотрите внимательно на рисунок 7 из DS
Go to the top of the page
 
+Quote Post



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

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 00:39
Рейтинг@Mail.ru


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