Использование этой библиотеки значительно упрощает работу с семисегментным индикатором. Библиотека написана под четырехразрядный семисегментный индикатор с общим анодом или катодом. Она позволяет выводить на дисплей не только цифры, но и буквы, текущее время, бегущую строку, менять яркость свечения индикатора. Далее рассмотрим функции этой библиотеки(скачать файлы display.c и display.h можно внизу статьи).
display_init(void); - инициализация дисплея
set_brightness(uint8_t b); - установка яркости от 0 до 100
shift_in(char c); - сдвиг символа на одну позицию справа-налево
set_char_at(char c, uint8_t offset); - вывод символа в определенное знакоместо
Например: set_char_at('A', 0); // вывод символа А в первое знакоместо
set_char_at(2, 2); // вывод цифры 2 в третье знакоместо
set_segments_at(uint8_t segments, uint8_t offset); - вывод сегмента в определенное знакоместо
Например: set_segments_at(2, 1); // вывод сегмента "b" во второе знакоместо
shift_in_segments(uint8_t segments); - сдвиг сегмента на одну позицию справа-налево
set_number(uint16_t num); - вывод четырехразрядной переменной
clear_screen(void); - очистить дисплей
set_time(uint8_t hour, uint8_t min, uint8_t sec); - вывод времени в формате "ЧЧ.ММ"
set_number_4(uint8_t num_0, uint8_t num_1, uint8_t num_2, uint8_t num_3, uint8_t offset); - вывод значений поразрядно, вывод точки в позицию 1..4, 0 - неактивна
Для создания своего проекта как обычно добавляем к нему два файла display.c и display.h. Принцип работы библиотеки рассмотрим на примере часов. Используем для этого микроконтроллер atmega8, который тактируется от внешнего кварца частотой 8 МГц. Внешний кварц выбран для более точного хода часов. Сегменты индикатора подключаем к порту D, кстати в заголовочном файле display.h можно изменить конфигурацию подключения по своему желанию, если например, на печатной плате надо оптимизировать разводку дорожек. Общие аноды(катоды) подключаются к выводам PB3-PB0. Настройка часов осуществляется с помощью двух кнопок "Часы+" и "Минуты+", при нажатии на которые увеличиваются часы и минуты соответственно. При нажатии на обе кнопки изменяется яркость дисплея.
В нашей программе используются два таймера Т0 и Т1. Восьмибитный таймер Т0 используется для динамической индикации, шестнадцатибитный таймер Т1 используется для создания интервала в 1 секунду, он используется для подсчета времени. Как только наступает прерывание по совпадению Т1 переменная "second" увеличивается на 1 секунду, если "second" будет больше 60, переменная "minute" увеличится на 1 минуту, если переменная "minute" будет больше 60, переменная "hour" увеличится на 1 час, и т.д по кругу. Полный текст программы представлен ниже:
// Использование библиотеки для работы с семисегментным индикатором #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include "display.h" volatile unsigned char second, minute, hour, level; // Обработчик прерывания по совпадению Т1 ISR(TIMER1_COMPA_vect) { second++; // Увеличиваем секунды if(second == 60) { second = 0; minute++; // Увеличиваем минуты if(minute == 60) { minute = 0; hour++; // Увеличиваем часы if(hour == 24) hour = 0; } } set_time(hour,minute,second); // Выводим на дисплей } int main(void) { hour = 12; // Начальная установка времени minute = 0; second = 0; // Порты ввода/вывода DDRB |= (0 << PB5)|(0 << PB4); PORTB |= (1 << PB5)|(1 << PB4); // Настройка Т1 TCCR1B |= (1 << WGM12)|(1 << CS12); // 8MHz/256/(1+31249)=1Hz OCR1A = 31249; sei(); // Глобально разрешам прерывания set_brightness(80); // Начальная установка яркости дисплея display_init(); // Инициализация дисплея // Выводим бегущую строку "test display" shift_in('t'); _delay_ms(100); shift_in('E'); _delay_ms(100); shift_in('s'); _delay_ms(100); shift_in('t'); _delay_ms(100); shift_in(' '); _delay_ms(100); shift_in('d'); _delay_ms(100); shift_in('i'); _delay_ms(100); shift_in('s'); _delay_ms(100); shift_in('p'); _delay_ms(100); shift_in('L'); _delay_ms(100); shift_in('a'); _delay_ms(100); shift_in('y'); _delay_ms(100); shift_in(' '); _delay_ms(100); shift_in(' '); _delay_ms(100); shift_in(' '); _delay_ms(100); clear_screen(); _delay_ms(100); TIMSK |= (1 << OCIE1A); // Разрешаем прерывание по совпадению Т1 while(1) { unsigned char i, dr; // Если кнопка Часы+ и Минуты+ нажаты увеличиваем яркость if((PINB&(1 << PB4)) == 0 && (PINB&(1 << PB5)) == 0) { dr = 0; // Программный антидребезг контактов for(i = 0; i < 10; i++) { _delay_ms(5); if((PINB&(1 << PB4)) == 0 && (PINB&(1 << PB5)) == 0) dr++; } if(dr > 5) { if(level != 99) level++; // Увеличиваем яркость else level = 0; set_brightness(level); } } // Если кнопка Часы+ нажата увеличиваем часы if((PINB&(1 << PB4)) == 0 && PINB&(1 << PB5)) { dr=0; // Программный антидребезг контактов for(i = 0; i < 10; i++) { _delay_ms(5); if((PINB&(1 << PB4)) == 0) dr++; } if(dr > 5) { if(hour != 23) hour++; // Увеличиваем часы else hour = 0; set_time(hour,minute,second); // Выводим на дисплей } } // Если кнопка Минуты+ нажата увеличиваем минуты if((PINB&(1 << PB5))==0 && PINB&(1 << PB4)) { dr=0; // Программный антидребезг контактов for(i = 0; i < 10; i++) { _delay_ms(5); if((PINB&(1 << PB5)) == 0) dr++; } if (dr > 5) { if(minute != 59) minute++; // Увеличиваем минуты else minute = 0; set_time(hour,minute,second); // Выводим на дисплей } } } }
Обсуждение статьи на форуме
Архив для статьи "Использование библиотеки для работы с семисегментным индикатором. Делаем простые часы." | |
Описание: Проект AVRStudio и Proteus | |
Размер файла: 64.41 KB Количество загрузок: 4 756 | Скачать |
Комментарии
Ну не как с секундами не получается
Только переделывать библиотеку, если смогу выложу код.
Буду очень благодарен за помощь, вот если еще и на Си..........
Написал в форум radioparty.ru/forums/viewtopic.php?f=2&t=749
ели хочется вывести температуру например -15.2 14.82 ???
set_number(1000 );
Как вариант добавить свою функцию типа этого
Код:
void set_themperature(uint16_t themperature, uint8_t dot_digit)
{
set_number(themperature);
sbi(dots, dot_digit); // set dot 1 on
}
Код:
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "display.h"
volatile unsigned char second, minute, hour, level;
int main(void)
{
//порты
DDRA |= (1<<PA7)|(1<<PA6)|(1<<PA5)|(1<<PA4)|(1<<PA3)|(1<<PA2)|(1<<PA1)|(1<<PA0);//катоды
PORTA |= (0<<PA7)|(0<<PA6)|(0<<PA5)|(0<<PA4)|(0<<PA3)|(0<<PA2)|(0<<PA1)|(0<<PA0);//индикатора
DDRD |= (1<<PD7)|(1<<PD6)|(1<<PD5)|(1<<PD4)|(1<<PD3)|(1<<PD2)|(1<<PD1)|(1<<PD0);
PORTD |= (0<<PD7)|(0<<PD6)|(0<<PD5)|(0<<PD4)|(0<<PD3)|(0<<PD2)|(0<<PD1)|(0<<PD0); //сегменты индикатора
display_init(); // инициализация дисплея
set_brightness(99); // начальная установка яркости дисплея
while(1)
{
set_char_at('A', 2);
}
}
получается что на все индикаторы выводится "А",а на третьем индикаторе сегменты еле подсвечиваются. Индикатор с общим катодом в библиотеке выставил катод.
Библиотека не оптимизирована для работы с ключами, нужно будет немножко переделать исходник
Попробуйте так
Код:
// common cathode
#define SET_DIGIT sbi
#define CLEAR_DIGIT cbi
#define SET_SEGMENT sbi
#define CLEAR_SEGMENT cbi
Использовать часовой кварц и корректировку секунд, с обычными кварцами 8-16 мегагерц ничего путного не выходит.
К томуже появится возможность усыплять контроллер с таймером работающим в асинхронном режиме на случай потери питания.
Библиотека кстати огонь здоровенная.
Здравствуйте. Добавил в библиотеку функцию set_number_4, через нее вывел температуру, пример в файлах к этой статье