Страница 1 из 1

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

Добавлено: Ср янв 05, 2011 18:20:48
shootnikS
Уважаемые нужна помощь)) Atmega8, WINAvr, Proteus 7.6 SP2
Нужно сделать с помощью 2-ух 4-х разрядных индикаторов, 2 дешифраторов и 3-х кнопок устройство ввода/вывода (на индикаторы) 8-ми разрядного числа. Т.е. при нажатии соответствующей кнопки меняется разряд/величина числа, записывается в массив, а из него все это хоз-во выводится на индикатор))
На пинах PD5, PD6, PD7 расположены кнопки, осуществляющие сдвиг разряда и увелечение/уменьшение числа на 1. 2 дешифратора - один на число, другой на позицию (УРА! динамическая индикация). Все записывается в массив step и выводится на порт C.
Проблема: с порта С ничего нет, подозревается таймер/счетчик.
Прилагается: проект в WinAvr и проект в Proteus (извините за корявость, все делалось за 5 минут)

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

Добавлено: Ср янв 05, 2011 22:27:43
shootnikS
Наверное я не правильно озвучил тему: проблема не с индикацией, а с записью данных в масиив цифр и вывод их на индикатор.
Вообщем хелп ми)

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

Добавлено: Чт янв 06, 2011 10:04:35
shootnikS
Выяснил, что за проблема :idea: программа не хочет заполнять массив, только не понятно почему

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

Добавлено: Пт янв 07, 2011 00:11:16
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);}
   }
}

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

Добавлено: Пт янв 07, 2011 10:17:12
shootnikS
:)) Пасибо большое)
Уху))) :))

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

Добавлено: Пт янв 07, 2011 12:59:06
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);}
   }
}

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

Добавлено: Пт янв 07, 2011 15:10:23
shootnikS
как раз хотел написать про кнопки, уже ответили))
а что означает 0x12??

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

Добавлено: Пт янв 07, 2011 16:48:56
DX168B
Это физический адрес порта D
Компилятор не понимает, что такое PORTD в ассемблерной вставке и по этому я написал его адрес.
Все адреса МК можно узнать в файле m8def.inc, который можно найти в папке avr assembler из AVR Studio.

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

Добавлено: Сб янв 08, 2011 09:58:53
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.

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

Добавлено: Сб янв 08, 2011 12:16:16
sw1972
Чтобы частично задействовать линии порта можно использовать следующую запись, например:

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

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

Удачи!

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

Добавлено: Сб янв 08, 2011 13:19:34
shootnikS
Совсем обижаете, это естественно, просто когда присваиваешь порту переменную (линии порта установлены на выход), она кушает весь порт, и начихать, что перед этим я 4 линии инициализировал как выход, а 4 оставшиеся как вход, 4 как вход просто переходят в состояние z (неопределенное)

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

Добавлено: Вт янв 11, 2011 08:54:28
GP1
shootnikS писал(а):...она кушает весь порт, и начихать, что перед этим я 4 линии инициализировал как выход, а 4 оставшиеся как вход...

Вот...
а если зайти на страничку ARV и почитать про динамическую индикацию, то там как раз есть описание виртуального порта, в котором можно не только отдельными линиями управлять, а даже линии разных портов использовать как единый порт, почитай очень полезная штуковина.

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

Добавлено: Вт янв 11, 2011 15:39:53
ibiza11
зараза кушает весь порт

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

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

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