Суббота, 18.11.2017, 07:20 
Приветствую Вас Гость | RSS



Меню сайта
 

Личные странички
UA3EKK
RV3EFH
UA3EID
RA3EA
UA3EKJ
RA3ED
UA3ECX
RV3EF

Мини-чат

Погода


Наш опрос
Каким видом радиосвязи вас чаще всего можно услышать в эфире?
Всего ответов: 261

Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0

Albert

Форма входа
Логин:
Пароль:

Корзина
Ваша корзина пуста

Куплю/продам

[13.02.2012]
продам (1)
[19.12.2011]
icom R6 (0)
[16.10.2011]
Усилитель мощности на ГС31/ ГС35 (3)
[11.10.2011]
Нужны микросхемы (1)
[22.05.2011]
Рубрика технической взаимопомощи (2)

Фото

Праздники

Ваш IP
Узнай свой IP адрес

Главная » 2012 » Декабрь » 8 » Управление семисегментными индикаторами на C++
19:20
Управление семисегментными индикаторами на C++

Попалась мне плата готовая с четырьмя семисегментными индикаторами, семисегментным дешифратором и четыримя ключевыми транзисторами.


В динамическом режиме (режим поочерёдной быстрой развёртки) на семисегментных индикаторах можно получать разные цифры, даже с одним дешифратором.
Задумал подключить её к моей плате с регистрами, про которую я публиковал "статью" в предыдущей теме, и попробывать написать программку для индикации системного времени (в формате "ЧЧММ") на данных индикаторах. Там также присутствует 8-й сегмент - децимальная точка, которая по моей идее будет служить для визуализации секунд. В динамическом режиме, как я увидел, индикаторы горят в половину своей яркости, ибо не успевает полностью зажечься, как он тушиться и зажигается соседний. Из 16 портов регистра (у меня два по 8) я задействовал 9 портов: 4 порта для посыла бинарного кода отображаемой цифры на дешифратор, 4 порта на 4 ключа 4-х индикаторов и один порт на децимальную точку для визуализации секунд. Если обойтись без последнего, достаточно будет 8-ми портов, а следовательно, одного 8-портового регистра.

#include <stdio.h>

#include <iostream>

#include <windows.h>

#include "conio.h"

#include <fstream>

#include <stdlib.h>

 

using namespace std;

 

void DTR1(HANDLE h){

    EscapeCommFunction(h, 6);

}

 

void DTR0(HANDLE h){

    EscapeCommFunction(h, 5);

}

 

void RTS1(HANDLE h){

    EscapeCommFunction(h, 4);

}

 

void RTS0(HANDLE h){

    EscapeCommFunction(h, 3);

}

 

void TX1(HANDLE h){

    EscapeCommFunction(h, 8);

}

 

void TX0(HANDLE h){

    EscapeCommFunction(h, 9);

}

 

//Функция, возводящая целочисленное число в целочисленную степень. Стандартная функция pow работает некорректно.

int pow1(int a,int b){

    int i,c;

    c=1;

    for(i=0;i<b;i++){

         c*=a;

    }

    return c;

}

 

int main(){

    HANDLE h;

    h = CreateFile("COM1", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

    if(h==INVALID_HANDLE_VALUE){

         printf("COM1 port open error\n");

         scanf("1");

    }

    int i,j,t,m;

    int a[4]; //Массив цифр, отображаемые на индикаторах.

    SYSTEMTIME st; //Структурная переменная, в которую будут записаны текущие данные системмного времени, начиная от года и заканчивая милисекундами.

    while(1){ //Бесконечный цикл для непрерывного быстрого сканирования индикаторов.

         GetLocalTime(&st); //Получить текущее состояние системного времени и записать в переменную st.

         m=st.wHour; //Записать в переменную m часы из st.

         //Цикл, "вытаскивающий" цифры из двухзначного числа m (часы) одним из многочисленных способов. Если число меньше 10, ноль слева припишется автоматически. Две цифры (десятки и еденицы часов) запишутся в 1 и 2 элементы массива a[] и в дальнейшем будут отображены на 1 и 2 индикаторах.

         for(i=0;i<=1;i++){

             a[i]=0;

             while(m>=pow1(10,1-i)){

                 m-=pow1(10,1-i);

                 a[i]+=1;

             }

         }

         m=st.wMinute; //Записать в переменную m минуты из st.

         //Цикл, аналогичный циклу выше, только для минут. Две цифры (десятки и еденицы минут) запишутся в 3 и 4 элементы массива a[] и в дальнейшем будут отображены на 3 и 4 индикаторах.

         for(i=0;i<=1;i++){

             a[i+2]=0;

             while(m>=pow1(10,1-i)){

                 m-=pow1(10,1-i);

                 a[i+2]+=1;

             }

         }

         m=st.wSecond; //Записать в переменную m секунды из st.

         //Цикл по чередованию индикаторов (динамический режим).

         for(i=0;i<4;i++){

             //Запись 1-ого бита в регистр, соответствующий состоянию соединённых в месте выводов "dp" (сегмент h, децимальная точка) семисегментных индикаторов. Программа предполагает ежесекундное переключение этой точки с индикатора на следующий за ним индикатор. Таким образом эмулируется "тик" часов. Нижепреведённое условие обеспечивает посыл логической "1" в случае, если совпадает текущий номер четверти четвёрок секунд с текущим номером индикатора (i).

             if(m-m/4*4==i){ //Вычисление остатка в результате деления значения секунд на 4. Это и будет вышеописанный номер четверти.

                 RTS0(h);

             }else{

                 RTS1(h);

             }

             //Запись 1-ого бита в регистр.

             DTR1(h);

             DTR0(h);

             t=a[i]; //Запись во временную переменную t значение i-ой цифры, соответствующий текущему индикатору.

             //Цикл, в котором десятичное число (вышеуказанная цифра) осуществляется преобразование в двоичное и биты этого числа сразу же записываются в регистр.

             for(j=0;j<4;j++){ //Даже если будет достаточно представить число t тремя или меньше битами, двоичное число будет дополнено нулями до 4-х бит.

                 if(t-t/2*2){ //Расчёт остатка в результате деления на 2. Это будет текущий j-ый бит.

                     RTS0(h);

                 }else{

                     RTS1(h);

                 }

                 //Запись этого бита в регистр.

                 DTR1(h);

                 DTR0(h);

                 t=t/2; //Целочисленное деление на 2 для дальнейшего повтора операции разложения на биты в цикле.

             }

             //Следующий цикл определяет номера дисплеев, которые зажгуться в зависимости от текущего i. Нам нужно, чтобы загорался один i-ый дисплей, а все остальные были блокированы.

             for(j=0;j<4;j++){

                 if(j==i){ //Передача логической "1" в случае вышеуказанного совпадения. Во всех остальных трёх случаях - "0".

                     RTS0(h);

                 }else{

                     RTS1(h);

                 }

                 //Запись последних 4-х битов в регистр.

                 DTR1(h);

                 DTR0(h);

             }

 

             //В регистр записаны все 9 битов. Нижеуказанными функциями осуществляется открытие регистра на мгновение.

             TX1(h);

             TX0(h);

         }

    }

    scanf("1");

    TX0(h);

    RTS1(h);

    for(i=0;i<16;i++){

         DTR1(h);

         DTR0(h);

    }

    TX1(h);

    CloseHandle(h);

    return 0;

}

 



 

Просмотров: 3458 | Добавил: RV3EEQ
Всего комментариев: 3
2  
Интересный вариант, кстати можно попробовать увеличить частоту работы схемы? Тогда не будут успевать гаснуть сегменты, но увеличиться потребление тока.

3  
Причём тут гаснуть??? Наоборот частота сверхбыстрая! Они не успевают ЗАГОРАТЬСЯ до полной яркости! Тут надо наоборот, СНИЗИТЬ частоту, но до таких пределов, чтобы не было видно мерцания. Функцией Sleep, которая прерывает выполнение кода, я делал прерывание на 1 милисекунду ибо меньше делать нельзя. При этом мерцание было видно. Есть вариант задержки на r временных едениц интервалов работы COM порта for(k=0;k<r;k++){TX1;} Попробую в понедельник. И ЕЩЁ! Только сейчас до меня дошло, что время записи информации в регистр в десятки раз больше времени открытого состояния регистра. Это значит, что большую часть времени индикаторы не горят! И это не зависит от скорости работы COM порта. Вышеизложенное предложение должно помочь.

1  
Программу писал в Dev-C++. Видео, как оно работает, представлено ниже. В данном видео на мониторе исходный код отличается от вышеизложенного ибо видео снималось на этапе разработки.

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Мы в Контакте

R3E В Контакте
 


Наши соревнования

Соревнования Золотой Орел


Поиск

Время
MCK

Календарь
«  Декабрь 2012  »
ПнВтСрЧтПтСбВс
     12
3456789
10111213141516
17181920212223
24252627282930
31

Архив записей

Дни рождения
Дни рождения в Ноябре :
 
Александр  RN3E (10.11)
Виктор  Никитин (27.11)
Виктор  RA3POV (27.11)
Владимир  R3EAU (31.11)
 
Поздравляем !!!

E-mail отправителя *:
ФИО, позывной, день рождения:

Друзья сайта
  • RK3EWW
  • Сайт Ливенских радиолюбителей
  • Полезные ссылки:
  • QRZ.RU
  • Сервер Кубанских Радиолюбителей
  • Союз радиолюбителей России
  • Российский УКВ портал

  • Форум

    Коментарии

    Поиск на QRZ.RU
    Поиск в российском Callbook'e:
    ON-LINE поиск предоставлен сервером QRZ.RU

    Известные сайты
    Сервер радиолюбителей России - схемы, документация,
 соревнования, дипломы, программы, форумы и многое другое!

    Сервер 

Кубанских радиолюбителей

    Российский УКВ портал

    R-Quad - 

радиолюбительские антенны


    РАДИОФАНАТ - 

сайт Николая Большакова

    Орловский регион
    Радиоклуб Орловский Эфир. Региональное общественное объединение

    Детская коллективная радиостанция. Орел



    Сайт Ливенских радиолюбителей

    Разместите наш баннер

    Регионы России

    Smolradio.ru -
Сайт Радиолюбителей Смоленщины

    Сайт радиолюбителей Тульской области

    Сервер Тамбовских Радиолюбителей



    Тульский областной радиоклуб




    Принципиальные схемы

    Радиоклуб Орловский Эфир © 2017Сайт управляется системой uCoz