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

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Закрыто
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 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 скачиваний
Реклама
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 21
Зарегистрирован: Ср янв 05, 2011 17:51:35
Откуда: Пенза

Сообщение shootnikS »

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

Сообщение shootnikS »

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

Сообщение 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!
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 21
Зарегистрирован: Ср янв 05, 2011 17:51:35
Откуда: Пенза

Сообщение shootnikS »

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

Сообщение 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!
Контактная информация:
Реклама
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 21
Зарегистрирован: Ср янв 05, 2011 17:51:35
Откуда: Пенза

Сообщение shootnikS »

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

Сообщение DX168B »

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

Сообщение 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.
Открыл глаза
Аватара пользователя
Сообщения: 69
Зарегистрирован: Пт июл 30, 2010 20:20:15
Откуда: Чернигов, УССР

Сообщение sw1972 »

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

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

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

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

Сообщение shootnikS »

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

Сообщение GP1 »

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

Сообщение ibiza11 »

зараза кушает весь порт
вот так: (компилятор IAR AVR)

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

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

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