Проблема с динамической индикацией

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Аватара пользователя
shootnikS
Первый раз сказал Мяу!
Сообщения: 21
Зарегистрирован: Ср янв 05, 2011 17:51:35
Откуда: Пенза

Проблема с динамической индикацией

Сообщение shootnikS »

Уважаемые нужна помощь)) Atmega8, WINAvr, Proteus 7.6 SP2
Нужно сделать с помощью 2-ух 4-х разрядных индикаторов, 2 дешифраторов и 3-х кнопок устройство ввода/вывода (на индикаторы) 8-ми разрядного числа. Т.е. при нажатии соответствующей кнопки меняется разряд/величина числа, записывается в массив, а из него все это хоз-во выводится на индикатор))
На пинах PD5, PD6, PD7 расположены кнопки, осуществляющие сдвиг разряда и увелечение/уменьшение числа на 1. 2 дешифратора - один на число, другой на позицию (УРА! динамическая индикация). Все записывается в массив step и выводится на порт C.
Проблема: с порта С ничего нет, подозревается таймер/счетчик.
Прилагается: проект в WinAvr и проект в Proteus (извините за корявость, все делалось за 5 минут)
Вложения
приложение.rar
В Proteus укажите путь к hex коду программы.
(50.05 КБ) 180 скачиваний
Аватара пользователя
shootnikS
Первый раз сказал Мяу!
Сообщения: 21
Зарегистрирован: Ср янв 05, 2011 17:51:35
Откуда: Пенза

Re: Проблема с динамической индикацией

Сообщение shootnikS »

Наверное я не правильно озвучил тему: проблема не с индикацией, а с записью данных в масиив цифр и вывод их на индикатор.
Вообщем хелп ми)
Аватара пользователя
shootnikS
Первый раз сказал Мяу!
Сообщения: 21
Зарегистрирован: Ср янв 05, 2011 17:51:35
Откуда: Пенза

Re: Проблема с динамической индикацией

Сообщение shootnikS »

Выяснил, что за проблема :idea: программа не хочет заполнять массив, только не понятно почему
Аватара пользователя
DX168B
Друг Кота
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)
Контактная информация:

Re: Проблема с динамической индикацией

Сообщение DX168B »

Нет. Прерывание по таймеру не работает.
Исправь свою ошибку в строке TIMSK=(0<<TOIE0); на TIMSK=(1<<TOIE0); :)
Да и поменяй местами вывод на индикацию и опрос кнопок. Лучше выводить данные на индикатор по прерыванию таймера, а кнопки опрашивать в основной функции(main).
Вот тебе красивый пример вывода значений на индикатор в прерывании таймера:

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

volatile unsigned int step[8];
unsigned int j=0;   
ISR(TIMER0_OVF_vect)
{
   PORTB = j;
   PORTC = step[j];
   j++;
   if (j==8){j=0;}
   TCNT0=0x00;
}

Вот всё работает. Разбирайся. :)

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

#define F_CPU 3686400UL 
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
//***************************************************************************
volatile unsigned int step[8];
unsigned int j=0;
//***************************************************************************
//Вывод на индикатор по прерыванию таймера (каждый разряд по очереди)
ISR(TIMER0_OVF_vect)
{
   PORTB = j;
   PORTC = step[j];
   j++;
   if (j==8){j=0;}
   TCNT0=0x00;
}
//***************************************************************************
int main(void)             
{
   unsigned int i=0;
   TIMSK=(1<<TOIE0);
   TCCR0=(1<<CS00)|(0<<CS01)|(0<<CS02);
   PORTD=0xE0;
   DDRD=0x1B;
   PORTB=0x18;
   DDRB=0x07;
   PORTC=0x70;
   DDRC=0x0F;
   sei();
//----------
//Тут опрос кнопок по while
   while(1)
   {
      if(!(PIND & (1<<PIND5))){i++; if(i>7) {i=0;}}
      _delay_ms(20);
      if(!(PIND & (0<<PIND5))){_delay_ms(20);}
      
      if(!(PIND & (1<<PIND6))){step[i]++;if(step[i]>9){step[i]=0;}}
      _delay_ms(20);
      if(!(PIND & (0<<PIND6))){_delay_ms(20);}
      
      if(!(PIND & (1<<PIND7))){if(step[i]==0){step[i]=9;}else{ step[i]--;}}
      _delay_ms(20);
      if(!(PIND & (0<<PIND7))){_delay_ms(20);}
   }
}
I am DX168B and this is my favourite forum on internet!
Аватара пользователя
shootnikS
Первый раз сказал Мяу!
Сообщения: 21
Зарегистрирован: Ср янв 05, 2011 17:51:35
Откуда: Пенза

Re: Проблема с динамической индикацией

Сообщение shootnikS »

:)) Пасибо большое)
Уху))) :))
Аватара пользователя
DX168B
Друг Кота
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)
Контактная информация:

Re: Проблема с динамической индикацией

Сообщение DX168B »

Но!! У этой программы есть два минуса:
1 - Обработка кнопок. Надо реализовать так, чтобы цифра менялась только тогда, когда кнопку отпускают. Или хотя бы задержки чуть по длиннее (1000мс)
2 - Засветка индикатора. Для её устранения необходимо сначала погасить индикатор, поменять значения и только потом зажечь. Вот пример переработанной программы.
Тут необходимо соединить вывод МК PD0 c выводом RBI (№5) дешифратора 7448.

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

#define F_CPU 3686400UL 
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
//***************************************************************************
volatile unsigned int step[8];
unsigned int j=0;
//***************************************************************************
ISR(TIMER0_OVF_vect)
{
   asm("сbi 0x12, 0"); //Гасим весь индикатор.
   PORTB = j;
   PORTC = step[j];
   j++;
   if (j==8){j=0;}
   TCNT0=0x00;
   asm("sbi 0x12, 0"); //После всех переключений зажжём его.
}
//***************************************************************************
int main(void)             
{
   unsigned int i=0;
   TIMSK=(1<<TOIE0);
   TCCR0=(0<<CS00)|(1<<CS01)|(0<<CS02);
   PORTB=0x00;
   DDRB=(1<<PB0)|(1<<PB1)|(1<<PB2);
   PORTC=0x00;
   DDRC=(1<<PC0)|(1<<PC1)|(1<<PC2)|(1<<PC3);
   PORTD=(1<<PD0)|(1<<PD5)|(1<<PD6)|(1<<PD7);
   DDRD=(1<<PD0)|(1<<PD1)|(1<<PD2)|(1<<PD3)|(1<<PD4);
   sei();
//----------
   while(1)
   {
      if(!(PIND & (1<<PIND5))){i++; if(i>7) {i=0;}}
      _delay_ms(20);
      if(!(PIND & (0<<PIND5))){_delay_ms(20);}
      
      if(!(PIND & (1<<PIND6))){step[i]++;if(step[i]>9){step[i]=0;}}
      _delay_ms(20);
      if(!(PIND & (0<<PIND6))){_delay_ms(20);}
      
      if(!(PIND & (1<<PIND7))){if(step[i]==0){step[i]=9;}else{step[i]--;}}
      _delay_ms(20);
      if(!(PIND & (0<<PIND7))){_delay_ms(20);}
   }
}
I am DX168B and this is my favourite forum on internet!
Аватара пользователя
shootnikS
Первый раз сказал Мяу!
Сообщения: 21
Зарегистрирован: Ср янв 05, 2011 17:51:35
Откуда: Пенза

Re: Проблема с динамической индикацией

Сообщение shootnikS »

как раз хотел написать про кнопки, уже ответили))
а что означает 0x12??
Аватара пользователя
DX168B
Друг Кота
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)
Контактная информация:

Re: Проблема с динамической индикацией

Сообщение DX168B »

Это физический адрес порта D
Компилятор не понимает, что такое PORTD в ассемблерной вставке и по этому я написал его адрес.
Все адреса МК можно узнать в файле m8def.inc, который можно найти в папке avr assembler из AVR Studio.
I am DX168B and this is my favourite forum on internet!
Аватара пользователя
shootnikS
Первый раз сказал Мяу!
Сообщения: 21
Зарегистрирован: Ср янв 05, 2011 17:51:35
Откуда: Пенза

Re: Проблема с динамической индикацией

Сообщение shootnikS »

И еще вопрос:
Вот так PORTC=step[j], зараза кушает весь порт, хотя реально нужно всего 4 линии порта (отображение числа в 2-ом коде), подскажите как записать это в 4 линии, чтобы остальные были свободны,пробывал писать не чистым присваиванием, а с помощью |=, не получилось((.
Так же не могли бы вы подсказать, вот так можно запомнить первые 4 разряда числа и использовать дальше, например передать в какую-нибудь функцию число:
while(1){
//опросили кнопки ролучили заполненный массив
abc=step[0]*1000+step[1]*100+step[2]*10+step[3];
}

void temp(unsigned int temp);
{
//выполняем функцию
}
P.S.:В последних версиях библиотеки avr-libc, входящей в состав компилятора AVR-GCC, использующегося в WinAVR, больше не поддерживаются функции inp, outp, sbi и cbi.
Аватара пользователя
sw1972
Открыл глаза
Сообщения: 69
Зарегистрирован: Пт июл 30, 2010 20:20:15
Откуда: Чернигов, УССР

Re: Проблема с динамической индикацией

Сообщение sw1972 »

Чтобы частично задействовать линии порта можно использовать следующую запись, например:

линии PD0 и PD0 порта PORTD нужно установить в состояние "1": PORTD |= _BV(PD1)|_BV(PD0);

линии PD0 и PD0 порта PORTD нужно установить в состояние "0": PORTD &= ~(_BV(PD1)|_BV(PD0));

Удачи!
Хорошее - враг лучшего
Аватара пользователя
shootnikS
Первый раз сказал Мяу!
Сообщения: 21
Зарегистрирован: Ср янв 05, 2011 17:51:35
Откуда: Пенза

Re: Проблема с динамической индикацией

Сообщение shootnikS »

Совсем обижаете, это естественно, просто когда присваиваешь порту переменную (линии порта установлены на выход), она кушает весь порт, и начихать, что перед этим я 4 линии инициализировал как выход, а 4 оставшиеся как вход, 4 как вход просто переходят в состояние z (неопределенное)
Аватара пользователя
GP1
Поставщик валерьянки для Кота
Сообщения: 2401
Зарегистрирован: Пт май 23, 2008 19:32:22
Откуда: Россия, Волгоград
Контактная информация:

Re: Проблема с динамической индикацией

Сообщение GP1 »

shootnikS писал(а):...она кушает весь порт, и начихать, что перед этим я 4 линии инициализировал как выход, а 4 оставшиеся как вход...

Вот...
а если зайти на страничку ARV и почитать про динамическую индикацию, то там как раз есть описание виртуального порта, в котором можно не только отдельными линиями управлять, а даже линии разных портов использовать как единый порт, почитай очень полезная штуковина.
Чем дальше, тем больше становлюсь занудой...
Изображение
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Re: Проблема с динамической индикацией

Сообщение ibiza11 »

зараза кушает весь порт

вот так: (компилятор IAR AVR)

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

  unsigned char Prev,data;
  Prev = PORTB;
  Prev &= ~(0x0F); // это в случае, когда необходимо оставить неизменными старшие 4 бита порта
                   // очищаем биты которые нужно изменить, которые нужно оставить не трогаем
  Prev |= ( data&(0x0F) );  //очищаем ненужные 4 старших бита
  PORTB = Prev;
Ставим плюсы: )
Закрыто

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