WARNING: курение вредит вашему здоровью
Давеча я подсела на электронные сигареты (парилки).
И попалась мне среди прочих забавная пыхтелка от UDN - Bar X на 7000 затяжек.
Вот такая:
Сразу заметно, что она оснащена крохотным дисплейчиком, который показывает степень заряда аккумулятора, а также запас жижки для парения (на самом деле просто считает число затяжек).
Рачительная хозяйка всему в доме найдет применение, так что и речи не могло быть о том, чтобы выбрасывать такую ценную вещь!
Вскрытие показало, что внутри, помимо литиевого аккумулятора на 600 мАч, есть много ценного меха и два-три килограмма легкоусвояемого мяса чего интересного.
Во-первых, там стоит специализированный китайский чип управления пыхтелками CSC9090. К нему подключается аккумулятор, датчик затяжки, светодиод и нагревательная спираль.
Даташит лаконичен, поэтому приведу его прямо здесь на картинке:
Чем он может быть полезен в хозяйстве? Ну конечно, в качестве контроллера заряда акуумулятора! Кроме того, несмотря на свою малость, он способен управлять нагрузкой с током до 7 А.
Правда, время ее включения может быть ограничено десятками секунд (смотрия от буквенного обозначения чипа, надо полагать).
Самой же забавной мякоткой является дисплейчик, подключенный к МК без маркировки.
Вот им и займемся.
Методом научного тыка выяснилось, что он представляет собой простейший LED-дисплей, каждый сегмент которого подключен к своей паре выводов в прямом или обратном включении.
Таким образом, подавая на один из 6 выводов "плюс", а другой сажая на "землю", мы можем зажечь один из цифровых сегментов, цифру "1" впереди (она сделана для экономии как единый сегмент) или один из символов (красная/белая молния, значок %, красная/белая/зеленая капелька). Все остальные выводы в это время должны оставаться никуда не подключенными. Конечно, такой метод имеет свои недостатки: нужно 6 выводов МК, и прерывание таймера для динамической индикации. Впрочем, для простых поделок это не страшно.
Потребовался также небольшой испытательный стенд и тестовая программка, чтобы определить и записать все рабочие комбинации.
И, наконец, ловите тестовую программку, которую можно использовать как библиотечку. Дисплей нужно присоединять к выводам свободного порта МК, начиная с 0, 1 или 2 разряда. Порт прописываем в константу LP_PORT, стартовый пин - в LP_STARTPIN. К дисплею разряды порта присоединяются, начиная с вывода, расположенного около урезанной цифры "1", и далее по возрастанию. Дисплей может отображать числа и некоторые буквы.
' *** UDN BAR X POD LED 7-SEGMENT 2.5-DIGITS DISPLAY CODE ***
' *** by Cirno_9 https://t.me/Cirno9 ***
$regfile = "m328pdef.dat"
$crystal = 16000000
$hwstack = 64
$swstack = 128
$framesize = 128
' user defined constants
const LP_PORT = "D"
const LP_STARTPIN = 2 ' port start pin: 0, 1 or 2
' internal constants
const LP_CHARGE_RED_BIT = 0
const LP_CHARGE_WHITE_BIT = 1
const LP_BLOB_RED_BIT = 2
const LP_BLOB_WHITE_BIT = 3
const LP_BLOB_GREEN_BIT = 4
const LP_PERCENT_BIT = 5
const LP_1_BIT = 6
const LP_CHARGE_RED = 2 ^ LP_CHARGE_RED_BIT
const LP_CHARGE_WHITE = 2 ^ LP_CHARGE_WHITE_BIT
const LP_BLOB_RED = 2 ^ LP_BLOB_RED_BIT
const LP_BLOB_WHITE = 2 ^ LP_BLOB_WHITE_BIT
const LP_BLOB_GREEN = 2 ^ LP_BLOB_GREEN_BIT
const LP_PERCENT = 2 ^ LP_PERCENT_BIT
const LP_1 = 2 ^ LP_1_BIT
const LP_LOOKUP_BASE = 40
' internal vars
dim LP_symbols as byte ' LP_... bit holder
dim LP_digit1 as byte ' }
dim LP_digit2 as byte ' } segments table lookup base and then segments one
dim LP_string as string * 3 ' display content
dim LP_digit1_mask1 as byte ' mask V+ digit 1
dim LP_digit1_mask0 as byte ' mask V- digit 1
dim LP_digit2_mask1 as byte ' mask V+ digit 2
dim LP_digit2_mask0 as byte ' mask V- digit 2
dim LP_time2lite as byte
dim LP_time2dark as byte
' external
declare sub LP_Init(byval bBrighness as byte) ' brightness in percent
declare sub LP_ShowString(byval sShowString as string) ' up to 3 symbols
declare sub LP_ShowNumber(byval bShowNumber as byte) ' from 0 to 199
declare sub LP_ShowSymobls(byval bValue as byte) ' symbol_bits, see const LP_
' internal
declare sub LP_TimerProc()
' *** programm start ***
dim cnt as byte ' for test purpose only
LP_Init 30
LP_ShowSymobls LP_BLOB_GREEN or LP_CHARGE_RED
do
LP_ShowNumber cnt
incr cnt
if cnt = 200 then
cnt = 0
LP_ShowSymobls LP_BLOB_GREEN or LP_CHARGE_RED
end if
if cnt = 35 then LP_ShowSymobls LP_BLOB_GREEN or LP_CHARGE_WHITE
waitms 200
loop
end
' *** subs code ***
sub LP_Init(bBrighness as byte)
#if LP_PORT = "B"
PORT_OUT alias PORTB
PORT_DDR alias DDRB
#elseif LP_PORT = "C"
PORT_OUT alias PORTC
PORT_DDR alias DDRC
#elseif LP_PORT = "D"
PORT_OUT alias PORTD
PORT_DDR alias DDRD
#endif
PORT_DDR = 0
PORT_OUT = 0
if bBrighness > 100 then bBrighness = 100
LP_time2lite = bBrighness
LP_time2dark = 100 - bBrighness
set LP_digit1.7 ' set high bit indicated there notnig to display
config TIMER0 = COUNTER , PRESCALE = 1024
on TIMER0 LP_TimerProc
enable interrupts
enable TIMER0
start TIMER0
end sub
sub LP_ShowString(sShowString as string)
' gets the symbol(s) segments data
reset LP_symbols.LP_1_BIT
if len(sShowString) = 1 then
LP_digit1 = asc(sShowString) - LP_LOOKUP_BASE ' get lookup base
LP_digit1 = lookup(LP_digit1 , segments) ' get segments data
LP_digit2 = &b0000_0000 ' empty space
elseif len(sShowString) = 2 then
LP_digit1 = asc(sShowString , 2) - LP_LOOKUP_BASE
LP_digit1 = lookup(LP_digit1 , segments)
LP_digit2 = asc(sShowString , 1) - LP_LOOKUP_BASE
LP_digit2 = lookup(LP_digit2 , segments)
elseif len(sShowString) = 3 then
LP_digit1 = asc(sShowString , 3) - LP_LOOKUP_BASE
LP_digit1 = lookup(LP_digit1 , segments)
LP_digit2 = asc(sShowString , 2) - LP_LOOKUP_BASE
LP_digit2 = lookup(LP_digit2 , segments)
set LP_symbols.LP_1_BIT
else
set LP_digit1.7 ' set high bit indicated there notnig to display
end if
end sub
sub LP_ShowNumber(bShowNumber as byte)
if bShowNumber < 199 then
LP_ShowString str(bShowNumber)
end if
end sub
sub LP_ShowSymobls(bValue as byte)
if LP_symbols.LP_1_BIT <> 0 then
LP_symbols = bValue or LP_1
else
LP_symbols = bValue
end if
end sub
sub LP_TimerProc()
local segment as byte
' show symbols
if LP_symbols.LP_CHARGE_RED_BIT <> 0 then
LP_digit1_mask1 = &b00010000
LP_digit1_mask0 = &b00000001
shift LP_digit1_mask1 , left , LP_STARTPIN ' fit bits to port pins start
shift LP_digit1_mask0 , left , LP_STARTPIN
' show
PORT_DDR = LP_digit1_mask1 or LP_digit1_mask0
PORT_OUT = LP_digit1_mask1
waitus LP_time2lite
PORT_DDR = 0
PORT_OUT = 0
waitus LP_time2dark
end if
if LP_symbols.LP_CHARGE_WHITE_BIT <> 0 then
LP_digit1_mask1 = &b00010000
LP_digit1_mask0 = &b00000010
shift LP_digit1_mask1 , left , LP_STARTPIN ' fit bits to port pins start
shift LP_digit1_mask0 , left , LP_STARTPIN
' show
PORT_DDR = LP_digit1_mask1 or LP_digit1_mask0
PORT_OUT = LP_digit1_mask1
waitus LP_time2lite
PORT_DDR = 0
PORT_OUT = 0
waitus LP_time2dark
end if
if LP_symbols.LP_BLOB_RED_BIT <> 0 then
LP_digit1_mask1 = &b00010000
LP_digit1_mask0 = &b00001000
shift LP_digit1_mask1 , left , LP_STARTPIN ' fit bits to port pins start
shift LP_digit1_mask0 , left , LP_STARTPIN
' show
PORT_DDR = LP_digit1_mask1 or LP_digit1_mask0
PORT_OUT = LP_digit1_mask1
waitus LP_time2lite
PORT_DDR = 0
PORT_OUT = 0
waitus LP_time2dark
end if
if LP_symbols.LP_BLOB_WHITE_BIT <> 0 then
LP_digit1_mask1 = &b00010000
LP_digit1_mask0 = &b00100000
shift LP_digit1_mask1 , left , LP_STARTPIN ' fit bits to port pins start
shift LP_digit1_mask0 , left , LP_STARTPIN
' show
PORT_DDR = LP_digit1_mask1 or LP_digit1_mask0
PORT_OUT = LP_digit1_mask1
waitus LP_time2lite
PORT_DDR = 0
PORT_OUT = 0
waitus LP_time2dark
end if
if LP_symbols.LP_BLOB_GREEN_BIT <> 0 then
LP_digit1_mask1 = &b00100000
LP_digit1_mask0 = &b00010000
shift LP_digit1_mask1 , left , LP_STARTPIN ' fit bits to port pins start
shift LP_digit1_mask0 , left , LP_STARTPIN
PORT_DDR = LP_digit1_mask1 or LP_digit1_mask0
PORT_OUT = LP_digit1_mask1
waitus LP_time2lite
PORT_DDR = 0
PORT_OUT = 0
waitus LP_time2dark
end if
if LP_symbols.LP_PERCENT_BIT <> 0 then
LP_digit1_mask1 = &b00010000
LP_digit1_mask0 = &b00000100
shift LP_digit1_mask1 , left , LP_STARTPIN ' fit bits to port pins start
shift LP_digit1_mask0 , left , LP_STARTPIN
' show
PORT_DDR = LP_digit1_mask1 or LP_digit1_mask0
PORT_OUT = LP_digit1_mask1
waitus LP_time2lite
PORT_DDR = 0
PORT_OUT = 0
waitus LP_time2dark
end if
if LP_symbols.LP_1_BIT <> 0 then
LP_digit1_mask1 = &b00001000
LP_digit1_mask0 = &b00000100
shift LP_digit1_mask1 , left , LP_STARTPIN ' fit bits to port pins start
shift LP_digit1_mask0 , left , LP_STARTPIN
' show
PORT_DDR = LP_digit1_mask1 or LP_digit1_mask0
PORT_OUT = LP_digit1_mask1
waitus LP_time2lite
PORT_DDR = 0
PORT_OUT = 0
waitus LP_time2dark
end if
if LP_digit1.7 = 1 then goto skip_digits ' there is no digits to display
for segment = 0 to 7
if LP_digit1.segment = 1 then
LP_digit1_mask1 = lookup(segment , dig1mask1) ' get masks
LP_digit1_mask0 = lookup(segment , dig1mask0)
else
LP_digit1_mask1 = 0
LP_digit1_mask0 = 0
end if
if LP_digit2.segment = 1 then
LP_digit2_mask1 = lookup(segment , dig2mask1)
LP_digit2_mask0 = lookup(segment , dig2mask0)
else
LP_digit2_mask1 = 0
LP_digit2_mask0 = 0
end if
shift LP_digit1_mask1 , left , LP_STARTPIN ' fit bits to port pins start
shift LP_digit1_mask0 , left , LP_STARTPIN
shift LP_digit2_mask1 , left , LP_STARTPIN
shift LP_digit2_mask0 , left , LP_STARTPIN
' show digit 1 segment
PORT_DDR = LP_digit1_mask1 or LP_digit1_mask0
PORT_OUT = LP_digit1_mask1
waitus LP_time2lite
PORT_DDR = 0
PORT_OUT = 0
waitus LP_time2dark
' show digit 2 segment
PORT_DDR = LP_digit2_mask1 or LP_digit2_mask0
PORT_OUT = LP_digit2_mask1
waitus LP_time2lite
PORT_DDR = 0
PORT_OUT = 0
waitus LP_time2dark
next
skip_digits:
' Now we must reset the interrupt marker bit, because we have long time interrupt handler, and more than one interrupts can be occurs
#if _chip = 83 OR _chip = 81 OR _chip = 80 OR _chip = 46 OR _chip = 44 OR _chip = 45 OR _chip = 48 OR _chip = 47 OR _chip = 34 OR _chip = 61 OR _chip = 61 OR _chip = 43 OR _chip = 41 OR _chip = 105 OR _chip = 105 OR _chip = 100 OR _chip = 60 OR _chip = 60 OR _chip = 60 OR _chip = 32 OR _chip = 92 OR _chip = 92 OR _chip = 55 OR _chip = 223 OR _chip = 102 OR _chip = 33 OR _chip = 33 OR _chip = 62 OR _chip = 62 OR _chip = 200 OR _chip = 200 OR _chip = 208 OR _chip = 219 OR _chip = 212 OR _chip = 202 OR _chip = 209 OR _chip = 204 OR _chip = 228 OR _chip = 213 OR _chip = 206 OR _chip = 206 OR _chip = 205 OR _chip = 220 OR _chip = 214 OR _chip = 203 OR _chip = 215 OR _chip = 210 OR _chip = 201 OR _chip = 207 OR _chip = 227 OR _chip = 211
set TIFR0.TOV0
#elseif _chip = 26 OR _chip = 0 OR _chip = 1 OR _chip = 2 OR _chip = 3 OR _chip = 4 OR _chip = 5 OR _chip = 6 OR _chip = 7 OR _chip = 8 OR _chip = 27 OR _chip = 15 OR _chip = 30 OR _chip = 30 OR _chip = 16 OR _chip = 111 OR _chip = 110 OR _chip = 64 OR _chip = 11 OR _chip = 31 OR _chip = 31 OR _chip = 36 OR _chip = 22 OR _chip = 58 OR _chip = 49 OR _chip = 85 OR _chip = 441 OR _chip = 35 OR _chip = 56 OR _chip = 91 OR _chip = 157 OR _chip = 841 OR _chip = 38 OR _chip = 57 OR _chip = 112 OR _chip = 90 OR _chip = 10 OR _chip = 21 OR _chip = 103 OR _chip = 103 OR _chip = 40 OR _chip = 20 OR _chip = 39 OR _chip = 12 OR _chip = 28 OR _chip = 13 OR _chip = 52 OR _chip = 52 OR _chip = 52 OR _chip = 420 OR _chip = 42 OR _chip = 29 OR _chip = 29 OR _chip = 29 OR _chip = 29 OR _chip = 18 OR _chip = 18 OR _chip = 107 OR _chip = 178 OR _chip = 77 OR _chip = 14 OR _chip = 152 OR _chip = 151 OR _chip = 0 OR _chip = 51 OR _chip = 105 OR _chip = 50 OR _chip = 23 OR _chip = 113 OR _chip = 82 OR _chip = 23 OR _chip = 106 OR
set TIFR.TOV0
#endif
end sub
' *** data ***
segments:
' GFEDCBA
data &B01011000 '/( 0x28
data &B01001100 '/)
data &B01100011 '*
data &B00000000 '
data &B10000000 ',
data &B01000000 '-
data &B00000000 '.
data &B00000000 '
data &B00111111 '0
data &B00000110 '1
data &B01011011 '2
data &B01001111 '3
data &B01100110 '4
data &B01101101 '5
data &B01111101 '6
data &B00000111 '7
data &B01111111 '8
data &B01101111 '9
data &B00000000 '
data &B00000000 '
data &B00000000 '
data &B01001000 '=
data &B00000000 '
data &B00000000 '
data &B00000000 '
data &B01110111 'A
data &B01111100 'b
data &B00111001 'C
data &B01011110 'd
data &B01111001 'E
data &B01110001 'F
data &B01111101 'G
data &B01110110 'H
data &B00110000 'I
data &B00001110 'J
data &B00000000 '
data &B00111000 'L
data &B00000000 '
data &B01010100 'n
data &B00111111 'O
data &B01110011 'P
data &B01100111 'q
data &B11110111 'R
data &B01101101 'S
data &B01111000 't
data &B00111110 'U
data &B00000000 '
data &B00000000 '
data &B00000000 '
data &B00000000 '
data &B00000000 '
data &B00111001 '[
data &B00000000 '
data &B00001111 ']
data &B00000000 '
data &B00001000 '_
data &B00000000 '
data &B11011111 'a
data &B01111100 'b
data &B01011000 'c
data &B01011110 'd
data &B01111001 'E
data &B01110001 'F
data &B11101111 'g
data &B01110100 'h
data &B00010000 'i
data &B00001110 'J
data &B00000000 '
data &B00111000 'L
data &B00000000 '
data &B01010100 'n
data &B01011100 'o
data &B01110011 'P
data &B01100111 'q
data &B01010000 'r
data &B01101101 'S
data &B01111000 't
data &B00011100 'u
data &B00000000 '
data &B00000000 '
data &B00000000 '
data &B00000000 '
data &B00000000 '
dig1mask1:
data &b00000010 ' mask+ seg A1+
data &b00000001 ' mask+ seg B1+
data &b00000100 ' mask+ seg C1+
data &b00000001 ' mask+ seg D1+
data &b00001000 ' mask+ seg E1+
data &b00000001 ' mask+ seg F1+
data &b00000001 ' mask+ seg G1+
dig1mask0:
data &b00000001 ' mask- seg A1-
data &b00000010 ' mask- seg B1-
data &b00000001 ' mask- seg C1-
data &b00000100 ' mask- seg D1-
data &b00000001 ' mask- seg E1-
data &b00001000 ' mask- seg F1-
data &b00010000 ' mask- seg G1-
dig2mask1:
data &b00000100 ' mask+ seg A2+
data &b00000010 ' mask+ seg B2+
data &b00000100 ' mask+ seg C2+
data &b00000010 ' mask+ seg D2+
data &b00000010 ' mask+ seg E2+
data &b00000100 ' mask+ seg F2+
data &b00001000 ' mask+ seg G2+
dig2mask0:
data &b00000010 ' mask- seg A2-
data &b00000100 ' mask- seg B2-
data &b00001000 ' mask- seg C2-
data &b00001000 ' mask- seg D2-
data &b00010000 ' mask- seg E2-
data &b00010000 ' mask- seg F2-
data &b00010000 ' mask- seg G2-
Отредактировано Cirno_9 (2023-10-01 13:47:17)




