То есть – 3,4 и 5 выводы порта настроены на вход, а остальные на выход. С помощью DDR то же самое можно сделать одной строчкой… вот так…
......
DDRB = &B00001111 4 старших бита (PORTB.7 до PORTB.4) будут выходами...
Одинаково - это как?


vem566 писал(а):Работать это будет одинаково, так что как хочется, так и пишите.

Код: Выделить всё
$regfile = "m8def.dat"
$crystal = 4000000
' * * * заводим переменные * * *
Dim A As Integer
Dim W As Word
Dim B As Byte
Dim C As Byte
Dim N1 As Byte
Dim N2 As Byte
Dim N3 As Byte
Dim M1 As Integer
Dim M2 As Integer
Dim M3 As Integer
' включаем прерывания
Enable Interrupts
Enable Int0
Enable Int1
On Int1 Schet
On Int0 Knopka
Config Int0 = Falling
Config Int1 = Falling
Config Debounce = 20
Config Pinc.0 = Input
Config Pinc.1 = Input
Config Pinc.2 = Input
Config Pinc.3 = Input
' * * * настраиваем порты к которым цепляется индикатор на выход * * *
Config Portd.4 = Output
Config Portd.5 = Output
Config Portd.6 = Output
Ddrb = &B11111111
Reset A
$eeprom
Wdata:
Data 17%
$data
Readeeprom W , Wdata
' * * * Основной цикл программы * * *
Do
M1 = W ' вот это число будем отображать
M2 = M1
M3 = M1
M1 = M1 / 100 'обработка первого числа
N1 = Abs(m1)
M2 = M2 Mod 100 'обработка второго числа
M2 = M2 / 10
N2 = Abs(m2)
M3 = M3 Mod 10 ' обработка четвертого числа
N3 = Abs(m3)
Gosub Led 'после преобразования вызываем подпрограмму обработки индикации
Loop
'* * * подпрограма обработки индикации * * *
Led:
'зажигаем первое число
Portd = &B01000000 'зажигаем первое число
If N1 = 0 Then 'гашение не значащих нулей
Portd = &B00000000
End If
Select Case N1
Case 0 : Portb = &B11000000
Case 1 : Portb = &B11111001
Case 2 : Portb = &B10100100
Case 3 : Portb = &B10110000
Case 4 : Portb = &B10011001
Case 5 : Portb = &B10010010
Case 6 : Portb = &B10000010
Case 7 : Portb = &B11111000
Case 8 : Portb = &B10000000
Case 9 : Portb = &B10010000
End Select
Waitms 5
Portd = &B00100000 'зажигаем второе число вместе с точкой
If N2 = 0 And N1 = 0 Then 'гашение не значащих нулей
Portd = &B00000000
End If
Select Case N2
Case 0 : Portb = &B01000000
Case 1 : Portb = &B01111001
Case 2 : Portb = &B00100100
Case 3 : Portb = &B00110000
Case 4 : Portb = &B00011001
Case 5 : Portb = &B00010010
Case 6 : Portb = &B00000010
Case 7 : Portb = &B01111000
Case 8 : Portb = &B00000000
Case 9 : Portb = &B00010000
End Select
Waitms 5
Portd = &B00010000 'зажигаем третье число
Select Case N3
Case 0 : Portb = &B11000000
Case 1 : Portb = &B11111001
Case 2 : Portb = &B10100100
Case 3 : Portb = &B10110000
Case 4 : Portb = &B10011001
Case 5 : Portb = &B10010010
Case 6 : Portb = &B10000010
Case 7 : Portb = &B11111000
Case 8 : Portb = &B10000000
Case 9 : Portb = &B10010000
End Select
Waitms 5
Return
'Подпрограмма обработки прерываний от датчиков
Schet:
If Pinc.2 = 0 Then
Waitms 5
Incr A
End If
If Pinc.3 = 0 Then
Waitms 5
Decr A
End If
'коэффициент пересчёта
If A = 2 Then
Incr W
A = 0
End If
If A = -2 Then
Decr W
A = 0
End If
Writeeeprom W , Wdata
Return
'вот до сюда, работает
Knopka:
Readeeprom W , Wdata
M1 = W 'разбиваем число W на цифры- значения отдельных разрядов
M2 = M1
M3 = M1
M1 = M1 / 100
N1 = Abs(m1)
M2 = M2 Mod 100
M2 = M2 / 10
N2 = Abs(m2)
M3 = M3 Mod 10
N3 = Abs(m3)
Reset C
While Pinc.0 = 0 'если кнопка нажата
Incr B 'идёт приращение переменной B
If B => 200 Then 'если нажатие длиное
C = C + 1 'Прибавить Единицу К Переменной С
End If
B = 0
If C = 1 Then 'если значение С равно одному, то
Gosub Digit_3 'подпрограмму настройки третьего разряда
End If
If C = 2 Then 'если значение С равно двум, то
Gosub Digit_2
End If
If C = 3 Then 'если значение С равно трём, то
Gosub Digit_1
End If
If C = 4 Then
Gosub Vihod
End If
Wend
B = 0
'третий разряд
Digit_3:
C = 1
Do 'запуск цикла мигания третьим разрядом
Portd = &B01100000
Waitms 400
Portd = &B01110000
Waitms 400
While Pinc.0 = 0 'отслеживать повторное ДЛИТЕЛЬНОЕ нажатие
Incr B
If B => 200 Then 'при повторном длительном нажатии
B = 0
C = C + 1 'прибавить единицу к значению C
End If
Wend
If Pinc.0 = 0 Then 'в случае короткого нажатия
N3 = N3 + 1 'прибавить единицу к значению N3
End If 'при достижении N3 значения 9, сбросить N3 на ноль
If N3 > 9 Then
N3 = 0
End If
Loop Until C <> 1 'если значение C неравно одному, то выход из цикла
' второй разряд
Digit_2:
C = 2
Do 'запуск цикла мигания вторым разрядом
Portd = &B01010000
Waitms 400
Portd = &B01110000
Waitms 400
While Pinc.0 = 0 'отслеживать повторное ДЛИТЕЛЬНОЕ нажатие
Incr B
If B => 200 Then 'при повторном длительном нажатии
B = 0
C = C + 1 'прибавить единицу к значению C
End If
Wend
If Pinc.0 = 0 Then 'в случае короткого нажатия
N2 = N2 + 1 'прибавить единицу к значению N2
End If 'при достижении N2 значения 9, сбросить N2 на ноль
If N2 > 9 Then
N2 = 0
End If
Loop Until C <> 2 'если значение C неравно двум, то выход из цикла
'первый разряд
Digit_1:
C = 3
Do 'запуск цикла мигания первым разрядом
Portd = &B00110000
Waitms 400
Portd = &B01110000
Waitms 400
While Pinc.0 = 0 'отслеживать повторное ДЛИТЕЛЬНОЕ нажатие
Incr B
If B = 200 Then
B = 0 'при повторном длительном нажатии
C = C + 1 'прибавить единицу к значению C
End If
Wend
If Pinc.0 = 0 Then 'в случае короткого нажатия
N1 = N1 + 1 'прибавить единицу к значению N1
End If
If N1 > 9 Then 'при достижении N1 значения 9, сбросить N1 на ноль
N1 = 0
End If
Loop Until C <> 3 'если значение C неравно трём, то выход из цикла
N2 = N2 * 10
N2 = N2 + N3 'собираем обратно, из отдельных цифр N1, N2 и N3 число W
N1 = N1 * 100
W = N1 + N2
Writeeeprom W , Wdata 'записываем установленное значение
Vihod:
Reset C
Reset B
Returnvem566 писал(а):На первый взгляд, может не достаточно внимательный, сразу пришло в голову, что индикацию лучше привязать к таймеру.
То есть независимую от основного цикла. В этом же прерывании (от таймера) отслеживать время нажатия кнопки и в нем же режим мигания. Потом обратил внимание на постоянную запись в энергонезависимую память. А циклов там всего 100000 по паспорту. Казалось бы много, но во время работы это будет происходить постоянно по срабатыванию датчиков. Посчитайте, с какой частотой будут срабатывать датчики и на сколько времени хватит надежной работы памяти. Потом никто не угадает, что будет записываться. Может лучше переписывать только изменение в литрах. 100 тонн бензина проездить, это надолго.
Если эти предложения реализовать, будет другая программа с совсем другим алгоритмом.
vem566 писал(а):Насчет памяти. Одну ногу привязать к зажиганию и по отключению зажигания записывать показания. Приблуду можно отправить в спящий режим, хотя её потребление при отключенных индикаторах меньше саморазряда аккумулятора. А индикаторы тушить то же по зажиганию. Теперь про таймер для динамической индикации. Не буду сейчас сочинять на ходу. Примеров навалом. Например. Число индикаторов увеличивается до нужного. Ну и массив для отображения сегментов приложен.
В прерывании еще нужна будет переменная типа байт, которая постоянно увеличивается до 255 а затем снова с нуля. Пусть так и ходит по кругу. При нажатии кнопки эта переменная обнуляется, но таймер продолжает работать и увеличивать значение. В момент отпускания посмотреть значение переменной. Нажатие и отпускание можно посадить на прерывание. Или после нажатия ждать отпускания. Как угодно.
В общем идея такова.
kip96 писал(а):Интересно узнать, а чем обусловлена задача, только с одной кнопкой?
vem566 писал(а):kip96, мне попадались часы, которые настраивались одним сенсорным контактом. Как раз примерно так, как представляет LazarevSergey. Длинное нажатие - переход на параметр, короткое - его изменение. Неудобно, если постоянно что то менять нужно, а если раз в неделю, так вроде и пойдет.
kip96 писал(а):Мне кажется, энкодер с кнопкой (3 пина) пипец как облегчил бы задачу!
Код: Выделить всё
If Kn = 0 Then
Time_ret_button = 0 ' переменная увеличивается по таймеру, к примеру каждую секунду
While Kn = 0 ' пока удерживается кнопка
If Time_ret_button = 5 Then ' если удерживаем пять секунд, то делаем что надо. К примеру увеличиваем переменную cont
' и обозначаем это как нибудь(к примеру звуком)
end if
wend
select case cont
case 1: ' моргаем первым индикатором и кнопкой меняем его
case 2: ' моргаем вторым и кнопкой меняем его
case 0: ' делаем основную работу