Обсуждаем контроллеры компании Atmel.
Ответить

Динамическая индикация

Пт янв 31, 2020 19:07:28

Приветствую всех!
Подскажите, где в этом коде можно поменять частоту динамической индикации и сделать ее немного выше, а то заметно мерцание цифр очень.
Спасибо.



Код:
 /*****************************************************
CodeVisionAVR V2.05.0 Professional

Project : Clock and Termometr
Version : 3.0.2 (часы + несколько датчиков)
Date    : 02.02.2008 (начало проекта)
Author  : Pervakov Danil

Comments: версия поностью переработана с использованием исправленной библиотеки ds18b20.lib
          которая теперь возвращает число типа int вместо числа типа float
          + переработана ds1307.lib часть функций возвращает числа в двоичн.дес. системе.
          В библиотеки ds18b20.lib и ds1307.lib для стабильности добавлены запрет и разр.прерыв.

Chip type           : ATtiny2313
Clock frequency     : 4,000000 MHz
Memory model        : Tiny
External SRAM size  : 0
Data Stack size     : 32
*****************************************************/
//
// Fuse CKSEL = 0010, SUT = 10 (Int.RC 4 MHz)
//
// EEPROM usage: 0 byte(s), 0,0% of EEPROM
// Program size: 966 words (1932 bytes), 94,3% of FLASH
//
// РеалТайм часы DS1307 - (PORTA bit 0 - SCL, bit 1 - SDA)
//
// Датчик DS18B20 - (PORTD bit 2)
//
// Кнопки -  (PORTD bit 0, 1 - кнопоки через резисторы 1,5 кОм на землю)
//
// Черырехразрядный семисегментник (Общ.кат.)
//           аноды - (PORTB)"
//           катоды - (PORTD) digit1 - bit 3, digit2 - bit 4, digit3 - bit 5, digit4 - bit 6
//

// сердце - не Пентиум и не Атлон и частота не в ГГц, но если вспомнить IBM PC XT с его Intel 8088
#include <tiny2313.h>

// 1 Wire Bus functions (PORTD bit 2)
#asm
   .equ __w1_port=0x12
   .equ __w1_bit=2
#endasm

// I2C Bus functions (PORTA bit 0, 1)
#asm
   .equ __i2c_port=0x1b
   .equ __sda_bit=1
   .equ __scl_bit=0
#endasm

// DS18b20 Temperature Sensor functions
#include "ds18x20_v3.h" 

// DS1307 Real Time Clock functions
#include "ds1307_.h"

#include <delay.h>
#include <bcd.h>

// flash unsigned char digits[], flash unsigned char cursor[]
// перенесены сюда
#include "term.h"       
 

// Timer 1 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void) {
        PORTD&=0b10000111;    // потушить все (биты всех знакомест "0" - для Общ.анод+тр.ключи)
       
        PORTB=digits[digit_out[cur_dig]]; // символ на экран
        PORTD|=(cursor[cur_dig]);  // засветить нужный бит (бит знакоместа в "1" - для ОА + тр.ключи)
       
        if ((zpt_ON == 1) && (cur_dig == 1)) PORTB.3=1;  // запятая во втором разряде (нумерация нач. с нуля)

        cur_dig++; if (cur_dig>3) cur_dig=0;
}



// ----------
void time_view(void) {
   unsigned char tmp;

   rtc_get_time(&myhour, &mymin, &mysec);
       
   tmp = myhour >> 4;
          
   if (tmp) digit_out[0] = tmp;
   else     digit_out[0] = PROBEL;         
       
   digit_out[1] = myhour & 0x0F;
       
   digit_out[2] = mymin >> 4;
   digit_out[3] = mymin & 0x0F;
} //----------


// ---------- чтение состояния кнопок ----------
//
// подключены через 1,5 кОм ко 2 и 3 ножке тини2313 (или к bit_0 и bit_1 порта D) и на землю
//
void read_key(void) {
   unsigned char tmp;

   if (PIND.0 == 0){
      tmp=bcd2bin(myhour);
      tmp++; if (tmp > 23) tmp=0;
      myhour=bin2bcd(tmp);
      rtc_set_time(myhour, mymin, mysec);  //  часы +1
   }

   if (PIND.1 == 0){
      tmp=bcd2bin(mymin);
      tmp++; if (tmp > 59) tmp=0;
      mymin=bin2bcd(tmp);
      rtc_set_time(myhour, mymin, 0x00);  // минуты +1
   }
} // ----------




// ----------
void hex_to_dec(void) {
        unsigned char celie, drob, tmp;
        unsigned int temp, celie_tmp, drob_tmp;
 
        temp = (unsigned int) temperature;                     
       
        if (temperature>=0) {
                digit_out[0]=PROBEL;       // первый символ (сотни) пустой
        }
        else {       
                temp = ( ~temp ) + 0x0001; // если число отрицательное перевести его в норм.вид
                digit_out[0]=MINUS;        // и высветить знак минус (в дальнейшем атрибут отр.темп.)
             };
        digit_out[3]=GRADUS; zpt_ON=1;

        celie_tmp = temp >> 4;     // целая часть числа
        drob_tmp  = temp & 0x000F; // дробная часть числа с точностью 1/16 градуса
               
        celie = (unsigned char) celie_tmp;  // я люблю явное преведение типов
        drob  = (unsigned char) ((drob_tmp * 10) / 16); // преобразование дробной части в формате "1/16 градуса" в десятичный формат с точностью 0,1 градуса
       
        //if (celie >= 100) { tmp=bin2bcd(celie-100); digit_out[0] = 1;} else tmp=bin2bcd(celie); // версия для мега8
        tmp=bin2bcd(celie); // версия для тини2313
             
        if ((celie >= 100) || ((digit_out[0] == MINUS) && (celie >= 10))) { //  если больше 100,0 гр. или если темп. меньше -10 точность 1 гр.
                zpt_ON=0;
                digit_out[1] = tmp >> 4;    // десятки
                digit_out[2] = tmp & 0x0F;  // единицы
        }
       
        if ((digit_out[0] == MINUS) && (celie < 10)) { // если темп.меньше 0 и больше -10 точность 0,1 гр.
                digit_out[1]=celie; // единицы
                digit_out[2]=drob;  // дробная часть
        }
       
        if ((digit_out[0] == PROBEL) && (celie < 100)) { // если темп. меньше 100,0 гр и больше 0 гр точность 0,1 гр.
                if (tmp >> 4) digit_out[0] = tmp >> 4; // десятки - если десятков нет то и не показывать
                digit_out[1] = tmp & 0x0F;             // единицы
                digit_out[2]=drob;                     // дробная часть
        }
}  // ----------


void main(void) { //============= main ====================
unsigned char i, devices;
int t_tmp;

// Порт А на ввод + подтягивающие резисторы не включать
//DDRA=0x00;
//PORTA=0x00;

// Порт B на вывод (все биты в 0)
DDRB=0xFF;
//PORTB=0x00;

// Порт D (биты 6,5,4,3 на вывод, биты 2,1,0 на ввод, подтягивающие резисторы не включать (бит 2), включить (биты 1,0) )
// потушить все (биты всех знакомест "0" - для ОА, биты 6,5,4,3)
DDRD=0x78;   // 01111000
PORTD=0x83;  // 10000011

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
//TCCR0A=0x00;
//TCCR0B=0x00;
//TCNT0=0x00;
//OCR0A=0x00;
//OCR0B=0x00;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 62,500 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
//TCCR0A=0x00;
TCCR0B=0x03;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
//GIMSK=0x00;
//MCUCR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x02;

// Universal Serial Interface initialization
// Mode: Disabled
// Clock source: Register & Counter=no clk.
// USI Counter Overflow Interrupt: Off
//USICR=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;

 // 1 Wire Bus initialization
 w1_init();
 
 devices=w1_search(0xf0,rom_code);
 
 // i2c Bus initialization
 i2c_init();
 
 // бит 7 (CH) регистра секунд DS1307 останавливает или запускает генератор
 // (0 - запущен, 1 - остановлен)
 rtc_get_time(&myhour, &mymin, &mysec);
 mysec &= 0b01111111;                    // принудительная установка 7-го бита в "0"
 rtc_set_time(myhour, mymin, mysec);


 // на 1,5 секунды высветить на индикаторе Fnd 'кол-во найденых устройств'
 digit_out[0]=13;    // F
 digit_out[1]=14;    // n
 digit_out[2]=15;    // d.
 digit_out[3]=devices; // 'devices'

 // Global enable interrupts
 #asm("sei")                     


 if (devices >= 1) {  // если обнаружено больше одного датчика
    for (i=0;i<devices;i++) {
        t_tmp=ds18x20_temperature(&rom_code[i][0]); // первое чтение впустую
        delay_ms(500);
    }
}

   
 // ---------- рабочая часть ----------
 while (1) {
        for (i=0;i<20;i++){ // 10 сек. показывать время (20 * 0.5 сек.)
                time_view();
                if (zpt_ON == 0) zpt_ON=1; else zpt_ON=0;
                read_key();
                delay_ms(500);
        }
               
        if ((devices >= 1) && ((PIND & 0x03) == 0x03) ) {  // если обнаружено больше одного датчика и нет нажатий на кнопки
                for (i=0;i<devices;) {
                        temperature=ds18x20_temperature(&rom_code[i++][0]);
                        if (temperature!=-9999) hex_to_dec();
                        delay_ms(2000);
                }
        }
 } // ---------- рабочая часть (end) ----------

} // ========= end main ==============





//
// -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= The End -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
//
                                                                             

Re: Динамическая индикация

Пт янв 31, 2020 19:14:42

А фьюзы точно выставлены? В частности делитель на 8 отключен? Я делал подобные часы, ничего там не мерцает.

Re: Динамическая индикация

Пт янв 31, 2020 19:17:17

TCCR0B=0x03
заменить на
TCCR0B=0x02

Добавлено after 1 minute 9 seconds:
Martin! А я то думаю, где я это видел?

Re: Динамическая индикация

Пт янв 31, 2020 19:32:13

Martin76 , угу точно.

Добавлено after 1 minute 56 seconds:
оно не то чтобы мерцает, но когда боком смотришь хочется частоту повыше.

Добавлено after 1 minute 10 seconds:
Я чтото не могу найти статью на эти часы :(

Добавлено after 2 minutes 4 seconds:
вот фьюзы

Добавлено after 7 minutes 45 seconds:
dr.doc, огромное спасибо, индикация стоит как вкопанная!!!



У меня контролер 4313 и там еще места полно, вот бы еще что туда вставить :))
Вложения
0-02-0a-bd0777f5bd7ddfa5ca7a41d80847d86e602ed8df01b46962fc03a7e931766b56_5dd9f314.jpg
(175.88 KiB) Скачиваний: 199
0-02-0a-5eb6b8c999ac4d99371b262a553dc2348193c0ee5862620efd17c889559c0fa2_199edffe.jpg
(156.3 KiB) Скачиваний: 195
Безымянный.jpg
(173.8 KiB) Скачиваний: 195

Re: Динамическая индикация

Сб дек 23, 2023 20:53:42

Коллеги, а где поменять в коде чтобы на всех выходах были управляющие единицы.

Тоесть допустим индикатор с общим анодом, но на катоды тоже единицы посылались из контролера. Я просто использую (для огромных индикаторов) ULN2803 для сегментов, а UDN2981 для общего, а все эти драйверы управляются логической единицей. Просто у меня платы уже давно на JLCb заказанные лежат , а тут наткнулся на них - собрал, а на табло чушь :( Надеюсь понятно изложил. Не пинайте :)

Re: Динамическая индикация

Сб дек 23, 2023 22:44:33

Smith2011 писал(а):чтобы на всех выходах были управляющие единицы
там в заголовочном файле это настраивается, насколько я помню. Выкладывайте сюда архив с исходниками, гляну.
Если не ошибаюсь, на таком принципе можно сделать :)
Код:
#define A   1
#define B   2
#define C   4
#define D   8 
#define E  32
#define F  64
#define G 128
#ifdef CA // общий анод
    static flash unsigned char digits[] = {
    ~(A+B+C+D+E+F),   // 0
    ~(B+C),           // 1
    ~(A+B+D+E+G),     // 2
    ~(A+B+C+D+G),     // 3
    ~(B+C+F+G),       // 4
    ~(A+C+D+F+G),     // 5
    ~(A+C+D+E+F+G),   // 6
    ~(A+B+C),         // 7
    ~(A+B+C+D+E+F+G), // 8
    ~(A+B+C+D+F+G),   // 9
    ~(A+B+C+E+F),     // П - 10 помещение
    ~(B+C+D+F+G),     // У - 11 улица
    ~(A+D+E+F),       // C - 12
    ~(B+C+D+E+G),     // d - 13
    ~(A+D+E+F+G),     // E - 14
    ~(A+E+F+G),       // F - 15
    ~(G),             // 16 - знак минус
    ~(A+B+F+G),       // 17 - символ градус цельсия
    ~(0),             // 18 - пусто
    ~(C+E+G),         // n
    ~(D+E+F+G)        // t
    };
#else
    static flash unsigned char digits[] = {
    (A+B+C+D+E+F),   // 0
    (B+C),           // 1
    (A+B+D+E+G),     // 2
    (A+B+C+D+G),     // 3
    (B+C+F+G),       // 4
    (A+C+D+F+G),     // 5
    (A+C+D+E+F+G),   // 6
    (A+B+C),         // 7
    (A+B+C+D+E+F+G), // 8
    (A+B+C+D+F+G),   // 9
    (A+B+C+E+F+G),   // A - 10
    (C+D+E+F+G),     // b - 11
    (A+D+E+F),       // C - 12
    (B+C+D+E+G),     // d - 13
    (A+D+E+F+G),     // E - 14
    (A+E+F+G),       // F - 15
    (G),             // 16 - знак минус
    (A+B+F+G),       // 17 - символ градус цельсия
    (0),             // 18 - пусто
    (C+E+G),         // n
    (D+E+F+G)        // t
    };
#endif

Re: Динамическая индикация

Сб дек 23, 2023 23:24:49

можно просто инвертировать там, где значение присваивается портам

Re: Динамическая индикация

Вс дек 24, 2023 09:09:36

Вот исходник. Еще бы найти автора. :)

Если можно ткните новом где исправлять, бывает нужно. :oops:

Спасибо
Вложения
Clock-Term_tiny2313_DS1307_DS18B20_4LED_ULN_2dAT4ika.zip
(31.3 KiB) Скачиваний: 34

Re: Динамическая индикация

Вс дек 24, 2023 09:51:32

вот так сделайте (файл term.h)

Код:
static flash unsigned char digits[] = {
   ~(A+B+C+D+E+F),   // 0
   ~(B+C),           // 1
   ~(A+B+D+E+G),     // 2
   ~(A+B+C+D+G),     // 3
   ~(B+C+F+G),       // 4
   ~(A+C+D+F+G),     // 5
   ~(A+C+D+E+F+G),   // 6
   ~(A+B+C),         // 7
   ~(A+B+C+D+E+F+G), // 8
   ~(A+B+C+D+F+G),   // 9
   ~(G),             // 10 - знак минус
   ~(A+B+F+G),       // 11 - символ градус цельсия
   ~(0),             // 12 - пусто
   ~(A+E+F+G),       // 13 - F
   ~(C+E+G),         // 14 - n
   ~(B+C+D+E+G+H),   // 15 - d.
   ~(A+D+E+F+G),     // 16 - E
   ~(E+G),           // 17 - r
   ~(E+G+H)          // 18 - r.
};

Re: Динамическая индикация

Вс дек 24, 2023 09:59:44

не автора искать надо, а изучать программирование.

Код:
interrupt [TIM0_OVF] void timer0_ovf_isr(void) {
        PORTD&=0b10000111;    // потушить все (биты всех знакомест "0" - для Общ.анод+тр.ключи)
       
        PORTB=digits[digit_out[cur_dig]]; // символ на экран
        PORTD|=(cursor[cur_dig]);  // засветить нужный бит (бит знакоместа в "1" - для ОА + тр.ключи)
       
        if ((zpt_ON == 1) && (cur_dig == 1)) PORTB.3=1;  // запятая во втором разряде (нумерация нач. с нуля)

        cur_dig++; if (cur_dig>3) cur_dig=0;
}

Здесь надо инвертировать присваивание PORTD и PORTB, а term.h ни в коем случае не трогать

Добавлено after 4 minutes 50 seconds:
Код:
interrupt [TIM0_OVF] void timer0_ovf_isr(void) {
        PORTD&=0b01111000;    // потушить все (биты всех знакомест "0" - для Общ.анод+тр.ключи)
       
        PORTB=(unsigned char)(~(digits[digit_out[cur_dig]])); // символ на экран
        PORTD|=(unsigned char)(~(cursor[cur_dig]));  // засветить нужный бит (бит знакоместа в "1" - для ОА + тр.ключи)
       
        if ((zpt_ON == 1) && (cur_dig == 1)) PORTB.3=0;  // запятая во втором разряде (нумерация нач. с нуля)

        cur_dig++; if (cur_dig>3) cur_dig=0;
}

Re: Динамическая индикация

Пн дек 25, 2023 07:50:51

Martian, в протеусе не работает. :(

Re: Динамическая индикация

Пн дек 25, 2023 08:35:38

А причём тут Протеус? Если сказано было:
Smith2011 писал(а): у меня платы ... собрал, а на табло чушь

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

Добавлено after 4 minutes 59 seconds:
может быть, надо так: PORTD |= 0b01111000;
Определите для своей схемы, что надо присвоить порту D для отключения разрядов

Re: Динамическая индикация

Пн дек 25, 2023 09:21:11

Smith2011 писал(а):не работает
мой вариант пробовали?
Выложите свой файл протеуса, гляну. Там будет ясно, что у вас должно инвертироваться, а что нет.
Последний раз редактировалось metan Пн дек 25, 2023 09:26:02, всего редактировалось 1 раз.

Re: Динамическая индикация

Пн дек 25, 2023 09:23:48

metan, Ваш вариант точку будет учитывать? гашение всех разрядов?
файл протеуса он уже вылоржил в архиве

Re: Динамическая индикация

Пн дек 25, 2023 09:27:26

Martian писал(а):точку будет учитывать?
я пока не знаю.
А выложенный файл протеуса оригинальный, поэтому он не катит

Re: Динамическая индикация

Пн дек 25, 2023 10:00:40

не будет, потому что она в обработчике таймера, как и гашения. Поэтому, изменение символов - половинчатое решение. Хотя по быстродействию будет лучше...
metan писал(а):А выложенный файл протеуса оригинальный, поэтому он не катит
нда... ну, тогда даже отсутствие у меня Протеуса не влияет :)))

Re: Динамическая индикация

Пн дек 25, 2023 11:03:33

Martian писал(а):изменение символов - половинчатое решение
да что-то мне теперь сдается, что изменять символы вообще не нужно.
Если у пассажира общий анод, а на сегменты тоже единички должны выдаваться, значит только биты разрядов нужно инвертировать.
В оригинале на сегменты и так единички прут, без изменений.
Хотя ХЗ, схемы нет жеж переделанной.

Re: Динамическая индикация

Пн дек 25, 2023 12:53:24

да, мож его драйвера там как-то чего-то инвертируют, по описанию разбираться... подождём схему. Картинкой притом.

Re: Динамическая индикация

Вт дек 26, 2023 14:04:33

Martian писал(а):точку будет учитывать?
я пока не знаю.
А выложенный файл протеуса оригинальный, поэтому он не катит


Я не смотрю что в протеусе показывает индикаторы, я смотрю что идет с выхода контроллера. Поэтому эта схема протеуса пойдет. :))

Мне надо чтобы и на сегменты и на общий управляющие сигналы с контроллера были единицы, а гашение везде ноль. Ибо все мои ключи которые стоят перед индикатором управляются единицами.


После кода который предложил Martian разряды вообще перестают перебираться, все выставляются в единицу.

Re: Динамическая индикация

Вт дек 26, 2023 14:27:31

Smith2011 писал(а):Мне надо чтобы и на сегменты и на общий управляющие сигналы с контроллера были единицы, а гашение везде ноль.
тогда это так и есть, и не нужно вообще ничего переделывать, оригинальный код так и работает.
Может, у вас просто на печатке сегменты перепутаны? В программе они не по порядку идут.
Короче, пока от вас не будет схемы (какая у вас), будет продолжаться любовь мозга.
Последний раз редактировалось metan Вт дек 26, 2023 15:02:32, всего редактировалось 2 раз(а).
Ответить