UPD: не приложил фото дисплея, исправляюсь.
Морда:
Со стороны хвоста:
Код: Выделить всё
/*
Программа написана в среде Arduino IDE. Использован МК AtMega328 c внешним кварцем 16МГц.
_______________
Подключение индикатора: | 1 | 2 | 3 | 4 | 5 | 6 |
| PD0 | PD1 | PD2 | PD3 | PD4 | PD5 |
-------------------------------------------------------------
Сегменты по банкам:
1) A, B, C, D, E, F, G;
0) A, B, C, D, E, F, G;
Символы в массиве:
0 - Капля красная, 1 - Капля зеленая, 2 - Капля белая, 3 - Знак %, 4 - Молния красная, 5 - Молния белая;
Логика работы программы следующая:
Для работы используется прерывание таймера 1. Контроль работы а так же порядок выполнения операций осуществляется посредством счетчика на инкрементируемой переменной dyncounter. Частота прерываний - 10КГц.
Для вывода данных на индикатор в данный момент используется 16-ти байтный буфер buff[16], представляющий из себя одномерный массив содержащий
информацию для каждого из 16 сегментов в виде [A2,B2,A1,B1,C1,D1,E1,F1,G1,A0,B0,C0,D0,E0,F0,G0]. При выводе на индикатор в соответствии со значением
dyncounter в регистр данных порта PORTx записываются данные сегмента из ячейки буфера, а в регистр направления порта DDRx соответствующая
маска сегмента из массива segmentmask[16].
Функция buffops() занимается подготовкой выходных данных. Во время ее работы вывод информации на дисплей запрещен
чтобы отображаемые данные были достоверными. Исходное число val в десятичном формате разбивается на разряды функцией digdisass() и помещает его в переменную vals[2]. Всвязи с особенностью дисплея отображать
в старшем разряде только единицу? отображение этого разряда происходит по признаку val>=100. Если условие верное, показываем единичку, если нет, молчим в тряпочку. Она проверяет и в случае необходимости включает
старший разряд индикатора, по очереди берет исходное число, разбитое на десятки и единицы из массива vals[2] и по битовой маске числа, соответствующей необходимым сегментам на дисплее, заполняет буфер вывода по следующей
системе: переменной outseg1 присваивается значение битовой маски из массива segments1, где записаны битовые маски для чисел от 0 до 9.
путем сдвига на 1 влево обрезается ненужный старший бит, так как каждый символ кодируется только 7-ю битами.
в цикле каждый бит переменной segments1 сравнивается с маской digitmask, и пишет в выходной буфер данные для каждого из сегментов. В случае совпадения в соответствующую
ячейку буфера будет записано значение из массива segments1, где содержатся битовые маски для отображения сегментов первого разряда, в случае несовпадения будет записан
0, означающий, что текущий сегмент зажигать не надо. Здесь же присутствует операция гашения незначащего разряда, если исходное число меньше 10. Заполнение осуществляется
от сегмента A1 до сегмента G1. Далее таким же способом заполняется буфер для сегментов A0-G0, после чего снимается запрет на вывод дисплей и останавливается работа с буфером до полного обновления индикатора.
В программе присутствует переменная timecontr. Она нужна для автоинкремента исходного числа val в прерывании. Данная функция нужна для демонстрации работы программы.
Отображение символов пока не реализовано, оно ничем не отличается от отображения символов, необходимо увеличить обьем выходного буфера на 6 байт и дописать в функцию работы с буфером обработку символов.
мне, как истинному коту пока лень ))))
*/
byte digitmask = 0x80;
volatile byte outseg0 = 0;
volatile byte outseg1 = 0;
volatile unsigned int timecontr = 0;
volatile byte dyncounter = 0;
volatile bool buffupdate = 0;
volatile byte val = 0;
volatile byte vals[2] = { 0, 0 };
byte segments1[7] = { 0x08, 0x10, 0x20, 0x01, 0x04, 0x08, 0x10 };
byte segments0[7] = { 0x20, 0x01, 0x02, 0x08, 0x10, 0x20, 0x01 };
byte symbols[6] = { 0x10, 0x08, 0x02, 0x08, 0x20, 0x20 };
byte segmentsmask[16] = { 0x03, 0x05, 0x09, 0x11, 0x21, 0x03, 0x06, 0x0a, 0x12, 0x22, 0x05, 0x06, 0x0c, 0x14, 0x24, 0x09 };
byte cifraseg[10] = { 0x7e, 0x30, 0x6d, 0x79, 0x33, 0x5b, 0x5f, 0x70, 0x7f, 0x7b };
volatile byte outbuff[16];
void digdisass() {
if (val >= 100) {
vals[1] = (val - 100) / 10;
vals[0] = val % 10;
}
if (val < 100) {
vals[1] = val / 10;
vals[0] = val % 10;
}
}
void buffops() {
if (buffupdate == 1) {
digdisass();
if (val >= 100) {
outbuff[0] = 0x02;
outbuff[1] = 0x04;
}
if (val < 100) {
outbuff[0] = 0x00;
outbuff[1] = 0x00;
}
if (val < 10) {
outseg1 = 0x00;
} else {
outseg1 = cifraseg[vals[1]];
}
outseg1 = outseg1 << 1;
for (int i = 0; i <= 6; i++) {
if ((outseg1 & digitmask) == digitmask) {
outbuff[(i + 2)] = segments1[i];
}
if ((outseg1 & digitmask) != digitmask) {
outbuff[i + 2] = 0x00;
}
outseg1 = outseg1 << 1;
}
outseg0 = cifraseg[vals[0]];
outseg0 = outseg0 << 1;
for (int i = 0; i <= 6; i++) {
if ((outseg0 & digitmask) == digitmask) {
outbuff[i + 9] = segments0[i];
}
if ((outseg0 & digitmask)!= digitmask) {
outbuff[i + 9] = 0x00;
}
outseg0 = outseg0 << 1;
}
buffupdate = 0;
}
}
void displayout() {
PORTD = outbuff[dyncounter];
DDRD = segmentsmask[dyncounter];
}
void setup() {
// Заводим таймер1 в режим СТС на 10 КГц
cli();
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 24;
TCCR1B |= (1 << WGM12);
TCCR1B |= (1 << CS11) | (1 << CS10);
TIMSK1 |= (1 << OCIE1A);
sei();
}
ISR(TIMER1_COMPA_vect) {
if (buffupdate == 0) {
displayout();
}
dyncounter += 1;
if (dyncounter > 15) {
buffupdate = 1;
buffops();
dyncounter = 0;
}
timecontr += 1;
if (timecontr >= 1500) {
val += 1;
timecontr = 0;
}
if (val >= 200) {
val = 0;
}
}
void loop() {
}
Код: Выделить всё
ISR(TIMER1_COMPA_vect) {
if (buffupdate == 0) {
displayout();
}
if (++dyncounter > 15) {
buffupdate = 1;
buffops();
dyncounter = 0;
}
if (++timecontr >= 1500) {
if (++val >= 200) { // проверка только тогда, когда произошло приращение, а не всегда, выглядит более логичной
val = 0;
}
timecontr = 0;
}
}Код: Выделить всё
void digdisass() {
if (val >= 100) {
vals[1] = (val - 100) / 10;
vals[0] = val % 10;
}
if (val < 100) {
vals[1] = val / 10;
vals[0] = val % 10;
}
}Код: Выделить всё
void digdisass() {
if (val >= 100) {
vals[1] = (val - 100) / 10;
}
else {
vals[1] = val / 10;
}
vals[0] = val % 10;
}
Код: Выделить всё
void digdisass() {
vals[1] = (val >= 100) ? (val - 100) / 10 : val / 10; // тернарный оператор "?". На мой взгляд, читается хуже.
vals[0] = val % 10;
}
Код: Выделить всё
for (int i = 0; i <= 6; i++) {
if ((outseg1 & digitmask) == digitmask) {
outbuff[(i + 2)] = segments1[i];
}
if ((outseg1 & digitmask) != digitmask) {
outbuff[i + 2] = 0x00;
}
outseg1 = outseg1 << 1;
}