Radiohobby Forum

Интернет конференция журнала "Радиохобби"

Вы не вошли.

Объявление

Подписка на новые материалы от Николая Сухова - ролики, схемы, модели, онлайн конференции, консультации, чат.

Внимание! Почта в доменах Яндекс и Mail.ru не будет работать в профилях форумчан, из-за введённых правительством Украины санкций против этих компаний. Всем, кто ранее использовал подобную почту, для сохранения прежней функциональности форума, рекомендуется её поменять.

Огромная просьба, заливать тематические картинки и файлы в личные файловые каталоги на форуме, чтобы они не потерялись, со временем!

Ссылка "Загрузки" находится справа внизу формы набора сообщения.

Подписка на журнал "Радиохобби" прекращена. Подробности. Форум же - продолжает свою работу.

#341 08.03.2007 13:43:11

Xumuk
Новичок
Откуда: Харьков
Здесь с 19.01.2007
Сообщений: 19

Re: AVR для "чайников"

Пробовал подключать внешний резонатор 8.000 МГц и пробовал без него - МК не читается :-(
Я пользовался программой spiwc.exe, она как-то очень хитро принимает значения Fuse bits для записи -
2х значное число в Hex, потом меняет цифры местми, инвертирует их и тогда записывает 8 бит в МК.
Может я не совсем прав насчет параметров spiwc.exe, но я запутался основательно :-(
Похоже в МК записались совсем не те значения, которые я хотел.
Ну а посмотреть их я уже не могу.

Если кто знает, подскажите пожалуйста значения  всех Fuse bits  для использования внешнего резонатора с частотой 8 ... 16 Мгц.
Попробую отдать МК чтобы его перешили параллельным программатором, но вот что записать в fuse bits не уверен.
Спасибо.

Вне форума

#342 09.03.2007 10:58:45

Liv
Ветеран
Откуда: Минск
Здесь с 08.02.2004
Сообщений: 1,233

Re: AVR для "чайников"

Попробуйте подать на вывод XTAL1 внешнюю тактовую частоту.

Вне форума

#343 10.03.2007 20:42:49

avr123.nm.ru
Новичок
Здесь с 24.06.2006
Сообщений: 5

Re: AVR для "чайников"

Xumuk пишет:

что записать в fuse bits не уверен.
Спасибо.

Почитайте внимательно - winavr.nm.ru/07.htm - там подробно все расписано.

Вне форума

#344 11.03.2007 17:09:11

Xumuk
Новичок
Откуда: Харьков
Здесь с 19.01.2007
Сообщений: 19

Re: AVR для "чайников"

Большое спасибо ;-)
Хороший мануал, - буду разбираться.

Вне форума

#345 18.03.2007 12:23:51

Xumuk
Новичок
Откуда: Харьков
Здесь с 19.01.2007
Сообщений: 19

Re: AVR для "чайников"

Все, с этой проблемой я разобрался smile - мне перешили фьюзы на значения по-умолчанию параллельным программатором и все заработало big_smile
     Но когда я писал программу, столкнулся с такой проблемой:
при использовании мультиплексированных (надеюсь это так называется) семисегментных индикаторов приходится переключать питание на каждую цифру, затем выводить необходимый символ, удерживать его несколько милисекунд, потом тушить цифру на несколько милисекунд и так для всех знаков. Эта процедура занимает довольно много времени, втечении которого МК ничего кроме этого не делает. А для неприрывного отображения значений приходится помещать все это дело в цикл.
    В ходе нескольких экспериментов я написал вот такой код:

void displaySign(int value){
        if(value==0){
             PORTA=0b00011000;   
             return;
        }
        if(value==1){
             PORTA=0b01111011;   
             return;
        }
        if(value==2){
             PORTA=0b00101100;   
             return;
        }
        if(value==3){
             PORTA=0b00101001;   
             return;
        }
        if(value==4){
             PORTA=0b01001011;   
             return;
        }
        if(value==5){
             PORTA=0b10001001;   
             return;
        }
        if(value==6){
             PORTA=0b10001000;   
             return;
        }
        if(value==7){
             PORTA=0b00111011;   
             return;
        }
        if(value==8){
             PORTA=0b00001000;   
             return;
        }
        if(value==9){
             PORTA=0b00001001;   
             return;
        }
}
                         
void display(int value){
    PORTB=0b11001111;   
    displaySign(value/100);
    delay_ms(1);
    PORTA=255;
    delay_ms(1);
    PORTB=0b10101111;
    displaySign((value%100)/10);
    delay_ms(1);
    PORTA=255;
    delay_ms(1);
    PORTB=0b10011111;
    displaySign(value%10); 
    delay_ms(1); 
    PORTA=255;
    delay_ms(1); 
}

....
        for(i=0; i<1000; i++){
           for(j=0; j<20; j++) display(i);           
        }
....

Все работает отлично, но получается что МК постоянно занят выводом значений.
Каким образом можно реализовать нормальный вывод?
Можно ли как-нибудь запустить его в отдельном потоке? (шутка smile )
Подскажите пожалуйста.

Вне форума

#346 18.03.2007 14:09:09

Liv
Ветеран
Откуда: Минск
Здесь с 08.02.2004
Сообщений: 1,233

Re: AVR для "чайников"

Динамическую индикацию нужно делать по прерываниям таймера. Настраиваете таймер так, чтобы он генерировал прерывания каждую миллисекунду. Это можно сделать так: к примеру, для mega8 взять таймер 2, установить ему режим CTC (Clear Timer on Compare), загрузить регистр сравнения нужным числом, разрешить прерывания по совпадению и написать обработчик прерываний.

#define    FCLK 10.000   //частота кварца, Мгц
#define SYS_TM 1000.0 //период системного таймера, мкс
#define T2VAL (FCLK * SYS_TM / 64.0) //загрузочная величина таймера 2

  TCCR2 = (1<<WGM21) | (1<<CS22); //режим таймера 2: CTC, CK/64
  OCR2 = T2VAL - 1;     //загрузка регистра сравнения
  TIFR = (1 << OCIE2);  //сброс отложенных прерываний
  TIMSK = (1 << OCIE2); //разрешение прерывания по совпадению
  __enable_interrupt(); //разрешение прерываний

В обработчике вызывать SetSeg() для каждой из цифр по очереди. Для этого потребуется переменная Phase, которая будет говорить, какую цифру в данный момент индицируем.

#pragma vector = TIMER2_COMP_vect
__interrupt void Timer(void)
{
  static char Phase;

  Port_SCAN1_1; //выключение всех разрядов дисплея
  Port_SCAN2_1;
  Port_SCAN3_1;
  Port_SCAN4_1;

  switch(Phase) //проверка текущей фазы
  {
  case 0:
    SetSeg(SegData[0]); //вывод сегментов разряда 1
    Port_SCAN1_0;       //включение разряда 1
    break;
  case 1:
    SetSeg(SegData[1]); //вывод сегментов разряда 2
    Port_SCAN2_0;       //включение разряда 2
    break;
  case 2:
    SetSeg(SegData[2]); //вывод сегментов разряда 3
    Port_SCAN3_0;       //включение разряда 3
    break;
  case 3:
    SetSeg(SegData[3]); //вывод сегментов разряда 4
    Port_SCAN4_0;       //включение разряда 4
    break;
  }
  if(Phase < 3) Phase++; else Phase = 0; //следующая фаза
}

Ну и число Value нужно разложить на декады заранее и сохранить в массиве SegData[], а не делать деление на каждом цикле индикации. Лучше в массиве вообще хранить копию сегментов индикатора, чтобы каждый раз не перекодировать в 7-сегментный код. А в основной программе, когда требуется что-то вывести на индикатор, вызываается функция Display(Value), которая просто заполняет  массив SegData[], разложив Value на тетрады и перекодировав в семисегментный код. Всё.

Я бы мог полностью привести исходный текст программы, но пользы от этого, думаю, будет ноль. Лучше пишите сами, постите сюда исходник, будем править.

Отредактировано Liv (18.03.2007 14:11:47)

Вне форума

#347 18.03.2007 19:31:09

Xumuk
Новичок
Откуда: Харьков
Здесь с 19.01.2007
Сообщений: 19

Re: AVR для "чайников"

Большое спасибо за помощь и замечания wink буду разбираться

Вне форума

#348 19.03.2007 08:55:43

Xumuk
Новичок
Откуда: Харьков
Здесь с 19.01.2007
Сообщений: 19

Re: AVR для "чайников"

С прерываниями вроде разобрался smile
Для примера решил сделать таймер обратного отсчета, поместил функцию, зависящую от времени, в функцию обработки таймера, а в main(){} поместил функцию вывода на табло. Вроде все работает, но тут есть две непонятности:
Уход времени на пяти минутах составил ~6 секунд - это из-за внутреннего генератора на 1 МГЦ? Какая будет точность с внешним резонатором?
И еще я чего-то не понял с настройками частоты таймера, перебрал все делители из DataSheet, но максимальная частота оказалась 3,906 КГц.

int time=0;

interrupt [TIM1_OVF] void timer1_ovf_isr(void)
{
        time++;
        if(time==3906){               
                displayValue++;
                time = 0;
        }
}


void main(void)
{
PORTA=0x00;
DDRA=0xFF;

PORTB=0x00;
DDRB=0xF0;

TCCR0=0x00;
TCNT0=0x00;

PLLCSR=0x00;
TCCR1A=0x00;
TCCR1B=0x01;
TCNT1=0x00;
OCR1A=0x00;
OCR1B=0x00;
OCR1C=0x00;


GIMSK=0x00;
MCUCR=0x00;

TIMSK=0x04;
USICR=0x00;
ACSR=0x80;

#asm("sei")

while (1)
      {             
                display(displayValue);
      };
}

Вне форума

#349 21.03.2007 01:17:42

Liv
Ветеран
Откуда: Минск
Здесь с 08.02.2004
Сообщений: 1,233

Re: AVR для "чайников"

Xumuk пишет:

Уход времени на пяти минутах составил ~6 секунд - это из-за внутреннего генератора на 1 МГЦ? Какая будет точность с внешним резонатором?

Возможно. Для внутреннего RC-генератора уход на 2% - обычное дело. С внешним кварцевым резонатором точность будет значительно  лучше. Конкретное значение зависит от примененного резонатора.

Xumuk пишет:

И еще я чего-то не понял с настройками частоты таймера, перебрал все делители из DataSheet, но максимальная частота оказалась 3,906 КГц.

Всё верно. Вы используете прерывание по переполнению, таймер 8-разрядный, 1 МГц / 256 = 3.90625 КГц.

Вне форума

#350 21.03.2007 12:04:29

Xumuk
Новичок
Откуда: Харьков
Здесь с 19.01.2007
Сообщений: 19

Re: AVR для "чайников"

Прошу прощения за бестактный вопрос  roll
А какие еще прерывания по таймеру я могу использовать чтобы отмерять более короткие промежутки времени?

Я хочу сделать хронограф - прибор для измерения скорости полета пули, устройство преддельно простое:  2 оптических датчика в трубке. Для получения высокой точности при малом удалении датчиков друг от друга, мне нужно измерять время до микроСекунд. Каким образом мне можно реализовать такое измерение времени?

Отредактировано Xumuk (21.03.2007 12:06:07)

Вне форума

Сейчас в этой теме пользователей: 0, гостей: 1
[Bot] ClaudeBot

Подвал форума

Под управлением FluxBB
Модифицировал Visman

[ Сгенерировано за 0.046 сек, 7 запросов выполнено - Использовано памяти: 628.8 Кбайт (Пик: 679.16 Кбайт) ]