Динамическая индикация

Обсуждаем контроллеры компании Atmel.
Ответить
Аватара пользователя
Dan Swano
Открыл глаза
Сообщения: 42
Зарегистрирован: Пн июл 04, 2011 13:42:43
Откуда: Тула
Контактная информация:

Динамическая индикация

Сообщение Dan Swano »

Всем привет. :)
Начал осваивать AVR, есть Arduino на Atmega328P, делаю задание по подключению двухразрядного LED-индикатора, в перспективе - термометр. Набросал код и не пойму, в Протеусе в обоих разрядах индикатора одинаковые цифры. Это ошибка в коде или надо как-то настроить Протеус?
Сильно не пинайте, я только учусь.
Вот схема:
Изображение
и код, присутствуют некоторые Ардуино-специфичные функции:
Спойлер

Код: Выделить всё

/*
 * Соответствие отображаемого знака данным порта
общий анод
_____
     |   двоичный вид по сегментам   |            |                   |
Цифра|dp | G | F | E | D | C | B | A | Десятичный | Шестнадцатиричный |
-----|---|---|---|---|---|---|---|---|----------|----------|
  0  | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |    192     |        0xC0       |
  1  | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |    249     |        0xF9       |
  2  | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 0 |    164     |        0xA4       |
  3  | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 |    176     |        0xB0       |
  4  | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 |    153     |        0x99       |
  5  | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 0 |    146     |        0x92       |
  6  | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |    130     |        0x82       |
  7  | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |    248     |        0xF8       |
  8  | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |    128     |        0x80       |
  9  | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |    144     |        0x90       |
 dp  | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |    127     |        0x7F       |
-----*---*---*---*---*---*---*---*---*----------*----------+
 */
#include <avr/io.h>
#include <avr/interrupt.h>
#include <OneWire.h>
// пример использования библиотеки OneWire DS18S20, DS18B20, DS1822
#define DIG_BASE 10 // основание системы счисления для перевода
#define MAX_SIZE 2 // максимальное число выводимых символов
#define SPACE_CHAR 0xFF // символ "пустого" места
#define NEG_CHAR 0xBF // символ "минус"
// Определения, к каким выводам подключены сегменты индикатора и разряды
#define SEG_A 6
#define SEG_B 7
#define SEG_C 8
#define SEG_D 9
#define SEG_E 10
#define SEG_F 11
#define SEG_G 12
#define RAZR_1 4
#define RAZR_2 5
// массив символов, соответствующих ЦИФРАМ выбранной системы счисления
unsigned char SYMBOLS[DIG_BASE] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
volatile unsigned char out[MAX_SIZE]; // выходной массив символов (экранная область)
unsigned char segm[7] = {6,7,8,9,10,11,12}; // массив с номерами выводов, к которым подключены сегменты (A-G)
unsigned char razr[MAX_SIZE] = {4,5}; // массив с номерами выводов управления разрядами
     
OneWire ds(13); // на пине D13 (нужен подтягивающий резистор 4,7 кОм)

void convert(unsigned int NUM) {
  int i, m, sign = 0;
  if(NUM <0) {
    // если число отрицательное
    sign = 1; // установим признак наличия знака
    NUM *= -1; // а само число возьмем по модулю
  }
  // выводим уже положительное число
  i=MAX_SIZE-1;
  do {
    // цикл заполнения выходного массива СПРАВА НАЛЕВО
    m = NUM % DIG_BASE; // находим остаток от деления числа на основание
    if((NUM==0)&&(i!=(MAX_SIZE-1)))
      break; // закончим цикл вывода числа
    else
      out[i] = SYMBOLS[m]; // иначе выводим символ нужной ЦИФРЫ
      NUM /= DIG_BASE;  // уменьшаем число в DIG_BASE раз
    } while (--i >= 0);
  // число выведено, проверяем свободное место и выводим при необходимости знак
  if (i < 0) return; // места не хватает - выход
  if (sign) out[i--] = NEG_CHAR; // выводим знак, если нужно
  for(; i>=0;i--) out[i] = SPACE_CHAR; // очищаем незначащие позиции
}

void setup(void) {
  // Функция инициализации МК
  OCR0A = 0x0F;  // До какого значения считать
  TIMSK0 |= _BV(OCIE0A);  // Прерывание по совпадению таймера (устанавливает в "1" бит, другой вариант записи - TIMSK0 |= 1 << OCIE0A)
  // устанавливаем режимы для пинов
  pinMode(SEG_A, OUTPUT);
  pinMode(SEG_B, OUTPUT); 
  pinMode(SEG_C, OUTPUT);
  pinMode(SEG_D, OUTPUT);
  pinMode(SEG_E, OUTPUT);
  pinMode(SEG_F, OUTPUT);
  pinMode(SEG_G, OUTPUT);
  pinMode(RAZR_1, OUTPUT);
  pinMode(RAZR_2, OUTPUT);
  Serial.begin(9600);  // инициализация консоли
  interrupts();  // разрешаем прерывания (аналог - sei();)
}

void loop(void) {
  // Основная функция программы
  unsigned char disp = 0;
    // Тестовый вывод цифр на индикатор
    while (1) {
    disp++;
    Serial.print(" Data to display = ");
    Serial.print(disp);
    Serial.println();
    convert(disp);
    if (disp >= 255) disp = 0;
    delay(500);
    }
}

SIGNAL (TIMER0_COMPA_vect) {
  // Обработчик прерывания таймера
  static unsigned char pos = 0, i;
//  digitalWrite(RAZR_1,HIGH); // Выключаем оба знакоместа
//  digitalWrite(RAZR_2,HIGH);
  PORTD |= 3<<4; // Устанавливаем в 1 разряды порта PD4-PD5, выключаем знакоместа
  for (i = 0; i <= 50; i++) {} // Пустой цикл для задержки выключения транзистора разряда
  PORTD |= 3<<6; // По идее, устанавливаем в 1 биты PD6-PD7 (сегменты A и B)
  PORTB |= 0x1F; // Устанавливаем в 1 разряды порта PB0-PB4 (сегменты C-G), это гасит сегменты
  for (i = 0; i <= 50; i++) {} // Пустой цикл для задержки
  i = out[pos] | 0xFC; // Выделяем из байта "видеопамяти" два младших бита, помещаем их во временную переменную
  PORTD &= i << 6; // Сдвигаем эти два бита на 6 позиций влево, перемещая их в позиции 6 и 7 и зажигаем сегменты (устанавливая 0)
  PORTB &= out[pos] >> 2; // Берем остальные биты (сегменты C-G) и сдвигаем их в позиции PB0-PB4
  if(pos == 0) digitalWrite(RAZR_1,LOW); else digitalWrite(RAZR_2,LOW); // Включаем разряд
  for (i = 0; i <= 50; i++) {}
//  Если pos достиг максимального значения - обнуляем его, иначе - инкрементируем
  (pos == MAX_SIZE-1) ? pos = 0 : pos++;
}
Alkul
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

Re: Динамическая индикация

Сообщение Alkul »

Простите, в Си-шном коде разбираться лень, но скажу про схему подключения.
Наконец-то я вижу нормальную схему подключения индикатора. Когда индикатор взят с ОА, когда в цепях катодов стоят резисторы, а на аноды питание подается не с портов МК напрямую, а как положено - с "+" питания через транзисторы.
Автор, Вы правильно учитесь - даже в учебном проекте нужно использовать правильную схемотехнику.

А когда я вижу вот такую схему, у меня глаз начинает дергаться.
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: Динамическая индикация

Сообщение COKPOWEHEU »

Зачем в симуляторе резисторы и транзисторы? Транзисторы и в реальной схеме не нужны, тока порта вполне хватает для маленьких индикаторов, а вот резисторами да, пренебрегать не стоит. Глупо ставить транзистор для усиления сигнала от допустимого для контроллера 40 мА до восьмикратного тока сегмента - 8-20 мА.
Dan Swano, вы на ардуинской библиотеке пишете или на обычном Си? Хорошо бы определиться с чем-то одним. Побитовое шаманство в прерывании непонятно, нельзя ли переписать попроще?
Аватара пользователя
Dan Swano
Открыл глаза
Сообщения: 42
Зарегистрирован: Пн июл 04, 2011 13:42:43
Откуда: Тула
Контактная информация:

Re: Динамическая индикация

Сообщение Dan Swano »

Схема в симуляторе приближена к реальной. Реальная состоит из ардуинообразной платы EduBoard и шилда к ней, еще из-за этого такое подключение индикатора к портам (часть ног к порту B, часть - к D).
COKPOWEHEU писал(а):Dan Swano, вы на ардуинской библиотеке пишете или на обычном Си? Хорошо бы определиться с чем-то одним. Побитовое шаманство в прерывании непонятно, нельзя ли переписать попроще?

Я склоняюсь к ардуинской библиотеке, просто в процессе изучения понял, что "побитовое шаманство" компактнее записать. Был немного другой вариант с использованием функций Ардуино:

Код: Выделить всё

SIGNAL (TIMER0_COMPA_vect) {
  static unsigned char pos = 0, i;
  digitalWrite(RAZR_1,HIGH); // Выключаем оба знакоместа
  digitalWrite(RAZR_2,HIGH);
  for (i = 0; i <= 50; i++) {} // Пустой цикл для задержки выключения транзистора разряда
  if(bitRead(out[pos],0)) digitalWrite(SEG_A,HIGH); else digitalWrite(SEG_A,LOW);
  if(bitRead(out[pos],1)) digitalWrite(SEG_B,HIGH); else digitalWrite(SEG_B,LOW);
  if(bitRead(out[pos],2)) digitalWrite(SEG_C,HIGH); else digitalWrite(SEG_C,LOW);
  if(bitRead(out[pos],3)) digitalWrite(SEG_D,HIGH); else digitalWrite(SEG_D,LOW);
  if(bitRead(out[pos],4)) digitalWrite(SEG_E,HIGH); else digitalWrite(SEG_E,LOW);
  if(bitRead(out[pos],5)) digitalWrite(SEG_F,HIGH); else digitalWrite(SEG_F,LOW);
  if(bitRead(out[pos],6)) digitalWrite(SEG_G,HIGH); else digitalWrite(SEG_G,LOW);
  if(pos == 0) digitalWrite(RAZR_1,LOW); else digitalWrite(RAZR_2,LOW); // Включаем разряд
// Пустой цикл для задержки включения транзистора разряда
  for (i = 0; i <= 50; i++) {}
  if(++pos == MAX_SIZE-1) pos = 0;
}

Такая функция занимает на 122 байта больше памяти.
Alkul
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

Re: Динамическая индикация

Сообщение Alkul »

COKPOWEHEU писал(а):Зачем в симуляторе резисторы и транзисторы?

Для того, чтобы программу правильно написать. Без транзистора при подаче питания от порта на ОА на этом порте надо лог.1 выставить, а при правильном подключении (через PNP - транзистор) для подачи питания на ОА на базу транзистора надо лог.0 подать.
А то "наэкономят" в симуляторе, а потом на реальной схеме код не подправят и начинается - "Помогите - в протеусе работает, в железе не хочет"
Схема в симуляторе должна быть полностью такой же, что и реальная схема. Во-всяком случае, надо четко понимать, где в симуляторе можно отступить от реальной схемы, а где - нет. В данном случае - нельзя, логика подачи питания на ОА получится инверсной. Я не понимаю, что, транзисторы в симуляторе платные, что-ли?

COKPOWEHEU писал(а):Транзисторы и в реальной схеме не нужны, тока порта вполне хватает для маленьких индикаторов

Да-да, конечно. Какие еще "маленькие" индикаторы? При любом кол-ве разрядов в каждый момент времени запитывается только один разряд.
Так ток одного сегмента - 20 мА. При зажигании цифры "8" суммарный ток - 160 мА! При допустимых 40 мА.
Допустим, используется двухразрядный индикатор и режим индикации со скважностью 2, т.е., когда паузы отсутствуют - зажигается один разряд, выдерживается, допустим, 2 мс, гасится и сразу же зажигается другой разряд. какой ток будет протекать через вывод порта, напрямую подающего питание на ОА? 160 мА со скважностью 2 (на каждом из двух выводов). Сомневаюсь, что порт долго "протянет". греться, во всяком случае, будет здорово.

Человек учится правильно. Он сразу использует грамотную схемотехнику. Я думал, только китайцы экономят в таких случаях на резисторах и транзисторах. Оказывается, и у нас есть индивидуумы.
Аватара пользователя
Dan Swano
Открыл глаза
Сообщения: 42
Зарегистрирован: Пн июл 04, 2011 13:42:43
Откуда: Тула
Контактная информация:

Re: Динамическая индикация

Сообщение Dan Swano »

Заметил, что во время выполнения в функции loop() переменная disp увеличивается, о чем выдаются сообщения на консоль. Содержимое массива out[] ("видеопамять", которая должна выдаваться на индикаторы) соответствует нужным семисегментным кодам, а выдается в оба разряда значение десятков (при значениях переменной disp на индикаторах пусто, при значениях от 10 до 19 на индикаторах 11, при disp = 20...29 - на индикаторах 22 ну и т.д.). В железе схему не собирал, сравнить не могу.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Динамическая индикация

Сообщение Аlex »

Код: Выделить всё

  PORTD |= 3<<4; // Устанавливаем в 1 разряды порта PD4-PD5, выключаем знакоместа
Их нужно включать по-очереди, а не оба сразу. На то она и дин. индикация.
У Вас каша в реализации индикации, разберитесь с ней.
Аватара пользователя
Dan Swano
Открыл глаза
Сообщения: 42
Зарегистрирован: Пн июл 04, 2011 13:42:43
Откуда: Тула
Контактная информация:

Re: Динамическая индикация

Сообщение Dan Swano »

Аlex писал(а):

Код: Выделить всё

  PORTD |= 3<<4; // Устанавливаем в 1 разряды порта PD4-PD5, выключаем знакоместа
Их нужно включать по-очереди, а не оба сразу.

Индикаторы включаются низким уровнем на портах, т.к. там p-n-p транзисторы. Эта команда, как мне кажется, устанавливает в "1" соответствующие разряды, закрывая транзисторы и отключая индикаторы.
А здесь

Код: Выделить всё

if(pos == 0) digitalWrite(RAZR_1,LOW); else digitalWrite(RAZR_2,LOW);

устанавливаем низкий уровень на PD4 при pos == 0 или на PD5 при pos <> 0, включая разряд. Если не прав - поправьте, могу ошибаться.
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: Динамическая индикация

Сообщение COKPOWEHEU »

Alkul писал(а):Во-всяком случае, надо четко понимать, где в симуляторе можно отступить от реальной схемы, а где - нет. В данном случае - нельзя, логика подачи питания на ОА получится инверсной. Я не понимаю, что, транзисторы в симуляторе платные, что-ли?
В данном случае нужно заменить транзисторы на логическое НЕ, либо выставлять в свойствах транзисторов и резисторов "цифровое". Да, за все лишние компоненты придется расплачиваться скоростью работы.
Alkul писал(а):Какие еще "маленькие" индикаторы? При любом кол-ве разрядов в каждый момент времени запитывается только один разряд.
Так ток одного сегмента - 20 мА. При зажигании цифры "8" суммарный ток - 160 мА! При допустимых 40 мА.
у меня вот под рукой индикаторы с размером сегмента около сантиметра, ему достаточно тока в несколько миллиампер, отсюда и суммарный ток 8-20 мА. А подавать 20 мА на один сегмент это какие должны быть индикаторы...
Alkul писал(а):Человек учится правильно. Он сразу использует грамотную схемотехнику. Я думал, только китайцы экономят в таких случаях на резисторах и транзисторах. Оказывается, и у нас есть индивидуумы.
На первом этапе обучения может и нормально, потом надо будет учиться моделировать только главное. Но, похоже, не все здесь это понимают. Протеус переживет подключение хоть 100 кА на выход контроллера, главное на реальной схеме рассчитать рабочий ток и поставить соответствующие резисторы. И не путать модель с реальным устройством.
"побитовое шаманство" компактнее записать. Был немного другой вариант с использованием функций Ардуино:
Наверное, его лучше и оставить. Ардуинская среда сама по себе не способствует оптимальному коду, так что пусть хоть писать и читать удобно будет.
if((NUM==0)&&(i!=(MAX_SIZE-1)))
break; // закончим цикл вывода числа
Возможно, стоит заполнить ведущие нули пробелами.Иначе там останется результат предыдущего преобразования.
// Пустой цикл для задержки включения транзистора разряда
for (i = 0; i <= 50; i++) {}
В конце прерывания этот цикл не нужен.
В самом отладчике протеусе смотрели, в out[0], out[1] нормальные значения?
Alkul
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

Re: Динамическая индикация

Сообщение Alkul »

COKPOWEHEU писал(а):А подавать 20 мА на один сегмент это какие должны быть индикаторы...

Да, к примеру, DA56-11EWA. Далеко не великИ индикаторы. Однако все параметры даны для тока 20мА

COKPOWEHEU писал(а):у меня вот под рукой индикаторы с размером сегмента около сантиметра

Да разве в размере дело? Вот, пожалуйста, SMD-светодиод. А ток - все равно 20 мА.

Автор, вот на ассемблере я б Вам показал пример индикации, как раз для Вашей схемы.
akl
Друг Кота
Сообщения: 4444
Зарегистрирован: Пт мар 07, 2008 06:54:43
Откуда: Ижевск

Re: Динамическая индикация

Сообщение akl »

Я бы ещё добавил резисторы 300 Ом в базы PNP транзисторов.
Alkul
Держит паяльник хвостом
Сообщения: 933
Зарегистрирован: Ср апр 13, 2011 11:09:20
Откуда: Екатеринбург

Re: Динамическая индикация

Сообщение Alkul »

akl писал(а):Я бы ещё добавил резисторы 300 Ом в базы PNP транзисторов.

Согласен, я этот момент как-то упустил. Но это, конечно, для реальной схемы важно.
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: Динамическая индикация

Сообщение COKPOWEHEU »

Вы уверены что всем и всегда нужна максимальная яркость? Цифры прекрасно видно и при единицах миллиампер, при большем токе может начать отвлекать, впрочем это уже зависит от применения.
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

Re: Динамическая индикация

Сообщение Аlex »

Dan Swano писал(а):
Аlex писал(а):

Код: Выделить всё

  PORTD |= 3<<4; // Устанавливаем в 1 разряды порта PD4-PD5, выключаем знакоместа
Их нужно включать по-очереди, а не оба сразу.

Индикаторы включаются низким уровнем на портах, т.к. там p-n-p транзисторы. Эта команда, как мне кажется, устанавливает в "1" соответствующие разряды, закрывая транзисторы и отключая индикаторы.
Извиняюсь, был невнимателен. Вместо "выключаем", прочитал "включаем" :oops:

Dan Swano писал(а):Я склоняюсь к ардуинской библиотеке, просто в процессе изучения понял, что "побитовое шаманство" компактнее записать. Был немного другой вариант с использованием функций Ардуино:

Код: Выделить всё

SIGNAL (TIMER0_COMPA_vect) {
  static unsigned char pos = 0, i;
  digitalWrite(RAZR_1,HIGH); // Выключаем оба знакоместа
  digitalWrite(RAZR_2,HIGH);
  for (i = 0; i <= 50; i++) {} // Пустой цикл для задержки выключения транзистора разряда
  if(bitRead(out[pos],0)) digitalWrite(SEG_A,HIGH); else digitalWrite(SEG_A,LOW);
  if(bitRead(out[pos],1)) digitalWrite(SEG_B,HIGH); else digitalWrite(SEG_B,LOW);
  if(bitRead(out[pos],2)) digitalWrite(SEG_C,HIGH); else digitalWrite(SEG_C,LOW);
  if(bitRead(out[pos],3)) digitalWrite(SEG_D,HIGH); else digitalWrite(SEG_D,LOW);
  if(bitRead(out[pos],4)) digitalWrite(SEG_E,HIGH); else digitalWrite(SEG_E,LOW);
  if(bitRead(out[pos],5)) digitalWrite(SEG_F,HIGH); else digitalWrite(SEG_F,LOW);
  if(bitRead(out[pos],6)) digitalWrite(SEG_G,HIGH); else digitalWrite(SEG_G,LOW);
  if(pos == 0) digitalWrite(RAZR_1,LOW); else digitalWrite(RAZR_2,LOW); // Включаем разряд
// Пустой цикл для задержки включения транзистора разряда
  for (i = 0; i <= 50; i++) {}
  if(++pos == MAX_SIZE-1) pos = 0;
}

Такая функция занимает на 122 байта больше памяти.
А этот вариант работал ? Если нет, то как он себя вёл ?
Криминала особо не видно. Если только ноги не перепутаны.
Morroc
Друг Кота
Сообщения: 19495
Зарегистрирован: Чт фев 20, 2014 18:57:55

Re: Динамическая индикация

Сообщение Morroc »

А эта штука

Код: Выделить всё

static unsigned char pos = 0, i;

случаем не сбрасывает при каждом входе в прерывание pos в 0 ? Я так понимаю задумано по другому. Может ее описать в начале кода с volatile лучше ?
"Вся военная пропаганда, все крики, ложь и ненависть исходят от людей, которые на эту войну не пойдут !" / Джордж Оруэлл /
"Война - это,когда за интересы других,гибнут совершенно безвинные люди." / Уинстон Черчилль /
Аватара пользователя
Dan Swano
Открыл глаза
Сообщения: 42
Зарегистрирован: Пн июл 04, 2011 13:42:43
Откуда: Тула
Контактная информация:

Re: Динамическая индикация

Сообщение Dan Swano »

COKPOWEHEU писал(а):В самом отладчике протеусе смотрели, в out[0], out[1] нормальные значения?

Я не знаю, как в отладчике смотреть значения переменных. Поэтому выводил элементы массива на последовательную консоль в функции loop(), значения элементов массива верные.
Аlex писал(а):А этот вариант работал ? Если нет, то как он себя вёл ?
Криминала особо не видно. Если только ноги не перепутаны.

Ноги не перепутаны, проверил. Такой вариант с digitalWrite() вел себя точно так же, выводя две одинаковые цифры.
Morroc писал(а):

Код: Выделить всё

static unsigned char pos = 0, i;

Может ее описать в начале кода с volatile лучше ?

Спасибо, вечерком попробую. Такой вариант был взят из примера на каком-то сайте, было написано, что переменная так специально объявлена, причину не помню...

Может, у меня с настройкой таймера что-то не так? Таймер0 занят в Ардуине для ее функций, поэтому его нельзя перепрограммировать или использовать прерывание по переполнению. Частота кварца там 16 МГц, делится на 64 до 250 кГц, а библиотечный обработчик прерывания по переполнению вызывается с частотой 976 Гц. Поэтому я использую прерывание по совпадению с OCR0A, как в этом случае посчитать частоту срабатывания прерывания и вычислить время горения индикатора?
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Динамическая индикация

Сообщение ARV »

Morroc писал(а):А эта штука

Код: Выделить всё

static unsigned char pos = 0, i;
случаем не сбрасывает при каждом входе в прерывание pos в 0 ?
эта штука не может сбрасываться в 0 при каждом входе в прерывание - она же static!
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: Динамическая индикация

Сообщение COKPOWEHEU »

Проверить у себя не могу, нет ардуинской среды и опыта работы с ней.
В протеусе есть компонент 7SEG-BCD, можно подключить два таких к одному порту, например, PORTB и вывеси туда значение переменной, например, вывести с интервалом пару секунд out[1], out[0].
Не увидел у вас настройку таймера, с какой частотой он работает? Само прерывание вызывается? Меняется ли переменная pos?
Выносить pos из прерывания не надо, лучше если у посторонних не будет доступа к локальным переменным. А вот переменную i лучше сделать просто локальной, не static.
Аватара пользователя
Dan Swano
Открыл глаза
Сообщения: 42
Зарегистрирован: Пн июл 04, 2011 13:42:43
Откуда: Тула
Контактная информация:

Re: Динамическая индикация

Сообщение Dan Swano »

COKPOWEHEU писал(а):Не увидел у вас настройку таймера, с какой частотой он работает? Само прерывание вызывается? Меняется ли переменная pos?

Извините за молчание, пришлось отъезжать на неделю.
Таймер настраивается вот так, но это я скопировал где-то, пока не очень понимаю его настройку.

Код: Выделить всё

  OCR0A = 0x0F;
  TIMSK0 |= _BV(OCIE0A);  // (устанавливает в "1" бит, другой вариант записи - TIMSK0 |= 1 << OCIE0A)

Прерывание вызывается, раз цифры на индикаторе меняются. А вот как посмотреть изменение переменной pos - не знаю... :(
Аватара пользователя
Dan Swano
Открыл глаза
Сообщения: 42
Зарегистрирован: Пн июл 04, 2011 13:42:43
Откуда: Тула
Контактная информация:

Re: Динамическая индикация

Сообщение Dan Swano »

Перенес обработку прерывания с таймера 0 на таймер 2. Похоже, что переменная pos не изменяется, я подключил к ардуине компонент 7SEG-BCD через порт С и в обработчике прерывания написал PORTC = pos, но на индикаторе постоянно ноль и не видно, что он пытается переключиться. Наверно, прерывание всё-таки не вызывается, как бы это проверить?
И еще, зачем нужен регистр TIFR? Может быть, при инициализации прерываний в него надо тоже что-то записать? Сейчас инициализация выглядит так:

Код: Выделить всё

  TCCR2A = 0;
  TCCR2B = 1<<CS22 | 0<<CS21 | 1<<CS20; // Устанавливаем биты, соответствующие коэффициенту деления 1024
  TIMSK2 = 1<<TOIE2;  // Или TIMSK2 |= (1<<TOIE2) Разрешаем прерывание по переполнению
  TCNT2 = 0;  // Начинаем считать с нуля
  interrupts();  // Разрешаем прерывания, аналог asm("sei)

Достаточно ли этого?
Ответить

Вернуться в «AVR»