Собрал на макетке схему семисегментного индикатора на 4 разряда с обвязкой( для выбора разрядов ключи pnp с резисторами 1 кОм на базе, выводы сегментов через резисторы 1кОм). Получилось 4 вывода для управления выбором разрядов, 8 выводов для управления сегментами. Активный уровень управления 0 В.
Решил сделать тестовую прошивку. Начальные числа для разрядов 0, 1, 2, 3. Каждую секунду происходит инкремент числа каждого разряда. Использую динамическую индикацию, поэтому нужно переключать разряды с частотой 400 Гц(4 разряда х 100 раз в секунду для одного разряда).
Использовал два таймера в режиме совпадения - таймер1 для периода 1с( 1 Гц), таймер0 для частоты 400 Гц. Таймер1 генерирует прерывания для инкремента значений разрядов. Таймер0 отвечает за динамическую индикацию и не генерирует прерываний, а только устанавливает флаг совпадения, поэтому проверку флага и перебор разрядов нужно производить в основном цикле.
Правильно я сделал? Прошивку не тестировал ещё( боюся
).
Главный вопрос - если несколько источников прерываний срабатывают одновременно, как они срабатывают по приоритету? Сначала обрабатывается прерывание с большим приоритетом, а с меньшим приоритетом затем обрабатывается автоматически или нужны махинации с регистрами? Может, поделитесь ссылками на примеры с несколькими источниками прерываний.
$regfile = "m328pdef.dat"
$crystal = 16000000
Declare Sub View(byval Digit_value As Byte , Byval Number_digit As Byte , Byval Dp_view As Byte)
' процедура вывода сегментов для отдельного разряда
Dim Digit1 As Byte , Digit2 As Byte , Digit3 As Byte , Digit4 As Byte ' значения разрядов
Dim Dp As Byte ' флаг отображения точки
Dim Next_digit As Byte ' номер отображаемого разряда в данный момент времени
Dim View_flag as Byte ' флажок в неоходимости изменения сегментов
Digit1 = 0 : Digit2 = 1 : Digit3 = 2 : Digit4 = 3
Dp = 0
Next_digit = 1 : View_flag = 0
Restore Digits
Config Portb = Output ' управление разрядами
Config Portd = Output ' управление сегментами
Config Portb.5 = Output
Config Timer1 = Timer , Prescale = 256 , Compare_a = Disconnect , Clear_timer = 1
Compare1a = 62500 ' 1 sec
On Oc1a Pr1
Config Timer0 = Timer , Prescale = 256 , Compare_a = Disconnect , Clear_timer = 1
Ocr0a = 155 ' 400Hz
Enable Oc1a
Enable Interrupts
Start Timer1
Start Timer0
Do
If Tifr0.1 = 1 Then
Next_digit = Next_digit + 1
View_flag = 1 ' разряд изменился - сегменты надо обновить на другие
Tifr0.1 = 1 ' сброс флага ocr1a
End If
If Next_digit > 4 Then
Next_digit = 1
End If
If View_flag = 1 Then
Select Case Next_digit
Case 1 : Call View(digit1 , Next_digit , 0)
Case 2 : Call View(digit2 , Next_digit , 0)
Case 3 : Call View(digit3 , Next_digit , 0)
Case 4 : Call View(digit4 , Next_digit , 0)
End Select
View_flag = 0 ' сброс флажка обновления
End If
Loop
Sub View(digit_value As Byte , Number_digit As Byte , Dp_view As Byte)
'Local L1 As Byte
'L1 = Number_digit
Portd = 255
Select Case Number_digit
Case 1 : Portb = &B00001110
Case 2 : Portb = &B00001101
Case 3 : Portb = &B00001011
Case 4 : Portb = &B00000111
End Select
Portd = Lookup(digit_value , Digits)
End Sub
Pr1:
Digit1 = Digit1 + 1
Digit2 = Digit2 + 1
Digit3 = Digit3 + 1
Digit1 = Digit4 + 1
If Digit1 > 9 Then
Digit1 = 0
End If
If Digit2 > 9 Then
Digit2 = 0
End If
If Digit3 > 9 Then
Digit3 = 0
End If
If Digit4 > 9 Then
Digit4 = 0
End If
Return
End
Digits:
Data &B11000000 , &B11111001 , &B10100100 , &B10110000 , &B10011001
Data &B10010010 , &B10000010 , &B11111000 , &B10000000 , &B10010000
Отредактировано Sikorsky (2017-04-12 23:16:21)

Это же вообще не логично...





