Помогите вывести значение на семисегментники через 74HC595
- Хатуль_мадан
- Электрический кот
- Сообщения: 1004
- Зарегистрирован: Ср мар 03, 2010 11:48:00
- Откуда: Уфа
Re: Помогите вывести значение на семисегментники через 74HC5
Все верно, советы Аlex и ARV совершенно "в точку", добавлю и свои 5 копеек.
Вижу схему в протеусе, т.е. модель с аналогичной моей схеме организацией включения сегментов, так вот, тоже пытался долго найти ошибку, почему в модели индикация не хочет работать, пока не спаял плату, в железе все отлично заработало. Потом оказалось все просто, надо изменить свойства моделирования и индикатора, тогда вроде можно получить приемлемый результат.
Второе, это использовать для вывода аппаратный SPI, очень сокращает и упрощает процедуру вывода.
Вижу схему в протеусе, т.е. модель с аналогичной моей схеме организацией включения сегментов, так вот, тоже пытался долго найти ошибку, почему в модели индикация не хочет работать, пока не спаял плату, в железе все отлично заработало. Потом оказалось все просто, надо изменить свойства моделирования и индикатора, тогда вроде можно получить приемлемый результат.
Второе, это использовать для вывода аппаратный SPI, очень сокращает и упрощает процедуру вывода.
- Вложения
-
- TEST_LCD.rar
- фото, схема.
- (132.35 КБ) 212 скачиваний
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Помогите вывести значение на семисегментники через 74HC5
Действительно, не то что можно (как я написал), а НУЖНО защёлкивать после передачи всех байтов.ARV писал(а):да, главное: защелкивать регистр надо после вывода 2-х байтов, а не после каждого, иначе будет фигня, они же оба одновременно защелкиваются
Теперь я ступил. 1:1
Re: Помогите вывести значение на семисегментники через 74HC5
Не понятный для меня феномен кто то может обьяснить как правильно его лечить?
При небольшой частоте обновления мерцают сегменты которые при большой частоте вовсе не светятся.
В принципе решил это двойным выводом каждого сегмента, но наверное это как то не рационально.
#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);
}
}
При небольшой частоте обновления мерцают сегменты которые при большой частоте вовсе не светятся.
В принципе решил это двойным выводом каждого сегмента, но наверное это как то не рационально.
#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 КБ) 379 скачиваний
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Помогите вывести значение на семисегментники через 74HC5
У Вас в массиве SEGMENTE всего 10 элементов. Откуда 11-13 взялись ?SEGMENTE[11];
......
SEGMENTE[12];
......
SEGMENTE[13];
А как Вы задаёте эту частоту ?При небольшой частоте обновления
У Вас в цикле постоянно крутится запись в регистры, сделайте хотябы задержечку, для начала.
Re: Помогите вывести значение на семисегментники через 74HC5
SEGMENTE 11-13 это байт для зажигания цифры на индикаторе (катод).
Задержка у меня стоит в функции write_display _delay_ms(3); когда ставлю 50 мс, то мерцают сегменты те что при 3мс вообще не светятся.
Пробовал делать задержку в цикле не помогло.
Задержка у меня стоит в функции write_display _delay_ms(3); когда ставлю 50 мс, то мерцают сегменты те что при 3мс вообще не светятся.
Пробовал делать задержку в цикле не помогло.
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Помогите вывести значение на семисегментники через 74HC5
Дык у Вас в массиве то ВСЕГО 10 ЭЛЕМЕНТОВ ! А Вы пытаетесь выдернуть из него 11-ый, 12-ый и 13-ый !djrec писал(а):SEGMENTE 11-13 это байт для зажигания цифры на индикаторе (катод).
Мало того, у Вас ещё и таблица составлена неверно, значения в ней какие-то подозрительные
Пересмотрите их...
Re: Помогите вывести значение на семисегментники через 74HC5
Все там верно, просто коментарий не переписывал. И притом при двойном вызове функции все нормально выводится.
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Помогите вывести значение на семисегментники через 74HC5
Ну правильно, значит правильно. Не хотите слушать, не надо. Да и на вопросы Вы, видимо, не любите отвечать.
Удачи в разборках...
Удачи в разборках...
Re: Помогите вывести значение на семисегментники через 74HC5
Чем вас смущает массив с 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};
То есть в один регистр я загоняю значение анодов (массив от 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};
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Помогите вывести значение на семисегментники через 74HC5
Тьфу, блин, не досмотрел, что в массиве дописано ещё 3 байта.
Извиняюсь
Извиняюсь
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Помогите вывести значение на семисегментники через 74HC5
Странно, а зачем тогда из массива их выдёргивать ? Пишите в 0-вой байт напрямую эти константы, да и всё.
Что касается проблемы. Скорее всего, это протеус глючит. Даже по картинке видно, что цифра 2 должна светиться полностью. Если судить по цветам кубиков на выводах дисплея. На железе всё будет показывать нормально. Просто протеусу нужно гашение. Посылайте сначала нулевые байты, а потом уже с данными.
И задержку воткните в главный цикл, после каждой зажжёной цифры. А то как-то нелгично её видеть в функции передачи, т.к. именно к этой функции она никакого отношения не имеет.
Что касается проблемы. Скорее всего, это протеус глючит. Даже по картинке видно, что цифра 2 должна светиться полностью. Если судить по цветам кубиков на выводах дисплея. На железе всё будет показывать нормально. Просто протеусу нужно гашение. Посылайте сначала нулевые байты, а потом уже с данными.
И задержку воткните в главный цикл, после каждой зажжёной цифры. А то как-то нелгично её видеть в функции передачи, т.к. именно к этой функции она никакого отношения не имеет.
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Помогите вывести значение на семисегментники через 74HC5
Можно сделать немного по другому.
Измените схему так, чтобы первый регистр шел на аноды (выбор индикатора), а второй на катоды (сегменты).
Тогда для гашения достаточно будет послать всего 1 байт с единичками и защёлкнуть его там. А затем ещё 2 байта уже с актуальными данными, для зажигания необходимого индикатора.
Как-нибудь так, приблизительно :
Измените схему так, чтобы первый регистр шел на аноды (выбор индикатора), а второй на катоды (сегменты).
Тогда для гашения достаточно будет послать всего 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);
}
}
//***********************************************************************************************
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Помогите вывести значение на семисегментники через 74HC5
Или вообще, лучше сделать как-нибудь так, что уже будет намного ближе к истине :
Спойлер
Код: Выделить всё
//***********************************************************************************************
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
Наверное когда сделаю уже в железе попробую свою программу с одиночным выводом, если не будет проблем то оставлю, притом уже переделал на два трехразрядных семисегментника.
Спасибо за помощь.
Спасибо за помощь.
- alex-wolf
- Открыл глаза
- Сообщения: 63
- Зарегистрирован: Сб мар 09, 2013 21:46:01
- Откуда: Уфа
- Контактная информация:
Re: Помогите вывести значение на семисегментники через 74HC5
всех приветствую
поднимаю тему
индикация - !СТАТИЧЕСКАЯ!
первоисточник
http://radiokot.ru/circuit/digital/home/68/
только вместо "DM632" использования немного облегчённая
4 разряда, т.е. 2 "DM135B"
компилятор CVAVR2.0.5
результат - отрицательный
не получается вывести,
только 1 разряд выводит


выслушаю, рекомендации.
поднимаю тему
индикация - !СТАТИЧЕСКАЯ!
первоисточник
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);
};


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