Статья №8
Рассмотрим ещё один пример применения шины I2C. Это работа часов реального времени DS1307 совместно с микроконтроллером ATtiny2313.
DS1307 - это малопотребляющие полные двоично – десятичные часы – календарь, включающие 56 байтов энергонезависимой статической ОЗУ. Адреса и данные передаются по двухпроводной двунаправленной шине. Часы – календарь отсчитывают секунды, минуты, часы, день, дату, месяц и год. Последняя дата месяца автоматически корректируется для месяцев с количеством дней меньше 31, включая коррекцию високосного года. Часы работают как в 24 –часовом, так и в 12 – часовом режиме с индикатором АМ/РМ. DS1307 имеет встроенную систему наблюдения за питанием , которая обнаруживает перебои питания и автоматически переключается на питание от батареи. Устройство работоспособно при напряжении питания выше 1,25 В. Однако, когда к часам подключена батарея 3 В, при напряжении питания ниже 1,25 В чтение и запись запрещены, но функция отсчёта продолжает работать. Частота подключаемого к контактам Х1 и Х2 кварца – 32,768 КГц.
DS1307 работает на двухпроводной последовательной шине как ведомое устройство. Доступ к нему достигается установкой условия START и передачей устройству идентификационного кода, за которым следует адрес регистра. К следующим за ним регистрам доступ может осуществляться последовательно, пока не будет выполнено условие STOP.
Информация от часов и календаря получается чтением соответствующих байтов регистра. Регистры показаны в табл.1:
Бит 7 регистра секунды (адрес 00Н) – это бит останова часов (1 – тактовый генератор выключен, 0 – включён). Поскольку при включении питания состояние регистров не определено, необходимо принудительно включать тактовый генератор (СН=0) во время начальной инициализации.
Бит 6 регистра часов (адрес 02Н) отвечает за выбор режима работы 1 – 12 часовой режим работы 0 – 24 часовой режим работы. В 12 – часовом режиме бит 5 – это бит АМ/РМ, в 24 – часовом режиме бит 5 – это бит второго десятка часов.
Управляющий регистр (адрес 07Н) используется для управления выводом SQW/OUT (Scuare Wave/Output Driver – сигнал с прямоугольными импульсами). Бит OUT управляет логическим уровнем на выводе SQW/OUT: если OUT=1, то SQW/OUT=1; если OUT=0 , то SQW/OUT=0.
Бит SQWE (=1) включает генерацию прямоугольных импульсов, частота которых зависит от состояния битов RS1, RS0 регистра управления (адрес 07H).
Адрес DS1307 - 1101000. В режиме приёма часы декодируют адресный байт и выдают в линию SDA подтверждение, после чего ведущий передаёт в устройство адрес регистра. Это установит регистровый указатель. Затем ведущий начинает передачу байтов данных, каждый из которых будет подтверждаться DS1307. Чтобы завершить запись данных, ведущий генерирует условие окончания.
В режиме ведомого передатчика DS1307 начинает передавать данные, начиная с указанного адреса, находящегося в регистровом указателе. Если перед началом чтения указатель регистра не записан, то первым читаемым адресом будет тот, который был сохранён в нём последним.
На Рис.1 представлена схема подключения DS1307 к ATtiny2313. Индикация значений часов и календаря происходит с помощью ЖКИ типа МТ-16S2H (фирма – изготовитель МЭЛТ).
Регистр управления DS1307 сконфигурирован таким образом, что на контакте SQW/OUT генерируется токовые импульсы частотой 1 Гц, заставляющие мигать светодиод HL1, что позволяет контролировать работу часов. Шины SDA и SDL имеют подтяжку резисторами R2, R3 – 10 КОм. Резистор R1 и конденсатор С1 образуют цепь сброса микроконтроллера.
Основная программа ATtiny2313 cчитывает из часов и индуцирует на дисплее в цикле значения часов и минут.
Для установки часов необходимо нажать кнопку «Установка» (S2), тогда включится прерывание INT0, при обработке которого с помощью кнопок «Увеличение» (S5) и «Продолжение» (S4). Блок – схема программы “Clock” приведена на Рис.2, где основной цикл заключается в считывании значений часов и минут по I2C из DS1307
декодировании их из двоично – десятичного кода и отображении на ЖКИ.
Подпрограмма установки состоит из кодирования значений часов и минут в двоично – десятичный код и отправки их по I2C в DS1307. Текст программы приводится ниже:
$regfile = "attiny2313a.dat" 'настройки
$crystal = 4000000
$hwstack = 40
$swstack = 16
$framesize = 32
Config Sda = Portb.5 'конфигурация I2C
Config Scl = Portb.7
Config I2cdelay = 10
Config Int0 = Falling 'прерывание по спаду импульса
Config Debounce = 75
Config Pind.4 = Input
Config Pind.5 = Input
Const Adressr = &B11010001 'cчитывание
Const Adressw = &B11010000 'запись
Const Secadress = &H00 'адреса регистров часов
Const Minadress = &H01
Const Clockadress = &H02
Const Datadress = &H04
Const Uprbyte = &B00010000
Const Upradress = &H07
Const Sec1 = &B00000000
Dim Sec As Byte 'объявления переменных
Dim Minut As Byte
Dim Eminut As Byte
Dim Clock As Byte
Dim Eclock As Byte
Dim Z As Integer
Dim Ones As Byte
Dim Tens As Byte
Declare Sub Ed 'определение подпрограммы-выделение десятков и единиц
On Int0 Button 'определение подпрограмм прерываний
I2cstart 'запись в регистр упрaвления
I2cwbyte Adressw
I2cwbyte Upradress
I2cwbyte Uprbyte
I2cstop
Enable Interrupts 'разрешение прерываний
Enable Int0
I2cstart 'Запуск Часов
I2cwbyte Adressw
I2cwbyte Secadress
I2cwbyte Sec1
I2cstop
Do 'считывание минут и часов из DS1307
I2cstart
I2cwbyte Adressr
I2cwbyte Minadress
I2crbyte Minut , Ack 'считывание минут
I2crbyte Clock , Nack 'считывание часов
I2cstop
‘декодирование значений часов и минут
Eminut = Minut And &B00001111 ' единицы минут
Minut = Minut And &B11110000
Shift Minut , Right , 4 'десятки минут
Eclock = Clock And &B00001111 'единицы часов
Clock = Clock And &B11110000
Shift Clock , Right , 4 'десятки часов
Cls
Lcd " " ; Clock ; Eclock ; ":" ; Minut ; Eminut 'индикация часов и минут
Wait 1
Loop
Button: 'установка
Waitms 75
Do 'установка минут
If Portd.4 = 0 Then 'кнопка "далее" нажата?-переход к переводу минут в двоич.-дес.код
Exit Do
End If
If Portd.5 = 0 Then 'кнопка "увеличить" нажата?
Waitms 75
Minut = Minut + 1
End If
If Minut = 60 Then ’проверка по предельному значению
Minut = 0
End If
Cls
Lcd "Minut=" ; Minut
Loop
Waitms 75
Z = Minut 'выделение десятков и единиц минут
Call Ed
Eminut = Ones
Minut = Tens
Shift Minut , Left , 4
Minut = Minut + Eminut 'получение знач. минут в двоич.- десятичном коде
Do 'установка часов
If Portd.4 = 0 Then
Exit Do
End If
If Portd.5 = 0 Then
Waitms 75
Clock = Clock + 1
End If
If Clock = 24 Then
Clock = 0
End If
Cls
Lcd "Clock=" ; Clock
Loop
Waitms 75
I2cstart 'установка 24-хчасового режима
I2cwbyte Adressw
I2cwbyte Clockadress
I2cwbyte Sec1
I2cstop
Z = Clock
Call Ed
Eclock = Ones
Clock = Tens
Shift Clock , Left , 4
Clock = Clock + Eclock 'получение знач.часов в двоич.- десятичном коде
I2cstart 'запись минут и часов в DS1307
I2cwbyte Adressw
I2cwbyte Minadress
I2cwbyte Minut
I2cwbyte Clock
I2cstop
Return
Sub Ed 'подпрограмма выделения единиц и десятков
Tens = 0
Ones = 0
Do 'выделение десятков
Z = Z - 10
If Z < 0 Then Exit Do
Tens = Tens + 1
Loop
Z = Z + 10 'выделение единиц
Ones = Z
End Sub
End 'end program
Блок – схема программы “Clok” приведена на Рис.2.
До сих пор для отображения информации мы использовали жидкокристаллический индикатор. Однако, это же можно сделать и с помощью семисегментного светодиодного индикатора. Используя для управления данным индикатором микроконтроллер AVR, а не отдельную микросхему дешифратора, с помощью них можно отображать очень многое, например: латинские буквы (c, C, d, E, F, G, h, H, I, P, и др.).
Общепринятые обозначения сегментов индикаторов приведены во многих учебниках, отметим только, что сегменты индикатора являются светодиодами и могут быть подключены по схеме либо с общим катодом, либо - с общим анодом.
Если вы, например, используете индикаторы с общим катодом, то для включения сегментов нужно подать на их аноды напряжение высокого уровня, а управление организовать через ключи, подключающие катоды индикаторов к земле. Выводы семисегментных индикаторов желательно подключать к одному порту. Это облегчит программирование и упростит топологию печатной платы.
На Рис.3 представлена схема подключения двухсекционного семисегментного светодиодного индикатора типа DC56-11SRWA (с общим катодом) к микроконтроллеру ATtiny2313. Как видно из схемы сегменты индикаторов подключены к порту В через токоограничивающие резисторы 430 Ом. Управление индикаторами осуществляется с помощью контактов PD6 (индикация десятков), PD5 (индикация единиц), которые управляют ключами транзисторной сборки DA2 (IRF7103), подключающими катоды индикаторов К1 и К2 к земле.
Микроконтроллер с персонального компьютера через RS-232 принимает числа от 0 до 99. Принятое число разделяется на количество десятков и количество единиц. Далее количество десятков и количество единиц идентифицируются с кодами семисегментного индикатора. Затем семисегментный код десяток помещается в порт В и индуцируется на первом индикаторе. Потом первый индикатор выключается, в порт В помещается семисегментный код единиц и включается второй индикатор (а первый выключается). Поочередное быстрое включение и выключение индикаторов создаёт для человеческого глаза впечатление одновременной индикации десятков и единиц. Такое включение индикаторов называется динамическим.
На Рис.4 приведена блок – схема программы “Ledindi”. Как видно из блок – схемы, программа содержит основной цикл, в котором происходит индикация принятого по RS-232 числа, и подпрограммы обработки прерывания по завершению приёма, в которой происходит обработка принятого числа. Ниже приведен текст программы.
Программа “Ledindi”:
$regfile = "attiny2313a.dat"
$crystal = 4000000
$hwstack = 40
$swstack = 16
$framesize = 32
Ddrb = &B11111111 'PORTB - все выхода
Portb = 0 'PORTB - на всех выходах низкий уровень
Config Pind.5 = Output 'общий катод - единицы
Config Pind.6 = Output 'общий катод - десятки
Config Pind.0 = Input 'RxD
Dim Tens As Byte 'объявление переменных
Dim Ones As Byte
Dim Cod(10) As Byte
Dim Index As Byte
Dim Codd As Byte
Dim Code As Byte
Dim Z As Integer
On Urxc Rx 'определение подпрограммы прерывания по приёму
Enable Interrupts 'разрешение прерываний
Enable Urxc
Do 'основная программа
Portb = Codd 'индикация десятков
Reset Portd.5
Set Portd.6
Waitms 100 'задержка 100 мс
Portb = Code 'индикация единиц
Reset Portd.6
Set Portd.5
Waitms 100
Loop
Rx: 'подпрограмма обработки прерываний по приёму
Input , Z 'приём числа
Tens = 0
Ones = 0
Do 'выделение десятков
Z = Z - 10
If Z < 0 Then Exit Do
Tens = Tens + 1
Loop
Z = Z + 10 'выделение единиц
Ones = Z
Tens = Tens + 1 'определение кода индикатора для десятков
Restore M1
For Index = 1 To 10
Read Cod(index)
If Index = Tens Then
Codd = Cod(index)
End If
Next Index
Ones = Ones + 1 'определение кода индикатора для единиц
Restore M1
For Index = 1 To 10
Read Cod(index)
If Index = Ones Then
Code = Cod(index)
End If
Next Index
Return
End 'end program
M1:
Data &B00111111 , &B00000110 , &B00011011 , &B01001111 , &B00100100 , &B01101101 , &B01111101 , &B00000111 , &B01111111 , &B01101111
Данную программу вы можете симулировать, не собирая схемы. Но не забудьте для отключения задержек после настроек поставить оператор $sim.
Программы “Clok” и “Ledini” находятся в приложении 1 данной статьи.