Например TDA7294

Форум РадиоКот • Просмотр темы - Использование внешних прерываний + Таймера Т0.
Форум РадиоКот
Здесь можно немножко помяукать :)





Текущее время: Чт апр 18, 2024 05:46:57

Часовой пояс: UTC + 3 часа


ПРЯМО СЕЙЧАС:



Начать новую тему Ответить на тему  [ Сообщений: 14 ] 
Автор Сообщение
Не в сети
 Заголовок сообщения: Использование внешних прерываний + Таймера Т0.
СообщениеДобавлено: Пт май 05, 2017 03:41:41 
Потрогал лапой паяльник
Аватар пользователя

Карма: 3
Рейтинг сообщений: 3
Зарегистрирован: Ср май 03, 2017 03:22:26
Сообщений: 303
Рейтинг сообщения: 0
Здравствуйте форумчане, может кто подсказать как организовать использования двух типов прерываний на одном МК.

Используются внешние прерывания для определения перехода фазы через ноль.

За его обработку у меня отвечает INT0
Спойлер
Код:
//настройка внешнего прерывния INT0
void int0_init( void )
{
   //настраиваем на срабатывание INT0 по переднему фронту
   MCUCR |= (1<<ISC01)|(0<<ISC00);
   //разрешаем внешнее прерывание INT0
   En_INT0
}

ISR(INT0_vect)
{
   int i=100;
   int tempMS=(value+1);
   for (;;)
   {
      i--;
      _delay_us(10);
      if (i<=tempMS)
      {
         break;
      }
   }
   int k;
   for(k=0; k<5; k++)
   {
   PORTB |= (1<<1);
   _delay_us(2);
   PORTB &= ~(1<<1);
   _delay_us(2);
   }
}

Внутрение прерывания которые отвечают за индикацию используют Таймер Т0.

Спойлер
Код:
void init_io()
{
   //порт, к которому подкл. сегменты
   PORTA = 0xff;
   DDRA = 0xff;
   //порт, к которому подкл. катод
   DDRB |=(1<<0)|(1<<1)|(1<<2);
   PORTB =0x00;
   //инициализация таймера Т0
   TIMSK = (1<<TOIE0);
   TCCR0B = (1<<CS02)|(0<<CS01)|(1<<CS00);  // правка на 461
   TCNT0L =  T0_TICKS;  //правка на  461
   //иницилизация прерываний
   
}

//прерывания таймера Т0 - вывод на индикатор
ISR(TIMER0_OVF_vect)  //правка на 461
{
   static unsigned char count = 0;
   TCNT0L += T0_TICKS; //правка на 461
   //гасим оба разряда
   PORTB |=(1<<PB0);
   PORTB |=(1<<PB2);
   PORTA = 0b11111110;   
   //зажигаем следующий разряд
   if (count == 0)
   {
      segchar(data2);
      PORTB &= ~(1<<2);
   }
   if (count == 1)
   {
      segchar(data1);
      PORTB &= ~(1<<0);
   }
   count++;
   if (count == 2) count = 0;
}

Но при испытаниях в протеусе , при внешних прерываниях в 100гц. Складывается такое ощущения что обработка кнопок сильно зависает от прерываний по INT0.

Можно ли сделать на МК ATTINY461 организовать подобие много поточности. Чтобы 2 типа прерываний оказывали друг на друга минимальное влияние ?..

Весь код:
Спойлер
Код:
#define F_CPU   8000000          //Hz

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

#define T0_TICK_RATE    200     // Hz
#define T0_CLK  ((F_CPU)/1024)
#define T0_TICKS  (0x100 - T0_CLK / T0_TICK_RATE)

#define DEBOUNCE_TIME          20

#define BUTTON_PIN             PINB
#define POWER_BIT            PB3
#define UP_BIT               PB4
#define DOWN_BIT            PB5

#define KEY_POWER         0b00001000
#define KEY_DOWN         0b00100000
#define KEY_UP            0b00010000

#define  En_INT0      GIMSK|=(1<<6);
#define  Dis_INT0     GIMSK&=~(1<<6);     // выключаем прерывание INT0

volatile unsigned char data1=0;
volatile unsigned char data2=0;
volatile unsigned char value;
volatile int _buzzer = 0;
volatile int _pressed = 0;

void init_io();
void segchar(unsigned char seg);
void handle_button(int key);
void handle_buttons();
void process_power();
void process_up();
void process_down();

//настройка внешнего прерывния INT0
void int0_init( void )
{
   //настраиваем на срабатывание INT0 по переднему фронту
   MCUCR |= (1<<ISC01)|(0<<ISC00);
   //разрешаем внешнее прерывание INT0
   En_INT0
}


ISR(INT0_vect)
{
   int i=100;
   int tempMS=(value+1);
   for (;;)
   {
      i--;
      _delay_us(10);
      if (i<=tempMS)
      {
         break;
      }
   }
   int k;
   for(k=0; k<5; k++)
   {
   PORTB |= (1<<1);
   _delay_us(2);
   PORTB &= ~(1<<1);
   _delay_us(2);
   }
}

int main(void)
{
   value=0;
   init_io();
   sei();
   int0_init();
   while(1)
   {
      handle_buttons();
   }
   return 0;
}


void segchar (unsigned char seg)
{
   switch (seg)
   {
      case 1: PORTA = 0b01111100; break;
      case 2: PORTA = 0b10000100; break;
      case 3: PORTA = 0b01000100; break;
      case 4: PORTA = 0b01101000; break;
      case 5: PORTA = 0b01000010; break;
      case 6: PORTA = 0b00000010; break;
      case 7: PORTA = 0b01110100; break;
      case 8: PORTA = 0b00000000; break;
      case 9: PORTA = 0b01000000; break;
      case 0: PORTA = 0b00010000; break;
   }
}

void init_io()
{
   //порт, к которому подкл. сегменты
   PORTA = 0xff;
   DDRA = 0xff;
   //порт, к которому подкл. катод
   DDRB |=(1<<0)|(1<<1)|(1<<2);
   PORTB =0x00;
   //инициализация таймера Т0
   TIMSK = (1<<TOIE0);
   TCCR0B = (1<<CS02)|(0<<CS01)|(1<<CS00);  // правка на 461
   TCNT0L =  T0_TICKS;  //правка на  461
   //иницилизация прерываний
   
}

//прерывания таймера Т0 - вывод на индикатор
ISR(TIMER0_OVF_vect)  //правка на 461
{
   static unsigned char count = 0;
   TCNT0L += T0_TICKS; //правка на 461
   //гасим оба разряда
   PORTB |=(1<<PB0);
   PORTB |=(1<<PB2);
   PORTA = 0b11111110;   
   //зажигаем следующий разряд
   if (count == 0)
   {
      segchar(data2);
      PORTB &= ~(1<<2);
   }
   if (count == 1)
   {
      segchar(data1);
      PORTB &= ~(1<<0);
   }
   count++;
   if (count == 2) count = 0;
}

void handle_button(int key)
{
   int bit;
   switch (key)
   {
      case KEY_POWER: bit = POWER_BIT; break;
      case KEY_UP:    bit = UP_BIT; break;
      case KEY_DOWN:    bit = DOWN_BIT; break;
      default: return;
   }

   if (bit_is_clear(BUTTON_PIN, bit))
   {
      if (_pressed == 0)
      {
         _delay_ms(DEBOUNCE_TIME);
         if (bit_is_clear(BUTTON_PIN, bit))
         {
            _pressed |= key;
            
            // key action
            switch (key)
            {
               case KEY_POWER: process_power(); break;
               case KEY_UP:    process_up(); break;
               case KEY_DOWN:    process_down(); break;
            }
         }
      }
   }
   else
   {
      _pressed &= ~key;
   }
}

void handle_buttons()
{
   handle_button(KEY_POWER);
   handle_button(KEY_DOWN);
   handle_button(KEY_UP);
}

void process_power()
{
   
}
void process_up()
{
   if (value < 99)
   {
      value++;
      unsigned char tmp;
      tmp = value % 10;
      data1 = tmp;
      tmp = value/10;
      data2= tmp;
   }
}
void process_down()
{
   if (value > 0)
   {
      value--;
      unsigned char tmp;
      tmp = value % 10;
      data1 = tmp;
      tmp = value/10;
      data2= tmp;
   }
}



Вложения:
Комментарий к файлу: Proteus + AtmelStudio
Для Ф.rar [58.71 KiB]
Скачиваний: 225

_________________
andrei23061996@gmail.com
.................................................................................................................


Последний раз редактировалось 7seg Пт май 05, 2017 09:27:38, всего редактировалось 1 раз.
Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Использование внешних прерываний + Таймера Т0.
СообщениеДобавлено: Пт май 05, 2017 04:05:40 
Родился

Зарегистрирован: Чт ноя 24, 2016 20:16:46
Сообщений: 18
Рейтинг сообщения: 3
Чтобы прерывания оказывали друг на друга минимальное влияние их обработка должна занимать как можно меньше времени. А у вас в обработчике delay, который за зря тратит время.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Использование внешних прерываний + Таймера Т0.
СообщениеДобавлено: Пт май 05, 2017 04:20:46 
Потрогал лапой паяльник
Аватар пользователя

Карма: 3
Рейтинг сообщений: 3
Зарегистрирован: Ср май 03, 2017 03:22:26
Сообщений: 303
Рейтинг сообщения: 0
Это просто моя наработка для регулирования яркостью лампы через симистор путем путем детектирования нуля при переходе фазы через нейтраль. а дальше отсчет времени на включение симистра по процентам. Конечно дальше хотел заменить делай на таймеры и записывать значение в переменные т1 и т2 - это 2 перехода Через ноль.
А включение высчитывать по формуле (т2-n1)/100 - это и есть 1% мощности.

Походу надо в целом пересмотреть подход. Хотя еще думаю о вложенных прерываниях но это кажется как то не очень разумно.

_________________
andrei23061996@gmail.com
.................................................................................................................


Вернуться наверх
 
PCBWay - всего $5 за 10 печатных плат, первый заказ для новых клиентов БЕСПЛАТЕН

Сборка печатных плат от $30 + БЕСПЛАТНАЯ доставка по всему миру + трафарет

Онлайн просмотровщик Gerber-файлов от PCBWay + Услуги 3D печати
Не в сети
 Заголовок сообщения: Re: Использование внешних прерываний + Таймера Т0.
СообщениеДобавлено: Пт май 05, 2017 06:51:00 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
Во-первых, у вас в прерываниях сплошь и рядом обращения к функциям, причем даже к библиотечным. Это не кошерная практика. Как минимум, сделайте все функции, к которым идут обращения из прерываний, static, но лучше обойдитесь без них вообще.
Во-вторых, логика у вас сильно хромает. Делать обработку кнопок поочередно?! Впервые такое встречаю.
Ну и по остальному коду то же самое - зачем в синхронизации с 0 у вас какие-то циклы, задержки? Логика фазового управления (для диммера) должна быть такой или очень похожей на такую: в момент перехода через 0 (в обработчике прерывания то есть) запускаем таймер на отсчет нужной фазы. Когда таймер отсчитает фазу, по его прерыванию включаем импульс управления тиристором и перезапускаем таймер на интервал длительности импульса, по истечению интервала импульс отключаем, таймер останавливаем.
Не забывайте о том, что схема может сильно влиять на поведение программы: как у вас цепь синхронизации с сетью сделана?

Советы общего плана, как и вопрос ваш не очень конкретный...

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

Мой уютный бложик... заходите!


Вернуться наверх
 
Организация питания на основе надежных литиевых аккумуляторов EVE и микросхем азиатского производства

Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: Использование внешних прерываний + Таймера Т0.
СообщениеДобавлено: Пт май 05, 2017 08:25:40 
Потрогал лапой паяльник
Аватар пользователя

Карма: 3
Рейтинг сообщений: 3
Зарегистрирован: Ср май 03, 2017 03:22:26
Сообщений: 303
Рейтинг сообщения: 0
AVR, Большое спасибо за советы. Сейчас есть над чем подумать.

Добавлено after 17 minutes 3 seconds:
Схемка
[img]
download/file.php?id=284457
[/img]


Вложения:
Комментарий к файлу: схема
123.JPG [59.47 KiB]
Скачиваний: 670

_________________
andrei23061996@gmail.com
.................................................................................................................
Вернуться наверх
 
Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.

Подробнее>>
Не в сети
 Заголовок сообщения: Re: Использование внешних прерываний + Таймера Т0.
СообщениеДобавлено: Пт май 05, 2017 08:59:45 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 0
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
по схеме тоже предлагаю подумать :) я бы на вашем месте отказался от того огорода с транзисторами, что вы сделали для синхронизации с сетью, а просто со вторичной обмотки трансформатора завел бы через резисторы на входы аналогового компаратора МК сигналы, и вместо INT0 использовал бы прерывание от компаратора.

ну или точно так же без всяких транзисторов завел бы сигнал на INT0... хотя первый вариант мне нравится больше :)

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

Мой уютный бложик... заходите!


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Использование внешних прерываний + Таймера Т0.
СообщениеДобавлено: Пт май 05, 2017 09:10:39 
Потрогал лапой паяльник
Аватар пользователя

Карма: 3
Рейтинг сообщений: 3
Зарегистрирован: Ср май 03, 2017 03:22:26
Сообщений: 303
Рейтинг сообщения: 0
Насчет предлагаемых вами изменениях конечно подумаю , если честно не рассматривал с данного ракурса. Но пока охота все-таки через прерывания по ИНТ0 все это сделать.
Эхх первый проект и должен быть таким тяжелым, и лишь тогда что то останется в голове.

Пока решил по изучать датишь на 128мегу( единственный что мне попался на русском). А пока буду его читать заодно по анализирую ответы на форуме.

_________________
andrei23061996@gmail.com
.................................................................................................................


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Использование внешних прерываний + Таймера Т0.
СообщениеДобавлено: Сб май 06, 2017 05:40:24 
Потрогал лапой паяльник
Аватар пользователя

Карма: 3
Рейтинг сообщений: 3
Зарегистрирован: Ср май 03, 2017 03:22:26
Сообщений: 303
Рейтинг сообщения: 0
А есть у кого примеры фазо импульсного управления на аттини ? или примеры димеров ?

_________________
andrei23061996@gmail.com
.................................................................................................................


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Использование внешних прерываний + Таймера Т0.
СообщениеДобавлено: Сб май 06, 2017 06:43:33 
Друг Кота
Аватар пользователя

Карма: 32
Рейтинг сообщений: 482
Зарегистрирован: Сб сен 10, 2011 17:46:25
Сообщений: 3832
Рейтинг сообщения: 1
можно обойтись и без прерываний INT0 - ждем пока на ноге порта не будет лог. "0" (переход сетевого напряжения через 0), на таймере организуем задержку, в нужное время подаем импульс на УЭ симистора.
Изображение


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Использование внешних прерываний + Таймера Т0.
СообщениеДобавлено: Сб май 06, 2017 08:01:24 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 1
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
А есть у кого примеры фазо импульсного управления на аттини ? или примеры димеров ?

допустим, у меня есть. на тини13. я даже многократно схему приводил:
Изображение
можете посмотреть, как синхронизация с сетью реализована - 2 резистора всего-навсего. хоть схема и не от устройства-диммера, сделать диммер - будет точно такая же схема.

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

Мой уютный бложик... заходите!


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Использование внешних прерываний + Таймера Т0.
СообщениеДобавлено: Вс май 07, 2017 06:19:23 
Потрогал лапой паяльник
Аватар пользователя

Карма: 3
Рейтинг сообщений: 3
Зарегистрирован: Ср май 03, 2017 03:22:26
Сообщений: 303
Рейтинг сообщения: 0
ARV, А можно на листинг программы взглянуть ? если это не тайна конечно ?

_________________
andrei23061996@gmail.com
.................................................................................................................


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Использование внешних прерываний + Таймера Т0.
СообщениеДобавлено: Вс май 07, 2017 08:16:17 
Ум, честь и совесть. И скромность.
Аватар пользователя

Карма: 97
Рейтинг сообщений: 2058
Зарегистрирован: Чт дек 28, 2006 08:19:56
Сообщений: 18030
Откуда: Новочеркасск
Рейтинг сообщения: 1
Медали: 2
Получил миской по аватаре (1) Мявтор 3-й степени (1)
взглянуть можно, но вряд ли вы разберетесь...
Спойлер
Код:
/*
 * main.c
 *
 *  Created on: 05.09.2010
 *      Author: ARV
 */
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include <avr_helper.h>
#include "rc5.h"

/// рабочий порт для выхода на симистор
#define OUTPORT      PORTB
/// выходной пин порта для управления симистором
#if defined(__AVR_ATtiny2313__)
#define   OUT         _BV(PB7)
#else
#define OUT         _BV(PB4)
#endif
/// длительность выходного импульса управления симистором
#define PULSE_LEN   50
/// действие по совпадению канала А
#define do_comp_A()   if(on) OUTPORT &= ~OUT
/// действие по совпадению канала В
#define do_comp_B()   OUTPORT |= OUT

/// предделитель таймера
#define TMR_DIV      8

#define MAX_P      200
#define PHASE_STEP   5
#define MIN_P      PHASE_STEP
#define PHASE_OFF   (MAX_P + PHASE_STEP)

/// частота следования битов по стандарту RC5 (1778 мкс на 1 бит)
#define F_RC   562UL
/// полное значение делителя таймера 1
#define T1_DIV   (TMR_DIV * CTC)
/// Длительность интервала передачи 1 бита
#define   T1   ((F_CPU / T1_DIV / F_RC) + 5)
/// Длительность 1 бита при "соседних" битах 01 или 10
#define   T2   (T1*3UL/2UL)
/// Максимальный интервал протокола
#define   T3   (2UL*T1)
/// Установка сброса для режима СТС
#define CTC         (F_CPU/TMR_DIV/MAX_P/100)

volatile uint8_t    COUNTER;// = 0;
volatile uint8_t   COMP_A;
volatile uint8_t   COMP_B;
volatile uint16_t   COMP_C;
volatile uint8_t    timeout;
volatile uint8_t   out_phase = PHASE_OFF;
volatile uint8_t   sel_phase;// = PHASE_OFF;
//volatile uint8_t   ocr_c_enable   = 0;
volatile uint8_t   on = 0;

/// локальная переменная, в которой хранится принятый код
volatile uint16_t rc_code;
/// переменная, накапливающая принимаемые биты
volatile uint16_t code;
/// счетчик принятых бит
volatile uint8_t  count;

EEMEM rc5_t cmd[4] = {
   make_rc5_code(RC5ADDR_PHONO,RC5CMD_STOP),
   make_rc5_code(RC5ADDR_PHONO,RC5CMD_PLAY),
   make_rc5_code(RC5ADDR_PHONO,RC5CMD_VOLPLUS),
   make_rc5_code(RC5ADDR_PHONO,RC5CMD_VOLMINUS)
};

#ifndef TIM0_COMPA_vect
#define TIM0_COMPA_vect TIMER0_COMPA_vect
#endif

/** Прерывание по переполнению таймера.
 * Таймер без делителя, прерывание возникает каждые 256 тактов.
 * Обработчик прерыания реализует виртуальный 16-битный таймер с регистрами сравнения и т.п.
 */
ISR(TIM0_COMPA_vect){
   COUNTER++;                     // ведем программный таймер
   if(COUNTER == COMP_A){
      do_comp_A();
   }
   if(COUNTER == COMP_B){
      do_comp_B();
   }
   if(COMP_C){
      if(!--COMP_C){
         // проанализируем число принятых бит
         switch(count){
         case RC5_CODELEN-1:
               // если принято на 1 бит меньше, чем нужно - дополняем нулем
               code <<= 1;
         case RC5_CODELEN:
               // если принято нормальное число бит - обновляем код
               rc_code = ignore_toggle(code);
         default:
               // что бы ни было принято - всегда обнуляется счетчик бит
               // который является признаком готовности к новому приему
               count = 0;
         }
      }
   }
}

#ifndef PCINT0_vect
#define PCINT0_vect PCINT_vect
#endif

/** Прерывание по изменению состояния синхро-пина.
 * Возникает по фронту и спаду синхроимпульса.
 * Реализует синхронизацию с сетью.
 */
ISR(PCINT0_vect){
   uint8_t tmp = COUNTER;            // запоминаем счетчик

   OUTPORT   |= OUT;               // выключаем на всякий случай выход
   COMP_A    = tmp + out_phase;         // задаем момент включения выходного сигнала
   COMP_B   = tmp + out_phase + PULSE_LEN;
   if(on){
      if(sel_phase > out_phase){
         out_phase += 1;//PHASE_STEP;
      } else if(sel_phase < out_phase){
         out_phase -= 1;//PHASE_STEP;
      }
   }
   if(timeout) timeout--;
}



#ifndef TIMSK0
#define TIMSK0 TIMSK
#endif

#define SND _BV(PB3)
static void beep(void){
   for(uint8_t i=255; i; i--){
      PORTB ^= SND;
      _delay_us(150);
   }
}

static uint16_t get_ir(void){
   uint16_t code = 0;
   
   while(PINB & _BV(PB0)) wdt_reset();
   _delay_us(BIT_TIME / 4.0);
   for(uint8_t i=0; i < RC5_CODELEN; i++){
      wdt_reset();
      code <<= 1;
      if(!(PINB & _BV(PB0))) code |= 1;
      _delay_us(BIT_TIME);
   }
   return code;
}
MAIN(){
   uint8_t   off_phase = MIN_P;
   uint16_t code, oldcode;

   // настройка периферии
   wdt_enable(WDTO_1S);            // сторожа разрешим для страховки
   ACSR   = _BV(ACD);               // компаратор отключается для экономии энергии
   DDRB   = OUT | SND;                  // выходной пин
   PORTB   = OUT;
   MCUCR   = _BV(ISC01);            // запрос прерывания по падающему фронту
   TCCR0A   = _BV(WGM01);            // режим СТС
   OCR0A   = CTC;                  // порог сброса
   TCCR0B    = TIMER_CLK_DIV(TMR_DIV);   // делитель таймера

   TIMSK0    = _BV(OCIE0A);            // прерывания по сбросу таймера
   PCMSK   = _BV(PCINT0);            // 0-й пин используется для синхронизации с сетью
   GIMSK   = _BV(INT0) | _BV(PCIE);   // разрешаем внешний запрос и прерывание по смене уровня пина

   // временно
#if defined(__AVR_ATtiny2313__)
   DDRD = _BV(PD5);
   PORTD = _BV(PD5) | _BV(PD2);
#endif
   sei();
   while(1){

      while(!(code = get_ir())){
         wdt_reset();
         _delay_ms(10);
      }

      if(oldcode != code){
         oldcode = code;
      } else if(timeout) continue;

      // обработка принятого кода
      if(code == eeprom_read_word((void*)&cmd[0])){
         timeout = 200;
         beep();
         if(on){
            off_phase = sel_phase;
         m1:
            sel_phase = PHASE_OFF;
            out_phase = PHASE_OFF;
            on = 0;
         } else {
         m2:
            sel_phase = off_phase;
            on = 1;
         }
      } if(code == eeprom_read_word((void*)&cmd[2])){
         if(!on) goto m2;
         timeout = 5;
         // изменение
         if(sel_phase > PHASE_STEP){
            sel_phase -= PHASE_STEP;
            beep();
         }
      } else if(code == eeprom_read_word((void*)&cmd[3])){
         timeout = 5;
         // изменение
         if(sel_phase < PHASE_OFF){
            beep();
            sel_phase += PHASE_STEP;
         } else {
            off_phase = PHASE_STEP;
            goto m1;
         }
      }
   }
}
только показанный код немного от другого проекта - от проекта диммера с RC5-дистанционным управлением, т.е. схема, что ранее показал, несколько отличается. К сожалению, саму схему я утерял, но принцип синхронизации точно такой же, как и на схеме, и как я текстом описывал.

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

Мой уютный бложик... заходите!


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Использование внешних прерываний + Таймера Т0.
СообщениеДобавлено: Вс май 07, 2017 09:10:39 
Друг Кота
Аватар пользователя

Карма: 32
Рейтинг сообщений: 482
Зарегистрирован: Сб сен 10, 2011 17:46:25
Сообщений: 3832
Рейтинг сообщения: 1
А можно на листинг программы взглянуть ?

можно листинг на Си и немного теории подсмотреть в документе от Микрочип "PICDIM Lamp Dimmer for the PIC12C508" 1997 года, хоть и для пика, но Си он и в Африке Си. Там диаграмки и схема есть. Прерываний нет.


Вернуться наверх
 
Не в сети
 Заголовок сообщения: Re: Использование внешних прерываний + Таймера Т0.
СообщениеДобавлено: Чт май 11, 2017 12:06:23 
Потрогал лапой паяльник
Аватар пользователя

Карма: 3
Рейтинг сообщений: 3
Зарегистрирован: Ср май 03, 2017 03:22:26
Сообщений: 303
Рейтинг сообщения: 0
Опытным путем и научным методом тыка переделал немного программку, таким образом как думаете вот такой димер если правильно рассчитать время переполнения таймера. Имеет право на жизнь ?

Код:

#define F_CPU   8000000          //Hz

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

#define T0_TICK_RATE    1000     // Hz
#define T0_CLK  ((F_CPU)/1024)
#define T0_TICKS  (0x100 - T0_CLK / T0_TICK_RATE)

#define DEBOUNCE_TIME          20

#define BUTTON_PIN             PINB
#define POWER_BIT            PB3
#define UP_BIT               PB4
#define DOWN_BIT            PB5

#define KEY_POWER         0b00001000
#define KEY_DOWN         0b00100000
#define KEY_UP            0b00010000



#define  En_INT0      GIMSK|=(1<<6);
#define  Dis_INT0     GIMSK&=~(1<<6);     // выключаем прерывание INT0




volatile unsigned char data1=0;
volatile unsigned char data2=0;
volatile unsigned char value;
volatile int _buzzer = 0;
volatile int _pressed = 0;

volatile unsigned char sw=0;

void init_io();
void segchar(unsigned char seg);
void handle_button(int key);
void handle_buttons();
void process_power();
void process_up();
void process_down();

//настройка внешнего прерывни¤ INT0
void int0_init( void )
{
   //настраиваем на срабатывание INT0 по переднему фронту
   MCUCR |= (1<<ISC01)|(0<<ISC00);
   //разрешаем внешнее прерывание INT0
   En_INT0   
}


ISR(INT0_vect)
{
   sw=1;
   static unsigned char count = 0;
   //гасим оба разр¤да
   PORTB |=(1<<PB0);
   PORTB |=(1<<PB2);
   PORTA = 0b11111110;
   //зажигаем следующий разр¤д
   if (count == 0)
   {
      segchar(data2);
      PORTB &= ~(1<<2);
   }
   if (count == 1)
   {
      segchar(data1);
      PORTB &= ~(1<<0);
   }
   count++;
   if (count == 2) count = 0;

}

int main(void)
{
   value=0;
   init_io();
   sei();
   int0_init();
   while(1)
   {
      handle_buttons();
   }
   return 0;
}


void segchar (unsigned char seg)
{
   switch (seg)
   {
      case 1: PORTA = 0b01111100; break;
      case 2: PORTA = 0b10000100; break;
      case 3: PORTA = 0b01000100; break;
      case 4: PORTA = 0b01101000; break;
      case 5: PORTA = 0b01000010; break;
      case 6: PORTA = 0b00000010; break;
      case 7: PORTA = 0b01110100; break;
      case 8: PORTA = 0b00000000; break;
      case 9: PORTA = 0b01000000; break;
      case 0: PORTA = 0b00010000; break;
   }
}

void init_io()
{
   //порт, к которому подкл. сегменты
   PORTA = 0xff;
   DDRA = 0xff;
   //порт, к которому подкл. катод
   DDRB |=(1<<0)|(1<<1)|(1<<2);
   PORTB =0x00;
   //инициализаци¤ таймера “0
   TIMSK = (1<<TOIE0);
   TCCR0B=(0<<CS01)|(1<<CS00);   // правка на 461
   TCNT0H=0x00;
   TCNT0L=0xff;  //правка на  461
   //иницилизаци¤ прерываний
   
}

volatile unsigned char lvl=0;
//прерывани¤ таймера “0 - вывод на индикатор
ISR(TIMER0_OVF_vect)  //правка на 461
{
   //cli();
   TCNT0L=0xff; //правка на 461
   if (sw==1)
   {
      lvl++;
      if (lvl==(value))
      {
         for(int k=0; k<5; k++)
         {
            PORTB |= (1<<1);
            _delay_us(10);
            PORTB &= ~(1<<1);
            _delay_us(1);
         }
      }
      
   }
}

void handle_button(int key)
{
   int bit;
   switch (key)
   {
      case KEY_POWER: bit = POWER_BIT; break;
      case KEY_UP:    bit = UP_BIT; break;
      case KEY_DOWN:    bit = DOWN_BIT; break;
      default: return;
   }

   if (bit_is_clear(BUTTON_PIN, bit))
   {
      if (_pressed == 0)
      {
         _delay_ms(DEBOUNCE_TIME);
         if (bit_is_clear(BUTTON_PIN, bit))
         {
            _pressed |= key;
            
            // key action
            switch (key)
            {
               case KEY_POWER: process_power(); break;
               case KEY_UP:    process_up(); break;
               case KEY_DOWN:    process_down(); break;
            }
         }
      }
   }
   else
   {
      _pressed &= ~key;
   }
}

void handle_buttons()
{
   handle_button(KEY_POWER);
   handle_button(KEY_DOWN);
   handle_button(KEY_UP);
}

void process_power()
{

}
void process_up()
{
   if (value < 99)
   {
      value++;
      unsigned char tmp;
      tmp = value % 10;
      data1 = tmp;
      tmp = value/10;
      data2= tmp;
   }
}
void process_down()
{
   if (value > 0)
   {
      value--;
      unsigned char tmp;
      tmp = value % 10;
      data1 = tmp;
      tmp = value/10;
      data2= tmp;
   }
}


_________________
andrei23061996@gmail.com
.................................................................................................................


Вернуться наверх
 
Показать сообщения за:  Сортировать по:  Вернуться наверх
Начать новую тему Ответить на тему  [ Сообщений: 14 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на форуме

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 26


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Русская поддержка phpBB
Extended by Karma MOD © 2007—2012 m157y
Extended by Topic Tags MOD © 2012 m157y