Подключение схемы DS1307 к микроконтроллеру по интерфейсу TWI. Подключение схемы DS1307 к микроконтроллеру по интерфейсу TWI H – Часы, которые настраиваются

Отзывы об этих часах в интернете самые противоречивые. Кто-то говорит что часы замечательные, а кто-то называет их убогой поделкой Далласа. И вот я, дабы развеять все недостоверные слухи, достал микруху из загашника начала экспериментировать.

Особенности:

  • Очень маленькое энергопотребление. Производитель обещает 10 лет работы часов от одной стандартной батарейки CR2032
  • 56 байт памяти для хранения пользовательских данных. Думаю не особо нужная опция, но может кому-то и пригодится.
  • Программируемый вывод для тактирования внешних устройств. Может выдавать 1 Гц, 4.096 кГц, 8.192 кГц и 32.768 кГц.
  • 24-х часовой и 12-ти часовой режим

Распиновка

Выводы часов расположены следующим образом:

X1, X2 — Выводы для подключения кварцевого резонатора на частоту 32.768 кГц
VBAT — Вывод для подключения 3-х вольтовой батареи резервного питания
GND — Земля
SDA — линия данных шины i2c
SCL — линия тактовых импульсов шины i2c
SQW/OUT – выходной сигнал для тактирования внешних устройств
VCC — питание 5 вольт

Подключение к контроллеру
Обвязка минимальна. Потребуется кварц 32.768 кГц, пара резисторов для работы шины i2c и батарейка на три вольта.

Правильная разводка платы
Точность хода да и вообще работоспособность часов, зависит от разводки печатной платы. Даллас в своем даташите рекомендует сократить до минимума длинну проводников от микросхемы до кварцевого резонатора и окружить эти проводники прямоугольником подключенным к земле. Кроме этого для надежности я припаял к корпусу кварца проводок идущий к земле и параллельно питанию поставил конденсатор на 0.1 мкф.

Кстати может работать и без кварца. Для этого на ногу X1 подают внешний тактовый сигнал с частотой 32.768 кГц, а X2 остаётся висеть в воздухе.

Организация памяти часов
Данная микруха наделена 64 байтами памяти. Первые восемь байт — рабочие. В них хранится время, дата, день недели. Остальные выделены под нужды пользователя. В них можно хранить например какие-нибудь настройки или еще что-нибудь. Естественно, когда резервное питание пропадает, вся информация в этой памяти разрушается. Вся работа с часами (чтение и установка времени/даты) сводится к тому, чтобы читать и записывать нужные ячейки памяти.

Все числа в памяти хранятся в двоично-десятичном формате. Это значит что в одном байте может хранится сразу две цифры. Например число 0x23 — содержит в себе цифру 2 и цифру 3. На каждую цифру выделяется по 4 бита. Зачем так сделано? Для удобства и экономии памяти. Кроме времени и даты в памяти хранятся несколько бит настроек:

  • Clock Halt — управляет часами. Когда бит установлен то часы стоят. Чтобы запустить ход часов необходимо записать в этот бит 0. После подключения батареи резервного питания, этот бит уставлен и часы не считают время! Об этом нужно помнить.
  • 24/12 — этот бит выбора режима часов. Когда этот бит равен единице то используется 12-ти часовой режим. В противном случае 24-х часовой. Если используется 12-ти часовой режим то пятый бит показывает AM или PM сейчас. Если бит равен 1 то значит PM. В 24-х часовом режиме этот бит используется для хранения десятков часов совместно с битом 4.
  • Output — управляет состоянием ноги SQW/OUT. Бит установлен — на ноге лог 1. Сброшен — на ноге 0. Для управления таким образом, бит SQWE должен быть сброшен.
  • SQWE — когда бит установлен, на ноге SQW/OUT появляются прямоугольные импульсы.
  • RS1, RS0 — этими битами задается частота импульсов. Зависимость частоты от комбинации бит находится в таблице ниже:

Софт

Для работы с часами DS1307 была написана нехитрая библиотека содержащая следующие базовые функции:

DS_start — запускает часы. Запустить часы можно так же установив время.
DS_stop — останавливает часы
DS_set_time — Установка времени. Перед вызовом процедуры нужно поместить в tmp1 — секунды в tmp2 — минуты и в tmp3-часы. Часы в 24-х часовом формате.
DS_get_time: — считывание времени из часов. секунды будут записаны в tmp1, минуты в tmp2, часы в tmp3
DS_get_date: — считывание даты из часов. День будет записан в tmp1, месяц в tmp2, год в tmp3
DS_set_date: — установка даты. Перед вызовом процедуры нужно поместить в tmp1 — день в tmp2 — месяц и в tmp3-год (последние 2 цифры)

Процедуры установки/чтения времени и даты могут воспринимать/возвращать входные данные в двоично-десятичном формате и в десятичном. Для выбора желаемого формата нужно закомментировать или раскомментировать по три строчки в каждой процедуре (в коде есть примечания по этому поводу).

Тестовая программа позволяет управлять часами через UART (скорость 9600, контроллер работает на частоте 8 мГц). При запуске сразу выдаются время, дата и приглашение ввести команду от 1 до 3. При выборе варианта 1 происходит повторное считывание времени/даты. Вариант 2 позволяет установить время, а вариант 3 дату. Если хочется попробовать поиграть с часами в то в архив с исходником включён файл для симуляции.

Точность
Тут очень многое зависит от применяемого кварца и разводки платы. Даташит сообщает что емкость кварца должна быть 12.5 пф. Говорят, что лучше всего применять кварцы от материнских плат. Для коррекции хода можно подпаять к резонатору подстроечный конденсатором и при помощи него в небольших пределах менять частоту. Лично у меня эти часы работают вторые сутки и отстали на 3 секунды. Что-то мне подсказывает, что дело в ёмкости кварца, попробую другой отпишусь.

Вывод
Неплохие часы. Для любительского применения идеальный вариант. Хотя некоторые пишут о глюках, но я пока не столкнулся.

DS1307 ещё называют RTC (Real Time Clock). Данная микросхема представляет из себя часы реального времени и календарь. Связь с микросхемой осуществляется по интерфейсу I 2 C. Её преимущество в том, что она работает (считает время) при выключенном основном питании от резервного источника питания в 3 вольта (например, от батареики типа CR3022). Но в DS1307 есть один недостаток: в ней нет проверки на правильность введённых данных. Для работы с микросхемой потребуется минимальный обвес: кварц на 32768Hz, батарея на 3 вольта и два резистора на 4,7кОм. Схема подключения DS1307:

Работа с DS1307 в BASCOM-AVR

Для начала работы с микросхемой необходимо сконфигурировать порты, к которым подключена микросхема, для этого воспользуемся командой Config :
Config Sda = (Порт микроконтроллера к которому подключена нога SDA микросхемы DS1307)
Config Scl = (Порт микроконтроллера к которому подключена нога SCL микросхемы DS1307)
Например:
Config Sda = Portb.1
Config Scl = Portb.0

После конфигурации портов можно начать работать с микросхемой: считывать и записывать данные. Время и дату с микросхемы DS1307 можно считать так:

I2cstart I2cwbyte &HD0 I2cwbyte &H00 I2cstart I2cwbyte &HD1 I2crbyte (переменная в которую запишем секунды) , Ack I2crbyte (переменная в которую запишем минуты) , Ack I2crbyte (переменная в которую запишем часы) , Ack I2crbyte (переменная в которую запишем номер дня недели) , Ack I2crbyte (переменная в которую запишем дату), Ack I2crbyte (переменная в которую запишем номер месяца) , Ack I2crbyte (переменная в которую запишем год) , Nack I2cstop

После чтения данных необходимо перевести их в десятичный формат, вот так:
(переменная секунд) = Makedec((переменная секунд))
(переменная минут) = Makedec((переменная минут))
(переменная часов) = Makedec((переменная часов))
(переменная дня недели) = Makedec((переменная дня недели))
(переменная даты) = Makedec((переменная даты))
(переменная месяца) = Makedec((переменная месяца))
(переменная года) = Makedec((переменная года))

Вот пример чтения времени и даты, а также перевод их в десятичный формат:

I2cstart I2cwbyte &HD0 I2cwbyte &H00 I2cstart I2cwbyte &HD1 I2crbyte Seco , Ack I2crbyte Mine , Ack I2crbyte Hour , Ack I2crbyte Day , Ack I2crbyte Dat , Ack I2crbyte Month , Ack I2crbyte Year , Nack I2cstop Seco = Makedec(seco) Mine = Makedec(mine) Hour = Makedec(hour) Day = Makedec(day) Dat = Makedec(dat) Month = Makedec(month) Year = Makedec(year)

Данные считывать научились, теперь попробуем записывать данные в DS1307. Вот так:
(Переменная которую запишем) = Makebcd((Переменная которую запишем))
I2cstart
I2cwbyte &HD0
I2 cwbyte (Ячейка в которую запишем данные)
I2 cwbyte (Переменная которую запишем)
I2cstop

Обратите внимание, что командаMakebcd переводит переменную в двоично-десятичный формат. Номера и обозначения ячеек:

Вот пример записи переменной секунд:
Seco = Makebcd(seco)
I2cstart
I2cwbyte &HD0
I2cwbyte 0
I2cwbyte Seco
I2 cstop
Кстати, следует учесть, что при первом запуске DS1307 (например, при подключении батареи резервного питания) микросхема будет возвращать в секундах значение 80, это означает, что часы остановлены. Для их запуска запишите в секунды значение 1. Если DS1307 при чтении любых данных возвращает значение 255 или 168 это означает что, микросхема неправильно подключена, либо отсутствует батарея резервного питания.

Практическая работа с микросхемой DS1307

Теперь попробуем поработать с микросхемой DS1307 на практике: соберём простые часы с установкой времени с помощью кнопок. Для этого возьмём саму микросхему DS1307, микроконтроллер Attiny2313, LCD индикатор на контроллере HD44780 и несколько дискретных компонентов. Соберём простую схему:

И напишем простую программу, применяя полученные знания:

$regfile = "attiny2313.dat" $crystal = 4000000 Config Lcdpin = Pin , Db4 = Portb.4 , Db5 = Portb.5 , Db6 = Portb.6 , Db7 = Portb.7 , E = Portb.3 , Rs = Portb.2 Config Lcd = 16 * 2 Config Pind.5 = Input Config Pind.4 = Input Config Sda = Portb.1 Config Scl = Portb.0 Dim Seco As Byte Dim Mine As Byte Dim Hour As Byte Initlcd Cls Cursor Off Do I2cstart I2cwbyte &HD0 I2cwbyte &H00 I2cstart I2cwbyte &HD1 I2crbyte Seco , Ack I2crbyte Mine , Ack I2crbyte Hour , Nack I2cstop Seco = Makedec(seco) Mine = Makedec(mine) Hour = Makedec(hour) Locate 1 , 1 Lcd Hour ; ":" ; Mine ; ":" ; Seco ; " " If Pind.5 = 0 Then Incr Mine Mine = Makebcd(mine) I2cstart I2cwbyte &HD0 I2cwbyte 1 I2cwbyte Mine I2cstop Waitms 100 End If If Pind.4 = 0 Then Incr Hour Hour = Makebcd(hour) I2cstart I2cwbyte &HD0 I2cwbyte 2 I2cwbyte Hour I2cstop Waitms 100 End If Loop End

Тема часов на микросхеме DS1307 довольно актуальна — это простое, но в то же время интересное устройство. Кроме того, оно может реально пригодиться. Но описывать отдельно микросхему смысла нет, поэтому я решил собрать себе подобное устройство, заодно рассказать о том, какие шишки набил при этом. Сам процесс разработки и сборки буду описывать, по мере прохождения некоторых этапов готовности девайса.

Update 17.10.2015
Вначале это была серия статей, целью которых было рассказать про создание устройства с нуля до состояния готовности, но внезапно у меня появилась аллергия на все что называется «часы», поэтому я слил все в одну статью. Устройство закончено на 99.9%, (осталось закрутить винты), но сделать это ой как не просто 🙂 Как только аллергия пройдет появится окончательная фотка.

Начнем с того, что пока нам ничего не известно про ds1307 кроме того, что с ее помощью делают часы. Поэтому качаем документацию, на эту микросхему и читаем список «вкусностей», которыми она обладает. Итак, из первого абзаца в целом понятно, что она обладает низким энергопотреблением, информация передается по I2C, можно узнать дату и время, 12 и 24 часовой формат, автоматическая подстройка даты. Но самое интересное это схема (TYPICAL OPERATING CIRCUIT).

Курим даташит и пытаемся разобраться что к чему. Идем слева направо, CPU — микроконтроллер (то есть наша atmega), два резистора, написано pull up — значит подтягивающие (можно взять по 10к), кварц на 32768Гц, сама микросхема и батарейка. Выход SQW/OUT может дрыгаться с частотой 1Hz, 4kHz, 8kHz, 32kHz, пока нам это не интересно. Пожалуй, этой информации пока достаточно, хочется уже чего нибудь накодить 🙂

Создаем проект в CodeVision, в разделе I2C находим ds1307 и включаем его в проект. Хорошо бы еще выводить куда нибудь информацию, например на LCD и пара кнопок не помешает.

Все что нужно это LCD настроить на порт D и три кнопки с подтяжкой на вход. Далее нужно вывести на LCD время, для этого заглянем в мануал CodeVision и возьмем оттуда пример. Оказывается все просто — есть функция устанавливающая время:
rtc_set_time(3,0,0); //установить 03:00:00

т.е. после вызова данной функции в переменных h, m, s будут находиться часы(h), минуты(m) и секунды(s). Осталось вывести их на экран. Уж это мы умеем делать)
Итоговый код будет выглядеть так:

#include #include #include #include // Alphanumeric LCD Module functions #asm .equ __lcd_port= 0x12 ; PORTD #endasm #include char lcd_buf[ 33 ] ; void main(void ) { char hour, min, sek; PORTC= 0x07 ; DDRC= 0x00 ; // I2C Bus initialization i2c_init() ; rtc_init(0 , 0 , 0 ) ; // LCD module initialization lcd_init(16 ) ; rtc_set_time(3 , 0 , 0 ) ; while (1 ) { rtc_get_time(& hour,& min,& sek) ; lcd_clear() ; lcd_gotoxy(0 , 0 ) ; sprintf (lcd_buf, "%2d:%02d:%02d\n " , hour, min, sek) ; lcd_puts(lcd_buf) ; delay_ms(500 ) ; } ; }

#include #include #include // Alphanumeric LCD Module functions #asm .equ __lcd_port=0x12 ;PORTD #endasm #include char lcd_buf; void main(void) { char hour,min,sek; PORTC=0x07; DDRC=0x00; // I2C Bus initialization i2c_init(); // DS1307 Real Time Clock initialization rtc_init(0,0,0); // LCD module initialization lcd_init(16); rtc_set_time(3,0,0); while (1) { rtc_get_time(&hour,&min,&sek); lcd_clear(); lcd_gotoxy(0,0); sprintf(lcd_buf,"%2d:%02d:%02d\n",hour,min,sek); lcd_puts(lcd_buf); delay_ms(500); }; }

Собираем и тестируем в протеусе:

Схема и прошивка

Продолжим модернизировать нашу прошивку. Начнем со следующей задумки: у DS1307 есть выход SQW/OUT, который может генерировать несколько частот. Если настроить этот выход на 1Гц, и подать этот сигнал на вход внешнего прерывания, то получится, что раз в секунду 1307 будет дергать «за хвост» нашу atmega8. Для меги это будет сигналом к тому, что пора обновлять время. Это позволит не нагружать микроконтроллер постоянным обновлением времени, информация о текущем времени будет обновляться ровно раз в секунду.

Добавим в проект внешнее прерывание по низкому уровню (low level) на ножке Int1 и включим подтяжку. Выход DS1307 настроим на частоту 1Гц. Кстати, читать мануалы полезно, нашел интересную особенность — подтягивающие резисторы на ножках SCL, SDA должны быть 3,3k — 4,7k. Учтем это.

Получившийся код будет выглядеть так:

interrupt [ EXT_INT1] void ext_int1_isr(void ) { time_flag= 1 ; }

interrupt void ext_int1_isr(void) { time_flag=1; }

В прерывании выставляем флаг, разрешающий вывод времени, в основном цикле, если флаг выставлен, то показываем время, если не выставлен ничего не делаем.

if (time_flag== 1 ) { rtc_get_time(& hour,& min,& sek) ; lcd_gotoxy(0 , 0 ) ; sprintf (lcd_buf, "%02d:%02d:%02d\n " , hour, min, sek) ; lcd_puts(lcd_buf) ; }

if(time_flag==1) { rtc_get_time(&hour,&min,&sek); lcd_gotoxy(0,0); sprintf(lcd_buf,"%02d:%02d:%02d\n",hour,min,sek); lcd_puts(lcd_buf); }

Теперь перейдем к следующему вопросу, на сколько эффективно использовать sprintf? Чтобы не разводить пустых разговоров, приведу 2 куска кода, которые выполняют одно и тоже — выводят информацию о времени на дисплей.

Первый вариант, уже нам известный:

sprintf (lcd_buf, "%02d:%02d:%02d\n " , hour, min, sek) ; lcd_puts(lcd_buf) ;

sprintf(lcd_buf,"%02d:%02d:%02d\n",hour,min,sek); lcd_puts(lcd_buf);

Согласитесь просто в использовании и наглядно. Теперь вариант номер 2:

lcd_putchar(hour/ 10 + 0x30 ) ; lcd_putchar(hour% 10 + 0x30 ) ; lcd_putchar(":" ) ; lcd_putchar(min/ 10 + 0x30 ) ; lcd_putchar(min% 10 + 0x30 ) ; lcd_putchar(":" ) ; lcd_putchar(sek/ 10 + 0x30 ) ; lcd_putchar(sek% 10 + 0x30 ) ;

lcd_putchar(hour/10+0x30); lcd_putchar(hour%10+0x30); lcd_putchar(":"); lcd_putchar(min/10+0x30); lcd_putchar(min%10+0x30); lcd_putchar(":"); lcd_putchar(sek/10+0x30); lcd_putchar(sek%10+0x30);

Не очень наглядно, но разобраться можно. Как мы их будем сравнивать? Делается это очень просто — запускаем отладчик AVR STUDIO и смотрим количество тактов затраченных на их выполнение. Итак, «барабанная дробь», результаты… Первый кусок кода выполнялся 16 466 тактов, что равносильно 2 058,25 мкс, при рабочей частоте в 8МГц, для второго куска кода эта цифра составила 12 278 тактов или 1 534,75 мкс. Согласитесь, снизить время выполнения, а значит и разгрузить микроконтроллер на ~25% достаточно весомая причина, чтобы не использовать sprintf. Выкидываем sprintf из нашего проекта, в след за ним можно выкинуть stdio.h и lcd_buf.

Некрасиво, когда в основном цикле мешанина из кода, поэтому вывод информации можно засунуть в функцию. В основном цикле останется

while (1 ) { if (time_flag== 1 ) { show_time() ; //показать информацию о текущем времени } } ;

while (1) { if(time_flag==1) { show_time(); //показать информацию о текущем времени } };

Объявление самой функции будет выглядеть так:

void show_time() { rtc_get_time(& hour,& min,& sek) ; lcd_gotoxy(0 , 0 ) ; lcd_putchar(hour/ 10 + 0x30 ) ; lcd_putchar(hour% 10 + 0x30 ) ; lcd_putchar(":" ) ; lcd_putchar(min/ 10 + 0x30 ) ; lcd_putchar(min% 10 + 0x30 ) ; lcd_putchar(":" ) ; lcd_putchar(sek/ 10 + 0x30 ) ; lcd_putchar(sek% 10 + 0x30 ) ; time_flag= 0 ; }

void show_time() { rtc_get_time(&hour,&min,&sek); lcd_gotoxy(0,0); lcd_putchar(hour/10+0x30); lcd_putchar(hour%10+0x30); lcd_putchar(":"); lcd_putchar(min/10+0x30); lcd_putchar(min%10+0x30); lcd_putchar(":"); lcd_putchar(sek/10+0x30); lcd_putchar(sek%10+0x30); time_flag=0; }

Теперь в нашу прошивку, нужно добавить вывод даты. Установка даты, производится следующей функцией:

rtc_set_date(6,13,10,13); //6- день недели, 13 - день, 10 - месяц, 13 - год

rtc_get_date(&week_day,&day,&month,&year); //день недели, день, месяц, год

Вывод даты можно организовать, пока что в основном цикле, рядом со временем, полный исходный код получился такой:

#include // I2C Bus functions #asm .equ __i2c_port= 0x18 ; PORTB .equ __sda_bit= 0 .equ __scl_bit= 1 #endasm #include // DS1307 Real Time Clock functions #include // Alphanumeric LCD functions #include char hour= 0 , min= 0 , sek= 0 , day= 0 , month= 0 , year= 0 , week_day= 0 ; bit time_flag= 0 ; char menu= 0 ; // External Interrupt 1 service routine interrupt [ EXT_INT1] void ext_int1_isr(void ) { time_flag= 1 ; } void show_time() { rtc_get_time(& hour,& min,& sek) ; rtc_get_date(& week_day,& day,& month,& year) ; lcd_gotoxy(0 , 0 ) ; lcd_putchar(hour/ 10 + 0x30 ) ; lcd_putchar(hour% 10 + 0x30 ) ; lcd_putchar(":" ) ; lcd_putchar(min/ 10 + 0x30 ) ; lcd_putchar(min% 10 + 0x30 ) ; lcd_putchar(":" ) ; lcd_putchar(sek/ 10 + 0x30 ) ; lcd_putchar(sek% 10 + 0x30 ) ; lcd_gotoxy(0 , 1 ) ; lcd_putchar(day/ 10 + 0x30 ) ; lcd_putchar(day% 10 + 0x30 ) ; lcd_putchar("/" ) ; lcd_putchar(month/ 10 + 0x30 ) ; lcd_putchar(month% 10 + 0x30 ) ; lcd_putchar("/" ) ; lcd_putchar(year/ 10 + 0x30 ) ; lcd_putchar(year% 10 + 0x30 ) ; time_flag= 0 ; } void main(void ) { PORTC= 0x0F ; DDRC= 0x00 ; PORTD= 0x08 ; DDRD= 0x00 ; // I2C Bus initialization i2c_init() ; // DS1307 Real Time Clock initialization // Square wave output on pin SQW/OUT: On // Square wave frequency: 1Hz rtc_init(0 , 1 , 0 ) ; // External Interrupt(s) initialization // INT0: Off // INT1: On // INT1 Mode: Low level GICR|= 0x80 ; MCUCR= 0x00 ; GIFR= 0x80 ; // LCD module initialization lcd_init(16 ) ; rtc_set_time(12 , 0 , 0 ) ; rtc_set_date(6 , 13 , 10 , 13 ) ; #asm("sei") while (1 ) { if (time_flag== 1 ) { show_time() ; } } ; }

#include // I2C Bus functions #asm .equ __i2c_port=0x18 ;PORTB .equ __sda_bit=0 .equ __scl_bit=1 #endasm #include // DS1307 Real Time Clock functions #include // Alphanumeric LCD functions #include char hour=0,min=0,sek=0,day=0,month=0,year=0,week_day=0; bit time_flag=0; char menu=0; // External Interrupt 1 service routine interrupt void ext_int1_isr(void) { time_flag=1; } void show_time() { rtc_get_time(&hour,&min,&sek); rtc_get_date(&week_day,&day,&month,&year); lcd_gotoxy(0,0); lcd_putchar(hour/10+0x30); lcd_putchar(hour%10+0x30); lcd_putchar(":"); lcd_putchar(min/10+0x30); lcd_putchar(min%10+0x30); lcd_putchar(":"); lcd_putchar(sek/10+0x30); lcd_putchar(sek%10+0x30); lcd_gotoxy(0,1); lcd_putchar(day/10+0x30); lcd_putchar(day%10+0x30); lcd_putchar("/"); lcd_putchar(month/10+0x30); lcd_putchar(month%10+0x30); lcd_putchar("/"); lcd_putchar(year/10+0x30); lcd_putchar(year%10+0x30); time_flag=0; } void main(void) { PORTC=0x0F; DDRC=0x00; PORTD=0x08; DDRD=0x00; // I2C Bus initialization i2c_init(); // DS1307 Real Time Clock initialization // Square wave output on pin SQW/OUT: On // Square wave frequency: 1Hz rtc_init(0,1,0); // External Interrupt(s) initialization // INT0: Off // INT1: On // INT1 Mode: Low level GICR|=0x80; MCUCR=0x00; GIFR=0x80; // LCD module initialization lcd_init(16); rtc_set_time(12,0,0); rtc_set_date(6,13,10,13); #asm("sei") while (1) { if(time_flag==1) { show_time(); } }; }

Результат:

Схема и прошивка:

Перейдем к организации меню. Самый главный вопрос состоял в том, как оно все должно выглядеть, т.е. нужно было сформулировать техническое задание(т.з.).
Мне хотелось, чтобы это были отдельные экраны:
-главный экран;
-экран настройки времени;
-экран настройки даты;
-экран настройки будильника.

При этом обойтись четырьмя кнопками — вверх, вниз, влево, вправо. Переход между экранами должен осуществляться кнопками вверх и вниз. Настройка производится на соответствующем экране. Применяемый микроконтроллер atmega8. Вот такое примитивное т.з.

То что размер кода будет достаточно большой было понятно изначально. При этом нужно было его разбить на логически связанные части. С частями все понятно — обработка одного экрана одна часть кода. Поэтому начал с того, что основной цикл разбил на четыре части, переключения между которыми производится оператором switch. Внутрь засунул функции — пустышки. Кнопки 0(вверх) и 3(вниз) порта C позволяют изменить переменную menu. Таким образом мы скачем между менюшками. Но пока такая прошивка еще работать не могла, ибо функции еще не определены.

while (1 ) { switch (menu) { case 0 : show_time() ; break ; case 1 : set_time() ; break ; case 2 : set_date() ; break ; case 3 : set_alarm() ; break ; } } ;

while (1) { switch(menu) { case 0: show_time(); break; case 1: set_time(); break; case 2: set_date(); break; case 3: set_alarm(); break; } };

Следующий шаг определение этих функций, изначально я нарисовал статичные названия, вроде lcd_puts(«Set time»); функции получились, такими.

void set_alarm() { ////////просмотр настроек будильника lcd_gotoxy(0,0); lcd_puts("Set alarm"); } void set_time() { ////////просмотр настроек времени lcd_gotoxy(0,0); lcd_puts("Set time"); }

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

Встал следующий вопрос: как организовать сам процесс настройки? Поразмыслив, мне показалась интересной следующая идея: переходим кнопками вверх/вниз в интересующее нас меню, нажимаем вправо, появляется курсор, говорящий нам о том, что идет процесс настройки. Кнопками вверх/вниз мы изменяем величину, влево/вправо скачем курсором между настраиваемыми параметрами. Когда курсор находится под последним параметром, повторное нажатие кнопки вправо позволяет выйти из настройки. Курсор при этом скрывается, что говорит о том что мы вышли из настройки и можем снова переключаться между менюшками.

Но есть небольшие проблемы, например, кнопка вверх должна изменять параметры и при этом, переключать следующий экран. Т.е. логику кнопок внутри одного экрана, пришлось разделить. Из за этого код здорово разросся. Например, на экране будильника, вводим подпрограмму настройки(sub_alarm), соответственно кнопки внутри подпрограммы обрабатываются одним образом, а вне другим.

void set_alarm() //Функция обработки будильника { //режим отображения меню настроек будильника if(sub_alarm==0) { if(PINC.0==0) //кнопка вверх - смена экрана меню { menu=0; ..... } } //подменю настройки будильника if(sub_alarm==1) { if(PINC.0==0) //кнопка вверх - увеличить величину { a_hour++; .... } }

Есть еще такой момент, когда зашли в подменю настройки одна и таже кнопка (возьмем опять в качестве примера кнопку вверх), может менять часы, а может минуты. Поэтому была введена еще одна переменная subProgram.
Например:

if(PINC.0==0) //кнопка вверх { if(subProgram==1) //subProgram=1 - изменяем часы { a_hour++; ... } if(subProgram==2) //subProgram=2 - изменяем минуты { a_min++; ... } if(subProgram==3) //subProgram=3 изменяем флаг будильника { ... } }

Единственное о чем стоит упомянуть это спецсимвол, который выводится на главном экране, когда будильник включен.

Пример взят из примеров в папке CodeVision\examples\lcd char.

typedef unsigned char byte; //переопределяем тип flash byte char_table[ 8 ] = { //рисуем свой символ 0b10000000 , 0b10000100 , 0b10001110 , 0b10001110 , 0b10001110 , 0b10011111 , 0b10100100 , 0b11000000 } ; // function used to define user characters void define_char(byte flash * pc, byte char_code) { byte i, address; address= (char_code<< 3 ) | 0x40 ; for (i= 0 ; i< 8 ; i++ ) lcd_write_byte(address++,* pc++ ) ; } void main(void ) { byte i, address; lcd_init(16 ) ; define_char(char_table, 0 ) ; //Грузим символ в лсд while (1 ) { lcd_putchar(0 ) ; //выводим символ на дисплей }

typedef unsigned char byte; //переопределяем тип flash byte char_table={ //рисуем свой символ 0b10000000, 0b10000100, 0b10001110, 0b10001110, 0b10001110, 0b10011111, 0b10100100, 0b11000000}; // function used to define user characters void define_char(byte flash *pc,byte char_code) { byte i,address; address=(char_code<<3)|0x40; for (i=0; i<8; i++) lcd_write_byte(address++,*pc++); } void main(void) { byte i,address; lcd_init(16); define_char(char_table,0); //Грузим символ в лсд while(1) { lcd_putchar(0); //выводим символ на дисплей }

Рисовать можно символ 5х7, единичка — пиксел закрашен, ноль — не закрашен. Получился символ колокольчика.

Прошивка

Следующий шаг, это продумывание внешнего вида устройства. В моем представлении это будет жк экран и четыре кнопки на лицевой части, внутри будет печатная плата на которой будут все остальные элементы. Питание будет от блока питания, аналогично тому что сделан из китайской зарядки.

Начнем с печатной платы, для этого требуется программа, которая позволяет рисовать печатки. Существует множество подобных программ: P-cad, Altium, Sprint layout… Мне нравится Альтиум, только потому, что для него куча готовых библиотек с элементами, ибо тратить время на набивку собственной библиотеки элементов, на мой взгляд не дело. Общий смысл всех подобных программ одинаков — сначала рисуется электрическая схема.

В трассировщике все элементы уже знают, какой с каким должен соединяться, благодаря электрической схеме.

Остается только удобно расположить элементы и соединить их проводниками.


В этом материале будет рассмотрен топорный вариант работы с TWI модулем на примере часов реального времени - микросхемы DS1307. Топорный, потому что обмен по I2C будет организован без прерываний и анализа статусных кодов, чтобы сильно не грузить начинающих.

DS1307

Микросхема DS1307 предназначена для счета времени - секунд, минут, часов, дней, месяцев и лет. То есть по сути, это часы с календарем.

Она тактируется от собственного кварцевого генератора с частотой 32768 Гц и может работать от двух источников питания - основного и резервного. Важная фишка этой микросхемы заключается в низком потреблении - меньше 500 nA в рабочем режиме. При таком потреблении DS1307 может проработать от трехвольтовой батарейки (типа CR2032 емкостью ~200 мА*ч) несколько лет. Также DS1307 может генерировать на одном из выводов меандр и в ее составе есть 56 байт оперативной памяти, которую можно использовать для хранения данных.

Минимальная схема подключения DS1307 включает в себя часовой кварц и один источник питания. Обмен данными с микросхемой осуществляется по I2C, причем DS1307 может работать на шине только как подчиненное устройство (слейвом).

С чего начать?

Подключение любой микросхемы начинается с изучения даташита. В случае DS1307 нам нужно выяснить: какую скорость обмена поддерживает микросхема, какой она имеет адрес, как выглядит карта памяти, есть ли у нее управляющие биты или регистры, как передать данные и как прочитать их. Ниже приведены скриншоты из даташита, в которых я нашел требуемую информацию.

Скорость обмена DS1307




Адрес, по которому DS1307 отзывается на I2C шине




Карта памяти DS1307

Карта памяти показывает, по каким адресам расположены регистры микросхемы и сколько их вообще.

По нулевому адресу располагается регистр секунд. Младшие 4 разряда регистра отведены для единиц, там может быть число от 0 до 9. Старшие - для десятков секунд.


Это так называемый двоично-десятичный формат представления чисел (BCD).При таком формате один байт может представить числа только от 0 до 99. Остальные регистры часов и календаря содержат данные в таком же формате.

7-й разряд регистра секунд - управляющий. 0 в этом разряде разрешает работу часов, 1 - запрещает. При подачи питания этот разряд устанавливается в 1.

По первому адресу расположен регистр минут. С ним все понятно.

По второму адресу располагается регистр часов. 6-й бит этого регистра задает формат представления времени. Если он установлен в 1 используется 12 часовой формат, если сброшен -24 часовой.

По седьмому адресу располагается регистр, управляющий выводом SQW. На него можно выводить внутренний тактовый сигнал разной частоты. Значения битов описаны в даташите. Нас они сейчас не интересуют.

Ну и адреса с 8 по 63-й отведены для оперативной памяти. Их можно использовать для хранения данных.

Как записать данные в DS1307

DS1307 может работать в двух режимах: как подчиненный приемник и как подчиненный передатчик. В первом режиме ведущее устройство передает DS1307 данные, а DS1307 принимает их. Во втором - ведущее устройство принимает от DS1307 данные, а та в свою очередь передает их. (Но обмен в обоих случаях начинает ведущий!)

Для каждого режима в даташите есть описание и диаграмма обмена. Запись данных выполняется согласно следующей последовательности.



2. Ведущий выдает на шину адрес DS1307 с нулевым битом квитирования (адресный пакет), что сигнализирует ведомому о последующей записи данных.
3. Если на шине присутствует микросхема DS1307, она отвечает ведущему - ACK.
4. После получения ответа ведущий передает DS1307 адрес регистра, с которого начнется запись данных. Это значение записывается во внутренний счетчик адреса DS1307.
5. DS1307 снова отвечает ведущему.
6. Получив ответ, ведущий передает ведомому байт данных, который предназначен для записи в регистр DS1307.
7. DS1307 отвечает ведущему.
8. Шаги 6, 7 повторяются несколько раз.
9. Ведущий формирует на шине состояние СТОП.

Адрес, по которому выполняется запись в DS1307, автоматически увеличивается на единицу. Дойдя до последнего адреса, счетчик обнуляется. Записывать можно любое число байт - хоть один, хоть все.



1. Ведущий формирует на шине состояние СТАРТ.
2. Ведущий выдает на шину адрес DS1307 с установленным битом квитирования, что сигнализирует ведомому о последующем чтении данных.
3. DS1307 отвечает ведущему.
4. DS1307 передает ведущему байт данных, на который указывает внутренний счетчик адреса.
5. Ведущий отвечает, что принял данные.
6 . Шаги 4, 5 повторяются несколько раз.
7. DS1307 передает ведущему байт данных.
7. Ведущий неформирует ответ DS1307.
8. Ведущий выдает на шину состояние СТОП.

Поскольку чтение данных выполняется по адресу внутреннего счетчика, его значение нужно предварительно инициализировать. Это делается с помощью операции записи, которая обрывается после передачи адреса регистра.

Код

Теперь можно перейти к коду. Нам понадобится минимум три функции:

Функция инициализации,
- функция записи данных,
- функция чтения данных.

Инициализация


#define F_I2C 50000UL
#define TWBR_VALUE (((F_CPU)/(F_I2C)-16)/2)

#if ((TWBR_VALUE > 255) || (TWBR_VALUE == 0))
#error "TWBR value is not correct"
#endif

void RTC_Init(void)
{
TWBR = TWBR_VALUE;
TWSR = 0;
}

Скорость задается с помощью макроса TWBR_VALUE. Здесь используется формула, разобранная в предыдущей части. При компиляции расчетное значение проверяется с помощью директив препроцессора, чтобы убедиться, что оно не выходит за диапазон.

Передача данных

Передача данных начинается с состояния СТАРТ. Чтобы сформировать его, нужно включить TWI модуль, установить бит TWSTA и сбросить флаг прерывания TWINT. Это выполняется в одну строчку, записью в управляющий регистр TWCR.

Когда микроконтроллер выдаст на шину состояние СТАРТ, установится бит TWINT и в статусном регистре TWSR изменится статусный код. Микроконтроллер должен дождаться установки бита TWINT, прежде чем перейдет к следующей операции. Ожидание в нашем случае выполняется циклическим опросом (тупо поллингом.. не путать с троллингом).


TWCR = (1< while(!(TWCR & (1<

Каждая установка бита TWINT сопровождается определенным статусным кодом в регистре TWSR. По хорошему, мы должны проверять эти коды, чтобы контролировать успешность операций. Но поскольку код у нас торный (учебный), мы не будем этого делать.

Далее на шину нужно выдать адресный пакет. В регистр данных TWDR загружаем адрес, а бит квитирования устанавливаем нулевым. После загрузки адреса сбрасываем бит TWINT, инициируя дальнейшую работу TWI модуля, и дожидаемся, когда она завершится, опрашивая TWINT.


/*выдаем на шину пакет SLA-W*/
TWDR = (DS1307_ADR<<1)|0;
TWCR = (1<while(!(TWCR & (1<

Посылаем на шину адрес, с которого будет производиться запись в DS1307. Для этого загружаем в регистр данных требуемое значение, сбрасываем бит TWINT и дожидаемся его установки.



TWDR = adr;
TWCR = (1<while(!(TWCR & (1<


/*формируем состояние СТОП*/
TWCR = (1<

Полный код функции записи будет выглядеть примерно так.


void RTC_SetValue(uint8_t adr, uint8_t data)
{
/*формируем состояние СТАРТ*/
TWCR = (1< while(!(TWCR & (1<

/*выдаемна шину пакет SLA-W*/
TWDR = (DS1307_ADR<<1)|0;
TWCR = (1< while(!(TWCR & (1<

/*передаем адрес регистра ds1307*/
TWDR = adr;
TWCR = (1< while(!(TWCR & (1<

/*передаем данные или пропускаем*/
if (data != RTC_RESET_POINTER){
/*это чтобы привести данные к BCD формату*/
data = ((data/10)<<4) + data%10;

TWDR = data;
TWCR = (1< while(!(TWCR & (1< }

/*формируем состояние СТОП*/
TWCR = (1<}

С помощью этой функции можно производить запись отдельных регистров и инициализировать внутренний регистр адреса DS1307 для последующей операции чтения данных. Пример использования функции есть в тестовых проектах.

Чтение данных из DS1307

Формируем состояние СТАРТ.


/*формируем состояние СТАРТ*/
TWCR = (1< while(!(TWCR & (1<

Посылаем на шину адресный пакет - адрес и установленный бит квитирования.


/*выдаемна шину пакет SLA-R*/
TWDR = (DS1307_ADR<<1)|1;
TWCR = (1< while(!(TWCR & (1<

Получаем данные. Сбрасываем бит TWINT, инициирую работу TWI модуля. Бит TWEA должен быть установлен в 1, чтобы ведущее устройство сигнализировало ведомому о приеме очередного байта.
Когда бит TWINT снова установится в 1, в регистре данных будет байт принятый от ведомого.


/*считываем данные с подтверждением*/
TWCR = (1< while(!(TWCR & (1< data = TWDR;


/*считываем данные без подтверждения*/
TWCR = (1< while(!(TWCR & (1< data = TWDR;

/*формируем состояние СТОП*/
TWCR = (1<

Полный код функции чтения одного байта данный из DS1307 будет выглядеть примерно так.


uint8_t RTC_GetValue(void)
{
uint8_t data;

/*формируем состояние СТАРТ*/
TWCR = (1< while(!(TWCR & (1<

/*выдаем на шину пакет SLA-R*/
TWDR = (DS1307_ADR<<1)|1;
TWCR = (1< while(!(TWCR & (1<

/*считываем данные*/
TWCR = (1< while(!(TWCR & (1< data = TWDR;

/*формируем состояние СТОП*/
TWCR = (1<

Return data;
}

Тестовый проект для DS1307

Как обычно тестовый проект, объединяющий все выше сказанное. Программа простая. Инициализируем периферию, загружаем в DS1307 начальное значение. Далее в цикле считываем временя и выводим на LCD. Для общения с DS1307 используются всего три функции.

DS1307 – часы реального времени с последовательным интерфейсом, поддерживают. Часами можно управлять, используя микроконтроллер Atmega128 или другой МК, который имеет последовательный двухпроводной интерфейс. DS1307 подключается напрямую к двум портам I/O микроконтроллера, а двухпроводной интерфейс обеспечивается драйверами низкого уровня, которые описываются в разделе.

Основными характеристиками DS1307 являются: низкая потребляемая мощность, полный BCD часы/календарь и 56 байт энергонезависимой памяти SRAM. Адрес и данные передаются последовательно через двухпроводную двунаправленную шину. Часы/календарь выдают следующую информацию: секунды, минуты, часы, дни, месяцы и годы. Конец месяца автоматически устанавливается для тех месяцев, в которых менее 31 дня. Имеется поправка на високосный год. Часы работают в 24-часовом или 12-часовом формате с индикатором AM/PM. DS1307 имеет встроенную схему контроля питания, которая обнаруживает ошибки питания и автоматически переключается на батарейное питание.

DS1307 работает как «ведомое» устройство на последовательной шине. Для доступа к нему нужно установить состояние START и передать следом за адресом регистра идентификационный код устройства. К следующим регистрам можно обращаться последовательно, пока не установлено состояние STOP. Состояния START и STOP генерируются драйверами низкого уровня.

DS1307 имеет двухпроводную шину, подключённую к двум выводам порта I/O МК: SCL – PD0, SDA – PD1. Напряжение VDD равно 5В, схема использует кварцевый (часовой) резонатор с частотой 32.678 кГц.

В процессе передачи данных, при переходе линии тактового сигнала в высокое состояние, линия данных должна оставаться стабильной. Изменения состояния линии данных в тот момент, когда тактовая линия находится в высоком состоянии, будут пониматься как управляющие сигналы.

В соответствии с этим должны быть оговорены следующие условия:

Начало передачи данных. Изменение состояния линии данных при переходе из высокого в низкое, в то время как тактовая линия находится в высоком состоянии, определяется как состояние START.

Остановка передачи данных. Изменение состояния линии данных при переходе из низкого в высокое, в то время как тактовая линия находится в высоком состоянии, определяется как состояние STOP.


Действительные данные. Состояние линии данных соответствует действительным данным тогда, когда после условия START линия данных стабильна во время высокого состояния тактового сигнала. Данные на линии должны быть изменены во время низкого состояния тактового сигнала. Один тактовый импульс на один бит данных.

Рис. 2.40. Передача данных по последовательной двухпроводной шине

Каждая передача данных начинается при наступлении состояния START и прекращается при наступлении состояния STOP. Количество байт данных переданных между состояниями START и STOP не ограничено и определяется «ведущим» устройством. Информация передаётся побайтно, и каждый приём подтверждается девятым битом.

Подтверждение приёма. Каждое приёмное устройство, при обращении к нему, вынуждено генерировать подтверждение приёма после получения каждого байта. «Ведущее» устройство должно генерировать дополнительные тактовые импульсы, которые ставятся в соответствие битам подтверждения. Если сигнал подтверждения приёма находится в высоком состоянии, то по приходу тактового импульса бита подтверждения, подтверждающее приём устройство должно переводить линию SDA в низкое состояние. Конечно, должны учитываться время установки и время удержания. «Ведущее» устройство должно сигнализировать об окончании передачи данных «ведомому» устройству, прекращая генерацию бита подтверждения, при получении от «ведомого» тактового импульса подтверждения приёма. В этом случае, «ведомый» должен перевести линию данных в низкое состояние, чтобы позволить «ведущему» генерировать условие STOP.

На рис. 2.40 показано завершение передачи данных по двухпроводной линии. В зависимости от состояния бита R/-W, возможны два типа передачи:

1. Режим «ведомого» приемника (режим записи в DS1307): последовательные данные и такты получены через SDA и SCL соответственно. После передачи каждого байта передаётся подтверждающий бит (рис.2.40). Состояния START и STOP понимаются как начало и конец последовательной передачи. Распознавание адреса выполняется аппаратно после приема адреса «ведомого» и бита направления. Байт адреса является первым байтом, принимаемым после возникновения состояния START, генерируемого «ведущим». Байт адреса содержит семь битов адреса DS1307, равных 1101000, сопровождаемых битом направления (R/#W), который для записи равен 0 (рис. 2.40а). После приёма и декодирования байта адреса DS1307 выдаёт подтверждение на линию SDA. После подтверждения DS1307 адреса «ведомого» и бита записи, «ведущий» передает адрес регистра DS1307. Тем самым будет установлен указатель регистра в DS1307. Затем «ведущий» начнет передавать каждый байт данных с последующим приёмом подтверждения получения каждого байта. По окончании записи «ведущий» сформирует состояние STOP, для прекращения передачи данных.

2. Режим «ведомого» передатчика (режим чтения из DS1307): Первый байт принимается и обрабатывается как в режиме «ведомого» приёмника. Однако в этом режиме бит направления укажет, что направление передачи изменено. Последовательные данные передаются DS1307 по SDA, тактовые импульсы - по SCL. Состояния START и STOP понимаются как начало и конец последовательной передачи (рис. 2.40). Байт адреса является первым байтом, принимаемым после возникновения состояния START, генерируемого «ведущим». Байт адреса содержит семь битов адреса DS1307, равных 1101000, сопровождаемых битом направления (R/-W), который для чтения равен 1. После приёма и декодирования байта адреса DS1307 принимает подтверждение с линии SDA. Тогда DS1307 начинает передавать данные с адреса, на который показывает указатель регистра. Если указатель регистра не записан перед инициализацией режима чтения, то первым прочитанным адресом является последним адрес, сохранённый в указателе регистра. DS1307 должен послать бит «неподтверждения», чтобы закончить чтение (рис. 2.40б).

Схема подключения DS1307 к МК Atmega128 приведена на рис. 2.41, где кнопки SA1 и SA2 предназначены для начальной настройки часов.

Рис. 2.41. Подключение схемы DS1307 микроконтроллеру по интерфейсу IIC (шина TWI)

Контрольные вопросы

1. В чем отличие RISC –процессора от CISC-процессор?

2. В чем преимущества аккумуляторной архитектуры от архитектуры с регистрами общего назначения?

3. Что значит команды с фиксированной разрядностью? Дайте разъяснение.

4. Перечислите периферийные устройства МК и приведите примеры их использования.

5. Назначение отладочных средств. Что дает программисту использования отладчиков?

6. На какие линии делятся МК фирмы Atmel? В чем их отличие.

7. Где используются МК сверхмалым энергопотреблением?

8. Какие меры принимаются для снижения энергопотребления фирмами-разработчиками?

Глава III. Лабораторный практикум по микроконтроллерам семейства AVR фирмы ATMEL

Лабораторный практикум предназначен для изучения студентами специальностей 22.01.00, 23.03.00 и 23.05 всех форм обучения основных принципов построения и программирования, цифровых систем управления и обработки данных и является частью учебно-методических разработок по дисциплинам «Микропроцессорные системы», «Микропроцессорные устройства систем управления», «Микропроцессорные системы управления», «Машинно-ориентированные языки программирования». Приведенные в практикуме лабораторные работы позволят получить практические навыки по разработке аппаратного, алгоритмического и программного обеспечения микроконтроллерных систем управления и обработки данных.

В настоящем лабораторном практикуме наряду с описаниями лабораторных работ приводятся основные справочные и теоретические положения по теме выполняемой работы или ссылки на соответствующий материал данного учебного пособия, необходимый при подготовке и выполнении работы, а также контрольные вопросы, которые позволяют оценить степень подготовленности к работе.

Все работы проводятся на учебно-лабораторном стенде УЛС-ATmega8535, разработанным автором по единой схеме «Получение задания [Анализ задания [ Разработка алгоритма решения задачи [ Разработка и отладка программного обеспечения на отладчике AVR Studio 4 [ Программирование реальной системы с использованием PonyProg2000[Проверка работоспособности и демонстрации реальной системы [ Составление и защита отчета».

Отличительными особенностями стенда являются:

· универсальность;

· возможность подключения различных типов датчиков и исполнительных устройств;

· возможность использования современных аппаратно–программных средств отладки и программирования микроконтроллеров в реальных условиях;

Эффективность использования УЛС в учебном процессе определяется:

1. Универсальностью стенда, т.к. стенд позволяет посредством коммутации перестраивать структуру стенда для решения различных задач, что даст возможность на одном стенде проводить большое количество лабораторных работ (более 30);

2. Повышением эффективности проведения занятий, так как отладкапрограммного обеспечения стенда производится на отладчике AVR Studio 4, a программирование реального МК производится с использованием аппаратно-программных средств PonyProg2000;

3. Возможностью решения поставленных задач по схеме «Получение задания [Анализ задания [ Разработка алгоритма решения задачи [ Разработка и отладка программного обеспечения на отладчике AVR Studio 4 [ Программирование реальной системы с использованием PonyProg2000[Проверка работоспособности и демонстрации реальной системы [ Составление и защита отчета» с использованием реальных микроконтроллеров и современных аппаратно–программных средств отладки и программирования микроконтроллерных систем управления и обработки данных.

4. Получением дополнительных навыков по работе с различными периферийными устройствами (системами индикации на основе ЖКИ, интерфейсами UART, SPI, IIC и RS-232) и т.д.;

5. Возможностью разработки собственных вариантов лабораторных работ.

Принципиальная схема УЛС и расположение элементов на печатной плате приведены на рисунках 3.1 и 3.2.

Основные элементы УЛС следующие:

1. Кнопка включения напряжения питание SB9 (В качестве источника питания стенда используется блок питания компьютера +5В, что обеспечивает безопасность работы на стенде).

2. Светодиод HL17 индицирует наличие напряжения +5В.

3. . Микросхема D1 - микроконтроллер Atmega8535 семейства AVR, производства фирмы ATMEL, 8-восьмиразрядный, с тактовой частотой от 0 до 16 МГц. В своем составе имеет – Flash-память программ 8 Кбайт, ОЗУ (оперативное запоминающее устройство) 512 байт, 512 байт EEPROM (электрически перепрограммируемая память), два 8-разрядных и один 16-разрядный таймеры/счетчики, 8-канальный 10-битный АЦП (а налого-ц ифровой п реобразователь), программируемый последовательный интерфейс UART, последовательные интерфейсы SPI и I2C.

4. Жидкокристаллический индикатор (ЖКИ) LCD, подключенный к микроконтроллеру через параллельный порт (8 линий данных и 3 линии управления, разъемы Х8 и Х11 соответственно). ЖКИ дает возможность наглядно устанавливать (посредством кнопок настройки часов) и отображать текущее время и результаты работы АЦП.

5. Кнопки SB1, …, SB8 и светодиодные индикаторы HL1- HL8, предназначены для имитации дискретных сигналов ввода.

6. Линейка индикации дискретных сигналов вывода, реализованной на светодиодах HL9- HL16.

7. Резисторы переменного сопротивления R20, R21 для имитации датчиков угла поворота (задающее устройство в системах управления) или для формирования входного аналогового сигнала АЦП.

8. Кнопки-имитаторы внешних сигналов запроса прерывания S16, S17.

Похожие публикации