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

 
 
> WinAVR, задержки > 250мс, Help, me!!!
Alex_NEMO
сообщение Nov 16 2008, 17:28
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 106
Регистрация: 13-05-05
Пользователь №: 4 977



Помаленьку осваиваю AVR, пишу в WinAVR. Всякие простейшие "моргалки", вроде освоил, решил светофор сбацать. Вроде элементарно, но в

WinAVR столкнулся с проблемами с задержками > 250 ms.

Версия WinAVR - 20070525, все проверялось в Proteus 7.2SP6.
Вот, что получилось:
Код
//Электронный светофор, =AVR.
// cpu: ATMega8
// speed: 1 mhz

#include <avr/io.h>
#include <util/delay.h>

#define F_CPU 1000000UL

int main(void)  {        //Начало программы  

    // Инициализация портов
    PORTB=0x20;
    DDRB=0x1F;
    PORTC=0x00;
    DDRC=0x00;
    PORTD=0x00;
    DDRD=0x00;
        
    while (1) //Бесконечный цикл                                        
        {
            PORTB |= _BV(PB0);        // Уст. пин 0 порта B в "1" - вкл. красный
            PORTB |= _BV(PB3);        // Уст. пин 3 порта B в "1" - вкл. зеленый для пеших
            _delay_ms(250);        // Пауза 3 сек. - пока горит  красный
            _delay_ms(250);
            _delay_ms(250);
            _delay_ms(250);
            _delay_ms(250);
            _delay_ms(250);
            _delay_ms(250);
            _delay_ms(250);
            _delay_ms(250);
            _delay_ms(250);
            PORTB |= _BV(PB1);        // Уст. пин 1 порта B в "1"-  вкл. желтый
            _delay_ms(250);
            _delay_ms(250);
            PORTB &= ~_BV(PB0);        // Уст. пин 0 порта B в "0" - выкл. красный
            PORTB &= ~_BV(PB3);        // Уст. пин 3 порта B в "0" - выкл. зеленый для пеших
            _delay_ms(250);        // Пауза 1 сек. - пока горит  желтый
            _delay_ms(250);
            _delay_ms(250);
            _delay_ms(250);
            PORTB &= ~_BV(PB1);        // Уст. пин 1 порта B в "0"-  выкл. желтый
            PORTB |= _BV(PB2);        // Уст. пин 1 порта B в "1"-  вкл. зеленый
            PORTB |= _BV(PB4);        // Уст. пин 3 порта B в "1" - вкл. красный для пеших
            _delay_ms(250);        // Пауза 3.5 сек. - пока горит  зеленый
            _delay_ms(250);
            _delay_ms(250);
            _delay_ms(250);
            _delay_ms(250);
            _delay_ms(250);
            _delay_ms(250);
            _delay_ms(250);
            _delay_ms(250);
            _delay_ms(250);
            _delay_ms(250);
            _delay_ms(250);
            _delay_ms(250);
            _delay_ms(250);
            PORTB &= ~_BV(PB2);        // Уст. пин 2 порта B в "0"-  выкл. зеленый
            PORTB |= _BV(PB1);        // Уст. пин 1 порта B в "1"-  вкл. желтый
            PORTB &= ~_BV(PB4);        // Уст. пин 3 порта B в "0" - выкл. красный для пеших
            _delay_ms(250);        // Пауза 1 сек. - пока горит  желтый
            _delay_ms(250);
            _delay_ms(250);
            _delay_ms(250);
            PORTB &= ~_BV(PB1);        // Уст. пин 1 порта B в "0"-  выкл. желтый
        } //
}
Т.е., что бы получить требуемые задержки, как я думал, типа _delay_ms(3000), _delay_ms(1000) и _delay_ms(4500), прошлось делать "порно" в виде последовательных команд _delay_ms(250);
То же самое - в CVAVR - все ОК:
Код
/*****************************************************
Project : TrafficLights
Version : 1 alpha
Date    : 16.11.2008
Author  : Freeware, for evaluation and non-commercial use only
Chip type           : ATmega8
Program type        : Application
Clock frequency     : 8,000000 MHz
Memory model        : Small
External RAM size   : 0
Data Stack size     : 256
*****************************************************/

#include <mega8.h>
#include <delay.h>

void main(void)
{

// Input/Output Ports initialization
PORTB=0x20;
DDRB=0x1F;
PORTC=0x00;
DDRC=0x00;
PORTD=0x00;
DDRD=0x00;

while (1)
      {
      // Place your code here
      PORTB.0 = 1;        // Уст. пин 0 порта B в "1" - вкл. красный
      delay_ms(3000);        // Пауза 3 сек. - пока горит  красный
      PORTB.0 = 0;           // Уст. пин 0 порта B в "0" - выкл. красный
      PORTB.1 = 1;        // Уст. пин 1 порта B в "1"-  вкл. желтый
      delay_ms(1000);        // Пауза 1 сек. - пока горит  желтый
      PORTB.1 = 0;            // Уст. пин 1 порта B в "0"-  выкл. желтый
      PORTB.2 = 1;        // Уст. пин 1 порта B в "1"-  вкл. зеленый
      delay_ms(4500);        // Пауза 1 сек. - пока горит  зеленый
      PORTB.2 = 0;            // Уст. пин 2 порта B в "0"-  выкл. зеленый
      PORTB.1 = 1;        // Уст. пин 1 порта B в "1"-  вкл. желтый
      delay_ms(1000);        // Пауза 1 сек. - пока горит  желтый
      PORTB.1 = 0;            // Уст. пин 1 порта B в "0"-  выкл. желтый
      };
}

Здесь - все четко - в Preteus'е все переключается(правильные задержки) как надо!

В чем косяк в случае с WinAVR?!! Как решать проблему?!!
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
ReAl
сообщение Nov 16 2008, 21:41
Сообщение #2


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



1) почитать документацию на _delay_ms() используемой версии, увидеть в ограничение макс. времени в зависимости от частоты процессора
2) взять хоть немного более свежую версию (WinAVR-0071221 сгодится) - там упор уже в 6,5секунды независимо от частоты.
3) написать свою delay_msec(unsigned msec) { while(msec--) _delay_ms(1); }


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Alex_NEMO
сообщение Nov 18 2008, 15:54
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 106
Регистрация: 13-05-05
Пользователь №: 4 977



Цитата(ReAl @ Nov 17 2008, 00:41) *
2) взять хоть немного более свежую версию (WinAVR-0071221 сгодится) - там упор уже в 6,5секунды независимо от частоты.

Да, установка WinAVR-20071221 - помогла, спасибо!
Ещё в ходе эксперементов родилась такая подпрограмка:
Код
float delay_s(float t)   {
uint8_t i, j;
   j = t * 100;
   for(i=0;i<j;i++)
   _delay_ms(10);
}

вызывал так: delay_s(5); или delay_s(3.5);
На глаз, все правильно считает!
Только один вопрс - при компиляции выскакивает один Warning: control reaches end of non-void function
- чем ему закрывающая скобка не нравится в моей ф-ции? Или это "особенности" компилера из разряда "странностей"?!! laughing.gif
Go to the top of the page
 
+Quote Post
Aesthete Animus
сообщение Nov 18 2008, 16:17
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 222
Регистрация: 9-06-07
Пользователь №: 28 317



Цитата(Alex_NEMO @ Nov 18 2008, 18:54) *
Только один вопрс - при компиляции выскакивает один Warning: control reaches end of non-void function
- чем ему закрывающая скобка не нравится в моей ф-ции? Или это "особенности" компилера из разряда "странностей"?!! laughing.gif

..Потому что функция ваша имеет возращаемый тип (не void функция), но return-а в ней нет
А вообще, во-первых, не используйте числа с плавающей точкой без очень сильной на то необходимости. А во вторых, ну не поместится в однобайтовую переменную i число, скажем, 350!
Go to the top of the page
 
+Quote Post
Alex_NEMO
сообщение Nov 18 2008, 16:52
Сообщение #5


Частый гость
**

Группа: Свой
Сообщений: 106
Регистрация: 13-05-05
Пользователь №: 4 977



Цитата(Aesthete Animus @ Nov 18 2008, 19:17) *
..Потому что функция ваша имеет возращаемый тип (не void функция), но return-а в ней нет
А вообще, во-первых, не используйте числа с плавающей точкой без очень сильной на то необходимости. А во вторых, ну не поместится в однобайтовую переменную i число, скажем, 350!

Понял, спасибо за помощь, понял свои ошибки!
А float использовал только для "универсальности" (напр., для получения 3,5 сек.).
Итого, получилось:
Код
float delay_s(float t)   {
uint16_t i, j;
    j = t * 100;
   for(i=0;i<j;i++)
   _delay_ms(10);
    return 0;
}
Теперь - все ОК!
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Nov 18 2008, 18:04
Сообщение #6


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Alex_NEMO @ Nov 18 2008, 20:52) *
А float использовал только для "универсальности" (напр., для получения 3,5 сек.).

Ну так и используйте uint32_t на крайняк - если даже использовать микросекундное (!) разрешение - получите больше часа максимальную задержку.
Стока не живут даже в коллайдере biggrin.gif
А плавучка - это же страшно ресурсоемко и медленно на данной архитектуре.
ЗЫ:
можно сразу идти дальше и завести себе тип timer_t, разрядность которого можно менять в зависимости от требований проекта.
Код
/*Нужное откомментить*/
// typedef uint8_t timer_t
// typedef uint16_t timer_t
// typedef uint32_t timer_t


А дальше - очень рекомендую написать это простенькое прерывание в посте Aesthete Animus и по аналогии - чтением тиков таймера можно управлять независимо несколькими десятками светофоров.
Go to the top of the page
 
+Quote Post



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

 


RSS Текстовая версия Сейчас: 29th July 2025 - 06:54
Рейтинг@Mail.ru


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