Перейти к содержанию

таймер на Atmega8


Рекомендуемые сообщения

помогите, делаю этот таймер 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
//******************************************************************************


 

 

Ссылка на комментарий
Поделиться на другие сайты

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Новый аккумулятор EVE серии PLM для GSM-трекеров, работающих в жёстких условиях (до -40°С)

Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре. 

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

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

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

Ссылка на комментарий
Поделиться на другие сайты

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

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

Изменено пользователем Alexeyslav

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

Ссылка на комментарий
Поделиться на другие сайты

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

Ссылка на комментарий
Поделиться на другие сайты

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

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

Ссылка на комментарий
Поделиться на другие сайты

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

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

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

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

Ссылка на комментарий
Поделиться на другие сайты

 

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

Изменено пользователем Sergey-Ufa
Ссылка на комментарий
Поделиться на другие сайты

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

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.

Ссылка на комментарий
Поделиться на другие сайты

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

В том же даташите на 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

 

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

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...