Обсуждаем контроллеры компании Atmel.
Ответить

Re: Таймеры/счётчики в AVR

Сб фев 24, 2018 13:18:53

Идея такая: сделать на АВР аналог советского чипа УМС8. А в самом идеальном случае - сделать, чтобы чип выдавал мелодию в два голоса, т. е. две частоты сразу. Можно в принципе и на 25 (вернее, 85), но тогда придётся отказаться от тактирования кварцем - не хватит ног под три управляющих входа.

Re: Таймеры/счётчики в AVR

Сб фев 24, 2018 13:31:36

здорово, буду следить за проектом. если дверной звонок, то, имхо, и без кварца можно обойтись, делал на тине 2313 и микроСД карте дверной звонок (ВАВ проигрыватель) и без кварца ничего не "уплывает". а если заплавает - значит скоро менять батарейки...

Re: Таймеры/счётчики в AVR

Сб фев 24, 2018 13:54:50

Ещё вопрос. Может ли tiny85 работать при 1.5 В? В даташите заявлено 1.8 В при 1 МГц, а что в реале?

Re: Таймеры/счётчики в AVR

Сб фев 24, 2018 13:59:55

скорее всего заткнётся - тут индивидуально пробовать надо (ну и понятно, меньше частота - меньше напруга, но не до фанатизма), ещё, т.к. первыми при снижении напруги загибаются еепром и генератор (если БОД не включен), то может помочь внешний генератор.

Re: Таймеры/счётчики в AVR

Сб фев 24, 2018 14:09:12

БОД включать нет смысла - он очень сильно жрёт энергию (до 20 мкА в слипе). ЕЕПРОМ не нужен вообще. Генератор скорее всего придётся использовать встроенный - нужно два ШИМ выхода и три управляющих входа, все линии будут заняты.

Re: Таймеры/счётчики в AVR

Вт фев 27, 2018 21:21:33

Не могу пока придумать, как делать затухание звука. В оригинальной УМС это ведь как-то сделано. Тут приходит в голову разве что ШИМить таймером с очень высокой частотой...

Re: Таймеры/счётчики в AVR

Вт фев 27, 2018 22:30:22

то ли лыжи не едут то ли..... захотелось посмотреть как таймер Т0 работает,почитал шит вроде ниче сложного...но видимо что-то упущено....
задумано дрыгать ножкой в прерывании по совпадению. OCR0-выбран рандомно.
Спойлер
Код:
#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>



ISR(TIMER0_OVF_vect)
{
   PORTD|=(1<<5);
   _delay_ms(1);
   PORTD&=~(1<<5);
   _delay_ms(1);
}


void init_T0(void)
{
   
   TCCR0|=(1<<WGM01)|(1<<CS01); // режим СТС, предделитель 8
   TIMSK|=(1<<OCIE0);           // включение прерывания при совпадении
   OCR0=25;
}


int main(void)
{
   DDRD|=1<<5;
   PORTD&=~(1<<5);
   init_T0();
   
   sei();

   while (1)
   {
      
      
   }
}

Re: Таймеры/счётчики в AVR

Ср фев 28, 2018 06:20:14

watchmaker писал(а):как делать затухание звука
коротить сигнал через батарею резисторов на массу (по аналогии с цап)

Добавлено:
или даже ещё проще - играться не только частотой, но и заполнением


Добавлено after 4 minutes 30 seconds:
ROMan2947 писал(а):то ли лыжи не едут...
наверно лыжи :))
ROMan2947 писал(а):задумано дрыгать ножкой в прерывании по совпадению.
а в коде ISR(TIMER0_OVF_vect) по переполнению...
второй делай_мс(1) не нужен (сам подумай почему)
ну это так, на первый взгляд...

Re: Таймеры/счётчики в AVR

Ср фев 28, 2018 08:49:00

а в коде ISR(TIMER0_OVF_vect) по переполнению...
что значит по переполнению в этом коде?чет не догоняю?

Re: Таймеры/счётчики в AVR

Ср фев 28, 2018 09:05:12

TIMER0_OVF_vect = Timer0 OVeFlow vector = таймер0 переполнения вектор
а должно быть
таймер0 совпадения вектор = timer0 compare vector = TIMER0_COMP_vect
примерно (я не в студии работаю, потому правописание может отличаться)
Последний раз редактировалось Ivanoff-iv Ср фев 28, 2018 09:21:03, всего редактировалось 1 раз.

Re: Таймеры/счётчики в AVR

Ср фев 28, 2018 09:18:59

еще вот так бы я добавил

Код:
while(1)
   {
      asm ("nop");         
   }

а то студия бывает выпендривается
и настройки в студии надо посмотреть по симуляции прерываний

а так да по совпадению выше правильно сказано ISR TIMER0_COMPA_vect

Re: Таймеры/счётчики в AVR

Ср фев 28, 2018 09:26:17

поправил: COMPA=>COMP тут надо обратить внимание, что регистров совпадения может быть один, а может и больше, тогда они помечаются вконце буквами A, B
например в CVAVR обработчик совпадения по регистру B выглядит
interrupt [TIM0_COMPB] void timer0_compb_isr(void) {тело обработчика}

Re: Таймеры/счётчики в AVR

Ср фев 28, 2018 10:33:40

TIMER0_OVF_vect = Timer0 OVeFlow vector = таймер0 переполнения вектор
:oops: :oops: :oops:

исправил, анализатор фиксирует результат. :beer:

Добавлено after 1 minute 43 seconds:
еще вот так бы я добавил


буду иметь ввиду. Но пока студия молчала)

Re: Таймеры/счётчики в AVR

Ср фев 28, 2018 10:35:44

она и будет молчать, но, вот возьмёт и, в рамках оптимизации, пустого цикла не сделает, а майн программа не должна кончаться.

Re: Таймеры/счётчики в AVR

Ср фев 28, 2018 10:42:49

она и будет молчать, но, вот возьмёт и, в рамках оптимизации, пустого цикла не сделает, а майн программа не должна кончаться.

Точно! это уже от настроек оптимизации будет зависеть ведь? хотя интереса ради поставил оптимизацию -O3 цикл не урезало :dont_know:

Re: Таймеры/счётчики в AVR

Ср фев 28, 2018 11:00:32

возможно этим грешили старые версии, но тот, кто один раз нарвётся, и сам перестраховываться будет, и другим расскажет

Re: Таймеры/счётчики в AVR

Ср фев 28, 2018 19:29:19

В прерывании по таймеру произвожу опрос клавиатуры из тактовых кнопок (4шт.) осциллографом замерил время нажатия кнопки в районе 250 мс.
Выставляю предделитель 1024 и при записи в OCR0=255, по расчетам получаю время 32640 мкс =32,64 мс. Это что максимально время,на которое можно выставить таймер?За время нажатия кнопки МК уйдет в прерывание почти 8 раз кварц 8МГц. при 32 мс в меню пункты проскакивают до крайнего. до использования таймера выставлял _delay_ms(100); работало стабильно.

Спойлер
Код:

ISR(TIMER0_COMP_vect)
{
   for(char i =stroka_1; i>=stroka_2;i--)
   {
      
      KEY_PORT_OUT&=~(1<<i);
      RES=(KEY_PORT_OUT&0xC0)|((KEY_PIN&0xC0)>>2);
      KEY_PORT_OUT|=1<<i;

      switch (RES)
      {
         case Enter  : A=Enter   ;break;
         case Cancel: A=Cancel ;break;
         case UP      : A=UP      ;break;
         case DN     : A=DN      ;break;
      } 

   }
   
}

int main (void)
sei();
   
   while(1)
   {
      if(select==NULL) displey_time();
      
      if((A==Enter)|(A==Cancel)|(A==UP)|(A==DN))
       MENU(&A,&select,Electric,GWS,HWS);   
   }

Re: Таймеры/счётчики в AVR

Ср фев 28, 2018 22:32:00

или даже ещё проще - играться не только частотой, но и заполнением

То есть задавать звуковую частоту и менять ширину импульса? Это меняет не только громкость, но и тембр звука, особенно если давать сигнал на динамик, а не на пьезопищалку.

Re: Таймеры/счётчики в AVR

Чт мар 01, 2018 04:40:42

да, короткий импульс даст слышымую вторую (а может и больше) частоту, придется RC фильтр добавить — короткий импульс зарядит кондей слабже, чем длинный - будет изменение амплитуды, заодно вч наводки посрезает.

Добавлено after 11 minutes 6 seconds:
В прерывании по таймеру произвожу опрос клавиатуры
Ты на верном пути, осталось добавить счётчк, чтобы не кидаться выполнять первый же сигнал. (будет отдельно регулируемая задержка и повтор).
счетчик достаточен один и один буфер — сравниваем карту нажатых клавиш с сохранённой в буфере если не равны - сбрасываем счетчик, если равны инкрементируем счетчик, если счет дошел до порога - выполняем действие и сбрасываем счетчик на величину разницы между задержкой и повтором (чтобы в следующий раз дошел быстрее).
ПС: чем чаще опрашивается клавиатура, тем плавнее и предсказуемей она работает (один раз за задержку - очень плохо, т.к. этот таймер тикает независимо и можно очень коротким тычком попасть в момент опроса, а можно и более длинным не попасть. 8 раз - уже хорошо, не будет заметного дрожжания врпмени срабатывания кнопок).

Re: Таймеры/счётчики в AVR

Пт мар 02, 2018 08:52:08

осталось добавить счётчк


счетчик подобно этому?:
Спойлер
Код:
#define KEY_DDR_OUT DDRD
#define KEY_PORT_OUT PORTD

#define KEY_DDR_IN DDRC
#define KEY_PORT_IN PORTC
#define KEY_PIN PINC

#define stroka_1  7
#define stroka_2  6
#define stolbec_1 6
#define stolbec_2 7

#define Enter  0x90   //10010000
#define Cancel 0x60   //01100000
#define DN     0x50   //01010000
#define UP     0xA0   //10100000
#define DREBESK 80
ISR(TIMER0_COMP_vect)
{
   for(char i =stroka_1; i>=stroka_2;i--)
   {
      
      KEY_PORT_OUT&=~(1<<i);
      RES=(KEY_PORT_OUT&0xC0)|((KEY_PIN&0xC0)>>2);
      KEY_PORT_OUT|=1<<i;

      switch (RES)
      {
         case Enter : buffer=Enter  ;break;
         case Cancel: buffer=Cancel ;break;
         case UP    : buffer=UP     ;break;
         case DN    : buffer=DN     ;break;
      }

   }
   
   if(buffer)
   {
      if(count==DREBESK)
      {
         A=buffer;
         buffer=0;
      }
      else
      {
         count++;
      }
   }
   
   else
   {
      count=0;
   }
   
}


Добавлено after 18 minutes 3 seconds:
Решил испробовать Т1 в режиме захвата.Для этого достал ультразвуковой датчик расстояния НС_SR04. в одном из примеров нашел, что после импульса команды на измерения в цикле while(status); ждем окончания измерения, в моем коде программа зацикливается не могу понять почему,да и дебагером никак не могу отловить...а если убрать проверку завершения измерения программа работает,но вывод TRIG захламляется командами на начало измерения. И еще вопрос,правильно считать,что во время задержки _delay_ms() прерывания могут уходить в вектор?
Спойлер
Код:

#define F_CPU 8000000UL
#include <avr/io.h>

 #include <stdlib.h>
#include <stdio.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "LCD_HCSR.h"

#define TRIG_HIGT    PORTD|=1<<5;
#define TRIG_LOW     PORTD&=~(1<<5);
#define ECHO 6
#define CS_00 0
#define CS_01 1
#define CS_02 0

uint8_t status=1;
int TIME=0,d=0;
int print (char *data, uint8_t c)
{
   
   write_command(0x80|c);
   for(int x=0; data[x]!='\0';x++)
   {
      write_data(data[x]);
   }
   _delay_ms(5);
   
   return 0;
}
void init_T1(void)
{
   TIMSK=1<<TICIE1; // включаем прерывание при захвате
   TCCR1B=(1<<ICNC1)|(1<<ICES1)|(CS_02<<CS02)|(CS_01<<CS01)|(CS_00<<CS00); // включаем шумопдавитель, событие по переднему фронту,предделитель 8
   
}

ISR(TIMER1_CAPT_vect)
{
   if(PIND&(1<<6))
   {
      TCNT1=0;
       TCCR1B=(1<<ICNC1)|(CS_02<<CS02)|(CS_01<<CS01)|(CS_00<<CS00);
      TIFR=1<<ICF1;
   }
   else
   {
      TIME=ICR1;
      TCCR1B=(1<<ICNC1)|(1<<ICES1)|(CS_02<<CS02)|(CS_01<<CS01)|(CS_00<<CS00); //
      TIFR=1<<ICF1;
      status=0;
   }
   
}

int main(void)
{
   LCD_init();
   DDRD|=1<<5;
   DDRD &=~(1<<ECHO);
   PORTD&=~(1<<ECHO);
   init_T1();
   char A[10]={0};
   sei();
   
   
          while (1)
    {
      
           status=1;
      //if(!(PIND&(1<<6)))
      //{
      TRIG_HIGT
      _delay_us(10);
      TRIG_LOW
      //}
      
while(status);


      TIME=TIME/58;
      sprintf(A,"%d.%d",TIME/100,TIME%100);
      write_command(0x01);
      print(A,0x00);
      _delay_ms(500);
      
     }
}

Ответить