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

Основы программирования на мк, а в частности дин. индикация

Добавлено: Вт июн 05, 2012 23:39:58
The Rock
Прошу помощи, я программирую на С++ для Atmega88

Я написал программу в которой на индикаторе выставляется время задержки с точностью до 0.05 сек (это вообще возможно сделать на атмеге без внешнего кварца)? точность нужна +\-0.02 сек

Впринципе я её написал, она исправно работает. Но есть но, во время всех задержек у меня индикатор горит на том символе на котором окончилась его динамическая индикация и выжидает окончание задержки. Одновременная работа задержки и индикатора для меня абсолютно ново (раньше программировал в основном на php). Подскажите, как обойти данную проблему, чтобы и задержка отсчитывалась и индикатор отображал нужную информацию, а не зависал.

Вот код (вырезаны инициализации портов, если надо вставить то могу исправить)

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

/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.8 Professional
Automatic Program Generator
© Copyright 1998-2007 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project : 
Version : 
Date    : 29.05.2012
Author  : F4CG                            
Company : F4CG                            
Comments: 


Chip type           : ATmega88
Program type        : Application
Clock frequency     : 4,000000 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 256
*****************************************************/

#include <mega88.h>
#include <delay.h>

// Declare your global variables here

int i;        
int inz; // переменная включения микроконтроллера
int array[10] = {0b00111111,0b00000110,0b01011011,0b01100110,0b01101101,0b01111101,0b00000111,0b01111111,0b01101111,0b11111111}; // таблица с цифрами
int kd[4] = {0,0,0,0};  
int t; // переменная сервсиная                                 

// Вывод цифр на индикатор, x - число, у - точка
void led(unsigned char x,unsigned char y)
{
        switch (x)
        {
                case 0: {PORTB=0b00111111; break; }
                case 1: {PORTB=0b00000110; break;}
                case 2: {PORTB=0b01011011; break; }
                case 3: {PORTB=0b01001111; break; }
                case 4: {PORTB=0b01100110; break;  }
                case 5: {PORTB=0b01101101; break; }
                case 6: {PORTB=0b01111101; break; }
                case 7: {PORTB=0b00000111; break; }
                case 8: {PORTB=0b01111111; break; }
                case 9: {PORTB=0b01101111; break; }
        }                                          
        if (y == 0) 
        {
                PORTB.7 = 0;
        }
        else
        {
                PORTB.7 = 1;
        }
        if ( x == 10) { PORTB = 0; }
}

// функция иницилизации индикатора
void ini(void)
{
        for(i = 0; i <= 9; i++)
        {
                if (i <= 4) {led(i,0);}
                else { led(i,1);}
                delay_ms(200); 
        }
        led(10,0);
}

void main(void)
{

inz = 0;

while (1)                    
      {     
      // инициализация индикатор
      if (inz == 0) { ini(); inz = 1; i = 0; }
                     
        while(1)
        {       
                for(i=0;i<4;i++)
                {   
                // динамическое подключение нужного общего провода
                        switch (i)
                        {
                                case 0: {PORTC.0 = 0; PORTC.1 = 1; PORTC.2 = 1; PORTC.3 = 1; break; }
                                case 1: {PORTC.0 = 1; PORTC.1 = 0; PORTC.2 = 1; PORTC.3 = 1; break; }
                                case 2: {PORTC.0 = 1; PORTC.1 = 1; PORTC.2 = 0; PORTC.3 = 1; break; }
                                case 3: {PORTC.0 = 1; PORTC.1 = 1; PORTC.2 = 1; PORTC.3 = 0; break; }
                        }           
                                
                        PORTB = array [kd[i]];
                        // Проверка нажатия кнопки сотых   
                        if (PIND.0 == 0 || PIND.1 == 0 || PIND.2 == 0)
                        {
                                if (PIND.0 == 0 )
                                {
                                        kd[3] = kd[3] + 4;   
                                        if (kd[3] > 4)
                                        {
                                                kd[2] = kd[2]+1;
                                                kd[3] = 0;
                                                if(kd[2] > 8) 
                                                {
                                                        kd[2] = 0;
                                                }
                                        }
                                }
                                if (PIND.1 == 0)   // проверка нажатия целых 
                                {
                                        kd[1]++; 
                                        if(kd[1] > 8) 
                                        {
                                                kd[1] = 0;
                                        }      
                                }                                              
                                if (PIND.2 == 0)
                                {
                                        PORTC.4 = 1;
                                        PORTC.5 = 1;
                                        delay_ms(kd[1]*1000+kd[2]*10+kd[3]);
                                        PORTC.4 = 0;
                                        PORTC.5 = 0;
                                }
                                while(PIND.0 == 0 || PIND.1 == 0 || PIND.2 == 0) {};       // Если отпустили кнопку выходим из цикла
                        }                       
                        
                        delay_ms(4);            
                }
        }
}
}

Re: Основы программирования на мк, а в частности дин. индика

Добавлено: Ср июн 06, 2012 06:48:49
igor-x
вариантов разных можно предложить.. я например использую вывод на индикаторы по прерыванию таймера.
программируеш таймер на 25*N герц (N- число разрядов). как мне показалось 25 герц достаточно для того чтобы глаз не видел мелькания, а точности здесь как раз и не надо - кварц это лишнее, если нужна только индикация

Re: Основы программирования на мк, а в частности дин. индика

Добавлено: Ср июн 06, 2012 07:33:03
hybroid
The Rock писал(а):я программирую на С++ для Atmega88
Кто вам это сказал? Я не вижу плюсов.
The Rock писал(а):(раньше программировал в основном на php)
Хоть и сам веб-программист, но это что за говнокод?

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

        switch (x)
        {
                case 0: {PORTB=0b00111111; break; }
                case 1: {PORTB=0b00000110; break;}
                case 2: {PORTB=0b01011011; break; }
                case 3: {PORTB=0b01001111; break; }
                case 4: {PORTB=0b01100110; break;  }
                case 5: {PORTB=0b01101101; break; }
                case 6: {PORTB=0b01111101; break; }
                case 7: {PORTB=0b00000111; break; }
                case 8: {PORTB=0b01111111; break; }
                case 9: {PORTB=0b01101111; break; }
        }                                         
Массив цифр выше же объявлен, почему не сделать по-человечески?

ЗЫ: Дальше читать нету сил, не думаю что сильно лучше..

Re: Основы программирования на мк, а в частности дин. индика

Добавлено: Ср июн 06, 2012 08:24:03
The Rock
2 hybroid, этот говнокод остался от самой моей первой "программы", просто пока функция ini работает на нем решил не трогать.

2 igor-x спасибо за совет! А можно пример кода как прерывание устанавливаются на С, а то в учебниках помойму либо слишком сложно, либо ASM

Re: Основы программирования на мк, а в частности дин. индика

Добавлено: Ср июн 06, 2012 08:37:03
igor-x
там надо не учебники по С читать а даташит от Меги + help на компилятор который вы используете

Re: Основы программирования на мк, а в частности дин. индика

Добавлено: Ср июн 06, 2012 16:03:01
Барсик
У Вас же 88 мега! Там есть целых ТРИ таймера. Используйте один как системные часы и забейте на функцию delay. Прерывания от него же - для динамической индикации.
The Rock писал(а):А можно пример кода как прерывание устанавливаются на С
Вы же используете Визард из CodeVisionAVR. Вот и поставьте соответствующие галки в нужном таймере, и получите пример кода. Используйте режим таймера CTC top=OSRxA и Compare Match A Interrupt. Если, например, использовать таймер2 и кварц на 4 МГц, то легко получить прерывание каждую миллисекунду.

И читайте даташит до полного понимания, как работают таймеры и прочая начинка микроконтроллера.

Re: Основы программирования на мк, а в частности дин. индика

Добавлено: Чт июн 07, 2012 13:00:13
The Rock
2 Барсик, а Вы не знаете, есть ли даташиты на русском языке ?

Re: Основы программирования на мк, а в частности дин. индика

Добавлено: Чт июн 07, 2012 13:10:45
hybroid
Микроконтроллеры AVR семейства Mega А.В.Евстифеев, 2007

Re: Основы программирования на мк, а в частности дин. индика

Добавлено: Чт июн 07, 2012 13:13:26
The Rock
hybroid писал(а):Микроконтроллеры AVR семейства Mega А.В.Евстифеев, 2007
Спасибо!

Re: Основы программирования на мк, а в частности дин. индика

Добавлено: Чт июн 07, 2012 13:18:21
ploop
как мне показалось 25 герц достаточно для того чтобы глаз не видел мелькания
Даже за сотню герц видно боковым зрением.

Re: Основы программирования на мк, а в частности дин. индика

Добавлено: Чт июн 07, 2012 13:22:24
igor-x
для начала опытов с дин индикацией можно вообще с 2 герц начать (забавно смотреть на прыгающие цыфры)- а потом уже подобрать удобную для глаза

Re: Основы программирования на мк, а в частности дин. индика

Добавлено: Чт июн 07, 2012 13:32:38
ploop
Я так первую свою и отлаживал.