Форум myROBOT.ru » Шаг за шагом » Программирование микроконтроллеров » Таймер, динамическая индикация

Страниц (1): [1]
 

1. 3bugatti - 27 Апреля, 2012 - 18:18:57 - перейти к сообщению
Добрый день!

Недавно решил разобраться с МК. С языком СИ вообще не знаком. Первые программки пошли на ура) помигать светодиодом, кнопка и т.п. Взялся за более сложное. Хочу вывести на матрицу 7х8 с общим анодом, при помощи tiny2313 хотябы букву, в последствии бегущую строку. Суть проблемы в следующем, нашел кучу статей по динамической индикации. Самая полная и разжеванная показалась мне эта: http://arv.radioliga.com/content/view/172/49/
Сделал. Зашиваю на МК никаких результатов... а код компилируется без ошибок.. что не так? помогите чайнику... высший восторг

Вот исходник, что пытаюсь впихнуть)

CODE:

#include <avr/io.h>
#include <avr/iotn2313.h>
//#include <avr/delay.h>

#define F_CPU 8000000UL // 8МГц

#define SCR_SZ 7 /* число знакомест дисплея */
#define ROWS PORTB /* порт «строк» дисплея, т.е. управления сегментами */
#define COLS PORTD /* порт управления «столбцами», т.е. общими катодами */
#define SKIP 15 /* число пропускаемых прерываний таймера */

unsigned char SCR[SCR_SZ]={0x80, 0x77, 0x77, 0x77, 0x80}; /*Массив вывода символа (A)*/

ISR (TIMER0_OVF_vect)
{
static unsigned char pos = 0;
static unsigned char skip = SKIP;
if (--skip) return;
skip = SKIP;
COLS = 0x00;
ROWS = SCR[pos];
COLS |= (1 << pos);
if(++pos == SCR_SZ) pos = 0;
}


int main(void)
{
DDRB=0xff; //инициализация как выводы
DDRD=0xff; //инициализация как выводы

TIMSK=0x10;
TCCR0B=0x01;
TCNT0=0x00;
TIFR = 0x10;

while(1)
{

}
}
2. mihail - 27 Апреля, 2012 - 22:30:55 - перейти к сообщению
3bugatti пишет:
что не так?
Как минимум, прерывания запрещены глобально, а должны быть разрешены.
CODE:
// Global enable interrupts
sei();
3. 3bugatti - 28 Апреля, 2012 - 10:07:44 - перейти к сообщению
CODE:

int main(void)
{
DDRB=0xff; //инициализация как выводы
DDRD=0xff; //инициализация как выводы

TIMSK=0x10;
TCCR0B=0x01;
TCNT0=0x00;
TIFR = 0x10;

sei();



правильно понимаю?
А есть еще какие нибудь проверенные алгоритмы индикации?
4. mihail - 28 Апреля, 2012 - 17:43:56 - перейти к сообщению
3bugatti пишет:
правильно понимаю?
Да.
5. Роботов - 28 Апреля, 2012 - 18:31:06 - перейти к сообщению
Кстати, проверте. У вас похоже у таймера 0 прерывание не включено.
Если мне не изменеяет склероз, включается оно так: TIMSK=0x01;
(Добавление)
Или я путаю с мегой 8?
6. 3bugatti - 28 Апреля, 2012 - 19:58:43 - перейти к сообщению
Пробовал менять на TIMSK |=(1<<TOIE0) без разницы. А так это взято из DataShet. Все скомпилировалось, прошил - и ничего(

Кто нибудь подскажет проверенные способы индикации, чем сами пользуетесь?

CODE:


#include <avr/io.h>
#include <avr/iotn2313.h>
//#include <avr/delay.h>
#include <avr/interrupt.h>

#define F_CPU 8000000UL // 8МГц

#define SCR_SZ 7 // число знакомест дисплея
#define ROWS PORTB // порт «строк» дисплея, т.е. управления сегментами
#define COLS PORTD // порт управления «столбцами», т.е. общими катодами
#define SKIP 15 // число пропускаемых прерываний таймера

unsigned char SCR[SCR_SZ]={0x80, 0x77, 0x77, 0x77, 0x80}; // Массив вывода символа (A)

int main(void)
{
DDRB=0xff; //инициализация как выводы
DDRD=0xff; //инициализация как выводы

TIMSK=0x10; // внешние прерывания разрешены
TCCR0B=0x01; //включить таймер
TCNT0=0x00; // с чего начинать считать
TIFR = 0x10; //

sei(); // глобальные прерывания

while(1)
{

}
}

ISR (TIMER0_OVF_vect)
{
static unsigned char pos = 0; // первое число массива
static unsigned char skip = SKIP; // число пропусканий таймера
if (--skip) return; // пропускаем, пока условие истина и уменьшаем на 1
skip = SKIP;
COLS = 0x00; // выключаем все столбны
ROWS = SCR[pos]; // выводим строку
COLS |= (1 << pos); // зажигаем столбец
if(++pos == SCR_SZ) pos = 0; // переходим к следующей строке массива
}
7. Роботов - 28 Апреля, 2012 - 21:15:25 - перейти к сообщению
В качестве индикации использую светодиод подключеный к свободному порту. Вставляю функцию включения светодиода в то место программы, которое хочу проконтролировать, если светодиод зажегся, значит все нормально, незажегся - программа не дошла до этого места по какой то причине.
8. mihail - 28 Апреля, 2012 - 22:45:31 - перейти к сообщению
+1 за светодиодик

/*******************************************
Program : LED matrix 8x7
Compiler : AVR GCC
Chip type : ATtiny2313
System Clock : 8 MHz
*******************************************/

#include <avr/io.h>
#include <avr/interrupt.h>

#define F_CPU 8000000UL // 8МГц

#define SCR_SZ 7 // число знакомест дисплея
#define ROWS PORTB // порт "строк" дисплея, т.е. управления сегментами
#define COLS PORTD // порт управления "столбцами", т.е. общими катодами

// Массив вывода символа (A)
const unsigned char SCR[] = {0b10000000,
0b01110111,
0b01110111,
0b01110111,
0b10000000};

unsigned char pos = 0; // первое число массива

void Ports_Init( void )
{
// Port A initialization
DDRA = 0b00000000;
PORTA = 0b00000000;

// Port B initialization
DDRB = 0b11111111;
PORTB = 0b00000000;

// Port D initialization
DDRD = 0b11111111;
PORTD = 0b00000000;
}

void Timer0_Init( void )
{
TCCR0A = 0b00000000;
TCCR0B = 0b00000100; // clk_I/O / 256
TCNT0 = 0b00000000;
TIMSK = 0b00000010; // Разрешено прерывание по переполнению
}

int main(void)
{
// Input/Output Ports initialization
Ports_Init();

// Timer/Counter 0 initialization
Timer0_Init();

// Global enable interrupts
sei();

while(1)
{

}

return 0;
}

ISR (TIMER0_OVF_vect)
{
COLS = 0b00000000; // выключаем все столбны
ROWS = SCR[pos]; // выводим строку
COLS = (1 << pos); // зажигаем столбец
pos += 1;
if(pos == SCR_SZ) pos = 0;
}
9. 3bugatti - 02 Мая, 2012 - 09:46:15 - перейти к сообщению
Роботов Со светодиодом - сильно! Обязательно приму на заметку! Спасибо)

mihail Спасибо за код, попробую) Кстати RETURN 0; - что эта строка делает? Понимаю, что возвращает "0" но куда и по какой причине, для чего не пойму(

Подскажите еще? Допустим из-за неправильно выставленных FUSE может не работать таймер?
10. cjA - 02 Мая, 2012 - 10:06:00 - перейти к сообщению
легко может не работать.
функция main() я тут уже с кем то спорил- обычная фунция и должна завершаться оператором return. В MAKEFILE Вы можете настроить вход в программу где угодно, даже сделать ее не програмой а эльфом или демоном.
Просто так принято в Си, даже если речь об маленьких МК. Улыбка
(Добавление)
Если этот код работает в ОС и произойдет ошибка ОС получит не 0 как код возврата, а другое число.
11. mihail - 02 Мая, 2012 - 19:36:16 - перейти к сообщению
3bugatti
В программе для МК завершение функции main() конструкцией return 0; исключительно для соответствия стандарту С (читай для красоты Улыбка ).
3bugatti пишет:
из-за неправильно выставленных FUSE может не работать таймер?
Врядли. Обычно, после изменения fuse bits МК либо работает, либо нет. Еще, изменением fuse bits можно отключить возможность внутрисхемного программирования. Тогда нельзя будет прошить МК посредством ISP. Но, зашитая ранее программа будет работать.
12. Роботов - 03 Мая, 2012 - 18:21:14 - перейти к сообщению
mihail пишет:
В программе для МК завершение функции main() конструкцией return 0; исключительно для соответствия стандарту С (читай для красоты ).

Во-во, именно для красоты. Особенно когда перед ней бесконечный цикл стоит Голливудская улыбка
13. 3bugatti - 04 Мая, 2012 - 12:36:25 - перейти к сообщению
Спасибо огромное! кто откликнулся))) все получилось! заработала конструкция mihail-а с инициализацией таймера как отдельная функция (если правильно все называю)

CODE:

#include <avr/io.h>
//#include <avr/iotn2313.h>
//#include <avr/delay.h> // для работы задержек
#include <avr/interrupt.h> // для глобального прерывания

#define F_CPU 8000000UL // 8МГц

#define SCR_SZ 7 // число знакомест дисплея
#define ROWS PORTB // порт «строк» дисплея, т.е. управления сегментами
#define COLS PORTD // порт управления «столбцами», т.е. общими катодами
#define SKIP 10 // число пропускаемых прерываний таймера

unsigned char SCR[SCR_SZ]={0x41, 0x3e, 0x3e, 0x3e, 0x41}; // Массив вывода символа (0)

void Ports_Init( void )

{
// Port B initialization
DDRB = 0b11111111;
PORTB = 0b00000000;

// Port D initialization
DDRD = 0b11111111;
PORTD = 0b00000000;
}



void Timer0_Init( void )
{
TCCR0A = 0x00;
TCCR0B = 0x01; // clk_I/O / без деления частоты процессора
TCNT0 = 0x00;
TIMSK = 0x02; // Разрешено прерывание по переполнению
}


int main(void)
{
// Input/Output Ports initialization
Ports_Init();

// Timer/Counter 0 initialization
Timer0_Init();

// Global enable interrupts
sei();

while(1)
{

}
return 0;
}

ISR (TIMER0_OVF_vect)
{
static unsigned char pos = 0; // первое число массива
static unsigned char skip = SKIP; // число пропусканий таймера
if (--skip) return; // пропускаем, пока условие истина и уменьшаем на 1
skip = SKIP;
COLS = 0x00; // выключаем все столбны
ROWS = SCR[pos]; // выводим строку
COLS |= (1 << pos); // зажигаем столбец
if(++pos == SCR_SZ) pos = 0; // переходим к следующей строке массива
}


P.S. С фьюзами разобрался) нашел разжеванное тут http://www.getchip.net/posts/068...-fyuzy-fuse-bit/ может кому поможет)
14. 3bugatti - 30 Мая, 2012 - 13:16:11 - перейти к сообщению
Добрый день!

Подскажите, двумя таймерами одновременно можно пользоваться? Допустим, один на отображении символов, а второй как счетчик ?

У меня AVRStudio в debug только один таймер работает, пока принудительно стрелочку не переставишь... При компиляции ошибок нет!