WinAvr в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение vitalik_1984 »

DruidCat писал(а): А как очищать буфер? Нулей в его записать?

Ну зачем же записать нулей? можно просто queueC обнулить после передачи последнего символа.
В поисках истины человек развивается.
maff
Родился
Сообщения: 4
Зарегистрирован: Вс авг 19, 2012 15:22:19

Re: WinAvr в вопросах и ответах

Сообщение maff »

DruidCat писал(а):Я человек новый в AVR, но хочу задать тебе вопрос, а ты Fuses (Фьюзы) прошил в своем МК на внешний кварц 8 Мгц?

Я и сам на это первое же и подумал:) Но получается так, что во flip'е нет настроек фьюзов. Целый день гуглил по поводу flip и fuse bits, frequency, clock ну и в том же духе. Перелазил кучу буржуйских форумов и нифига :cry:
Шью скомпиленое в CVAVR получаю 8Mhz. А если скомпиленое WinAVR'ом то 1MHz.
Аватара пользователя
zero648
Вымогатель припоя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Re: WinAvr в вопросах и ответах

Сообщение zero648 »

maff писал(а):Шью скомпиленое в CVAVR получаю 8Mhz. А если скомпиленое WinAVR'ом то 1MHz.

Это в симуляторе так частота настраивается, т.е. подразумевается, что камень будет прошит (не компилятором) под заявленную частоту, а в железе частота только по фузам.
Аватара пользователя
zero648
Вымогатель припоя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Re: WinAvr в вопросах и ответах

Сообщение zero648 »

maff , скорей всего у компиляторов разная оптимизация кода, да и в цикле не понятно где прерывание таймера включится. Попробуй использовать режим сна, так хотябы можно прерывания таймера котролировать, да и процик отоспица :))), когда он спит, жрать не просит :)))
maff
Родился
Сообщения: 4
Зарегистрирован: Вс авг 19, 2012 15:22:19

Re: WinAvr в вопросах и ответах

Сообщение maff »

zero648 писал(а):Это в симуляторе так частота настраивается, т.е. подразумевается, что камень будет прошит (не компилятором) под заявленную частоту, а в железе частота только по фузам.

Прошиваю я через 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 я просто в отчаянии :) Гугл недоумевает)
maff
Родился
Сообщения: 4
Зарегистрирован: Вс авг 19, 2012 15:22:19

Re: WinAvr в вопросах и ответах

Сообщение maff »

АЛИЛУЯ! Наконец! Делюсь открытиями :)
Такая штука как 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 :shock:
вот и надо было его программно извенить на 1
Аватара пользователя
DruidCat
Встал на лапы
Сообщения: 116
Зарегистрирован: Чт май 03, 2012 06:27:23
Откуда: Челябинск

Re: WinAvr в вопросах и ответах

Сообщение DruidCat »

vitalik_1984 писал(а):
DruidCat писал(а): А как очищать буфер? Нулей в его записать?

Ну зачем же записать нулей? можно просто queueC обнулить после передачи последнего символа.

vitalik_1984 подскажи код написания в С обнуления queueC, я не знаю как. :cry:
Кот должен прожить жизнь без сожаления.
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение vitalik_1984 »

например так:

Код: Выделить всё


 ISR
(USART_TXC_vect){ //Подпрограмма обработки прерывания при завершении передачи очередного символа
if (queueC != sendC){ UDR queue[sendC++];} //Если был передан не последний символ, то передаем текущий и увеличиваем счетчик переданных на 1
if (sendC>50) {sendC=0;}


 

но это опять же нужно целиком все согласовывать, у вас ведь очередь всего 50 символов, а это нигде не контролируется
В поисках истины человек развивается.
Аватара пользователя
Goldsmith
Опытный кот
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение Goldsmith »

DruidCat писал(а):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
Аватара пользователя
DruidCat
Встал на лапы
Сообщения: 116
Зарегистрирован: Чт май 03, 2012 06:27:23
Откуда: Челябинск

Re: WinAvr в вопросах и ответах

Сообщение DruidCat »

vitalik_1984 писал(а):например так:

Код: Выделить всё


 ISR
(USART_TXC_vect){ //Подпрограмма обработки прерывания при завершении передачи очередного символа
if (queueC != sendC){ UDR = queue[sendC++];} //Если был передан не последний символ, то передаем текущий и увеличиваем счетчик переданных на 1
if (sendC>50) {sendC=0;}
}
 

 

но это опять же нужно целиком все согласовывать, у вас ведь очередь всего 50 символов, а это нигде не контролируется

Спасибо большое. :beer:
Кот должен прожить жизнь без сожаления.
Аватара пользователя
DruidCat
Встал на лапы
Сообщения: 116
Зарегистрирован: Чт май 03, 2012 06:27:23
Откуда: Челябинск

Re: WinAvr в вопросах и ответах

Сообщение DruidCat »

Goldsmith писал(а):
DruidCat писал(а):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: Спасибо всем за советы, постораюсь их все учесть. Думал написал уже финальный исходный код, а оказывается, он почти не работает. Теперь я понимаю, что чувствовали разработчики игры "Сталкер: Чистые небеса." :)))
Кот должен прожить жизнь без сожаления.
Аватара пользователя
DruidCat
Встал на лапы
Сообщения: 116
Зарегистрирован: Чт май 03, 2012 06:27:23
Откуда: Челябинск

Re: WinAvr в вопросах и ответах

Сообщение DruidCat »

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 и заполняем строчки как на картинке.

Надеюсь кому-то это поможет из новичков. :)
Вложения
AStyle.jpg
(76.19 КБ) 390 скачиваний
Кот должен прожить жизнь без сожаления.
Аватара пользователя
DruidCat
Встал на лапы
Сообщения: 116
Зарегистрирован: Чт май 03, 2012 06:27:23
Откуда: Челябинск

Re: WinAvr в вопросах и ответах

Сообщение DruidCat »

Можно попросить совета по поводу симулятора 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 и не нахожу, не хотелось ребята вас тревожить такими вопросами. Может я и плохо ищу, меня постоянно отвлекает моя беременная жена:(
Кот должен прожить жизнь без сожаления.
Аватара пользователя
vitalik_1984
Поставщик валерьянки для Кота
Сообщения: 2482
Зарегистрирован: Пт авг 27, 2010 05:57:06
Откуда: Тюмень
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение vitalik_1984 »

Может я и плохо ищу, меня постоянно отвлекает моя беременная жена:(

А че мордашка то такая грустная?Жена беременна ! :idea: Радость должна быть вот так вот : :love: :chmoked: :kiss:
В поисках истины человек развивается.
Аватара пользователя
DruidCat
Встал на лапы
Сообщения: 116
Зарегистрирован: Чт май 03, 2012 06:27:23
Откуда: Челябинск

Re: WinAvr в вопросах и ответах

Сообщение DruidCat »

Да радуюсь я всем сердцем, скоро у меня наследник родится. :beer:
PS: Вопрос по симулятору я снимаю. Сегодня ночью с переводчиком читал документацию на симулятор. Разобрался. :idea:
Кот должен прожить жизнь без сожаления.
Аватара пользователя
DruidCat
Встал на лапы
Сообщения: 116
Зарегистрирован: Чт май 03, 2012 06:27:23
Откуда: Челябинск

Re: WinAvr в вопросах и ответах

Сообщение DruidCat »

Я тут недавно разобрался с симулятором 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)   //Формула расчета БОД

unsigned char queueC, sendC;   //Индексы текущего и переданного символа
unsigned char queue[50];   //Очередь

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);   //Пауза, цикл работает пока регистр данных не опустошён
    }
}

void
INIT_USART (void)
{
    //Функция настройка USART
    UCSRB = (0 << RXCIE) | (1 << TXCIE) | (0 << RXEN) | (1 << TXEN);   //Активизируем прерывание по окончание передачи и передатчик
    UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);   //размер слова 8 разрядов
    UBRRH = (unsigned char) (BAUD >> 8);   //Скорость передач
    UBRRL = (unsigned char) BAUD;   //Скорость передач
}


int
main (void)
{
    INIT_USART ();      //Вызываем функцию для настройки USART
    char HIGHT[] = "Высота 239";   //Массив символов HIGHT
    long int NUMBERS = 1234567;   //Число для преобразования NUMBERS
    char *CHAR_NUMBERS;      //Результат преобразования будет сюда записываться CHAR_NUMBERS
    char BUFFER[20];      //Символьный буфер преобразуемого числа
    CHAR_NUMBERS = ltoa (NUMBERS, BUFFER, 10);   //Отсылаем в функцию ltoa число
    while (1)         //Бесконечный цикл
    {
        SEND_USART (CHAR_NUMBERS);   //Отсылаем массив CHAR_NUMBERS в функцию SEND_USART
        SEND_USART (HIGHT);   //Отсылаем массив HIGHT в функцию SEND_USART
    }
}
Кот должен прожить жизнь без сожаления.
Аватара пользователя
Goldsmith
Опытный кот
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение Goldsmith »

Уже вполне прилично. Но совершенству нет предела. Несколько мелких придирок:

1.

Код: Выделить всё

    queue[queueC++] = 0x0D;   //Добавляем в конец очереди символы
    queue[queueC++] = 0x0A;   //возврата каретки и переноса строки
Я бы не стал этого делать. Не всегда действительно необходимо переходить на новую строку. Кому нужно, сам сделает переход явно. Ну и к тому же не все терминалы требуют именно такого сочетания.

2.

Код: Выделить всё

    UCSRB = (0 << RXCIE) | (1 << TXCIE) | (0 << RXEN) | (1 << TXEN);   //Активизируем прерывание по окончание 
Зачем разрешать прерывания, для которых не установлены обработчики? В лучшем случае это бесполезно. Не так давно было обсуждение этой темы. Тем более что передача все равно производится в поллинге:

Код: Выделить всё

        UDR = queue[sendC++];   //Передаем текущий символ и увеличиваем счетчик переданных на 1
        while ((UCSRA & (1 << UDRE)) == 0);   //Пауза, цикл работает пока регистр данных не опустошён
(логичнее было бы сначала дождаться готовности, а потом передавать, но в данном случае это не столь критично).

3.

Код: Выделить всё

unsigned char queue[50];   //Очередь
- название несколько сбивает с толку. Очередью традиционно называют буфер с дисциплиной FIFO (обычно кольцевой). В данном случае это просто буфер.

4. Раз уж зашла речь о буфере, и к тому же вывод полностью синхронный, можно было бы вообще отказаться от буфера. Для одних задач и 50-ти литер окажется много, и драгоценная память расходуется попусту. Для других может не хватить и сотни.

Пусть лучше функция-клиент просто передает подпрограмме вывода указатель на выводимую строку. Если этот буфер будет выделяться локально, то после завершения функции накладные расходы сведутся к нулю.

Если есть силы и желание совершенствовать дальше, теперь вполне можно замахнуться на асинхронный вывод по прерываниям. Ну и как вершина мастерства - предусмотреть возможность выбирать U(S)ART для кристаллов, которые имеют их в количестве более одного.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Аватара пользователя
DruidCat
Встал на лапы
Сообщения: 116
Зарегистрирован: Чт май 03, 2012 06:27:23
Откуда: Челябинск

Re: WinAvr в вопросах и ответах

Сообщение DruidCat »

Я все замечания исправил, кроме пункта №4 по указателям. Мне они даются крайне тяжело, не знаю почему. Еще с универа, когда я немного изучал С#. У меня ступор в голове происходит, когда я начинаю пользоваться указателями. :cry:
Кот должен прожить жизнь без сожаления.
Аватара пользователя
Goldsmith
Опытный кот
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение Goldsmith »

DruidCat писал(а):Я все замечания исправил, кроме пункта №4 по указателям. Мне они даются крайне тяжело, не знаю почему. Еще с универа, когда я немного изучал С#.
Так в C# указателями практически и не пользуются, слава богу. Оставлена на всякий случай лазейка для совместимости с "нативным" кодом, но используется крайне редко за ненадобностью в большинстве задач.

DruidCat писал(а):У меня ступор в голове происходит, когда я начинаю пользоваться указателями. :cry:
Скачайте книгу Ted Jensen, Tutorial on Pointers and Arrays in C. Небольшая, но толковая, к тому же официально бесплатная. Развеет любой ступор, будете чувствовать себя среди указателей и массивов, как рыба в воде.
Любой дурак может писать код. Настоящий профессионал - это тот, кто способен постоянно создавать продукт высокого качества, укладываясь при этом в бюджет.
J. Ganssle
Аватара пользователя
Goldsmith
Опытный кот
Сообщения: 736
Зарегистрирован: Пн янв 10, 2011 03:06:36
Откуда: Ростов-на-Дону
Контактная информация:

Re: WinAvr в вопросах и ответах

Сообщение Goldsmith »

Прошу прощения, еще один ляп пропустил:

Код: Выделить всё

...

unsigned char queue[50];   //Очередь

...

    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
Ответить

Вернуться в «AVR»