Семисегментный LED-индикатор. Эффекты анимации

Обсуждаем контроллеры компании Atmel.
Самсусамыч

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Самсусамыч »

Я вот тоже раде спортивного интереса попробовал написать пример для динамической индикации с использованием любых пинов для сегментов и разрядов… код в моём варианте увеличился от прежнего на 77 слов. Но это сходу без оптимизации… наверняка можно будет и минимизировать код, если очень понадобится… :)

Прошивка:
Test.hex
Для индикатора ОА, сегменты: a – PD0; b – PD1; c – PB3; d – PD3; e – PB1; f – PB5; g – PB6; h – PD6. Разряды (с лева на права): 1 – PB2; 2 – PB0; 3 – PB4; 4 – PB7.
МК тини2313, тактовая 8 МГц. На индикатор выводится «1234». :beer:
1.png
Реклама
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Demiurg »

Ггг. Хекс. Сразу в мозг. Нормально, че... Код в студию.
Реклама
Самсусамыч

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Самсусамыч »

Пишу на АВ (Algorithm Builder), так что мало кого он заинтересует. Да и примеры мои далеки от совершенства. :)
BlackKilkennyCat
Собутыльник Кота
Сообщения: 2905
Зарегистрирован: Ср ноя 29, 2017 06:58:50

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение BlackKilkennyCat »

какие проблемы с hex? легкое движение руки, и...
Спойлер

Код: Выделить всё

;
; +-------------------------------------------------------------------------+
; |   This file	has been generated by The Interactive Disassembler (IDA)       |
; +-------------------------------------------------------------------------+
;
; Input	MD5   :	1A03D017D8A1BBA575865473C53B776B
; Input	CRC32 :	53863590

; ---------------------------------------------------------------------------
; File Name   :	E:\user\Downloads\Test.hex
; Format      :	Intel Hex Object Format

; Processor	  : AVR	[AT90S2313]
; Target assembler: AVR	Assembler

; =====================

; Segment type:	Pure code
.CSEG ;	ROM
		.org 0
		rjmp	__RESET		; Processor reset
		.org 1

; =============== S U B	R O U T	I N E =====================

; External Interrupt Request 0

		; public INT0_
INT0_:
		reti
; End of function INT0_

		.org 2

; =============== S U B	R O U T	I N E =====================

; External Interrupt Request 1

		; public INT1_
INT1_:
		reti
; End of function INT1_

		.org 3

; =============== S U B	R O U T	I N E =====================

; Timer/Counter1 Capture Event

		; public TIMER1_CAPT1
TIMER1_CAPT1:
		reti
; End of function TIMER1_CAPT1

		.org 4

; =============== S U B	R O U T	I N E =====================

; Timer/Counter1 Compare Match

		; public TIMER1_COMP1
TIMER1_COMP1:
		reti
; End of function TIMER1_COMP1

		.org 5

; =============== S U B	R O U T	I N E =====================

; Timer/Counter1 Overflow

		; public TIMER1_OVF1
TIMER1_OVF1:
		reti
; End of function TIMER1_OVF1

; ---------------------------------------------------------------------------
		.org 6
		rjmp	TIMER0_OVF0	; Timer/Counter0 Overflow
		.org 7

; =============== S U B	R O U T	I N E =====================

; UART,	RX Complete

		; public UART_RX
UART_RX:
		reti
; End of function UART_RX

		.org 8

; =============== S U B	R O U T	I N E =====================

; UART Data Register Empty

		; public UART_UDRE
UART_UDRE:
		reti
; End of function UART_UDRE

		.org 9

; =============== S U B	R O U T	I N E =====================

; UART,	TX Complete

		; public UART_TX
UART_TX:
		reti
; End of function UART_TX

		.org 0xA

; =============== S U B	R O U T	I N E =====================

; Analog Comparator

		; public ANA_COMP
ANA_COMP:
		reti
; End of function ANA_COMP

; ---------------------------------------------------------------------------
		reti
; ---------------------------------------------------------------------------
		reti
; ---------------------------------------------------------------------------
		reti
; ---------------------------------------------------------------------------
		reti
; ---------------------------------------------------------------------------
		reti
; ---------------------------------------------------------------------------
		reti
; ---------------------------------------------------------------------------
		reti
; ---------------------------------------------------------------------------
		reti
; ---------------------------------------------------------------------------
		.dw 0xF9C0 ; Ащ
		.dw 0xB0A4, 0x9299, 0xF882, 0x9080

; =============== S U B	R O U T	I N E =====================

; Timer/Counter0 Overflow

		; public TIMER0_OVF0
TIMER0_OVF0:				; CODE XREF: ROM:0006j
		push	r16
		push	r17
		in	r16, SREG	; Status Register
		push	r16
		rcall	sub_92
		ldi	r17, 0
		cp	r12, r17
		breq	loc_21
		lsr	r11

loc_21:					; CODE XREF: TIMER0_OVF0+7j
		inc	r12
		ldi	r17, 5
		cp	r12, r17
		brcs	loc_29
		ldi	r16, 1
		mov	r12, r16
		ldi	r16, 8
		mov	r11, r16

loc_29:					; CODE XREF: TIMER0_OVF0+Cj
		push	r11
		ldi	r17, 1
		cp	r12, r17
		brne	loc_2F
		lds	r11, unk_10006A

loc_2F:					; CODE XREF: TIMER0_OVF0+14j
		ldi	r17, 2
		cp	r12, r17
		brne	loc_34
		lds	r11, unk_10006B

loc_34:					; CODE XREF: TIMER0_OVF0+19j
		ldi	r17, 3
		cp	r12, r17
		brne	loc_39
		lds	r11, unk_10006C

loc_39:					; CODE XREF: TIMER0_OVF0+1Ej
		ldi	r17, 4
		cp	r12, r17
		brne	loc_3E
		lds	r11, unk_10006D

loc_3E:					; CODE XREF: TIMER0_OVF0+23j
		ldi	r28, 0x60 ; '`'
		ldi	r29, 0
		add	r28, r11
		ldi	r17, 0
		adc	r29, r17
		ld	r11, Y
		rcall	sub_5B
		pop	r11
		rcall	sub_97
		pop	r16
		out	SREG, r16	; Status Register
		pop	r17
		pop	r16
		reti
; End of function TIMER0_OVF0


; =============== S U B	R O U T	I N E =====================


sub_4C:					; CODE XREF: __RESET+14p
		ldi	r30, 0x26 ; '&'
		ldi	r31, 0
		ldi	r28, 0x60 ; '`'
		ldi	r29, 0
		ldi	r18, 0xA

loc_51:					; CODE XREF: sub_4C+8j
		lpm	r16, Z+
		st	Y+, r16
		dec	r18
		brne	loc_51
		ret
; End of function sub_4C


; =============== S U B	R O U T	I N E =====================


sub_56:					; CODE XREF: __RESET+2p
		ser	r16
		out	DDRB, r16	; Port B Data Direction	Register
		ldi	r16, 0xF
		out	DDRD, r16	; Port D Data Direction	Register
		ret
; End of function sub_56


; =============== S U B	R O U T	I N E =====================


sub_5B:					; CODE XREF: TIMER0_OVF0+2Cp
		ldi	r18, 8

loc_5C:					; CODE XREF: sub_5B+35j
		lsr	r11
		brcc	loc_77
		cpi	r18, 8
		brne	loc_61
		sbi	PORTD, PORTD0	; Port D Data Register

loc_61:					; CODE XREF: sub_5B+4j
		cpi	r18, 7
		brne	loc_64
		sbi	PORTD, PORTD1	; Port D Data Register

loc_64:					; CODE XREF: sub_5B+7j
		cpi	r18, 6
		brne	loc_67
		sbi	PORTB, PORTB3	; Port B Data Register

loc_67:					; CODE XREF: sub_5B+Aj
		cpi	r18, 5
		brne	loc_6A
		sbi	PORTD, PORTD3	; Port D Data Register

loc_6A:					; CODE XREF: sub_5B+Dj
		cpi	r18, 4
		brne	loc_6D
		sbi	PORTB, PORTB1	; Port B Data Register

loc_6D:					; CODE XREF: sub_5B+10j
		cpi	r18, 3
		brne	loc_70
		sbi	PORTB, PORTB5	; Port B Data Register

loc_70:					; CODE XREF: sub_5B+13j
		cpi	r18, 2
		brne	loc_73
		sbi	PORTB, PORTB6	; Port B Data Register

loc_73:					; CODE XREF: sub_5B+16j
		cpi	r18, 1
		brne	loc_76
		sbi	PORTD, PORTD6	; Port D Data Register

loc_76:					; CODE XREF: sub_5B+19j
		rjmp	loc_8F
; ---------------------------------------------------------------------------

loc_77:					; CODE XREF: sub_5B+2j
		cpi	r18, 8
		brne	loc_7A
		cbi	PORTD, PORTD0	; Port D Data Register

loc_7A:					; CODE XREF: sub_5B+1Dj
		cpi	r18, 7
		brne	loc_7D
		cbi	PORTD, PORTD1	; Port D Data Register

loc_7D:					; CODE XREF: sub_5B+20j
		cpi	r18, 6
		brne	loc_80
		cbi	PORTB, PORTB3	; Port B Data Register

loc_80:					; CODE XREF: sub_5B+23j
		cpi	r18, 5
		brne	loc_83
		cbi	PORTD, PORTD3	; Port D Data Register

loc_83:					; CODE XREF: sub_5B+26j
		cpi	r18, 4
		brne	loc_86
		cbi	PORTB, PORTB1	; Port B Data Register

loc_86:					; CODE XREF: sub_5B+29j
		cpi	r18, 3
		brne	loc_89
		cbi	PORTB, PORTB5	; Port B Data Register

loc_89:					; CODE XREF: sub_5B+2Cj
		cpi	r18, 2
		brne	loc_8C
		cbi	PORTB, PORTB6	; Port B Data Register

loc_8C:					; CODE XREF: sub_5B+2Fj
		cpi	r18, 1
		brne	loc_8F
		cbi	PORTD, PORTD6	; Port D Data Register

loc_8F:					; CODE XREF: sub_5B:loc_76j sub_5B+32j
		dec	r18
		brne	loc_5C
		ret
; End of function sub_5B


; =============== S U B	R O U T	I N E =====================


sub_92:					; CODE XREF: TIMER0_OVF0+4p
		cbi	PORTB, PORTB2	; Port B Data Register
		cbi	PORTB, PORTB0	; Port B Data Register
		cbi	PORTB, PORTB4	; Port B Data Register
		cbi	PORTB, PORTB7	; Port B Data Register
		ret
; End of function sub_92


; =============== S U B	R O U T	I N E =====================


sub_97:					; CODE XREF: TIMER0_OVF0+2Ep
		ldi	r17, 8
		cp	r11, r17
		brne	loc_9B
		sbi	PORTB, PORTB2	; Port B Data Register

loc_9B:					; CODE XREF: sub_97+2j
		ldi	r17, 4
		cp	r11, r17
		brne	loc_9F
		sbi	PORTB, PORTB0	; Port B Data Register

loc_9F:					; CODE XREF: sub_97+6j
		ldi	r17, 2
		cp	r11, r17
		brne	loc_A3
		sbi	PORTB, PORTB4	; Port B Data Register

loc_A3:					; CODE XREF: sub_97+Aj
		ldi	r17, 1
		cp	r11, r17
		brne	locret_A7
		sbi	PORTB, PORTB7	; Port B Data Register

locret_A7:				; CODE XREF: sub_97+Ej
		ret
; End of function sub_97


; =============== S U B	R O U T	I N E =====================

; Processor reset

		; public __RESET
__RESET:				; CODE XREF: ROM:0000j
		ldi	r16, 0xDF ; 'Я'
		out	SPL, r16	; Stack	Pointer
		rcall	sub_56
		ldi	r30, 0x60 ; '`'
		ldi	r31, 0

loc_AD:					; CODE XREF: __RESET+Aj
		ldi	r16, 0
		st	Z+, r16
		cpi	r30, 0xE0 ; 'а'
		ldi	r17, 0
		cpc	r31, r17
		brne	loc_AD
		ldi	r30, 0x1E
		ldi	r31, 0

loc_B5:					; CODE XREF: __RESET+Fj
		dec	r30
		st	Z, r16
		brne	loc_B5
		ldi	r16, 3
		out	TCCR0, r16	; Timer/Counter0 Control Register
		ldi	r16, 2
		out	TIMSK, r16	; Timer/Counter	Interrupt Mask Register
		rcall	sub_4C
		ldi	r16, 8
		mov	r11, r16
		sei
		ldi	r16, 1
		sts	unk_10006A, r16
		ldi	r16, 2
		sts	unk_10006B, r16
		ldi	r16, 3
		sts	unk_10006C, r16
		ldi	r16, 4
		sts	unk_10006D, r16

loc_CC:					; CODE XREF: __RESET+25j
		nop
		rjmp	loc_CC
; End of function __RESET

; ---------------------------------------------------------------------------
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение ARV »

про сегменты на разных портах с оптимизацией "вручную" я уже как-то писал... наилуший результат получается в том случае, если есть возможность произвольно тасовать сегменты по пинам. это я о ситуации, когда при создании знакогенератора мы выбираем, что по битам байта "символа" сегменты располагаются в порядке abcdefgh, а потом корячимся с тем, чтобы на порт D выводить --с-ehga, и на порт C dbgf---- (минусами - незадействованные пины).
так вот, если сразу в "знакогенераторе" заложить расположение сегментов dbcgehga, то и обработчик прерывания может получится гораздо оптимальнее.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Реклама
Самсусамыч

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Самсусамыч »

легкое движение руки, и...
Это чо мой код так выглядит? :facepalm: Или это Ваш код? :)
Реклама
BlackKilkennyCat
Собутыльник Кота
Сообщения: 2905
Зарегистрирован: Ср ноя 29, 2017 06:58:50

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение BlackKilkennyCat »

Он самый. Дизассемблирован из хекс
Самсусамыч

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Самсусамыч »

:)) У меня в АВ он выглядит посимпатичней… исходник для АВ:
7_seg_test_pin_OA.zip
1.png
2.png
3.png
Последний раз редактировалось Самсусамыч Вс авг 23, 2020 20:15:32, всего редактировалось 1 раз.
BlackKilkennyCat
Собутыльник Кота
Сообщения: 2905
Зарегистрирован: Ср ноя 29, 2017 06:58:50

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение BlackKilkennyCat »

у меня нет АВ, но охотно верю. Хотя иногда бывает и наоборот: мою дикую кашу из Си оптимизирует до красивого.
Вообще, меня в последнее время как-то тянет уйти в асм, после возни с ST7FOX (пример для которого тут и был выше опубликован)

Пока писал, картинки появились. Да, Красиво. Напоминает наш ДРАКОН (Дружелюбный Русский Алгоритмический язык, Который Обеспечивает Наглядность)
Самсусамыч

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Самсусамыч »

[uquote="BlackKilkennyCat",url="/forum/viewtopic.php?p=3882886#p3882886"]Да, Красиво. Напоминает наш ДРАКОН (Дружелюбный Русский Алгоритмический язык, Который Обеспечивает Наглядность)[/uquote]
Да, такой вид кода для меня просто как сказка… нравится очень… Геннадий Громов молодец… жаль что больше его не поддерживает.
BlackKilkennyCat
Собутыльник Кота
Сообщения: 2905
Зарегистрирован: Ср ноя 29, 2017 06:58:50

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение BlackKilkennyCat »

Да, мой друг ДРАКОН очень полюбил и мне рассказал. Мне понравилось, но привык к классическому варианту, тем более, что современные среды очень хорошо всё подсвечивают. В блок-схемах только общий проект рисую, ну или что-то совсем запутанное.
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Demiurg »

Я поначалу заинтересовался ДРАКОН-ом. Потом понял, что не для меня. У Паронджанова я выхватил правила составления алгоритмов. Вот это действительно полезная вещь. Приучает составлять вменяемые читабельные, структурированные алгоритмы. А то иной порой смотришь на алгоритм и думаешь, что такое забористое автор курил... Блоки расставлены как попало, хрен поймешь...
BlackKilkennyCat
Собутыльник Кота
Сообщения: 2905
Зарегистрирован: Ср ноя 29, 2017 06:58:50

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение BlackKilkennyCat »

Да, именно правила там и ценны, на мой взгляд. Облегчают чтение, минимизируют ошибки
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Demiurg »

Предлагаю вашему вниманию два способа динамической индикации. Один реализован в лоб. If-ы и установка пинов вызовом функций. Второй - табличный метод.
Время прогона при первом методе установки общих выводов и сегментов занимает 133 такта, 8.31 мкс при тактовой частоте 16 мгц.
При втором методе 545 тактов и 34 мкс.

При создании проекта ставились следующие задачи: Выбор активного уровня сигнала для сегментов и общих выводов индикаторов. Произвольный выбор портов и пинов МК. В какой-то мере автора топика наверное следует поблагодарить. Давно подумывал довести до ума.

*.h
Спойлер

Код: Выделить всё

//==================
#ifndef SEVEN_SEGM_LED_IND_H

#define SEVEN_SEGM_LED_IND_H

#include "seven_segm_led_ind.h"
//==================

//==================
#include "main_def_func.h"
//==================

//==================
#define SEGM_A_DDR  DDRC
#define SEGM_A_PORT PORTC
//------------------------------------------------------------------------
#define SEGM_B_DDR  DDRC
#define SEGM_B_PORT PORTC
//------------------------------------------------------------------------
#define SEGM_C_DDR  DDRC
#define SEGM_C_PORT PORTC
//------------------------------------------------------------------------
#define SEGM_D_DDR  DDRC
#define SEGM_D_PORT PORTC
//------------------------------------------------------------------------
#define SEGM_E_DDR  DDRC
#define SEGM_E_PORT PORTC
//------------------------------------------------------------------------
#define SEGM_F_DDR  DDRC
#define SEGM_F_PORT PORTC
//------------------------------------------------------------------------
#define SEGM_G_DDR  DDRC
#define SEGM_G_PORT PORTC
//------------------------------------------------------------------------
#define SEGM_H_DDR  DDRC
#define SEGM_H_PORT PORTC
//==================

//==================
//----------------------------- Пины МК ----------------------------------
//-------------------------- Segments Outputs ----------------------------
#define S_A_OUT     6
#define S_B_OUT     7 //     A
#define S_C_OUT     3 //   F   B
#define S_D_OUT     2 //     G
#define S_E_OUT     1 //   E   C
#define S_F_OUT     5 //     D  H
#define S_G_OUT     4
#define S_H_OUT     0
//==================

//==================
#define COMM_1_DDR  DDRA
#define COMM_1_PORT PORTA
//------------------------------------------------------------------------
#define COMM_2_DDR  DDRA
#define COMM_2_PORT PORTA
//------------------------------------------------------------------------
#define COMM_3_DDR  DDRA
#define COMM_3_PORT PORTA
//------------------------------------------------------------------------
#define COMM_4_DDR  DDRA
#define COMM_4_PORT PORTA
//------------------------------------------------------------------------
#define COMM_5_DDR  DDRA
#define COMM_5_PORT PORTA
//------------------------------------------------------------------------
#define COMM_6_DDR  DDRA
#define COMM_6_PORT PORTA
//==================

//==================
//----------------------------- Пины МК ----------------------------------
//-------------------------- Commons Outputs -----------------------------
#define COMM_1     2
#define COMM_2     3
#define COMM_3     4
#define COMM_4     5
#define COMM_5     6
#define COMM_6     7
//------------------------------------------------------------------------
#define C_1        0
#define C_2        1
#define C_3        2
#define C_4        3
#define C_5        4
#define C_6        5
//==================

//==================
//------------------------- Segment numeric value ------------------------
#define S_A        0
#define S_B        1
#define S_C        2
#define S_D        3
#define S_E        4
#define S_F        5
#define S_G        6
#define S_H        7
//------------------------- Segment Boolean Value ------------------------
#define BV_S_A    (1<<S_A)
#define BV_S_B    (1<<S_B)
#define BV_S_C    (1<<S_C)
#define BV_S_D    (1<<S_D)
#define BV_S_E    (1<<S_E)
#define BV_S_F    (1<<S_F)
#define BV_S_G    (1<<S_G)
#define BV_S_H    (1<<S_H)
//==================

//==================
#define ZERO      (BV_S_A | BV_S_B | BV_S_C | BV_S_D | BV_S_E | BV_S_F)
#define ONE       (BV_S_B | BV_S_C)
#define TWO       (BV_S_A | BV_S_B | BV_S_D | BV_S_E | BV_S_G)
#define THREE     (BV_S_A | BV_S_B | BV_S_C | BV_S_D | BV_S_G)
#define FOUR      (BV_S_B | BV_S_C | BV_S_F | BV_S_G)
#define FIVE      (BV_S_A | BV_S_C | BV_S_D | BV_S_F | BV_S_G)
#define SIX       (BV_S_A | BV_S_C | BV_S_D | BV_S_E | BV_S_F | BV_S_G)
#define SEVEN     (BV_S_A | BV_S_B | BV_S_C)
#define EIGHT     (BV_S_A | BV_S_B | BV_S_C | BV_S_D | BV_S_E | BV_S_F | BV_S_G)
#define NINE      (BV_S_A | BV_S_B | BV_S_C | BV_S_D | BV_S_F | BV_S_G)
#define SPACE      0

#define CHAR_SPACE 10
//==================

//==================
#define MAX_LED_INDS 6
//==================

//==================
extern u08 dsp_buf [];

void clr_dsp_buf (void);
//==================

//==================
// Typedefs:
typedef void (*FuncPtr)(void);
//==================

//==================
typedef struct segments_switch
{
   FuncPtr segment_hi;
   FuncPtr segment_low;
} segments_switch;
//==================

//==================
void set_proc_7_segm_ind_on (void);
void set_proc_7_segm_ind_off (void);
void proc_7_segm_ind (void);
//==================

//==================
void Set_Segm_A_Hi (void);
void Set_Segm_A_Low (void);

void Set_Segm_B_Hi (void);
void Set_Segm_B_Low (void);

void Set_Segm_C_Hi (void);
void Set_Segm_C_Low (void);

void Set_Segm_D_Hi (void);
void Set_Segm_D_Low (void);

void Set_Segm_E_Hi (void);
void Set_Segm_E_Low (void);

void Set_Segm_F_Hi (void);
void Set_Segm_F_Low (void);

void Set_Segm_G_Hi (void);
void Set_Segm_G_Low (void);

void Set_Segm_H_Hi (void);
void Set_Segm_H_Low (void);
//==================

//==================
#define _Set_Segm_A_Hi()  set_bit (SEGM_A_PORT, S_A_OUT)
#define _Set_Segm_A_Low() clr_bit (SEGM_A_PORT, S_A_OUT)

#define _Set_Segm_B_Hi()  set_bit (SEGM_B_PORT, S_B_OUT)
#define _Set_Segm_B_Low() clr_bit (SEGM_B_PORT, S_B_OUT)

#define _Set_Segm_C_Hi()  set_bit (SEGM_C_PORT, S_C_OUT)
#define _Set_Segm_C_Low() clr_bit (SEGM_C_PORT, S_C_OUT)

#define _Set_Segm_D_Hi()  set_bit (SEGM_D_PORT, S_D_OUT)
#define _Set_Segm_D_Low() clr_bit (SEGM_D_PORT, S_D_OUT)

#define _Set_Segm_E_Hi()  set_bit (SEGM_E_PORT, S_E_OUT)
#define _Set_Segm_E_Low() clr_bit (SEGM_E_PORT, S_E_OUT)

#define _Set_Segm_F_Hi()  set_bit (SEGM_F_PORT, S_F_OUT)
#define _Set_Segm_F_Low() clr_bit (SEGM_F_PORT, S_F_OUT)

#define _Set_Segm_G_Hi()  set_bit (SEGM_G_PORT, S_G_OUT)
#define _Set_Segm_G_Low() clr_bit (SEGM_G_PORT, S_G_OUT)

#define _Set_Segm_H_Hi()  set_bit (SEGM_H_PORT, S_H_OUT)
#define _Set_Segm_H_Low() clr_bit (SEGM_H_PORT, S_H_OUT)
//==================

//==================
void Set_Comm_1_Hi (void);
void Set_Comm_1_Low (void);

void Set_Comm_2_Hi (void);
void Set_Comm_2_Low (void);

void Set_Comm_3_Hi (void);
void Set_Comm_3_Low (void);

void Set_Comm_4_Hi (void);
void Set_Comm_4_Low (void);

void Set_Comm_5_Hi (void);
void Set_Comm_5_Low (void);

void Set_Comm_6_Hi (void);
void Set_Comm_6_Low (void);
//==================

//==================
#define _Set_Comm_1_Hi()  set_bit (COMM_1_PORT, COMM_1)
#define _Set_Comm_1_Low() clr_bit (COMM_1_PORT, COMM_1)

#define _Set_Comm_2_Hi()  set_bit (COMM_2_PORT, COMM_2)
#define _Set_Comm_2_Low() clr_bit (COMM_2_PORT, COMM_2)

#define _Set_Comm_3_Hi()  set_bit (COMM_3_PORT, COMM_3)
#define _Set_Comm_3_Low() clr_bit (COMM_3_PORT, COMM_3)

#define _Set_Comm_4_Hi()  set_bit (COMM_4_PORT, COMM_4)
#define _Set_Comm_4_Low() clr_bit (COMM_4_PORT, COMM_4)

#define _Set_Comm_5_Hi()  set_bit (COMM_5_PORT, COMM_5)
#define _Set_Comm_5_Low() clr_bit (COMM_5_PORT, COMM_5)

#define _Set_Comm_6_Hi()  set_bit (COMM_6_PORT, COMM_6)
#define _Set_Comm_6_Low() clr_bit (COMM_6_PORT, COMM_6)
//==================

//==================
#define HI  true
#define LOW false
//==================

//==================
void Set_Commons_Level (bool level);
void Set_Segments_Level (bool level);
//==================

//==================
void handle_commons (void);
void handle_segments (void);
//==================

//==================
void handle_segments_temp (void);
void handle_commons_temp (void);
//==================

//==================
#endif
//==================
*.c
Спойлер

Код: Выделить всё

//==================
#include "seven_segm_led_ind.h"
//==================

//==================
__flash FUNC tab_commons_hi [6] =
{
   Set_Comm_1_Hi,
   Set_Comm_2_Hi,
   Set_Comm_3_Hi,
   Set_Comm_4_Hi,
   Set_Comm_5_Hi,
   Set_Comm_6_Hi,
};

__flash FUNC tab_commons_low [6] =
{
   Set_Comm_1_Low,
   Set_Comm_2_Low,
   Set_Comm_3_Low,
   Set_Comm_4_Low,
   Set_Comm_5_Low,
   Set_Comm_6_Low,
};
//==================

//==================
__flash FUNC tab_segments_hi [8] =
{
   Set_Segm_A_Hi,
   Set_Segm_B_Hi,
   Set_Segm_C_Hi,
   Set_Segm_D_Hi,
   Set_Segm_E_Hi,
   Set_Segm_F_Hi,
   Set_Segm_G_Hi,
   Set_Segm_H_Hi,
};

__flash FUNC tab_segments_low [8] =
{
   Set_Segm_A_Low,
   Set_Segm_B_Low,
   Set_Segm_C_Low,
   Set_Segm_D_Low,
   Set_Segm_E_Low,
   Set_Segm_F_Low,
   Set_Segm_G_Low,
   Set_Segm_H_Low,
};
//==================

//==================
u08 __flash table_7_segm_char [11] =
{
   ZERO,    ONE,
   TWO,     THREE,
   FOUR,    FIVE,
   SIX,     SEVEN,
   EIGHT,   NINE,
   SPACE,
};
//==================

//==================
soft_timer ST_PROC_7_SEGM_IND;
//------------------------------------------------------------------------
u08 dsp_buf [MAX_LED_INDS];
//------------------------------------------------------------------------
// Очистка буфера дисплея.

u08 dsp_buf [MAX_LED_INDS];

void clr_dsp_buf (void)
{
   for (u08 i = 0; i < MAX_LED_INDS; i++)
      dsp_buf [i] = CHAR_SPACE;
}
//==================

//==================
static u08 _proc_7_segm_ind;
static u08 cnt_commons;


void set_proc_7_segm_ind_on (void)
{
   _proc_7_segm_ind = 1;
}

void set_proc_7_segm_ind_off (void)
{
   _proc_7_segm_ind = 0;
}

void proc_7_segm_ind (void)
{
   switch (_proc_7_segm_ind)
   {
      case 0:
         break;

      case 1:
         cnt_commons = 0;
         set_soft_timer (ST_PROC_7_SEGM_IND, 1, 1);
         _proc_7_segm_ind = 2;
         break;

      case 2:
         if (handle_soft_timer (ST_PROC_7_SEGM_IND))
         {
//            handle_commons_temp ();
//            handle_segments_temp ();

            handle_commons ();
            handle_segments ();
            if (++cnt_commons >= MAX_LED_INDS) cnt_commons = 0;
         }
         break;

      default:
         break;
   }
}
//==================

//==================
void Set_Segm_A_Hi (void)  {_Set_Segm_A_Hi ();}
void Set_Segm_A_Low (void) {_Set_Segm_A_Low ();}

void Set_Segm_B_Hi (void)  {_Set_Segm_B_Hi ();}
void Set_Segm_B_Low (void) {_Set_Segm_B_Low ();}

void Set_Segm_C_Hi (void)  {_Set_Segm_C_Hi ();}
void Set_Segm_C_Low (void) {_Set_Segm_C_Low ();}

void Set_Segm_D_Hi (void)  {_Set_Segm_D_Hi ();}
void Set_Segm_D_Low (void) {_Set_Segm_D_Low ();}

void Set_Segm_E_Hi (void)  {_Set_Segm_E_Hi ();}
void Set_Segm_E_Low (void) {_Set_Segm_E_Low ();}

void Set_Segm_F_Hi (void)  {_Set_Segm_F_Hi ();}
void Set_Segm_F_Low (void) {_Set_Segm_F_Low ();}

void Set_Segm_G_Hi (void)  {_Set_Segm_G_Hi ();}
void Set_Segm_G_Low (void) {_Set_Segm_G_Low ();}

void Set_Segm_H_Hi (void)  {_Set_Segm_H_Hi ();}
void Set_Segm_H_Low (void) {_Set_Segm_H_Low ();}
//==================

//==================
void Set_Comm_1_Hi (void)  {_Set_Comm_1_Hi ();}
void Set_Comm_1_Low (void) {_Set_Comm_1_Low ();}

void Set_Comm_2_Hi (void)  {_Set_Comm_2_Hi ();}
void Set_Comm_2_Low (void) {_Set_Comm_2_Low ();}

void Set_Comm_3_Hi (void)  {_Set_Comm_3_Hi ();}
void Set_Comm_3_Low (void) {_Set_Comm_3_Low ();}

void Set_Comm_4_Hi (void)  {_Set_Comm_4_Hi ();}
void Set_Comm_4_Low (void) {_Set_Comm_4_Low ();}

void Set_Comm_5_Hi (void)  {_Set_Comm_5_Hi ();}
void Set_Comm_5_Low (void) {_Set_Comm_5_Low ();}

void Set_Comm_6_Hi (void)  {_Set_Comm_6_Hi ();}
void Set_Comm_6_Low (void) {_Set_Comm_6_Low ();}
//==================

//==================
static bool commons_level;

void Set_Commons_Level (bool level)
{
   commons_level = level;
}

void handle_commons (void)
{
   u08 a = tab_bv [cnt_commons]; // Битовая позиция commons.

   for (u08 i = 0; i < MAX_LED_INDS; i++)
   {
      if (commons_level == HI)
      {
         if (a & (1<<0)) tab_commons_hi [i] ();
         else            tab_commons_low [i] ();
      }
      else
      {
         if (a & (1<<0)) tab_commons_low [i] ();
         else            tab_commons_hi [i] ();
      }

      a >>= 1;
   }
}
//==================

//==================
static bool segments_level;

void Set_Segments_Level (bool level)
{
   segments_level = level;
}

void handle_segments (void)
{
   u08 a = table_7_segm_char [dsp_buf [cnt_commons]];

   for (u08 i = 0; i < 8; i++)
   {
      if (segments_level == HI)
      {
         if (a & (1<<0)) tab_segments_hi [i] ();
         else            tab_segments_low [i] ();
      }
      else
      {
         if (a & (1<<0)) tab_segments_low [i] ();
         else            tab_segments_hi [i] ();
      }

      a >>= 1;
   }
}
//==================

//==================
void handle_segments_temp (void)
{
   u08 a = table_7_segm_char [dsp_buf [cnt_commons]];

   if (segments_level)
   {
      if (a & (1<<S_A)) Set_Segm_A_Hi ();
      else              Set_Segm_A_Low ();

      if (a & (1<<S_B)) Set_Segm_B_Hi ();
      else              Set_Segm_B_Low ();

      if (a & (1<<S_C)) Set_Segm_C_Hi ();
      else              Set_Segm_C_Low ();

      if (a & (1<<S_D)) Set_Segm_D_Hi ();
      else              Set_Segm_D_Low ();

      if (a & (1<<S_E)) Set_Segm_E_Hi ();
      else              Set_Segm_E_Low ();

      if (a & (1<<S_F)) Set_Segm_F_Hi ();
      else              Set_Segm_F_Low ();

      if (a & (1<<S_G)) Set_Segm_G_Hi ();
      else              Set_Segm_G_Low ();

      if (a & (1<<S_H)) Set_Segm_H_Hi ();
      else              Set_Segm_H_Low ();
   }
   else
   {
      if (a & (1<<S_A)) Set_Segm_A_Low ();
      else              Set_Segm_A_Hi ();

      if (a & (1<<S_B)) Set_Segm_B_Low ();
      else              Set_Segm_B_Hi ();

      if (a & (1<<S_C)) Set_Segm_C_Low ();
      else              Set_Segm_C_Hi ();

      if (a & (1<<S_D)) Set_Segm_D_Low ();
      else              Set_Segm_D_Hi ();

      if (a & (1<<S_E)) Set_Segm_E_Low ();
      else              Set_Segm_E_Hi ();

      if (a & (1<<S_F)) Set_Segm_F_Low ();
      else              Set_Segm_F_Hi ();

      if (a & (1<<S_G)) Set_Segm_G_Low ();
      else              Set_Segm_G_Hi ();

      if (a & (1<<S_H)) Set_Segm_H_Low ();
      else              Set_Segm_H_Hi ();
   }
}
//==================

//==================
void handle_commons_temp (void)
{
   u08 a = tab_bv [cnt_commons]; // Битовая позиция commons.

   if (commons_level == HI)
   {
      if (a & (1<<C_1)) Set_Comm_1_Hi ();
      else              Set_Comm_1_Low ();

      if (a & (1<<C_2)) Set_Comm_2_Hi ();
      else              Set_Comm_2_Low ();

      if (a & (1<<C_3)) Set_Comm_3_Hi ();
      else              Set_Comm_3_Low ();

      if (a & (1<<C_4)) Set_Comm_4_Hi ();
      else              Set_Comm_4_Low ();

      if (a & (1<<C_5)) Set_Comm_5_Hi ();
      else              Set_Comm_5_Low ();

      if (a & (1<<C_6)) Set_Comm_6_Hi ();
      else              Set_Comm_6_Low ();
   }
   else
   {
      if (a & (1<<C_1)) Set_Comm_1_Low ();
      else              Set_Comm_1_Hi ();

      if (a & (1<<C_2)) Set_Comm_2_Low ();
      else              Set_Comm_2_Hi ();

      if (a & (1<<C_3)) Set_Comm_3_Low ();
      else              Set_Comm_3_Hi ();

      if (a & (1<<C_4)) Set_Comm_4_Low ();
      else              Set_Comm_4_Hi ();

      if (a & (1<<C_5)) Set_Comm_5_Low ();
      else              Set_Comm_5_Hi ();

      if (a & (1<<C_6)) Set_Comm_6_Low ();
      else              Set_Comm_6_Hi ();
   }
}
//==================
Изображение
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Reflector »

Так по сути ничего не поменялось... Ну ладно, дорабатываю свой небольшой демонстрационный класс:
Спойлер

Код: Выделить всё

template<Pins digits, Pins segs, bool CommonCatode = false>
class Semiseg
{
public:
	static void init()
	{
		PinList<segs, digits>::template mode<PinMode::PushPull>();
		digit = 0;
	}

	static void print(const char* buf)
	{
		put(digit, buf[digit]);
		if (++digit >= digits::Size) digit = 0;
	}

	static void put(char digit, char ch)
	{
		if (ch < '0' || ch > 'Y')  ch = 10;
		else ch -= '0';

		if constexpr (CommonCatode)
		{
			digits::write(~(1 << digit));
			segs::write(comCatodeTbl[ch]);
		}
		else
		{
			digits::write(1 << digit);
			segs::write(comAnodeTbl[ch]);
		}
	}

private:
	inline static uint8_t digit;

	static constexpr uint8_t comAnodeTbl[] =
	{
		0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0xFF, 0xFF, 0xFF, 0xFF,
		0xFF, 0xFF, 0xFF, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E, 0xC2, 0x89, 0xCF, 0xE1, 0xFF,
		0xC7, 0xFF, 0xAB, 0xC0, 0x8C, 0x98, 0xAF, 0x92, 0x87, 0xC1, 0xFF, 0xFF, 0xFF, 0x91
	};   // 0..Y
	static constexpr uint8_t comCatodeTbl[] =
	{
		0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x00, 0x00, 0x00, 0x00,
		0x00, 0x00, 0x00, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71, 0x3D, 0x76, 0x30, 0x1E, 0x00,
		0x38, 0x00, 0x54, 0x3F, 0x73, 0x67, 0x50, 0x6D, 0x78, 0x3E, 0x00, 0x00, 0x00, 0x6E
	};
};
Теперь он выводит строку из буфера(точки было лень добавлять:)), соответственно в таблицы добавились все буквы, которые можно на таких индикаторах вывести. Прописываем твои пины:

Код: Выделить всё

using segs = PinList<PC0, PC4, PC5, PC1, PC2, PC3, PC7, PC6>;
using digits = PinList<PA7, PA6, PA5, PA4, PA3, PA2>;
Semiseg<digits, segs> semiseg;

char buf[] = "123456";

while(true)
{
    delay_ms(1);
    semiseg.print(buf);
}
На Corteх-M0, у которого простенький набор команд, хотя есть полезный в данном случае сдвиг на заданное число бит, вызов print() отрабатывает за 63 такта. Но тут сегменты занимают весь порт, только они почему-то объявлены вперемешку, зачем нам это? Меняем последовательность сегментов на удобную для обработки:

Код: Выделить всё

using segs = PinList<PC7, PC6, PC5, PC4, PC3, PC2, PC1, PC0>;
Теперь сдвигать ничего не нужно, а для разрядов будет один сдвиг на 2 бита и все, т.е. никакого преимущества простенький кортекс уже не имеет. Замеряем и получает 33 такта, примерно столько же можно ожидать на AVR. Если, допустим, нужно 8 разрядов, то добавляем в списке digits два пина, если нужен общий катод, то передаем в качестве третьего параметра класса Semiseg - true.
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Demiurg »

И? Где произвольные порты, пины? AVR, напоминаю.
Последний раз редактировалось Demiurg Пн авг 24, 2020 16:09:09, всего редактировалось 1 раз.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение ARV »

заразили и меня, ироды :)))

классы, шаблоны - это, конечно, красиво, но и простой Си тоже не совсем плох. во всяком случае, гораздо понятнее:

Код: Выделить всё

#include <avr/io.h>
#include <avr/interrupt.h>

typedef struct{
	volatile uint8_t * port;
	uint8_t			   mask;
} seg_pin_t;

const __flash seg_pin_t pins[8] = {
	{&PORTB, _BV(0)},	// A
	{&PORTD, _BV(1)},	// B
	{&PORTB, _BV(2)},	// C
	{&PORTD, _BV(3)},	// D
	{&PORTB, _BV(4)},	// E
	{&PORTD, _BV(5)},	// F
	{&PORTB, _BV(6)},	// G
	{&PORTD, _BV(7)}	// H
};

volatile uint8_t data;

ISR(TIMER0_OVF_vect){
	volatile uint8_t *p;

	for(uint8_t i=0, m=1; m; i++, m<<=1){
		p = pins[i].port;
		*p = (*p & (~pins[i].mask)) | (data & m ? pins[i].mask : 0);
	}
}

что к чему:
1. описал структуру seg_pin_t, которая отвечает за распределение сегментов по любым портам. т.е. поле port - это адрес порта ВВ, а поле mask - это битовая маска соответствующего сегмента на этом самом порту.
2. создал массив "перекодировки" pins, в котором "распределил все сегменты знакогенератора ABCDEFGH по разным портам и пинам (пока для примера только PORTB и PORTD - чисто чтобы собрать проект).
3. в обработчике прерывания тупо беру данные (для теста просто байт data), и просматриваю массив pins, устанавливая нужные биты в нужных портах в соответствии с тем, что там за символ в data.

по листингу у меня вышло около 235 тактов на вывод символа, не считая пролога-эпилога обработчика прерывания. это не рекорд, но и не отстой, имхо. 100% гибкость и не так уж много тактов.

ну и сравните по понятности с ранее показанными исходниками...

P.S. само собой, всякие там переключения катодов-анодов, извлечение из массива самих данных, я не делал, т.к. эти "расходы" ресурсов все равно будут для любого варианта динамической индикации. и сложности в реализации это не представляет: в рамках моего подхода так же массивчик "катодов", и пусть они будут хоть все на разных пинах разных портов...

если принудить оптимизатор к разворачиванию циклов - будет вполне даже эффективно все скомпилировано.
Последний раз редактировалось ARV Пн авг 24, 2020 16:12:14, всего редактировалось 1 раз.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Reflector »

[uquote="Demiurg",url="/forum/viewtopic.php?p=3883182#p3883182"]И? Где произвольные порты, пины?[/uquote]
Как это где?

Код: Выделить всё

using segs = PinList<PC0, PC4, PC5, PC1, PC2, PC3, PC7, PC6>;
using digits = PinList<PA7, PA6, PA5, PA4, PA3, PA2>;
Прописываешь сюда любые пины с любых портов, а в digits еще и любое их количество, от 1 до 8.
AVR, напоминаю.
Без разницы какой мк, на AVR либа Чижова была минимум 10 лет назад. Я сам писал, моя либа более современная, но не под AVR...
Demiurg
Это не хвост, это антенна
Сообщения: 1480
Зарегистрирован: Ср июн 25, 2008 15:19:44
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение Demiurg »

[uquote="ARV",url="/forum/viewtopic.php?p=3883183#p3883183"]...[/uquote]
Хм, интересно, выложите плиз весь скомпилированный проект, и если можно сразу с файлом *.dbg для симуляции в студии. Усложняем. Выбор активного уровня для сегментов и общих выводов.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18546
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Семисегментный LED-индикатор. Эффекты анимации

Сообщение ARV »

Demiurg писал(а):выложите плиз весь скомпилированный проект
да нет у меня проекта... это чисто тест, посмотреть, что компилятор наворотит. ну и вручную посчитал такты по листингу.

проект придумывать надо, схему изобретать... лень.

Добавлено after 2 minutes 28 seconds:
Demiurg писал(а):Усложняем
когда-то пытался я сделать такое... чтобы одна прошивку умела работать с индикатором любого типа: OK и OA. сделать-то я сделал, да пользователям не понравилось. кроме, как баловством, эту идею я не назову. ну а на этапе компиляции все решается простой инверсией байта в паре мест. никакого усложнения
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Ответить

Вернуться в «AVR»