|
WinAVR, задержки > 250мс, Help, me!!! |
|
|
|
Nov 16 2008, 17:28
|
Частый гость
 
Группа: Свой
Сообщений: 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?!! Как решать проблему?!!
|
|
|
|
|
 |
Ответов
|
Nov 18 2008, 15:54
|
Частый гость
 
Группа: Свой
Сообщений: 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- чем ему закрывающая скобка не нравится в моей ф-ции? Или это "особенности" компилера из разряда "странностей"?!!
|
|
|
|
|
Nov 18 2008, 16:17
|

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

|
Цитата(Alex_NEMO @ Nov 18 2008, 18:54)  Только один вопрс - при компиляции выскакивает один Warning: control reaches end of non-void function- чем ему закрывающая скобка не нравится в моей ф-ции? Или это "особенности" компилера из разряда "странностей"?!!  ..Потому что функция ваша имеет возращаемый тип (не void функция), но return-а в ней нет А вообще, во-первых, не используйте числа с плавающей точкой без очень сильной на то необходимости. А во вторых, ну не поместится в однобайтовую переменную i число, скажем, 350!
|
|
|
|
|
Nov 18 2008, 16:52
|
Частый гость
 
Группа: Свой
Сообщений: 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; } Теперь - все ОК!
|
|
|
|
|
Nov 18 2008, 18:04
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(Alex_NEMO @ Nov 18 2008, 20:52)  А float использовал только для "универсальности" (напр., для получения 3,5 сек.). Ну так и используйте uint32_t на крайняк - если даже использовать микросекундное (!) разрешение - получите больше часа максимальную задержку. Стока не живут даже в коллайдере А плавучка - это же страшно ресурсоемко и медленно на данной архитектуре. ЗЫ: можно сразу идти дальше и завести себе тип timer_t, разрядность которого можно менять в зависимости от требований проекта. Код /*Нужное откомментить*/ // typedef uint8_t timer_t // typedef uint16_t timer_t // typedef uint32_t timer_t А дальше - очень рекомендую написать это простенькое прерывание в посте Aesthete Animus и по аналогии - чтением тиков таймера можно управлять независимо несколькими десятками светофоров.
|
|
|
|
Сообщений в этой теме
Alex_NEMO WinAVR, задержки > 250мс Nov 16 2008, 17:28 Aesthete Animus ...
4) не использовать задержки Nov 16 2008, 22:17 _Pasha 5) А использовать таймеры и прерывания. И проц не ... Nov 17 2008, 00:37 Alex_NEMO Цитата(ReAl @ Nov 17 2008, 00:41) 1) почи... Nov 17 2008, 13:01 Aesthete Animus Цитата(Alex_NEMO @ Nov 17 2008, 16:01) Ка... Nov 17 2008, 14:52 Alex_NEMO Цитата(Aesthete Animus @ Nov 17 2008, 17... Nov 17 2008, 16:28 Aesthete Animus 2_Pasha
+1
А вообще, кто-то верно сказал, что Бог... Nov 18 2008, 18:22 ReAl Против uint32_t ничего не имею
Однако плавучка то... Nov 18 2008, 18:27 Aesthete Animus Цитата(ReAl @ Nov 18 2008, 21:27) Против ... Nov 18 2008, 18:40
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|