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

Светодиоды Не Мигают Или Мигают Неправильно При Использовании Таймера (Atmega8A)


liosha

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

Всем привет!

Решил вот сделать ребенку мигающие светодиоды на велосипед (а заодно наконец покодить под микроконтроллеры).

Сам я по професии электрик (не радиотехника), но было это давно. Сечас программист на Java. Си тоже учил, но опять же давно.

Купил я ATMega8A, программатор TL866A и несколько светодиодов. Позапускал пару простых примеров, посмотрел/почитал мануалы и решил приступить к самому главному.

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

В связи с этим решил не использовать delay, а сделать правильно, через таймеры.

В общем написал код для таймера, для мигания, отладил в Atmel Studio 6 (AVR Studio) и попытался проэмулировать это дело в протеусе.

Вот тут началось неладное. Светодиоды мигали на глаз со случайной частотой. В отладчике студии время между вызовами таймера примерно совпадает с ожидаемым (+- пару миллисекунд).

Упростил немного код, пробовал менять частоту мигания таймера, ничего не помогает. Я подумал что в протеусе что-то со временем во время эмуляции, и решил проверить на реальной МК.

Но когда залил код в МК, оказалось что на нем светодиод вообще не мигает а просто светит. Думал дело в частоте МК, посмотрел фьюзы, вроде частота такая же как в отладке студии.

Вот код:

#include <avr/interrupt.h>
// Установить бит в 1
#define SB(reg, bit) reg |= (1<<bit)
// Установить бит в 0
#define CB(reg, bit) reg &= ~(1<<bit)
// Проверить установлен ли бит
#define VB(reg, bit) reg & (1<<bit)
// Инвертировать бит
#define TB(reg, bit) reg ^= (1<<bit)
// 0b00000001
#define T100MS 0
// 0b00000010
#define T500MS 1
// 0b00000100
#define T1000MS 2
// 0b00001000
#define T2000MS 3
// 0b00010000
#define T5000MS 4
uint8_t timer500ms = 0;
uint8_t timer1000ms = 0;
uint8_t timer2000ms = 0;
uint8_t timer5000ms = 0;
uint8_t dataTimer = 0b00000000;
// Прерывание каждые 100 миллисекунд
// Устанавливает флаг в соответствии с прошедшим временем
ISR(TIMER2_COMP_vect) {
   SB(dataTimer, T100MS);
   if ((++timer500ms) == 5) {
    timer500ms = 0;
    SB(dataTimer, T500MS);
   }
   if ((++timer1000ms) == 10) {
    timer1000ms = 0;
    SB(dataTimer, T1000MS);
   }
   if ((++timer2000ms) == 20) {
    timer2000ms = 0;
    SB(dataTimer, T2000MS);
   }
   if ((++timer5000ms) == 50) {
    timer5000ms = 0;
    TB(PORTC, 2);
    TB(PORTC, 3);
    TB(PORTC, 4);
    TB(PORTC, 5);
    SB(dataTimer, T5000MS);
   }
}
int main(void)
{
   DDRB |= 0b00000000;
   DDRC |= 0b00111111;
   DDRD |= 0b00001111;
   // Пределитель 1:1
   SB(TCCR2, CS20);
   // Режим сброс при совпадении
   CB(TCCR2, WGM20);
   SB(TCCR2, WGM21);
   // Прерывание при совпадении
   CB(TIMSK, TOIE2);
   SB(TIMSK, OCIE2);
   // Количество тактов перед прерыванием
   OCR2 = 100; // 1мгц
   // Разрешить глобальные прерывания
   asm("sei");
   while(1)
   {
    if (VB(dataTimer, T5000MS)) {
	    // TB(PORTC, 2);
	    // TB(PORTC, 3);
	    // TB(PORTC, 4);
	    // TB(PORTC, 5);
	    // Сброс времени
	    CB(dataTimer, T5000MS);
    }
   }
}

Думал что что-то с МК, добавил в основной цикл мигание с delay, примерно такое:

TB(PORTC, 5);
_delay_ms(1000);
TB(PORTC, 5);
_delay_ms(1000);

При этом в реальном МК светодиод мигал, но не через 1 секунду, а реже. К стати в это время другие светодиоды (оставшиеся на таймере) тоже мигали, но так же с неправильной частотой (вроде гораздо чаще чем должны).

Прикрепляю схему подключения МК. но при тесте я подключал только один слабенький светодиод с резистором. Всего остального небыло.

Очень прошу вашей помощи в решении этой проблемы.

post-164576-0-78238900-1410421157_thumb.png

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

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

Да ладно вам, код же студия подсвечивает в случае таких ошибок)) Название было другое, и тему я создал еще утром. Но форум ее не пропустил, вот я быстренько название и поменял.

Так что с кодом то не так? В чем мои ошибки?

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

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

82 просмотра и ни одного ответа. Мда, я ожидал большего.

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

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

// Установить бит в 1
#define SB(reg, bit) reg |= (1<<bit)
// Установить бит в 0
#define CB(reg, bit) reg &= ~(1<<bit)
// Проверить установлен ли бит
#define VB(reg, bit) reg & (1<<bit)
// Инвертировать бит
#define TB(reg, bit) reg ^= (1<<bit)

// 0b00000001
#define T100MS  0
// 0b00000010
#define T500MS  1
// 0b00000100
#define T1000MS 2
// 0b00001000
#define T2000MS 3
// 0b00010000
#define T5000MS 4

uint8_t timer100ms = 0;
uint8_t timer500ms = 0;
uint8_t timer1000ms = 0;
uint8_t timer2000ms = 0;
uint16_t timer5000ms = 0;
uint8_t dataTimer = 0b00000000;

ISR(TIMER2_COMP_vect) { // each 10ms
   if ((++timer100ms) == 10) {
       timer100ms = 0;
       SB(dataTimer, T100MS);
   }
   if ((++timer500ms) == 50) {
       timer500ms = 0;
       SB(dataTimer, T500MS);
   }
   if ((++timer1000ms) == 100) {
       timer1000ms = 0;
       SB(dataTimer, T1000MS);
   }
   if ((++timer2000ms) == 200) {
       timer2000ms = 0;
       SB(dataTimer, T2000MS);
   }
   if ((++timer5000ms) == 500) {
       timer5000ms = 0;
       SB(dataTimer, T5000MS);
   }
}

int main(void)
{
   DDRB |= 0b00000000;
   DDRC |= 0b00111111;
   DDRD |= 0b00001111;
   // Режим сброс при совпадении
   CB(TCCR2, WGM20);
   SB(TCCR2, WGM21);
   // Прерывание при совпадении
   CB(TIMSK, TOIE2);
   SB(TIMSK, OCIE2);
   // Количество тактов перед прерыванием
   OCR2 = 76; // ~10ms - подобрано опытным путем, без вычислений. Для мигания ледами такой точности достаточно.
   // Пределитель 1:1024 + Запуск таймера
   SB(TCCR2, CS22);
   SB(TCCR2, CS20);
   // Разрешить глобальные прерывания
   asm("sei");
   while(1)
   {
       //
       if (VB(dataTimer, T1000MS)) {
           TB(PORTC, 2);
           TB(PORTC, 3);
           TB(PORTC, 4);
           TB(PORTC, 5);
           // Сброс времени
           CB(dataTimer, T1000MS);
       }
   }
}

Сори за большой код, не нашел как тут вставлять спойлеры

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

  • 1 год спустя...

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

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

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

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

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

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

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

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

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

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

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

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

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