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

Все прочитали, вроде даже поняли, взяли паяльник - а нифига не получается? Скорее сюда! Поможем. Чем можем...
Ответить
Открыл глаза
Сообщения: 46
Зарегистрирован: Вт июн 05, 2012 23:32:13

Сообщение 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);            
                }
        }
}
}
Реклама
Мудрый кот
Аватара пользователя
Сообщения: 1817
Зарегистрирован: Пн ноя 29, 2010 15:58:43

Сообщение igor-x »

вариантов разных можно предложить.. я например использую вывод на индикаторы по прерыванию таймера.
программируеш таймер на 25*N герц (N- число разрядов). как мне показалось 25 герц достаточно для того чтобы глаз не видел мелькания, а точности здесь как раз и не надо - кварц это лишнее, если нужна только индикация
Реклама
Друг Кота
Аватара пользователя
Сообщения: 8007
Зарегистрирован: Вс ноя 14, 2010 19:24:26
Откуда: Лукалэнд

Сообщение 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; }
        }                                         
Массив цифр выше же объявлен, почему не сделать по-человечески?

ЗЫ: Дальше читать нету сил, не думаю что сильно лучше..
Открыл глаза
Сообщения: 46
Зарегистрирован: Вт июн 05, 2012 23:32:13

Сообщение The Rock »

2 hybroid, этот говнокод остался от самой моей первой "программы", просто пока функция ini работает на нем решил не трогать.

2 igor-x спасибо за совет! А можно пример кода как прерывание устанавливаются на С, а то в учебниках помойму либо слишком сложно, либо ASM
Реклама
Эиком - электронные компоненты и радиодетали
Мудрый кот
Аватара пользователя
Сообщения: 1817
Зарегистрирован: Пн ноя 29, 2010 15:58:43

Сообщение igor-x »

там надо не учебники по С читать а даташит от Меги + help на компилятор который вы используете
Последний раз редактировалось igor-x Чт июн 07, 2012 06:09:48, всего редактировалось 1 раз.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 3459
Зарегистрирован: Ср сен 27, 2006 16:18:57

Сообщение Барсик »

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

И читайте даташит до полного понимания, как работают таймеры и прочая начинка микроконтроллера.
Реклама
Открыл глаза
Сообщения: 46
Зарегистрирован: Вт июн 05, 2012 23:32:13

Сообщение The Rock »

2 Барсик, а Вы не знаете, есть ли даташиты на русском языке ?
Друг Кота
Аватара пользователя
Сообщения: 8007
Зарегистрирован: Вс ноя 14, 2010 19:24:26
Откуда: Лукалэнд

Сообщение hybroid »

Микроконтроллеры AVR семейства Mega А.В.Евстифеев, 2007
Открыл глаза
Сообщения: 46
Зарегистрирован: Вт июн 05, 2012 23:32:13

Сообщение The Rock »

hybroid писал(а):Микроконтроллеры AVR семейства Mega А.В.Евстифеев, 2007
Спасибо!
Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

как мне показалось 25 герц достаточно для того чтобы глаз не видел мелькания
Даже за сотню герц видно боковым зрением.
Мудрый кот
Аватара пользователя
Сообщения: 1817
Зарегистрирован: Пн ноя 29, 2010 15:58:43

Сообщение igor-x »

для начала опытов с дин индикацией можно вообще с 2 герц начать (забавно смотреть на прыгающие цыфры)- а потом уже подобрать удобную для глаза
Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

Я так первую свою и отлаживал.
Ответить

Вернуться в «Практика»