Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Помогите добить TWI
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
ingord
Здравствуйте! Две AtMega, одна - Master, другая Slave. За основу взял программу на Си, предложенную, не соврать бы, haker fox'ом. Slave корябаю сам. TWI аппаратный. Проблемы:
1. При формировании Master'ом СТАРТ прерывания у Slave возникают на каждый второй запуск. Т.е., первый СТАРТ прошел (импульсы на шинах проскакивают, пробовал менять их длительнсть в широких пределах) - прерывания нет, на второй СТАРТ прерывание возникает, на третий - тишина, четвертый - есть и т.д.
2. При формировании СТАРТ код статуса Master не равен 0х08.
Ну а дальше не смотрел. Добиться бы для начала хоть СТАРТ правильно делать.
Помогите, кто может.
Maddy
посмотри в сторону avrlib'а там есть кажись и то и другое (и Master и Slave) Procyon AVRlib для начала IMHO сам то .... Но она под gcc (WinAvr ) заточена .....
Lepeksiy
Посмотри у Атмела Application Note AVR311 и AVR315. Там есть и исходники на си для ИАРа.
Для связи меги с памятью 24Схх я использовал адаптированный для avr-gcc исходник из AVR315. Все прекрасно работало.
defunct
Цитата
1. При формировании Master'ом СТАРТ прерывания у Slave возникают на каждый второй запуск.
...
2. При формировании СТАРТ код статуса Master не равен 0х08.

Возможно тормозит слейв - держит 0 на линии, от этого у мастера не получается послать СТАРТ.
Написание слейва это достаточно сложная задача, т.к. требует очень точной и быстрой обработки событий i2c шины. Неправильная обработка событий на стороне слейва может привести к "подвисанию" мастера.

Я бы порекомендовал попрактиковаться вначале с готовым стандартным i2c слейвом, напр. AT24xx/DS13xx/FM31xx и т.п.. Когда мастер для стандартных слейвов у вас заработает, вы будете по крайней мере иметь представление, что должен делать ваш слейв.

На момент отладки режима слейва ставьте небольшую скорость шины 1-2kHz.
Diz
Может, и не в тему, но обратите внимание на длительность STOP-а - она в avr не привязана
к периоду шины и подтверждения прерыванием не имеет. Если скорость шины низкая, и
после STOPа сразу идет START (следующая посылка), то это не будет распознано слейвом и
посылка будет потеряна.

Самая первая посылка может быть потеряна, если вы начинаете обмен сразу после включения
питания устройств - можно попробовать первым вывести на шину слейва, и лишь затем мастера
после задержки.
rezident
Цитата(Diz @ Jan 7 2008, 09:49) *
Самая первая посылка может быть потеряна, если вы начинаете обмен сразу после включения
питания устройств - можно попробовать первым вывести на шину слейва, и лишь затем мастера
после задержки.
В стандарте I2C имеется рекомендация после подачи питания поclockать мастером шину SCL без выдачи предварительного START-условия. Не менее 9-10 тактов SCL нужно выдать. Этот прием позволяет вывести из ступора автомат приема у аппаратных Slave-ов, подключенных к шине.
Den64
Цитата(ingord @ Jan 6 2008, 02:45) *
1. При формировании Master'ом СТАРТ прерывания у Slave возникают на каждый второй запуск.


На сколько я знаю, у slave нет прерывания, при формировании мастером старта.
ingord
Ну хоть на пальцах обьясните, как что должно куда передаваться. Я от английских даташитов в перемешку с русским Евстифеевым заблудился окончательно. Повторяю - когда мастер дает старт - у слейва на каждую вторую передачу срабатывает прерывание. Даже если ввожу слейв в sleep - то же самое. Никаких других прерываний нет, в обработчике прерывания И2С единственное действие -"дрыгнуть " ножкой со светодиодом. "И все-таки она вертится!" - состояние светодиода меняется с каждой второй командой старт на слейве.
bodja74
Тут ясновидящих нет.
Выкладывайте
или подробное описание действий ,что в какой последовательности и в какой регистр
или свои части кода.

Вообще когда я цепляю новую микруху на И2С ,у меня практически всегда стопор ,редко когда проходит все гладко с первого раза ,в таких случаях неплохо помогает выбрасывать на терминалку статусы после каждой команды ,там уже сразу все видно ,что и в каком месте не так.
ingord
Рассказываю по порядку. Программу мастера взял готовую от хакер фокса из темы "Исходники..." -самая верхняя тема подфорума AVR. Добавил только
#pragma interrupt_handler int3_isr:5
void int3_isr(void)
{
i2c_start();
}
void main(void)
{
while (1)
asm ("sleep");
}

По внешнему сигналу на INT3 на шину выдается старт.
У слейва выкинул уже все, оставил только инициализацию и
#pragma interrupt_handler twi_isr:18
void twi_isr(void)
{
PORTB = ~PORTB;
}
Т.е при возникновении прерывания порт B меняет свое состояние (чтобы отследить по светодиодам).
Светодиоды гаснут(засвечиваются) на каждую вторую команду мастера при срабатывании INT3. При этом код статуса у мастера не равен 0х08, т.е. старт не отработан.
bodja74
Хорошо ,какой тогда статус у мастера после старта ?
И как может слейв моргнуть светодиодом ,если он не получил свой адресс ?,по одному только старту он не может войти в прерывание.
ingord
Статус мастера не знаю, т.к. ни терминала, ни симулятора - ничего нет. Плата уже готовая. Единственное - подпаял к свободной ножке светодиод и написал - если код равен 0х08 - засветить диод. Не светится, гад. В принципе, можно перебрать хотя-бы F8 и 00 - может чего и прояснится. А прерывание у слейва срабатывает каждый второй раз - это уже железобетонно, даже если слейв в спящем режиме. Вот и хотел спросить, как же оно работает, если адрес еще не передавался? Хотя, с другой стороны, если до передачи адреса ни один из слейвов никак не откликнется, может ли мастер гарантировать, что старт отработан корректно? Не логично как-то... А на даташит уже смотреть не могу...
artemm
От пример слейва на иаре. У меня работает

#pragma vector=TWI_vect
__interrupt void TWI(void)
{
switch (TWSR & 0xF8)
{
case TWI_SRX_ADR_ACK_M_ARB_LOST:
case TWI_SRX_ADR_ACK:
{
TWCR = (TWCR&0x0F)|(1<<TWINT)|(1<<TWEA); break;
}
case TWI_SRX_ADR_DATA_NACK:
case TWI_SRX_ADR_DATA_ACK:
{
PORTD = TWDR;
TWCR = (TWCR&0x0F)|(1<<TWINT)|(1<<TWEA); break;
}
case TWI_SRX_STOP_RESTART:
{

}
default:
{
TWCR = (TWCR&0x0F)|(1<<TWINT)|(1<<TWEA); break;
}
}
}


void TWI_Initialization()
{
TWDR = 0xFF;
TWBR = 0xF0;
TWSR = 0x03;
TWAR = 0x14; //(адрес 0x0A)
TWCR = (1<<TWINT)|(1<<TWIE)|(1<<TWEN)|(1<<TWEA);
}

int main(void)
{
TWI_Initialization();
__enable_interrupt();
DDRD = 0xFF;
PORTD = 0xFF;

while(1)
{
}
}
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.