Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Есть код для CodeVision. Хочу его адаптировать под WinAVR
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
-=Женек=-
Вот простенькая программка, работающая в CodeVision:

Код
unsigned char h=0,m=0,sec=0;

void timer_init(void)
{
// timer
TCNT1H=TCNT1L=0;
TCCR1A=0;
TCCR1B=12; // cl/256  1000000/256=15625
// 15625/5=3125
OCR1A=3125;
TIMSK=16;
asm("sei");
}    

char get_time()
{
   sec++;  

    if(sec==60)  {sec=0;m++;}
    if(m==60)  {m=0;h++;}
    if(h==23)  {h=0;}
}

interrupt[TIM1_COMPA] comp(void) {get_time();}  // на эту строку ругается компилятор.


Посмотрел я в хидеры - в CodeVision TIM1_COMPA равняется 8. В WinAVR восьмерке соответствует SIG_OUTPUT_COMPARE1B. По моему что-то не то...

В общем программка должна каждую секунду что-нибудь делать а точнее, запускать get_time().

Помогите, плз.
_Bill
Цитата(-=Женек=- @ Sep 18 2006, 12:44) *
Посмотрел я в хидеры - в CodeVision TIM1_COMPA равняется 8. В WinAVR восьмерке соответствует SIG_OUTPUT_COMPARE1B. По моему что-то не то...

В общем программка должна каждую секунду что-нибудь делать а точнее, запускать get_time().

Помогите, плз.

В WinAVR процедуры обработки пррываний, насколько мне известно, имеют квалификатор SIGNAL. А, а общем, смотрите руководство по компилятору. Там должно быть все написано.
-=Женек=-
мне бы примерчик прерывания по таймеру каждую секунду
singlskv
Цитата(-=Женек=- @ Sep 18 2006, 15:14) *
мне бы примерчик прерывания по таймеру каждую секунду

Лови:
Код
#include <avr/interrupt.h>
#include <avr\io.h>
#include <avr\iotn2313.h>

unsigned char h=0,m=0,sec=0;

void timer_init(void)
{
  TCNT1H=TCNT1L=0;
  OCR1A=15624;
  TCCR1A=0;
  TCCR1B=(1<<WGM12)|(1<<CS11)|(1<<CS10); //clk/64
  TIMSK=(1<<OCIE1A);
}    


ISR (TIMER1_COMPA_vect)
{
  if (sec!=59) {
    sec++;
    return;
  }
  sec=0;
  
  if (m!=59) {
    m++;
    return;
  }
  m=0;

  if (h!=23) {
    m++;
    return;
  }
  h=0;
}

int main(int argc, char* argv[])
{
  timer_init();
  asm("sei");

  while (1);

  return 0;
}
aesok
Цитата(-=Женек=- @ Sep 18 2006, 15:14) *
мне бы примерчик прерывания по таймеру каждую секунду


Пример работы с прерываниями таймера в WinAVR у вас на диску уже есть уже:
X:\WinAVR\examples\demo\demo.c
-=Женек=-
В Вашем коде таймер не срабатывает.
Кстати при компиляции выдается warning "unused parameter TIMER1_COMPA_vect"

И еще - на PD2 у меня подключена пишалка. В теле программы пока нет функции синтеза для нее звука, но при запуске вашей программы она стала жужать. )))

У меня контроллер ATMEGA32
singlskv
Цитата(-=Женек=- @ Sep 18 2006, 15:35) *
В Вашем коде таймер не срабатывает.
Кстати при компиляции выдается warning "unused parameter TIMER1_COMPA_vect"

И еще - на PD2 у меня подключена пишалка. В теле программы пока нет функции синтеза для нее звука, но при запуске вашей программы она стала жужать. )))

У меня контроллер ATMEGA32


Незнаю в чем у Вас дело,
но при замене
Код
#include <avr/interrupt.h>
#include <avr\io.h>
#include <avr\iotn2313.h>

на
Код

#include <avr/interrupt.h>
#include <avr\io.h>
#include <avr\iom32.h>

в AVR Studio все симулируется.

"unused parameter TIMER1_COMPA_vect", странно, это ведь номер прерывания.
-=Женек=-
Вот ваша программа - я добавил туда пикалку (функция beep()).

Код
#include <inttypes.h>
#include <stdio.h>
#include <avr/interrupt.h>
#include <avr\io.h>
#include  <avr\delay.h>
#include <avr\iom32.h>

unsigned char h=0,m=0,sec=0;



beep()
{
int i;

  for (i=0;i<300;i++)
  {
    PORTD |= _BV(PD2);  
    _delay_ms(1);
    PORTD &= ~_BV(PD2);  
    _delay_ms(1);
}
}

void tri_beep()
{
beep();
_delay_ms(100);
beep();
_delay_ms(100);
beep();
_delay_ms(100);
}


void timer_init(void)
{
  
  TCNT1H=TCNT1L=0;
TCCR1A=0;
TCCR1B=12; // cl/256  1000000/256=15625
// 15625/5=3125
OCR1A=3125;
TIMSK=16;

}    


ISR (TIMER1_COMPA_vect)
{
beep();
  }

int main(int argc, char* argv[])
{
DDRD =0xFF;
timer_init();
  
  asm("sei");
  
  
  
while (1);
  return 0;
}


обратите внимание на комментарии перед beep в главном цикле - если комментарий убрать - пикалка звучит постоянно
singlskv
Смотрите коментарии

Код
#include <inttypes.h>
#include <stdio.h>
#include <avr\interrupt.h>
#include <avr/io.h>
#include  <avr\delay.h>
#include <avr\iom32.h>

unsigned char h=0,m=0,sec=0;



beep()       // <--------------------------Примерно 600ms - 0,6sek
{
int i;

  for (i=0;i<300;i++)
  {
    PORTA |= _BV(PA2);  
    _delay_ms(1);
    PORTA &= ~_BV(PA2);  
    _delay_ms(1);
}
}

void tri_beep()
{
beep();
_delay_ms(100);
beep();
_delay_ms(100);
beep();
_delay_ms(100);
}


void timer_init(void)
{
  TCNT1H=TCNT1L=0;
  OCR1A=15624;
  TCCR1A=0;
  TCCR1B=(1<<WGM12)|(1<<CS11)|(1<<CS10); //clk/64
  TIMSK=(1<<OCIE1A);
}    


ISR (TIMER1_COMPA_vect)
{

  if (sec!=59) {
beep();                          //<--------- каждую сек beep - 0,6sek
    sec++;
    return;
  }
  sec=0;
  
  if (m!=59) {
    m++;
    return;
  }
  m=0;

  if (h!=23) {
    m++;
    return;
  }
  h=0;
}

int main(int argc, char* argv[])
{
  DDRA =0xFF;
  //beep();

  timer_init();
  asm("sei");
  while (1);
  return 0;
}


обратите внимание на комментарии перед beep в главном цикле - если комментарий убрать - пикалка звучит постоянно
[/quote]
Вызывать задержки из прерывания, да и еще такой длительности cranky.gif
Ваша программа только и делает что сидит в прерывании и пикает smile.gif
-=Женек=-
Хочу вам сказать, что с _delay_ms у меня явно какф-то фигня...
Вообще, блин.. начинаю ненавидеть WinAVR. В CodeVision все было как говорится "what you see is what you get". Все что я делал получалось с первого или почти с первого раза. Тут же - проблема на проблеме...

Так вот... delay_ms генерирует задежрку раз этак в 10 меньше чем указываешь. Так что там не 0,6 сек.

Цитата
Вызывать задержки из прерывания, да и еще такой длительности
Ваша программа только и делает что сидит в прерывании и пикает


Да дело не в этом - beep в обработчике прерывания вообще не вызывается. А работает beep тот, который ЕДИНОЖДЫ встречается в главном цикле.

Вы невнимательно читали мой код.
singlskv
Цитата(-=Женек=- @ Sep 18 2006, 16:41) *
Да дело не в этом - beep в обработчике прерывания вообще не вызывается. А работает beep тот, который ЕДИНОЖДЫ встречается в главном цикле.

А "собака" у Вас выключена?
Судя по всему у Вас постоянно происходит ресет.
-=Женек=-
Цитата
Судя по всему у Вас постоянно происходит ресет.



Хорошая мысль, ибо установка с помощью CSx делителя не влияет на характер звука.

Что за собака? Объясните.

См. выше пост №8- я привел код таким, какой он есть сейчас. Пикалка молчит.
singlskv
Цитата(-=Женек=- @ Sep 18 2006, 16:55) *
Цитата
Судя по всему у Вас постоянно происходит ресет.



Хорошая мысль, ибо установка с помощью CSx делителя не влияет на характер звука.

Что за собака? Объясните.

См. выше пост №8- я привел код таким, какой он есть сейчас. Пикалка молчит.


собака = Watchdog Timer
если включить, выполняет ресет через опред. время (подробнее в Datasheet)

Ищите почему у Вас происходит Reset.
-=Женек=-
Я привел вам код.
Неужели из него не ясно в каком остоянии находится собака?
SpiritDance
delay_ms() у Вас скорее всего съел оптимизатор.
watchdog может быть включен через фьюзы, убедитесь что это не так.
singlskv
Цитата(-=Женек=- @ Sep 18 2006, 17:06) *
Я привел вам код.
Неужели из него не ясно в каком остоянии находится собака?

Ну я ведь не знаю весь ли это код smile.gif

Чтобы выяснить причину ресета, при старте читайте MCUCSR и выводите
в какой-нибудь порт. По выставленным флагам будет все понятно.
-=Женек=-
ПРочел. биты 0 и 1 равны единице.

А вот мои фьюзы:

Код
Fuses
    OSCCAL    = CB, CB, C4, C5
    BLEV    = 1
    BODEN    = 1
    SUT    = 2
    CKSEL    = F
    BLB1    = 3
    BLB0    = 3
    OCDEN    = 1
    JTAGEN    = 1
    CKOPT    = 0
    EESV    = 1
    BSIZ    = 0
    BRST    = 1
singlskv
Цитата(-=Женек=- @ Sep 18 2006, 17:27) *
ПРочел. биты 0 и 1 равны единице.

Значит у Вас происходит External Reset.

Куда у Вас подключен пин Reset ?
-=Женек=-
к разъему для программирования. У меня Altera byte blaster, который можно не снимать после программирования. А еще кнопочка от ресета идет на питание для ручного сброса.

Вот еще что:
Код
void timer_init(void)
{
  
  TCNT1H=TCNT1L=0;
TCCR1A=0;
TCCR1B=12; // cl/256  1000000/256=15625  15625/5=3125
OCR1A=3125;
//TIMSK=16;

}


после комментирования строки TIMSK=16 контроллер перестает ресетиться.
aesok
Цитата(-=Женек=- @ Sep 18 2006, 15:35) *
В Вашем коде таймер не срабатывает.
Кстати при компиляции выдается warning "unused parameter TIMER1_COMPA_vect"


В ранних версиях 'avr-libv' для описания функции обработчика прерывания использовалось макро SIGNAL(), сейчас оно переименовано в ISR(). Посмотрите в определено ли в файле 'avr/interrupt.h' ISR()?

Какая у вас версия WinAVR?

Анатолий.
-=Женек=-
У меня WinAVR-20050214

в interrupt.h нет не SIGNAL() не ISR()
Но компилятор не ругается на ISR (TIMER1_COMPA_vect)

через поиск попробовал найти файлы содержащие строку "ISR" - не найдено

в очередной раз задаюсь вопросом - почему в CodeVision все работает как часы, а в WinAVR, который хвалят как очень
рациональную программу - вечно какие-то проблемы...
Перейти на WinAVR я был вынужден, так как библиотека для моего LCD есть только для WinAVR
aesok
Цитата(-=Женек=- @ Sep 18 2006, 19:12) *
У меня WinAVR-20050214

в interrupt.h нет не SIGNAL() не ISR()
Но компилятор не ругается на ISR (TIMER1_COMPA_vect)

через поиск попробовал найти файлы содержащие строку "ISR" - не найдено


тогда вместо ISR(...) должно быть:
SIGNAL(SIG_OUTPUT_COMPARE1A)

PS: Если компилятор сказал "warning" - это не значит что нет ошибки.

Анатолий.

ADD:

И добавте еще:
#include <avr/signal.h>
aesok
Цитата(-=Женек=- @ Sep 18 2006, 19:14) *
в очередной раз задаюсь вопросом - почему в CodeVision все работает как часы, а в WinAVR, который хвалят как очень
рациональную программу - вечно какие-то проблемы...


В WinAVR конечно-же есть проблемы, но в данном случае претензии к нему не уместны. Кто Вам мешает открыть файл X:\WinAVR\doc\avr-libc\avr-libc-user-manual.pdf и посмотреть как нужно определять прерывания.

Прерывания не определены в стандарте на язык C, и каждый разработчик компилятора имеет право придумать свой синтаксис.

Анатолий.
singlskv
Цитата(-=Женек=- @ Sep 18 2006, 18:17) *
к разъему для программирования. У меня Altera byte blaster, который можно не снимать после программирования. А еще кнопочка от ресета идет на питание для ручного сброса.

1. Отключите таки ByteBlaster и проверте что reset подтянут к питанию(через резистор).
2. флаг EXTRF в регистре MCUCSR однозначно указывает на то что у Вас происходит
External Reset.
3. И наконец смените вот этот код:
Код
void timer_init(void)
{
  
  TCNT1H=TCNT1L=0;
TCCR1A=0;
TCCR1B=12; // cl/256  1000000/256=15625  15625/5=3125
OCR1A=3125;
TIMSK=16;

}

1000000/256=15625 blink.gif это круто
15625/5=3125 откуда взялась 5 ?
1000000/256=3906,25

при ваших установках получаем:
OCR1=3125
T=(OCR1+1)*256=3126*256=800256 мкс

Я Вам настоятельно рекомендую сменить Вот на это:
Код
  TCNT1H=TCNT1L=0;
  OCR1A=15624;
  TCCR1A=0;
  TCCR1B=(1<<WGM12)|(1<<CS11)|(1<<CS10);  //clk/64   1000000/64=15625
  TIMSK=(1<<OCIE1A);


T=(OCR1+1)*64=15625*64=1000000 , т.е. ровно 1 сек.
-=Женек=-
УУУААААУУУУУУУ!!!!
Заработало!!!!!!

Оказалось нужны были обе меры - и SIGNAL(SIG_OUTPUT_COMPARE1A) и #include....

Теперь я понял, почему компилятор не ругался на ISR - он думал, что я определяю новую функцию с именем ISR, потому и выдавал warning по поводу unused parameter в ней.

Всем спасибо!!!!

Теперь все работает как часы.





Цитата
T=(OCR1+1)*64=15625*256=1000000 , т.е. ровно 1 сек.


Я вам верю, но пикает явны больше 1 раза в секнуду.

Сейчас у меня вот что:
Код
OCR1A = 0xf424;
    OCR1B = 0xf424;
    TCNT1 = 0x0bdc;
    TCCR1A = 0x00;
    TCCR1B = 0x04;
TIMSK=16;

сгенерировал при помощи AtmanAvr
-=Женек=-
...
viael
Цитата(-=Женек=- @ Sep 18 2006, 19:14) *
У меня WinAVR-20050214

в interrupt.h нет не SIGNAL() не ISR()
Но компилятор не ругается на ISR (TIMER1_COMPA_vect)

через поиск попробовал найти файлы содержащие строку "ISR" - не найдено

в очередной раз задаюсь вопросом - почему в CodeVision все работает как часы, а в WinAVR, который хвалят как очень
рациональную программу - вечно какие-то проблемы...
Перейти на WinAVR я был вынужден, так как библиотека для моего LCD есть только для WinAVR


В таком случае можно посоветовать AtmanAVR.Тот же GCC только удобства такие же как в CV и гемора с созданием проета нету(СodeЦizard,генерация makefile).
Имеется плугины там под LCD и еще чтото.Правда триальный период 30 дней,но лекарство в сети имеется.

http://www.atmanecl.com/EnglishSite/SoftwareEnglish.htm
-=Женек=-
Так... выплыла проблемка.... С заданием времени.
До этого я писал, что функция _delay_ms() дает значительно более короткие задержки. Я посчитал, что они короче в 16 раз. Теперь предложенный вами вами вариант инициализации таймера дает не 1, а 1/16 секунды.

Кристалл работает на 16 МГц. А компилятор наверное думает, что 1 МГц.

Собственно, вопрос, а где в проекте указывать что частота кристалла равна 16 МГц?
singlskv
Цитата
У меня WinAVR-20050214

в interrupt.h нет не SIGNAL() не ISR()
Но компилятор не ругается на ISR (TIMER1_COMPA_vect)

А у меня WinAVR-20060421
и ISR в interrupt.h есть smile.gif

Цитата(-=Женек=- @ Sep 18 2006, 20:39) *
Цитата
T=(OCR1+1)*64=15625*64=1000000 , т.е. ровно 1 сек.


Я вам верю, но пикает явны больше 1 раза в секнуду.

Сейчас у меня вот что:
Код
OCR1A = 0xf424;
    OCR1B = 0xf424;
    TCNT1 = 0x0bdc;
    TCCR1A = 0x00;
    TCCR1B = 0x04;
TIMSK=16;

сгенерировал при помощи AtmanAvr

Ну это конечно Ваше дело.
Те установки которые я давал, дают точно 1 сек. на кварце 1МГц.
-=Женек=-
А функция _delay_ms() из delay.h как должна испльзоваться? в хидере установлена частота 1 МГц. Менять хидер под новый кварц? Кстати #define F_CPU 16000000UL в фале программы не помогает.
singlskv
Цитата(-=Женек=- @ Sep 18 2006, 21:25) *
А функция _delay_ms() из delay.h как должна испльзоваться? в хидере установлена частота 1 МГц. Менять хидер под новый кварц? Кстати #define F_CPU 16000000UL в фале программы не помогает.

-=Женек=-
Убедительная просьба к Вам,
в следующий раз задавая вопрос пишите сразу же примерно так:
чип ATmega32
clock 16МГц
компилятор WinAVR-XXXXXXXX
далее суть проблемы...

Иначе слишком много времени тратится зря sad.gif
Shurmas
ИМХО оптимальный вариант из проги востановить алгоритм и записать его уже в CVAVR.
aesok
Цитата(-=Женек=- @ Sep 18 2006, 21:25) *
А функция _delay_ms() из delay.h как должна испльзоваться? в хидере установлена частота 1 МГц. Менять хидер под новый кварц? Кстати #define F_CPU 16000000UL в фале программы не помогает.


Я не использовал _delay_ms[us](). Но если F_CPU задаеться в Makefile то та установка будет иметь более высокий приоритет. Посмотрите чему равна F_CPU в Makefile и задайте правильное значение.

Анатолий.
singlskv
Цитата(-=Женек=- @ Sep 18 2006, 20:39) *
Сейчас у меня вот что:
Код
OCR1A = 0xf424
TCNT1 = 0x0bdc;
TCCR1A = 0x00;
TCCR1B = 0x04;
TIMSK=16;

сгенерировал при помощи AtmanAvr

неправильно !
должно быть:
Код
OCR1A = 0xf423
TCNT1 = 0;
TCCR1A = 0x00;
TCCR1B = 0x04;
TIMSK=16;
-=Женек=-
Я уже сделал, как мне советовали.

Код
TCNT1H=TCNT1L=0;
  OCR1A=15624;
  TCCR1A=0;
  TCCR1B=(1<<WGM12)|(1<<CS12)|(1<<CS10);  
  TIMSK=(1<<OCIE1A);


ТОлько делитель поменял, учитывая что частота 16 МГц
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.