реклама на сайте
подробности

 
 
> Опять двадцать пять, динамическая индикация
Василий_Безкатег...
сообщение Jun 19 2007, 12:34
Сообщение #1


Участник
*

Группа: Свой
Сообщений: 58
Регистрация: 15-09-06
Из: г. Смолевичи (Минская область)
Пользователь №: 20 403



Прошу не пинать сильно. Искал сабж по форуму, читал, но чегой-то недопонял. Есть Atmega16, компилятор IAR. К МК подключены 2 семисегментных индикатора (какие -то старенькие советские индикаторы). Схема подключения такая- на сегменты идёт сигнал с порта С (PC0-PC7)через резисторы 82 Ом, общие провода индикаторов подсоединены подсоединены к порту D (PD0 и PD2). Чтобы горели сразу два индикатора с неизменяющимся двухзначным числом написал такую программу.
---------------------------------------------------------------------------------------------------------


#include <ioavr.h>
#include <iom16.h>
#include <intrinsics.h>
int main( void )
{
int digit[10];

DDRC=0xFF; //настраиваем порт С на вывод
digit[0]=0x3F;
digit[1]=0x06;
digit[2]=0x5B;
digit[3]=0x4F; // цифры от 0 до 9
digit[4]=0x66;
digit[5]=0x6D;
digit[6]=0x7D;
digit[7]=0x07;
digit[8]=0x7F;
digit[9]=0x6F;
while(1) // бесконечный цикл
{
DDRD=0x04; // подаём единицу на PD2 -инициализируем один индикатор
PORTC =digit[1]; // подаём код цифры
__delay_cycles(2500); // задержка
DDRD=0x01; // подаём единицу на PD0-инициализируем второй индикатор
PORTC =digit[0]; // подаём код другой цифры
__delay_cycles(2500); // задержка
}
}
---------------------------------------------------------------------------------------------
А вот чтобы допустим 2 индикатора динамически отображали счёт до 99, например, не получается ;-(
Программа такая:
-------------------------------------------------------------------------
#include <ioavr.h>
#include <iom16.h>
#include <intrinsics.h>
int main( void )
{
int i;
int j;
int digit[10];
DDRC=0xFF;

digit[0]=0x3F;
digit[1]=0x06;
digit[2]=0x5B;
digit[3]=0x4F;
digit[4]=0x66;
digit[5]=0x6D;
digit[6]=0x7D;
digit[7]=0x07;
digit[8]=0x7F;
digit[9]=0x6F;
while(1)
{
for (j=0;j<10;j=j+1)
for (i=0;i<10;i=i+1)
{DDRD=0x04;
PORTC =digit[j];
__delay_cycles(90000);

DDRD=0x01;
PORTC =digit[i];
__delay_cycles(5000000);
}
}
}
=================================================
Пните пожалуйста, что и как писать чтобы считала до 99 в бесконечном цикле и при этом 2 индикатора горели постоянно. На Си это первые опыты для микроконтроллеров, с начала начал осваивать ассемблер.
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
rezident
сообщение Jun 19 2007, 13:21
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



У вас не совсем верный алгоритм. Счет числа от 0 до 99 и управление дин. индикацией в общем случае это асинхронные процессы. Точнее даже тут три асинхронных процесса:
- счет,
- вывод на индикацию,
- динамическая индикация.
Синхронизируются асинхронные процессы обычно с помощью буферов.
Считать вы можете с любой требуемой вам скоростью.
Выводить число на индикацию чаще 3 раз в секунду не имеет смысла, т.к. во-первых у человеческого глаза инерционность порядка 0,1с. Во-вторых, мозг человека информацию меняющуюся чаще 3 раз в сек просто не успевает адекватно обрабатывать.
А вот динамическую индикацию нужно обрабатывать не реже 25-30 раз в секунду, чтобы за счет инерционности зрения не видеть мерцания индикаторов.
Так что вам нужно реализовать как минимум два конечных автомата.
Один из них будет переключать символы (катоды в вашем случае) индикатора (через порт D) и выводить из своего собственного буфера значение для соответствующего индикатора в порт C. Эту процедуру рекомендую вызывать из регулярного прерывания, например, от правильным образом настроенного таймера.
Второй КА это просто функция, которая подготавливает данные для отображения на 7-сегментном индикаторе. Проще всего реализовать перевод символов/чисел в значение для индикатора на основе таблицы.
Вместо использования функции __delay_cycles() рекомендую в использовать функцию __delay_ms(), если такая есть. Хотя я лично предпочитаю использовать некое подобие RTC в виде простого счетчика миллисекунд. В том же прерывании от таймера, в котором "крутится" динамическая индикация, я инкрементирую 16-ти или 32-х разрядную переменную. Причем инкремент не на 1, а на число соответствующее периоду таймера в мс. Допустим у меня таймер работает с частотой перезагрузки 100 раз в сек. Следовательно я инкрементирую каждый раз счетчик мс на 10. Чтобы в основном цикле организовать задержку для вывода на индикацию в 0,3 сек достаточно вызвать delay_ms(300). Сама функция delay_ms совершенно простая. Типа такой.
Код
extern volatile unsigned int TimeCntrMS;
void delay_ms(unsigned int value)
{ unsigned int tmp=TimeCntrMS; //запомним текущее значение счетчика мс
while((TimeCntrMS-tmp)<value); //ждем пока счетчик мс не превысит свое запомненное состояние (tmp) плюс значение задержки (value)
}
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 26th July 2025 - 11:43
Рейтинг@Mail.ru


Страница сгенерированна за 0.01382 секунд с 7
ELECTRONIX ©2004-2016