Jump to content

Recommended Posts

помогите, делаю этот таймер http://sxem.org/2-vse-stati/22-tajmery/38-tajmer-na-atmega8 и он идет очень медленно, одна секунда равняется 3,5 минутам, как это исправить

Скрытый текст



// *****************************************************************************
// Project: Таймер на АТmega8
// Author: VasylYE
// Module description:
// *****************************************************************************

#include <avr\io.h>              // Most basic include files
#include <avr\interrupt.h>       // Add the necessary ones
//#include <avr\signal.h>        // here
//#define __AVR_ATmega8__
#include <avr\pgmspace.h>
#include <string.h>


//******************************************************************************
//  Определение констант
//******************************************************************************
#define IND_PORT  PORTD
#define IND_DDR  DDRD

#define IND_COM PORTB
#define IND_CDDR DDRB
#define IND_PIN PINB

#define IND_CA1   PB1   // Левый индикатор
#define IND_CA2   PB2
#define IND_CA3   PB3
#define IND_CA4   PB4   // Правый

#define KEY_PORT  PORTC
#define KEY_DDR DDRC
#define KEY_PIN PINC

#define KEY_HOURS PC0
#define KEY_MINUTES PC1
#define KEY_RUN PC2
#define KEY_RESET PC3

#define JUMPER PB0      // Джампер, определяющий работу после пропадания питания
#define CHECK_POWER PB5 // Вход для контроля наличия питания

#define SIGNAL_OUT PC4  // Выход для контрольного светодиода или пищалки

#define LOAD   PC5   // Выход управления нагрузкой

// Значения для таймеров
#define T0_VALUE (255-78)

#define KEY_DEBOUNCE 100

// Флаги
#define f_WholeSec 0   // Флаг указывает, что отсчитана целая секунда.
                        // Используется для мигающей точки, переключается
                        // каждые 0.5 секунд
#define f_CountDown 1  // Флаг, указывающий на то, что происходит обратный
                        // отсчет. Используется для гашения ведущих нулей в
                        // индикации часов.
#define f_TimerRunning 2 // Флаг, указывающий на то, что таймер был запущен

#define f_Power 3 // Флаг наличия общего питания

#define f_Signal 4 // Флаг работы сигнализации (звуковой или световой)


#define IND_OA 1  // Общий анод


const unsigned char DIGITS_OA[] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90};

//******************************************************************************
//  Глобальные переменные
//******************************************************************************
//typedef struct {
//   unsigned char Seconds;
//   unsigned char Minutes;
//   unsigned char Hours;
//} time;

//volatile time Time;
volatile unsigned char m_ucSecOnes = 0;
volatile unsigned char m_ucSecTens = 0;

volatile unsigned char m_ucMinOnes = 0;
volatile unsigned char m_ucMinTens = 0;

volatile unsigned char m_ucHrsOnes = 0;
volatile unsigned char m_ucHrsTens = 0;


volatile unsigned char sm_ucIndNum = 0;

volatile unsigned char m_ucFlags = 0;



volatile unsigned char ucKey_Run_Timeout = 0;
volatile unsigned char ucKey_Hours_Timeout = 0;
volatile unsigned char ucKey_Mins_Timeout = 0;

//******************************************************************************
//  Прерывания
//******************************************************************************
// Прерывание по переполнению таймера Т0, здесь мы выводим часы и минуты на
// индикатор, а также опрашиваем кнопки.
ISR(SIG_OVERFLOW0, ISR_NOBLOCK){ // Разрешены вложенные прервания
volatile unsigned char ucTemp = 0;  //
//volatile unsigned char ucKey_Run_Timeout;
   TCNT0 = T0_VALUE; // Перезагрузка таймера
   sm_ucIndNum++;
   	if (sm_ucIndNum > 3){
      	sm_ucIndNum = 0;
		}
	IND_COM &= ~((1<<IND_CA1)|(1<<IND_CA2)|(1<<IND_CA3)|(1<<IND_CA4));
	IND_PORT = 0xFF;
   // Во время работы таймера, когда идет отсчет, убираем ведущие ноли.
   // Если пропало питание (очищен флаг питания) индикация отключена
   switch (sm_ucIndNum){
      case 0:  {IND_COM |= (1<<IND_CA1);  // Индикация десятков часов
                ucTemp = DIGITS_OA[m_ucHrsTens];
                break;}
      case 1:  {IND_COM |= (1<<IND_CA2);  // Индикация единиц часов
                ucTemp = DIGITS_OA[m_ucHrsOnes];
                // Здесь мы мигаем точкой!
                if (m_ucFlags & (1 << f_WholeSec)){
                	ucTemp &= 0x7F;
                }
                break;}
      case 2:  {IND_COM |= (1<<IND_CA3);  // Индикация десятков минут
                ucTemp = DIGITS_OA[m_ucMinTens];
                break;}
      case 3:  {IND_COM |= (1<<IND_CA4);  // Индикация единиц минут
                ucTemp = DIGITS_OA[m_ucMinOnes];
                break;}
   }
   if (IND_PIN & (1 << CHECK_POWER)){	// Если пропало питание
	   IND_PORT = ucTemp;
	}
	else{
		IND_PORT = 0xFF;                 // отключаем индикацию
	}

   // Опрос кнопки Пуск/Пауза (KEY_RUN)
   if (!(KEY_PIN & (1 << KEY_RUN))){
      if (ucKey_Run_Timeout == 0){
         // Установка флага работы таймера
         // Этот флаг служит для блокировки кнопок и очищается
         // в обработчике прерывания таймера Т2
         m_ucFlags ^= (1 << f_CountDown);
         m_ucFlags |= (1 << f_TimerRunning);
         ucKey_Run_Timeout = 2*KEY_DEBOUNCE;
         // Устанавливаем флаг питания
         m_ucFlags |= (1 << f_Power);

         // Переключаем нагрузку
         if (m_ucFlags & (1 << f_CountDown)) KEY_PORT |= (1 << LOAD);
         else KEY_PORT &= ~(1 << LOAD);
      }
   }
   // Опрос кнопки настройки Часов
   // Только если не установлен флаг работы таймера
   if (!(m_ucFlags & (1 << f_TimerRunning))){
      if (!(KEY_PIN & (1 << KEY_HOURS))){
         if (ucKey_Hours_Timeout == 0){
            m_ucHrsOnes ++;
            if (m_ucHrsOnes > 9){
               m_ucHrsOnes = 0;
               m_ucHrsTens ++;
               if (m_ucHrsTens > 9) m_ucHrsTens = 0;
            }
            ucKey_Hours_Timeout = KEY_DEBOUNCE;
         }
      }
   }

   // Опрос кнопки настройки минут
   // Те же условия
   if (!(m_ucFlags & (1 << f_TimerRunning))){
      if (!(KEY_PIN & (1 << KEY_MINUTES))){
         if (ucKey_Mins_Timeout == 0){
            m_ucMinOnes ++;
            if (m_ucMinOnes > 9){
               m_ucMinOnes = 0;
               m_ucMinTens++;
               if (m_ucMinTens > 5) m_ucMinTens = 0;
            }
            ucKey_Mins_Timeout = KEY_DEBOUNCE;
         }
      }
   }

   // Опрос кнопки останова таймера
   if (!(KEY_PIN & (1 << KEY_RESET))){
      m_ucFlags &= ~(1 << f_CountDown);   // Очистка флагов
      m_ucFlags &= ~(1 << f_TimerRunning);
      // Отключаем нагрузку
      KEY_PORT &= ~(1 << LOAD);
      //

   }

   // Проверка наличия питания проводится только, если таймер в работе
   if (m_ucFlags & (1 << f_TimerRunning)){
   if (IND_PIN & (1 << CHECK_POWER)){ // power ok
      // Проверяем состояние джампера
      // и в зависимости от состояния флага питания делаем следующее
      if (!(m_ucFlags & (1 << f_Power))){ // Если питание пропадало
         if (IND_PIN & (1 << JUMPER)){
            // Если джампер не замкнут Останавливаем отсчет
            // нагрузка отключена
            m_ucFlags &= ~(1 << f_CountDown);
            KEY_PORT &= ~(1 << LOAD);
         }
         else{
            // Если джампер замкнут на 0
            // Продолжаем отсчет, включаем нагрузку
            m_ucFlags |= (1 << f_CountDown);
            KEY_PORT |= (1 << LOAD);
         }
         // Снова выставляем флаг, что с питанием все ок.
         if (IND_PIN & (1 << CHECK_POWER))
            m_ucFlags |= (1 << f_Power);
      }
   }
   else{ //power fail
      m_ucFlags &= ~(1 << f_Power);
      // Отключаем нагрузку
      KEY_PORT &= ~(1 << LOAD);
      // Выставляем флаг паузы отсчета
      m_ucFlags &= ~(1 << f_CountDown);
   }
   }

   if (ucKey_Run_Timeout > 0) ucKey_Run_Timeout--;
   if (ucKey_Hours_Timeout > 0) ucKey_Hours_Timeout--;
   if (ucKey_Mins_Timeout > 0) ucKey_Mins_Timeout--;


}


// Таймер Т2 работает все время, останавливается или запускается
// только отсчет времени.
// Прерывание по переполнению таймера Т2
ISR(SIG_OVERFLOW2){

   m_ucFlags ^= (1 << f_WholeSec); // Переключаем флаг
if (m_ucFlags & (1 << f_CountDown)){
   if (m_ucFlags & (1<<f_WholeSec)){
      m_ucSecOnes --;
      if (m_ucSecOnes > 9){
         m_ucSecOnes = 9;
         m_ucSecTens --;
         if (m_ucSecTens > 5){
            m_ucSecTens = 5;
            m_ucMinOnes --;
            if (m_ucMinOnes > 9){
               m_ucMinOnes = 9;
               m_ucMinTens --;
               if (m_ucMinTens > 5){
                  m_ucMinTens = 5;
                  m_ucHrsOnes --;
                  if(m_ucHrsOnes > 9){
                    m_ucHrsOnes = 9;
                     m_ucHrsTens --;
                     if(m_ucHrsTens > 9){  // Здесь мы дошли до конца отсчета
                        m_ucHrsTens = 0;
                        m_ucHrsOnes = 0;
                        m_ucMinTens = 0;
                        m_ucMinOnes = 0;
                        m_ucSecTens = 0;
                        m_ucSecOnes = 0;
                        // Очищаем флаг отсчета
                        m_ucFlags &= ~(1 << f_CountDown);
                        m_ucFlags &= ~(1 << f_TimerRunning);
                        // Коммутируем нагрузку
                        KEY_PORT &= ~(1 << LOAD);
                     }
                  }
               }
            }
         }
      }
   }
}
};

//******************************************************************************
//  Функции
//******************************************************************************




//******************************************************************************
//  Main program
//******************************************************************************

int main(void) {
   //***************************************************************************
   // Инициализация периферии
   //***************************************************************************

//int temp0, temp1;

   // Настройка порта для сегментов индикатора
   #ifdef IND_OA
      IND_PORT = 0xFF;
   #else
      IND_PORT = 0x00;
   #endif
   IND_DDR = 0xFF;
   // Настройка порта для общих выводов индикатора
   IND_CDDR = 0x00;
   IND_COM = 0x00;

   IND_CDDR = (1<<IND_CA1)|(1<<IND_CA2)|(1<<IND_CA3)|(1<<IND_CA4);
   IND_COM |= (1<<JUMPER)|(1<<CHECK_POWER)|(0<<IND_CA1)|(0<<IND_CA2)|(0<<IND_CA3)|(0<<IND_CA4);

   // Настройка порта для кнопок
   KEY_DDR &= ~((1<<KEY_HOURS)|(1<<KEY_MINUTES)|(1<<KEY_RUN)|(1<<KEY_RESET)); // input
   KEY_DDR |= (1<<SIGNAL_OUT)|(1<<LOAD);  // output
   KEY_PORT |=(1<<KEY_HOURS)|(1<<KEY_MINUTES)|(1<<KEY_RUN)|(1<<KEY_RESET);

   // Настройка таймера Т2, который работает в Асинхронном режиме
   // и тактируется от часового кварца на 32768 Гц
///// Ждем пока не стабилизируется работа внешнего кварца
//   for(temp0=0;temp0<0x0040;temp0++)   // Wait for external clock crystal to stabilize
//   {
//       for(temp1=0;temp1<0xFFFF;temp1++);
//   }
   TIMSK &=~((1<<TOIE2)|(1<<OCIE2));   // Запрещаем TC2 прерывания
   ASSR |= (1<<AS2);                   // Режим таймера - асинхронный
                                       // тактирование от внешн. кварца (32,768kHz)
   while (ASSR & (1 << TCN2UB)){};
   TCNT2 = 0x00;
   while (ASSR & (1 << TCR2UB)){};
   TCCR2 = 0x04;           //Делитель таймера / 64 для получения
                           // переполнения каждые 0.5 секунд

   TIMSK |= (1<<TOIE2);        //set 8-bit Timer/Counter2 Overflow Interrupt Enable
////////

   // Настройка таймера Т0, который используется для динамической индикации
   // и опроса кнопок. МК работает на частоте 1 МГц без внешнего кварца
   // Загрузка регистра таймера Т0
   TCNT0 = T0_VALUE;
   // Разрешение прерываний по переполнению таймера Т0
   TIMSK |= (1<<TOIE0);
   // Пуск таймера Т0
   TCCR0 = (0<<CS02)|(1<<CS01)|(1<<CS00);

   // Разрешение глобальных прерываний
   sei();
   while(1) {             // Infinite loop; define here the
      asm ("nop");                       // system behaviour
   }

}

//******************************************************************************
//  END of File
//******************************************************************************


 

 

Share this post


Link to post
Share on other sites

А индикация нормальная, не замедленная?

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


Учение - изучение правил. Опыт - изучение исключений.

Share this post


Link to post
Share on other sites

Приглашаем на вебинар «Новинки и уникальные решения Molex. На что обратить внимание и почему»

15 апреля приглашаем на вебинар, который будет интересен разработчикам и инженерам-схемотехникам, интересующимся тенденциями рынка, новыми перспективными решениями для соединений «провод-провод», «провод-плата», «плата-плата». Для инженеров КИПиА и IT будут освещены уникальные решения Molex для «удлинения» интерфейсов HDMI, DisplayPort и USB даже в условиях сильного зашумления, а также семейство бесконтактных датчиков Contrinex. Помимо этого, будет уделено внимание дальнейшему развитию направления антенн, где Molex имеет ряд интересных и уникальных решений.

Подробнее

                     

Выбираем преобразователь для портативных устройств

Портативные устройства могут различаться по типам элементов питания, а также по разным функциям. В статье на примере 3-х устройств демонстрируется, как многоканальные SIMO-преобразователи помогают эффективно реализовывать потенциал системы питания и первичного элемента, а также гибко подстраиваться под требуемый функционал.

Читать статью

У вас удивительная способность говорить противоречивые вещи в одном приложении. Так работает исправно или медленно? Счет секунд идет в прерывании второго таймера.

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


Учение - изучение правил. Опыт - изучение исключений.

Share this post


Link to post
Share on other sites

А как она мигает? С интервалом в 3.5 минут?


Учение - изучение правил. Опыт - изучение исключений.

Share this post


Link to post
Share on other sites

да, c интервалом в 3.5 минут, пробовал изменить кристалл но все четно, только кнопка выдает большее число вместо 1

Share this post


Link to post
Share on other sites

Изначально,с завода,мега8 идёт с включенным делителем на 8.Если фьюзы не перепрошивались то тактирование мк будет на частоте 1 Мгц.,может это влияет?

Share this post


Link to post
Share on other sites

Тогда она работала бы гораздо быстрее. Сейчас она тактируется частотой в 32768 герц! Второй таймер делит частоту на 64 предделителем и 256 ещё сам считает в итоге получается 0.5Гц - с этой частотой и должна мигать точка.

Единственное объяснение тому что секунды у вас идут с интервалом в 3.5 минут - таймер считает в 256 раз медленней! Других объяснений просто не остаётся - у тебя не работает кварцевый резонатор, а вывод ловит наводку в 50/100гц! Попробуй активировать фьюз CKOPT(поставить галочку) ИЛИ подключить внешние конденсаторы между выводами кварца и общим проводом. Убедись осциллографом что кварц работает и там есть частота в 32кГц. Иногда, вообще приходилось параллельно кварцу вешать резистор в 10МОм т.к. он набирал статику больше 4 вольт и генератор переставал работать.

Edited by Alexeyslav

Учение - изучение правил. Опыт - изучение исключений.

Share this post


Link to post
Share on other sites

закоротил ножки генератора через резистор и он заработал, правда уже слишком быстро, поэтому завтра пойду и куплю резистор на 10M, большое тебе спасибо, как только заработает нормально сниму процес роботи, а тебе + к карме

Share this post


Link to post
Share on other sites

Ты путаешь причину со следствием. Когда ты закоротил выводы генератор просто стал работать на максимальной частоте. Тебе надо добиться работы генератора на кварце - для этого там ДОЛЖНЫ БЫТЬ конденсаторы на общий провод. Они же активируются битом CKOPT в программаторе либо припаиваются внешние. Так же сам кварц может оказаться битым с низкой добротностью и не раскачивается. А резистор... поможет только если эта проблема поляризации кварца имеется, обычно это проявляется как работает-работает часов 6 а потом встаёт всё колом. Докоснёшься до кварца и опять часов 6 работает и встаёт.


Учение - изучение правил. Опыт - изучение исключений.

Share this post


Link to post
Share on other sites

сли не считать кристал то так уже пробовал, не работает, вообще работает только если пальцем прикоснусь

Share this post


Link to post
Share on other sites

выводы кварца должны быть как можно ближе к выводам МК

можно попробовать корпус кварца прицепить к земле

по поводу конденсаторов, они там не нужны, т.к. при активации асинхронного таймера подключаются внутренние конденсаторы на 36пФ, НО на практике как то было, что часики начинали тикать только если коснуться отверткой одного из выводов кварца и установка внешних конденсаторов помогла., кто виновен МК или сам кварц не знаю.., второго часового кварца под рукой не было чтобы выяснить.

фьюз СКОРТ нет смысла трогать при тактировании МК внутренним калиброванным генератором

купить новый кварц

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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


Учение - изучение правил. Опыт - изучение исключений.

Share this post


Link to post
Share on other sites

 

5 часов назад, Alexeyslav сказал:

CKOPT как раз и подключает те самые внутренние конденсаторы

Откуда вы это взяли? СКОРТ изменяет только режим усилителя в кварцевом генераторе.

The CKOPT Fuse selects between two different
Oscillator amplifier modes. When CKOPT is programmed, the Oscillator output
will oscillate a full rail-to-rail swing on the output.
This mode is suitable when operating
in a very noisy environment or when the output from XTAL2 drives a second clock
buffer. This mode has a wide frequency range. When CKOPT is unprogrammed, the
Oscillator has a smaller output swing.
This reduces power consumption considerably.
This mode has a limited frequency range and it cannot be used to drive other clock
buffers.

О каких либо внутренних конденсаторах здесь нет ни слова. Да и рекомендованные емкости конденсаторов для кварца одинаковы как для запрограммированного СКОРТ, так и для незапрограммированного.

 

изображение.png

Edited by Sergey-Ufa

Share this post


Link to post
Share on other sites

 все зависит от выбранного источника синхронизации.

9 часов назад, Alexeyslav сказал:

CKOPT как раз и подключает те самые внутренние конденсаторы

вы похоже путаете с источником синхронизации низкочастотным кварцевым резонатором 32.768 кГц

To use a 32.768kHz watch crystal as the clock source for the device, the Low-frequency Crystal Oscillator must be selected by setting the CKSEL Fuses to “1001”.

By programming the CKOPT Fuse, the user can enable internal capacitors on XTAL1 and XTAL2, thereby removing the need for external capacitors. The internal capacitors have a nominal value of 36pF.

Однако наше устройство тактируется внутренним RC генератором 1 MHz CKSEL Fuses to “0001”, а часовой кварц 32768 подключен к выводам TOSC1 и TOSC2 и работает совместно с асинхронным генератором таймера 2.

Share this post


Link to post
Share on other sites

Там нет условия на его применение. Независимо от выбранного источника тактирования он подключает внутренние конденсаторы к внешнему генератору.

В том же даташите на 32-й странице:

Цитата

For AVR microcontrollers with Timer/Counter Oscillator pins (TOSC1 and TOSC2), the crystal is
connected directly between the pins. By programming the CKOPT Fuse, the user can enable
internal capacitors on XTAL1 and XTAL2, thereby removing the need for external capacitors.
The Oscillator is optimized for use with a 32.768kHz watch crystal. Applying an external clock
source to TOSC1 is not recommended.

Note: The Timer/Counter Oscillator uses the same type of crystal oscillator as Low-Frequency Oscillator
and the internal capacitors have the same nominal value of 36pF

 


Учение - изучение правил. Опыт - изучение исключений.

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Similar Content

    • By Evgeniy90
      Здравствуйте. Проблема такая:после прошивки USBASP ноутбук перестал его определять. Ошибка в диспетчере устройств:сбой запроса дескриптора USB устройства.
      Прошивал через Arduino UNO и avrdude. Прошивку скачать с офф сайта(последнюю на сайте https://www.fischl.de/usbasp/). Все прошло успешно. Почти))
      Подскажите что можно сделать? 
    • By Evgeniy90
      Здравствуйте! Столкнулся со следующей проблемой: при сборке МД "Шанс" дошел до этапа прошивки МК, в итоге запорол 3 атмеги. Прошивал 3 способами:
      1. Через Arduino UNO(As ISP) просто МК
      2. Через Arduino UNO(As ISP) МК внутрисхемно(соответственно с обвязкой)
      3. Через USB ASP внутрисхемно(с обвязкой соответственно).
      Вышло так, что в наличии кварца 11.0592 МГц не было, и я временно впаял 12 МГц. Прошил трижды всё правильно(фьюзы , контакты и т.д). После прошивки просто не видит МК (ну и плата не работает без МК.да и Бог с ней, но МК всеравно не могу считать). В чем причина понять не могу. Одно думаю, что это разница между 11.0592 и 12 МГц. Посоветуйте как решить проблему.
      Коды ошибок после прошивки во всех трёх случаях одинаковые:
      Sinaprog -invalid device signature
      Averdude -avrdude: warning: cannot set sck period, please check for usbasp firmware update
      target don't answer
    • By Sova
      Добрый день. Опять ATMega, опять таймер 1, вопрос рутинный, но я за сегодня уже извёлся. Что я хотел сделать: МК должен рассчитывать положения моторов (SG90, регулируются временем импульса), включать их все вместе по совпадению таймера 2, затем рассчитывать, когда какой мотор надо отключить, получившийся список сортировать и ставить таймер 1. Таймер 1 сработал - выключили мотор, переставили таймер 1 на подальше. Снова сработал - снова что-то там сделали, увеличили OCR1A и так далее. Конечно же с первого раза не заработало и я начал упрощать и локализировать проблему.
      Получилось вот что: при срабатывании прерывания на совпадение таймера 1 с OCR1A я смотрю в отладчик - а там во-первых TIFR = OCF1A + OCF1B + TOV1, а TCNT1 равен чему угодно, но не OCR1A. Таймер как будто срабатывает не тогда. А когда я ставлю значение поменьше, допустим, OCR1A = 1000 и перехожу в пустой цикл while(1){}, то при наступлении OCR1A == 1000 просто ничего не происходит, прерывание не срабатывает. В целом так. Сейчас очень упрощённый, минимально не работающий код выглядит так:
      #define SET(_REGISTER, _BIT) _REGISTER |= 1 << _BIT #define UNSET(_REGISTER, _BIT) _REGISTER &= ~(1 << _BIT) void local_timer_setup(void) { SET(TCCR1B, CS10); //Setting timer 1 to x1 mode }; void local_timer_start(void) { TCNT1 = 0; SET(TIMSK, OCIE1A); //Allow timer 1 match A interruption }; void local_timer_off(void) { UNSET(TIMSK, OCIE1A); //Prohibit timer 1 match A interruption }; ISR(TIMER1_COMPA_vect) { PORTD = 0xFF; local_timer_off(); }; ISR(TIMER2_COMP_vect) { if (global_timer_count == 2) { global_timer_count = 0; TIFR = 0; PORTD = 0; if (current_step < 10) OCR1A = 0xFFF; else OCR1A = 0xFFFF; if (current_step == 20) current_step = 0; else current_step++; local_timer_start(); } else global_timer_count++; }; Полный код в файле. sei() не забыл. Кстати, таймер нормально выключать/включать через TIMSK, как у меня? Заранее спасибо. 
      Scarecrow_embeded.rar
    • By LemonTV
      Есть картинка из сайта с фьюзами, есть программа avrdude_prog3.3 Как выставить правильно фьюзы чтобы не испортить мк? Незнаю как это сделать есть прямые и инверсные фьюзы, ГДЕ СТАВИТЬ ГАЛОЧКИ И КРУЖОЧЕК НА ПРЯМЫХ ИЛИ ИНВЕРСНЫХ?


    • By Сергей Фомин
      Изучаю прерывания на attiny13. Пока остановился на прерываниях по переполнению. Сделал тестовый код в Atmel Studio и сразу через программатор заливаю на тиньку со светодиодом. Проблема в том что гореть он должен 10 секунд и выключаться, а горит примерно 20-23 секунды. Прошу помощи в правильном расчёте. Код ниже (пока учусь сильно не ругайтесь) :
      #define F_CPU 1000000 #define LED PB2 #include <avr/io.h> //#include <util/delay.h> #include <avr/interrupt.h> unsigned char work_time =384;    //  1000000/1024/256=3.8  (0.026 сек)    10/0.026=384 volatile unsigned char temp =0; ISR (TIM0_OVF_vect) {      TCNT0=0x00;     temp ++;     if (temp>=work_time)     {         PORTB &=~(1<<LED);  //Инвертируем состояние         TCCR0B=0x00    // остановка таймера         cli (); //общее запрещение прерываний     } } int main (void) {     init();               while (1)     {              } } void init () {          DDRB |= (1<<LED); // выход     PORTB =(1<<LED); //включен     TCCR0B =0x05; // установка делителя на 1024     TIMSK0 |= _BV(TOIE0);     sei();   // Либо SREG |= (1<<SREG_I); //Разрешаем прерывания глобально     TCNT0 = 0X00;        //Обнулить счётный регистр }  
×
×
  • Create New...