Я человек новый в AVR, но хочу задать тебе вопрос, а ты Fuses (Фьюзы) прошил в своем МК на внешний кварц 8 Мгц?
Я и сам на это первое же и подумал:) Но получается так, что во flip'е нет настроек фьюзов. Целый день гуглил по поводу flip и fuse bits, frequency, clock ну и в том же духе. Перелазил кучу буржуйских форумов и нифига Шью скомпиленое в CVAVR получаю 8Mhz. А если скомпиленое WinAVR'ом то 1MHz.
Шью скомпиленое в CVAVR получаю 8Mhz. А если скомпиленое WinAVR'ом то 1MHz.
Это в симуляторе так частота настраивается, т.е. подразумевается, что камень будет прошит (не компилятором) под заявленную частоту, а в железе частота только по фузам.
maff , скорей всего у компиляторов разная оптимизация кода, да и в цикле не понятно где прерывание таймера включится. Попробуй использовать режим сна, так хотябы можно прерывания таймера котролировать, да и процик отоспица , когда он спит, жрать не просит
Это в симуляторе так частота настраивается, т.е. подразумевается, что камень будет прошит (не компилятором) под заявленную частоту, а в железе частота только по фузам.
Прошиваю я через Atmel Flip(через аппаратный ЮСБ контроллера). Во Flip'e нет настройки фьюзов!!! - вот в чем беда.
zero648 писал(а):
maff , скорей всего у компиляторов разная оптимизация кода, да и в цикле не понятно где прерывание таймера включится. Попробуй использовать режим сна, так хотябы можно прерывания таймера котролировать, да и процик отоспица , когда он спит, жрать не просит
Цикл(смотрите код, приведенный выше) содержит только смену состояния светодиода спустя 4 переполнения таймер - оптимизировать нечего)) Светодиод меняет состояние с периодом примерно 1с(по факту). Предделитель таймера 1024. 4 переполниня. Таймер 8бит. Частота соответсвенно камня (4 * 1024 * 256) / 1 = 1048576ГЦ(1МГц). Скомпилено WinAVR'ом. Если компилить в CVAVR, то мигание с периодо в 1с получаются при 32 переполнениях, то есть частота будет (32 * 1024 * 256) / 1 = 8388608Гц(8МГц).
Так фьюзы хз как Флип прошивает, но разница в компиляторах на лицо) CVAVR чтото в hex дописывает видимо, но как добится этого от WinAVR я просто в отчаянии Гугл недоумевает)
АЛИЛУЯ! Наконец! Делюсь открытиями Такая штука как CLKPR = 0x00; - установить предделитель частоты камня равным 1. Уже пробовал юзать, но не помогло. Оказалось надо делать вот так:
Код:
CLKPR=0x80; //Установка бита CLKPCE/ Разрешает изменение предделителя CLKPR=0x00;
Причем они так подряд и пишутся в начале мэйна! Даташит at90usb говорит что-то типа
Цитата:
The CLKPCE bit must be written to logic one to enable change of the CLKPS bits. The CLKPCE bit is only updated when the other bits in CLKPR are simultaneously written to zero. CLKPCE is cleared by hardware four cycles after it is written or when CLKPS bits are written. Rewriting the CLKPCE bit within this time-out period does neither extend the time-out period, nor clear the CLKPCE bit.
Я так понял в at90usb162 фьюзы с завода идут на внешний кварц, но предделитель чатоты установлен на 8 вот и надо было его программно извенить на 1
ISR(USART_TXC_vect){ //Подпрограмма обработки прерывания при завершении передачи очередного символа if (queueC != sendC){ UDR = queue[sendC++];} //Если был передан не последний символ, то передаем текущий и увеличиваем счетчик переданных на 1 if (sendC>50) {sendC=0;} }
но это опять же нужно целиком все согласовывать, у вас ведь очередь всего 50 символов, а это нигде не контролируется
_________________ В поисках истины человек развивается.
while (1){ //Бесконечный цикл SEND_USART(CHAR_NUMBERS); //Отсылаем массив CHAR_NUMBERS в функцию SEND_USART _delay_ms(1000); //Пауза в 1сек SEND_USART(HIGHT); //Отсылаем массив HIGHT в функцию SEND_USART _delay_ms(1000); //Пауза в 1сек }
Ненадежное решение. Закладываетесь на то, что передача заведомо должна уложиться в определенное время.
В программе присутствует "магическое число" 1000 мс (1 с). По счастливой случайности этой задержки достаточно для отправки и данного преобразованного числа, и данного текстового сообщения при данной скорости 9600 бит/с. Достаточно либо повысить скорость передачи, либо увеличить длину сообщения, чтобы программа перестала работать. Такой код нельзя считать качественным.
Возможно два выхода из этой ситуации:
1. (попроще): добавить функцию, которая возвращает признак "передача буфера окончена", и в цикле ожидать, пока она станет истинной; 2. (немного сложнее, но корректнее): реализовать кольцевой буфер и передавать литеры на вывод через него, блокируя фоновое приложение при заполнении буфера.
Какой бы вариант Вы ни выбрали, в любом случае это решение будет надежнее, чем полагаться, что передача заведомо уложится в заданный интервал времени.
P.S. В случае кольцевого буфера также отпадет вопрос о его очистке.
_________________ Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет. J. Ganssle
ISR(USART_TXC_vect){ //Подпрограмма обработки прерывания при завершении передачи очередного символа if (queueC != sendC){ UDR = queue[sendC++];} //Если был передан не последний символ, то передаем текущий и увеличиваем счетчик переданных на 1 if (sendC>50) {sendC=0;} }
но это опять же нужно целиком все согласовывать, у вас ведь очередь всего 50 символов, а это нигде не контролируется
Спасибо большое.
_________________ Кот должен прожить жизнь без сожаления.
while (1){ //Бесконечный цикл SEND_USART(CHAR_NUMBERS); //Отсылаем массив CHAR_NUMBERS в функцию SEND_USART _delay_ms(1000); //Пауза в 1сек SEND_USART(HIGHT); //Отсылаем массив HIGHT в функцию SEND_USART _delay_ms(1000); //Пауза в 1сек }
Ненадежное решение. Закладываетесь на то, что передача заведомо должна уложиться в определенное время.
В программе присутствует "магическое число" 1000 мс (1 с). По счастливой случайности этой задержки достаточно для отправки и данного преобразованного числа, и данного текстового сообщения при данной скорости 9600 бит/с. Достаточно либо повысить скорость передачи, либо увеличить длину сообщения, чтобы программа перестала работать. Такой код нельзя считать качественным.
Блин, я эти паузы ставил просто для наглядности, чтоб строчки на терминале не мельтешили. А оказывается, если бы я их не поставил, у меня ничерта не заработало. Я только что убирал эти паузы, вообще ничего на терминале не появляется. Эх.
PS: Спасибо всем за советы, постораюсь их все учесть. Думал написал уже финальный исходный код, а оказывается, он почти не работает. Теперь я понимаю, что чувствовали разработчики игры "Сталкер: Чистые небеса."
_________________ Кот должен прожить жизнь без сожаления.
Astyle я тоже победил. Выкладываю инструкцию, как настроить Astyle в WINAVR: 1) Качаем утилиту Astyle от сюда http://sourceforge.jp/projects/sfnet_astyle/releases/ 2) Закидываем файл Astyle.exe сюда WinAVR-20100110\utils\bin\ 3) Настраиваем astyle в WINAVR Tools->Options->Tools->add и заполняем строчки как на картинке.
Можно попросить совета по поводу симулятора VMLAB и WINAVR. Ситуация такая, по некоторым причинам не могу пользоваться PROTEUS на том компьютере, где занимаюсь с WINAVR. Решил воспользоваться VMLAB. Когда создаю makefile через Mfile в WINAVR ставлю галочку в строке Debug format -> MVLAB 3.10+ (сам пользуюсь MVLAB 3.15). Пишу исходный код в main.c, компилирую его и не компилируется заветного файла main.prj с которым работает VMLAB. Запускаю сам MVLAB, создаю проект через Project -> New project и заполняю поля в wizard. Создаю проект, делаю Build. И в окне mesage вижу о том что успешно все создалось. Жму на светофор. Все запускается. Но симулятор работает не так как надо. На одном из порталов *123*, там очень много написанно по MVLAB и для компилятора CVAVR, а для WINAVR почти ничего. Я запускал проект предложенный на портале *123*, и мне там понравилось как в VMLAB появилась в control panel вкладка TTY(терминал), а у меня не появляется в моем проекте и не могу её я создать, так как во вкладке VMLAB Componets нет ни одной активной строки. Подскажите, хотя бы, как создать в симуляции терминал. PS: Я весь день сижу в инете и ищу ответы по MVLAB и не нахожу, не хотелось ребята вас тревожить такими вопросами. Может я и плохо ищу, меня постоянно отвлекает моя беременная жена:(
_________________ Кот должен прожить жизнь без сожаления.
Да радуюсь я всем сердцем, скоро у меня наследник родится. PS: Вопрос по симулятору я снимаю. Сегодня ночью с переводчиком читал документацию на симулятор. Разобрался.
_________________ Кот должен прожить жизнь без сожаления.
Я тут недавно разобрался с симулятором VMLAB, читал книжки по С и решил дописать функцию по выволу цифeр и символов по протоколу USART, я посторался учесть все замечания, которые мне давались. Полностью избавился от пауз _delay_, от прерываний и сделал защиту от переполнения массива в функции вывода символов. Пользовался стилем написания исходного кода AStyle. Выкладываю исходный код на всеобщее обозрение. Вдруг кому понадбится из новичков эта функция. Функция printf очень сильно увеличивает размер готовой программы. А функция, которую я написал с вашей помощью в два с половиной раза экономичней.
Код:
//******************************************************************************** // // Автор : DruidCat // // МК : ATMega8L // // Компилятор : WinAVR // // Назначение : Выводим число и строку по USART через универсальную функцию // // Дата : 03.09.2012 // //******************************************************************************** #include<avr/io.h> #include<stdlib.h>//Вызов функции itoa, ltoa #define F_CPU 8000000UL //Частота МК #define USART_SPEED 9600 //Скорость USART желаемая #define BAUD ((F_CPU/(USART_SPEED*16UL)) + 1) //Формула расчета БОД
void SEND_USART(char *s) { //Функция формирования очереди символов из строки queueC = 0; //Текущий символ - первый sendC = 0; //Первый символ для передачи queue[queueC++] = 0x0D; //Добавляем в конец очереди символы queue[queueC++] = 0x0A; //возврата каретки и переноса строки while (*s) { if (queueC>50)//Если колличество символов массива больше 50, то... { queueC = 50;//счетчик символов в массиве равен максимальному значению 50 } queue[queueC++] = *s++; //Просматриваем строку и помещаем в очередь символы } while (queueC != sendC) //Запускаем цикл передачи символов пока не будет равенство queue и sendC { UDR = queue[sendC++]; //Передаем текущий символ и увеличиваем счетчик переданных на 1 while ((UCSRA & (1 << UDRE)) == 0); //Пауза, цикл работает пока регистр данных не опустошён } }
Уже вполне прилично. Но совершенству нет предела. Несколько мелких придирок:
1.
Код:
queue[queueC++] = 0x0D; //Добавляем в конец очереди символы queue[queueC++] = 0x0A; //возврата каретки и переноса строки
Я бы не стал этого делать. Не всегда действительно необходимо переходить на новую строку. Кому нужно, сам сделает переход явно. Ну и к тому же не все терминалы требуют именно такого сочетания.
Зачем разрешать прерывания, для которых не установлены обработчики? В лучшем случае это бесполезно. Не так давно было обсуждение этой темы. Тем более что передача все равно производится в поллинге:
Код:
UDR = queue[sendC++]; //Передаем текущий символ и увеличиваем счетчик переданных на 1 while ((UCSRA & (1 << UDRE)) == 0); //Пауза, цикл работает пока регистр данных не опустошён
(логичнее было бы сначала дождаться готовности, а потом передавать, но в данном случае это не столь критично).
3.
Код:
unsignedchar queue[50]; //Очередь
- название несколько сбивает с толку. Очередью традиционно называют буфер с дисциплиной FIFO (обычно кольцевой). В данном случае это просто буфер.
4. Раз уж зашла речь о буфере, и к тому же вывод полностью синхронный, можно было бы вообще отказаться от буфера. Для одних задач и 50-ти литер окажется много, и драгоценная память расходуется попусту. Для других может не хватить и сотни.
Пусть лучше функция-клиент просто передает подпрограмме вывода указатель на выводимую строку. Если этот буфер будет выделяться локально, то после завершения функции накладные расходы сведутся к нулю.
Если есть силы и желание совершенствовать дальше, теперь вполне можно замахнуться на асинхронный вывод по прерываниям. Ну и как вершина мастерства - предусмотреть возможность выбирать U(S)ART для кристаллов, которые имеют их в количестве более одного.
_________________ Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет. J. Ganssle
Я все замечания исправил, кроме пункта №4 по указателям. Мне они даются крайне тяжело, не знаю почему. Еще с универа, когда я немного изучал С#. У меня ступор в голове происходит, когда я начинаю пользоваться указателями.
_________________ Кот должен прожить жизнь без сожаления.
Я все замечания исправил, кроме пункта №4 по указателям. Мне они даются крайне тяжело, не знаю почему. Еще с универа, когда я немного изучал С#.
Так в C# указателями практически и не пользуются, слава богу. Оставлена на всякий случай лазейка для совместимости с "нативным" кодом, но используется крайне редко за ненадобностью в большинстве задач.
DruidCat писал(а):
У меня ступор в голове происходит, когда я начинаю пользоваться указателями.
Скачайте книгу Ted Jensen, Tutorial on Pointers and Arrays in C. Небольшая, но толковая, к тому же официально бесплатная. Развеет любой ступор, будете чувствовать себя среди указателей и массивов, как рыба в воде.
_________________ Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет. J. Ganssle
while (*s) { if (queueC>50)//Если колличество символов массива больше 50, то... { queueC = 50;//счетчик символов в массиве равен максимальному значению 50 } queue[queueC++] = *s++; //Просматриваем строку и помещаем в очередь символы }
...
Если массив в C имеет размерность N, то индексы в нем могут принимать значения 0, 1, ..., N-1. 50-й элемент массива queue на самом деле не существует, обращение к нему имеет неопределенный результат (обычно попадаем в область памяти, занятую другой переменной). Диагностика выхода за границы массива в C отсутствует, якобы в целях пущей эффективности (экономия примерно такая же, как если не ставить перила на балконах верхних этажей, пусть сами не подходят близко к краю, и последствия ее тоже аналогичны).
Поэтому следует воздержаться от записи в элементы массива с индексом больше 49. Лучше, конечно, вообще избавиться от "магического" числа 50 и определить его символическим именем либо через макрос, либо через enum.
_________________ Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет. J. Ganssle
Сейчас этот форум просматривают: roman.com и гости: 20
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения