Дисплеи, датчики и прочие функциональные узлы, управляемые МК.
Ответить

Re: Помогите вывести значение на семисегментники через 74HC5

Пт мар 13, 2015 08:45:16

Все верно, советы Аlex и ARV совершенно "в точку", добавлю и свои 5 копеек.
Вижу схему в протеусе, т.е. модель с аналогичной моей схеме организацией включения сегментов, так вот, тоже пытался долго найти ошибку, почему в модели индикация не хочет работать, пока не спаял плату, в железе все отлично заработало. Потом оказалось все просто, надо изменить свойства моделирования и индикатора, тогда вроде можно получить приемлемый результат.
Второе, это использовать для вывода аппаратный SPI, очень сокращает и упрощает процедуру вывода.
Вложения
TEST_LCD.rar
фото, схема.
(132.35 KiB) Скачиваний: 196

Re: Помогите вывести значение на семисегментники через 74HC5

Пт мар 13, 2015 08:47:55

ARV писал(а):да, главное: защелкивать регистр надо после вывода 2-х байтов, а не после каждого, иначе будет фигня, они же оба одновременно защелкиваются
Действительно, не то что можно (как я написал), а НУЖНО защёлкивать после передачи всех байтов.
Теперь я ступил. 1:1 :))

Re: Помогите вывести значение на семисегментники через 74HC5

Вс мар 15, 2015 00:31:02

Не понятный для меня феномен кто то может обьяснить как правильно его лечить?

При небольшой частоте обновления мерцают сегменты которые при большой частоте вовсе не светятся.

В принципе решил это двойным выводом каждого сегмента, но наверное это как то не рационально.

#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
volatile unsigned int temperature;
// Массив значениий для семисегментного индикатора
//----------
char SEGMENTE[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D,
//----------
0x7D, 0x07, 0x7F, 0x6F, 0x00, 0xF7, 0xFB, 0xFD};


// Функция вывода данных через регистр
void write_display(unsigned char *data, unsigned char nbytes)
{
unsigned char mask,i;

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

unsigned char k=8;
while(k--){
if(data[i] & 0x80) PORTC |= (1 << PC0); // DATA 1
else PORTC &= ~(1 << PC0); // DATA 0
PORTC |= (1 << PC2); // CLK 1
PORTC &= ~(1 << PC2); // CLK 0
data[i]<<=1;
}

}
// защелкиваем регистр
PORTC |= (1 << PC1);
PORTC &= ~(1 << PC1);
_delay_ms(3);
}


int main(void)
{
DDRC = 0b00000111;
PORTC = 0b00000000;
sei(); // Глобально разрешаем прерывания

unsigned char display[2];

while(1)
{


/*// Если температура меньше 100 градусов гасим незначащий ноль
if(temperature < 100)
{
display[0] = SEGMENTE[temperature % 10];
display[1] = SEGMENTE[(temperature / 10) % 10];
display[2] = SEGMENTE[10];
}
// Иначе показываем все разряды
else */
{

temperature=123;

display[0] = SEGMENTE[11];
display[1] = SEGMENTE[temperature % 10];
write_display(display,2);
write_display(display,2);

display[0] = SEGMENTE[12];
display[1] = SEGMENTE[(temperature / 10) % 10];
write_display(display,2);
write_display(display,2);

display[0] = SEGMENTE[13];
display[1] = SEGMENTE[(temperature / 100) % 10];
write_display(display,2);
write_display(display,2);

}
// Отправляем данные на индикатор
//write_display(display,2);
}
}
Вложения
444444444444441.jpg
(126.64 KiB) Скачиваний: 361

Re: Помогите вывести значение на семисегментники через 74HC5

Вс мар 15, 2015 11:22:22

SEGMENTE[11];
......
SEGMENTE[12];
......
SEGMENTE[13];
У Вас в массиве SEGMENTE всего 10 элементов. Откуда 11-13 взялись ?

При небольшой частоте обновления
А как Вы задаёте эту частоту ?
У Вас в цикле постоянно крутится запись в регистры, сделайте хотябы задержечку, для начала.

Re: Помогите вывести значение на семисегментники через 74HC5

Вс мар 15, 2015 12:33:12

SEGMENTE 11-13 это байт для зажигания цифры на индикаторе (катод).


Задержка у меня стоит в функции write_display _delay_ms(3); когда ставлю 50 мс, то мерцают сегменты те что при 3мс вообще не светятся.

Пробовал делать задержку в цикле не помогло.

Re: Помогите вывести значение на семисегментники через 74HC5

Вс мар 15, 2015 15:22:26

djrec писал(а):SEGMENTE 11-13 это байт для зажигания цифры на индикаторе (катод).
Дык у Вас в массиве то ВСЕГО 10 ЭЛЕМЕНТОВ ! А Вы пытаетесь выдернуть из него 11-ый, 12-ый и 13-ый !

Мало того, у Вас ещё и таблица составлена неверно, значения в ней какие-то подозрительные :) Например для "пусто" должно быть 0x00.
Пересмотрите их...

Re: Помогите вывести значение на семисегментники через 74HC5

Вс мар 15, 2015 16:20:26

Все там верно, просто коментарий не переписывал. И притом при двойном вызове функции все нормально выводится.

Re: Помогите вывести значение на семисегментники через 74HC5

Вс мар 15, 2015 21:26:10

Ну правильно, значит правильно. Не хотите слушать, не надо. Да и на вопросы Вы, видимо, не любите отвечать.
Удачи в разборках...

Re: Помогите вывести значение на семисегментники через 74HC5

Вс мар 15, 2015 22:49:00

Чем вас смущает массив с 14 значений? Вот посмотрите, я взял с этого примера http://radioparty.ru/prog-avr/program-c ... on-74hc595 все так же до значения " 0x00 = пусто ", и в конце дописал еще три значения своих, для подачи на катод нуля 0xFB =11111011 , 0xFD = 11111101, 0xFE = 11111110.



То есть в один регистр я загоняю значение анодов (массив от 0 до 10), а во второй значения катодов 0xFB, 0xFD, 0xFE (11-13).

Пауза у меня стоит после защелкивания, то есть загнали значения, засветили сегменты и ждем немного, потот снова загоняем новое значение....

Для лучшей наглядности выровнял комментарий.

//----------
char SEGMENTE[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D,
//--6-----7-----8-----9----пусто
0x7D, 0x07, 0x7F, 0x6F, 0x00, 0xF7, 0xFB, 0xFD};

Re: Помогите вывести значение на семисегментники через 74HC5

Вс мар 15, 2015 22:52:29

Тьфу, блин, не досмотрел, что в массиве дописано ещё 3 байта.
Извиняюсь :oops:

Re: Помогите вывести значение на семисегментники через 74HC5

Вс мар 15, 2015 23:04:51

Странно, а зачем тогда из массива их выдёргивать ? Пишите в 0-вой байт напрямую эти константы, да и всё.
Что касается проблемы. Скорее всего, это протеус глючит. Даже по картинке видно, что цифра 2 должна светиться полностью. Если судить по цветам кубиков на выводах дисплея. На железе всё будет показывать нормально. Просто протеусу нужно гашение. Посылайте сначала нулевые байты, а потом уже с данными.
И задержку воткните в главный цикл, после каждой зажжёной цифры. А то как-то нелгично её видеть в функции передачи, т.к. именно к этой функции она никакого отношения не имеет.

Re: Помогите вывести значение на семисегментники через 74HC5

Вс мар 15, 2015 23:20:33

Можно сделать немного по другому.
Измените схему так, чтобы первый регистр шел на аноды (выбор индикатора), а второй на катоды (сегменты).
Тогда для гашения достаточно будет послать всего 1 байт с единичками и защёлкнуть его там. А затем ещё 2 байта уже с актуальными данными, для зажигания необходимого индикатора.

Как-нибудь так, приблизительно :
Спойлер
Код:
//***********************************************************************************************
volatile unsigned int temperature;
// Массив значениий для семисегментного индикатора
//----------
char SEGMENTE[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D,
//----------
 0x7D, 0x07, 0x7F, 0x6F, 0x00, 0xF7, 0xFB, 0xFD};
//***********************************************************************************************

//***********************************************************************************************
void out_latch(void){
PORTC |= (1 << PC1);
PORTC &= ~(1 << PC1);
}
//***********************************************************************************************
void out_byte(unsigned char data){
unsigned char i=8;
while(i--){
    if(data & 0x80)    PORTC |= (1 << PC0); // DATA 1
    else               PORTC &= ~(1 << PC0); // DATA 0
    PORTC |= (1 << PC2); // CLK 1
    PORTC &= ~(1 << PC2); // CLK 0
    data<<=1;
}
}
//***********************************************************************************************
void write_display(unsigned char *data){
out_byte(0xff);
out_latch();
out_byte(data[0]);
out_byte(data[1]);
out_latch();
}
//***********************************************************************************************


//***********************************************************************************************
void main(void){
unsigned char display[2];

temperature=123;

while(1){

display[0] = SEGMENTE[temperature % 10];
display[1] = 0xf7;
write_display(display);

_delay_ms(3);

display[0] = SEGMENTE[(temperature / 10) % 10];
display[1] = 0xfb;
write_display(display);

_delay_ms(3);

display[0] = SEGMENTE[(temperature / 100) % 10];
if(display[0]==SEGMENTE[0])    display[0]=SEGMENTE[10]; // Гашение нуля
display[1] = 0xfd;
write_display(display);

_delay_ms(3);

}
}
//***********************************************************************************************

Re: Помогите вывести значение на семисегментники через 74HC5

Пн мар 16, 2015 00:02:51

Или вообще, лучше сделать как-нибудь так, что уже будет намного ближе к истине :
Спойлер
Код:
//***********************************************************************************************
unsigned char display[4];
volatile unsigned int temperature;
// Массив значениий для семисегментного индикатора
//----------
char SEGMENTE[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x00};
//***********************************************************************************************

//***********************************************************************************************
void out_latch(void){
PORTC |= (1 << PC1);
PORTC &= ~(1 << PC1);
}
//***********************************************************************************************
void out_byte(unsigned char data){
unsigned char i=8;
while(i--){
    if(data & 0x80)    PORTC |= (1 << PC0); // DATA 1
    else               PORTC &= ~(1 << PC0); // DATA 0
    PORTC |= (1 << PC2); // CLK 1
    PORTC &= ~(1 << PC2); // CLK 0
    data<<=1;
}
}
//***********************************************************************************************
void write_display(unsigned char data, unsigned char ind_num){
out_byte(0xff);     // На железе эти 2 строки
out_latch();        // можно убрать !
out_byte(data);
out_byte(~(1<<ind_num));
out_latch();
}
//***********************************************************************************************


//***********************************************************************************************
void main(void){

temperature=123;

display[0] = SEGMENTE[10];
display[1] = SEGMENTE[1];
display[2] = SEGMENTE[2];
display[3] = SEGMENTE[3];


while(1){

//****** Замена обработчика прерываний ********//
_delay_ms(1);
{
static unsigned char i=0;
write_display(display[i], i);
if(++i>=4)  i=0;
}
//*********************************************//


}
}
//***********************************************************************************************

Re: Помогите вывести значение на семисегментники через 74HC5

Пн мар 16, 2015 09:15:51

Наверное когда сделаю уже в железе попробую свою программу с одиночным выводом, если не будет проблем то оставлю, притом уже переделал на два трехразрядных семисегментника.

Спасибо за помощь.

Re: Помогите вывести значение на семисегментники через 74HC5

Ср янв 31, 2018 22:23:16

всех приветствую

поднимаю тему

индикация - !СТАТИЧЕСКАЯ!

первоисточник
http://radiokot.ru/circuit/digital/home/68/
только вместо "DM632" использования немного облегчённая
4 разряда, т.е. 2 "DM135B"

компилятор CVAVR2.0.5


Код:
#include <mega128.h>
#include <delay.h>
#include <io.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define decc  4 // колличество разрядов
unsigned char  test_data[decc];
unsigned char  test_data_dot[decc];

////// DM135B --bit`s
///  D15=segA1; D14=segB1; D13=segC1; D12=segD1; D11=segE1; D10=segF1;  D9=segG1; D8=segH1;  --1DEC
///   D7=segA2;  D6=segB2;  D5=segC2;  D4=segD2;  D3=segE2;  D2=segF2;  D1=segG2; D0=segH2.  --2DEC

//////////////////////////
unsigned char char2byte( unsigned char ch ){
    switch(ch){
        case 0  : return 0x3f;
        case 1  : return 0x06;
        case 2  : return 0x5B;
        case 3  : return 0x4F;
        case 4  : return 0x66;
        case 5  : return 0x6D;
        case 6  : return 0x7D;
        case 7  : return 0x27;
        case 8  : return 0x7F;
        case 9  : return 0x6F;

        case 'a' : return 0x77;
        case 'b' : return 0x7C;
        case 'c' : return 0x39;
        case 'd' : return 0x5E;
        case 'e' : return 0x79;
        case 'f' : return 0x71;
        case 'g' : return 0x3D;
        case 'h' : return 0x74;
        case 'u' : return 0x3E;
        case 'o' : return 0x5C;
        case 'i' : return 0x30;
        case 't' : return 0x78;
        case 's' : return 0x6D;
        case 'r' : return 0x50;
        case 'П' : return 0x37;
        case 'p' : return 0x73;
        case 'Г' : return 0x31;
        case '_' : return 0x08;
        case '-' : return 0x40;
        case '+' : return 0x70;
        case '=' : return 0x48;
        case '°' : return 0x63;
        case '.' : return 0x80;
        case ' ' : return 0x00;
        default  : return 0x00;
    }
}
////////////////////
void clock()
{
PORTA = PORTA | (1<<1) ; //1
#asm("nop");
PORTA =  PORTA & ~(1<<1); //0
} ;

void _dm135(const char *data, unsigned char *dot_)
{         
       unsigned char i, j;
       // PORTA, configure pins 0..2 as outputs
       // pin0 - data, pin1 - clock, pin2 - latch:
       DDRA |= (1 << 2) | (1 << 1) | (1 << 0);
       // reset data, clock and latch pins:
       PORTA &= ~((1 << 2) | (1 << 1) | (1 << 0));
       // send bytes
       for (i = 0; i < decc; i++) {
            // 8 bits in each byte
            j = 8;

           while (j-- > 0) {
               // pin0 (1 << 0) - data
               if (dot_[i] == 1) { //    Кроме if (x & (1 << j)) других сдвигов не нужно!
                   if (( char2byte(data[i]) + 0x80 ) & (1 << j)) {
                          PORTA = PORTA |= 1;
                   } else {
                          PORTA = PORTA &= ~1;
                   }
                       
               } else {
                       
                   if (( char2byte(data[i]) + 0x00 ) & (1 << j)) {
                          PORTA = PORTA |= 1;
                   } else {
                          PORTA = PORTA &= ~1;
                   }                       
               }
               clock();
           }
       }
       // pulse latch input (0 to 1, then 1 to 0):
       PORTA |= (1 << 2);
       #asm("nop");
       PORTA &= ~(1 << 2);
}



результат - отрицательный
не получается вывести,

только 1 разряд выводит
Код:
void wr7seg__(unsigned char dig)
{ unsigned int tmp;
  tmp = font7seg[dig];
_dm135(tmp);
};


Изображение
Изображение

выслушаю, рекомендации.
Ответить