Динамическая индикация на x51 - нужна помощь с программой

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Родился
Сообщения: 7
Зарегистрирован: Чт апр 16, 2009 17:01:59

Сообщение opv88 »

Добрый день! Пытаюсь сделать динамическую индикацию на x51, в протеусе все работает отлично, а вот при сборке реальной схемы - нет. Никак не могу понять в чем дело, уже раза 3 переписывал все с нуля. Вот простой пример (вывод "УРА" на индикаторе)
Основные элементы в схеме:
1. Четырехзнаковый 7-SEG индикатор (точка не в счет), выводим на три знака
2. at89c2051 (или at89c51)
В схеме порт P3 - знакоместо, P1 - значение для вывода на индикатор. Компилируется все SDCC.

Вот прога:

#include "at89x51.h"
typedef unsigned char byte; // задаем свой тип - байт
const int myTik=10000; // интервал времени таймера

#define mySegA 0x01 // сегменты индикатора
#define mySegB 0x02
#define mySegC 0x04
#define mySegD 0x08
#define mySegE 0x10
#define mySegF 0x20
#define mySegG 0x40
#define mySegH 0x80

__code byte myInd[15]= // массив индицируемых цифр и букв
{
mySegA|mySegB|mySegC|mySegD|mySegE|mySegF, //0
mySegB|mySegC, //1
mySegA|mySegB|mySegG|mySegE|mySegD, //2
mySegA|mySegB|mySegC|mySegD|mySegG, //3
mySegB|mySegC|mySegF|mySegG, //4
mySegA|mySegF|mySegG|mySegC|mySegD, //5
mySegC|mySegD|mySegE|mySegF|mySegA|mySegG, //6
mySegA|mySegB|mySegC, //7
mySegA|mySegB|mySegC|mySegD|mySegE|mySegF|mySegG, //8
mySegA|mySegB|mySegC|mySegD|mySegF|mySegG, //9
mySegA|mySegB|mySegC|mySegE|mySegF|mySegG, //A
mySegB|mySegC|mySegD|mySegF|mySegG, //У
mySegA|mySegB|mySegE|mySegF|mySegG, //Р
mySegA|mySegC|mySegD|mySegE|mySegF|mySegG, //Б
mySegA|mySegD|mySegE|mySegF|mySegG //Е
};

#define myClearMask 0xC7 // Маска для обнуления незначащих битов порта P3 (в данном случае C7h=11000111, т.е. исп. P3.3-P3.5)

__code byte myNumber[3]={11,12,10}; // Значения для индикации, подставляются в массив myInd, в данном случае результат - "УРА"

byte myCount10ms=0; // Счетчик интервалов времени
byte RazmerInd=6; // Граничное значение бита порта P3, в который осуществится вывод (смотрим процедуру IndZn)
byte CountZn=3; // Начальный бит порта P3,с которого начинается вывод
int i=0; // Переменная для организации цикла

void IndZn () // Процедура индикации 3 символов
{
P3=P3&myClearMask; // Обнуляем незначащие биты порта P3, в которые осуществляется вывод
P1=~myInd[myNumber[CountZn-3]]; // Выводим в P1 значение для индикации (инверсия, так как при подаче нуля - сегмент горит)
P3=P3|(1<<CountZn); // Устанавливаем бит, определяющий знакоместо
CountZn++; // Инкремент номера знакоместа
if (CountZn==RazmerInd) CountZn=3; // Установка начального значения знакоместа при переполнении
}

void IntOverT0 (void) __interrupt TF0_VECTOR // прерывание по таймеру 0
{
myCount10ms++; // Инкремент счетчика
IndZn(); // Индикация символа
}

void main(void)
{
TMOD = M0_0;
TL0=~myTik;
TH0=~(myTik>>8);
TR0=1;
ET0 = 1;
EA = 1;
while(1); // Бесконечный цикл
}
Реклама
Liv
Вымогатель припоя
Аватара пользователя
Сообщения: 525
Зарегистрирован: Сб сен 20, 2008 12:12:30
Откуда: Minsk

Сообщение Liv »

Вы забыли сделать перезагрузку таймера в прерывании.
И хотелось бы увидеть схему, в частности, как управляются общие выводы индикаторов.
Контактная информация:
Реклама
Родился
Сообщения: 7
Зарегистрирован: Чт апр 16, 2009 17:01:59

Сообщение opv88 »

Liv писал(а):Вы забыли сделать перезагрузку таймера в прерывании.
И хотелось бы увидеть схему, в частности, как управляются общие выводы индикаторов.
Большое спасибо за ответ :) А "перезагрузка таймера в прерывании" это что такое? То есть нужно останавливать таймер и снова запускать?

Вот схема в протеусе: Изображение
В жизни схема почти такая же. Могу даже сказать, что конкрентно не работало: иной раз вроде происходило следущее: загоралось УРА, затем быстро все 8,затем снова УРА, затем опять быстро снова все 8...

P.S. С управлением выводами индикаторов, думаю, все в порядке, так как, просто подавая питание, была проверена работа сегментов и т.д...

Правильно я понял, что нужно в процедуру прерывания по таймеру вот это:
"
TR0=0;
TL0=~myTik;
TH0=~(myTik>>8);
TR0=1;
"
написать? Так?
Liv
Вымогатель припоя
Аватара пользователя
Сообщения: 525
Зарегистрирован: Сб сен 20, 2008 12:12:30
Откуда: Minsk

Сообщение Liv »

opv88 писал(а):Вот схема
В этой схеме два плохих момента.

1. У 2051 порты неспособны обеспечивать большой выходной ток при 1 на выходе. ПОэтому общие аноды индикаторов нужно подключать через транзисторные ключи. Самый простой вариант - использовать эмиттерные повторители, тогда не надо ни инверсии сигналов, ни резисторов.

2. В цепях сегментов A,B,C,D,E,F,G,H обязательно нужны ограничительные резисторы.
opv88 писал(а):Могу даже сказать, что конкрентно не работало: иной раз вроде происходило следущее: загоралось УРА, затем быстро все 8,затем снова УРА, затем опять быстро снова все 8...
На первый взгляд в программе нет ничего криминального. Это вся программа?
opv88 писал(а):Правильно я понял, что нужно в процедуру прерывания по таймеру вот это:
"
TR0=0;
TL0=~myTik;
TH0=~(myTik>>8);
TR0=1;
"
написать? Так?
Да. Иначе только первый интервал будет равен myTik. Все остальные будут на все 65536 тактов таймера.
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Родился
Сообщения: 7
Зарегистрирован: Чт апр 16, 2009 17:01:59

Сообщение opv88 »

Liv Спасибо большое )). Значит дело в перезагрузке таймера... Программа приведена вся...

Насчет резисторов и эмиттерных повторителей: сам не очень то разбираюсь (чайник в микрокнтроллерах :) ), но, понятно, что выходной ток у 2051 мал... Однако, дело в том, что эта схема работать-то должна 100%, это я знаю. И к тому же, ведь при нехватке тока, не горели бы сегменты отдельно или горели бы слабо, если я правильно понимаю, а тут дело в том, что горит не то, что должно ). Вот...

P.S. В понедельник-вторник проверю работу схемы... На выходных негде собрать ) Протеусу теперь не верю.
Реклама
Liv
Вымогатель припоя
Аватара пользователя
Сообщения: 525
Зарегистрирован: Сб сен 20, 2008 12:12:30
Откуда: Minsk

Сообщение Liv »

Вряд ли причина в перезагрузке таймера. Это могло всего лишь привести к пониженной частоте сканирования индикаторов. Нужно искать ошибку дальше.

В Вашей схеме ток будет ограничиваться портом микроконтроллера, кторый управляет анодами. Поэтому яркость индикаторов будет зависеть от количества одновременно включенных сегментов в каждом знакоместе. А это недопустимо.
Контактная информация:
Реклама
Родился
Сообщения: 7
Зарегистрирован: Чт апр 16, 2009 17:01:59

Сообщение opv88 »

Liv писал(а):Вряд ли причина в перезагрузке таймера. Это могло всего лишь привести к пониженной частоте сканирования индикаторов. Нужно искать ошибку дальше.

В Вашей схеме ток будет ограничиваться портом микроконтроллера, кторый управляет анодами. Поэтому яркость индикаторов будет зависеть от количества одновременно включенных сегментов в каждом знакоместе. А это недопустимо.
Ну тогда уже при сборке схемы посмотрим... А частота и вправду пониженная была ))

Там при реальной сборке у индикатора еще питание 7В, при изменении которого яркость сегментов менялась... К сожалению, не знаю конкретной модели индикатора...
Друг Кота
Аватара пользователя
Сообщения: 15763
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

и на кой ... надо связываться с растровым сканированием матрицы - яркость всегда низкая будет (3*7=24такта или 4*7=28тактов за одно "окошко" при частоте регенерации 50 Гц)
лучше уж не насиловать контроллер, а поставить 4 позиционных ключа, а в качестве сегментных использовать или uln2803 (общий анод) или чего-то типа кр1533ир22 (общий катод)
Liv
Вымогатель припоя
Аватара пользователя
Сообщения: 525
Зарегистрирован: Сб сен 20, 2008 12:12:30
Откуда: Minsk

Сообщение Liv »

А что такое "растровое сканирование матрицы"?
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 15763
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

матрица светодиодная 7-сегментная 4-х разрдная...
а растровое сканирование или растровая развертка изображения - один из видов развертки
где в каждый момент времени выводится информация только об одном элементе (в данном случае один сегмент)
можно или последовательно обходить сегменты в каждой позиции (знакоместе) или выводить по одному сегменту с последовательным переключением позиций ("построчно")
при этом частенько злоупотребляют заложенным в МК свойством ограничения тока кз на уроне ~25mA (особенно если увидят в datasheetе "Direct LED Drive Outputs"), да и яркость естественно будет ниже, чем в режиме "побайтового" вывода :cry:
Liv
Вымогатель припоя
Аватара пользователя
Сообщения: 525
Зарегистрирован: Сб сен 20, 2008 12:12:30
Откуда: Minsk

Сообщение Liv »

Так в представленном выше исходнике сканирование по разрядам, а не по отдельным сегментам.
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 15763
Зарегистрирован: Вт мар 16, 2010 22:02:27
Откуда: ДОНЕЦК

Сообщение BOB51 »

дык исходник надобно под схемку писать :cry:
а схемка как раз для посегментной классики (или слишком "мерцать" будет, да и у МК век недолгий... :))) )
на Сиии я не работаю, а с ассемблером можно бы и программу сочинить... независимо для кого mcs51/avr или младшие picи :dont_know:
Родился
Сообщения: 7
Зарегистрирован: Чт апр 16, 2009 17:01:59

Сообщение opv88 »

Итак, собрал сегодня схемку снова, добавив перезагрузку таймера... Ничего не мерцает, но вот незадача: сначала показывает УУУ, потом РРР, потом ААА,... Что же за ерунда-то такая? Получается на всех битах P3, где осуществляется выбор знакоместа единица? Как же так, ведь в программе я их обнуляю?
Liv
Вымогатель припоя
Аватара пользователя
Сообщения: 525
Зарегистрирован: Сб сен 20, 2008 12:12:30
Откуда: Minsk

Сообщение Liv »

Схемку реальную покажите.
Контактная информация:
Сверлит текстолит когтями
Аватара пользователя
Сообщения: 1132
Зарегистрирован: Пт фев 16, 2007 14:18:20
Откуда: Новосибирск

Сообщение Chip115 »

да,схему в студию...и еще замечание...
Если вы хотите написать код то:
0х01 есть такая кнопочка "code"
0х02 придерживайтесь иного стиля написания кода... делайте отступы и скобки функций располагайте одна над другой.
Пример:

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

 
for(i=0,k=0;i<MaxServo;i++,k++)
{
	if(Servo_sorted[i]->Position!=Servo_sorted[i+1]->Position)	//Если значения уникальные
	{
	     ServoNextOCR[k] = Servo_sorted[i]->Position;			// Записываем их как есть
	     ServoPortState[k+1] = Servo_sorted[i]->Bit;			// И битмаску туда же
	}
	else								// Но если совпадает со следующим
	{
	    ServoNextOCR[k] = Servo_sorted[i]->Position;			// Позицию записываем
	    ServoPortState[k+1] = Servo_sorted[i]->Bit;			// Записываем битмаску
 
	    for (j=1;(Servo_sorted[i]->Position == Servo_sorted[i+j]->Position)&&(i+j<MaxServo);j++)
		{
		      ServoPortState[k+1] |= Servo_sorted[i+j]->Bit;
		}
	   i+=j-1;						// Перед выходом корректируем индекс
	}						// На глубину зарывания в повторы
}	

Ну вот ооочень облегчают "разбор полетов" .. тем более в чужом коде
Теория — это когда все известно, но ничего не работает. Практика — это когда все работает, но никто не знает почему. Мы же объединяем теорию и практику: ничего не работает… и никто не знает почему!
© Альберт Эйнштейн
Контактная информация:
Родился
Сообщения: 7
Зарегистрирован: Чт апр 16, 2009 17:01:59

Сообщение opv88 »

Всем большое спасибо за участие! Все прекрасно заработало. Дело, действительно, было в том, что знакоместо управлялось инверсным сигналом.
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»