Двухпроводная последовательная шина данных
DS1307 поддерживает обмен данными по протоколу TWI по двухпроводной двунаправленной шине. Устройство, которое передаёт данные на шину, является передатчиком, а устройство, принимающее данные, - приёмником. Устройство, управляющее передачей данных, называется ведущим. Устройство, которым управляет ведущий, называется ведомым. Ведущее устройство генерирует синхроимпульсы (serial clock - SCL), управляет доступом к шине и генерирует условия START и STOP. DS1307 работает на шине как ведомое устройство.
Основные принципы передачи данных по шине TWI:
1) Передача данных может быть инициирована только когда шина свободна.
2) Во время передачи данные на линии SDA могут меняться только когда на линии SCL низкий уровень, в противном случае изменение данных будет интерпретироваться как управляющий сигнал.
Таким образом, возможны следующие состояния шины:
- Шина не занята - на линиях SDA и SCL сохраняется высокий уровень
- Начало передачи данных (условие START) - изменение состояния линии SDA с высокого на низкий, в то время как на линии SCL высокий уровень.
- Окончание передачи данных (условие STOP) - изменение состояния линии SDA с низкого на высокий, в то время как на линии SCL высокий уровень.
Каждая передача данных инициируется условием START и завершается условием STOP. Число байтов данных, передаваемых между условиями START и STOP, не ограничено и определяется ведущим устройством. Информация передаётся побайтово, и каждый байт приёмник подтверждает девятым битом (бит подтверждения - ACK). В спецификации двухпроводного интерфейса определены обычный режим (с тактовой частотой 100 кГц) и быстрый режим (с тактовой частотой 400 кГц). DS1307 работает только в обычном режиме (100 кГц).
- Подтверждение - каждое принимающее устройство, когда является адресуемым, обязано генерировать подтверждение после приёма каждого байта. Ведущее устройство должно генерировать дополнительный тактовый импульс, который предназначен для бита подтверждения.
На рис.4. показана временная диаграмма передачи данных по двухпроводной шине.
Рис.4
В зависимости от состояния бита возможны два типа передачи данных:
1) Передача данных от ведущего передатчика ведомому приёмнику.
Первый байт, передаваемый ведущим, - это адрес ведомого. Далее следует некоторое количество байтов данных. Ведомый возвращает подтверждающий бит после каждого принятого байта. Данные передаются, начиная со старшего бита
2) Данные передаются от ведомого передатчика ведущему приёмнику.
Первый байт (адрес ведомого) передаётся ведущим. Ведомый возвращает подтверждающий бит. За ним следует передаваемое ведомым некоторое количество байтов данных. Ведущий возвращает подтверждающий бит после всех принимаемых байтов кроме последнего байта. В конце последнего принятого байта возвращается "неподтверждение". Ведущее устройство генерирует все последовательные синхроимпульсы, а также условия START и STOP. Передача заканчивается условием STOP или повтором условия START. Поскольку повторение условия START также является и началом следующей последовательной передачи, шина не освобождается. Данные передаются, начиная со старшего бита.
DS1307 может работать в следующих двух режимах:
1) Режим ведомого приёмника (режим записи DS1307).
Последовательные данные принимаются по SDA и синхронизируются по SCL. После каждого принятого байта передаётся бит подтверждения. Условия START и STOP распознаются как начало и конец последовательной передачи. Распознавание адреса выполняется аппаратно после приёма адреса ведомого и бита направления (см. Рис. 5).
Байт адреса - это первый байт, принятый после генерации ведущим условия начала. Он содержит 7 битов адреса DS1307, который имеет значение 1101000, и следующий за ним бит направления ( ), который для записи равен 0. После приёма и декодирования адресного байта DS1307 выдаёт на линию SDA подтверждение, после чего ведущий передаёт в устройство адрес регистра. Это установит регистровый указатель. Затем ведущий начинает передачу байтов данных, каждый из которых будет подтверждаться DS1307. Чтобы завершить запись данных, ведущий генерирует условие окончания
Рис.5
2) Режим ведомого передатчика (режим чтения DS1307).
Первый байт принимается и обрабатывается так же, как и в режиме ведомого приёмника. Однако в этом режиме бит направления будет указывать, что направление передачи инвертировано. DS1307 передаёт последовательные данные по линии SDA пока на линию SCL поступают последовательные синхроимпульсы. Условия START и STOP распознаются в начале и в конце последовательной передачи (см. Рис. 6).
Байт адреса - первый байт, принимаемый после стартового условия, генерируется ведущим. Байт адреса состоит из 7-битного адреса DS1307, который равен 1101000, и следующего за ним бита направления передачи ( ), который для чтения равен 1. После приёма и декодирования байта адреса, устройство выдаёт подтверждение на линию SDA. Затем DS1307 начинает передавать данные, начиная с указанного адреса, находящегося в регистровом указателе. Если перед началом чтения указатель регистра не записан, то первый читаемый адрес - это адрес, который был сохранён в нём последним. DS1307 должен принять "неподтверждение" для окончания чтения.
Рис.6
Структура устройства
При построении устройства выводы модуля часов реального времени DS1307 подключаются к выводам порта D микроконтроллера: PD1 к линии данных SDA, PD0 к линии синхросигналов SCL, а выводы текстового дисплея к выводам порта С, аналогично показанному в выше приведенных примерах.
Взаимодействие модуля RTC с микроконтроллером может выполнятся в одном из двух режимов: режим записи и режим чтения.
Рассмотрим программу на Си, реализующая запись в модуль RTC:
Void RT_ Write ( ) {
1.Delay ms(1000);
2. TWI_Init (100000) ; // инициализация режима ведущего
3. TWI_Start ( ); // выдача “старт” сигнала
4.TWI_Write (0xD0); // адрес DS1307+W
5.TWI_Write (0); // начало с адреса REG0
6.TWI_Write (0x80) ; // запись $80 в REG0 ( отключение часов) и 0 сек
7.TWI_Write (0) ; // запись 0 минут в REG1
8.TWI_Write (0x40); // запись 0 часов в REG2; установка 12 часового режима
9.TWI_Write (0); // запись 0 дня недели в REG3
10.TWI_Write (0); // запись 0 числа в REG4
11.TWI_Write (0); // запись 0 месяца в REG5
12.TWI_Write (0); // запись 0 год в REG6
13.TWI_Stop ( ); // выдача стоп сигнала
14.TWI_Start ( ); // выдача старт сигнала
15.TWI_Write (0xD0); // адрес DS1307+W
16. TWI_Write (0); // установка указателя адреса в 0 (адрес REG0)
17.TWI_Write (0); // включение часов
18.TWI_Stop ( ); // выдача стоп сигнала
}
В начале выполняется инициализация блока TWI, установкой микроконтроллера в режим ведущего передатчика ( пункт 1 -функция TWI Init (100000)). С пункта 2 начинается цикл передачи пакетов от микроконтроллера к модулю RTC, формированием стартового состояния на шине TWI с использованием функции компилятора TWI Start ( ).Первый передаваемый пакет ( пункт 3) должен содержать семиразрядный адрес, уоторый для модуля RTC имеет шестнадцатеричное значение $68 (в двоичном коде 1101000) к которому приписывается 0 - признак записи. Итого $D0 (функция TWI Write (0xD0)). Первый передаваемый байт- адрес часов- $68 + 0 признак записи. Итого $D0 (пункт 4 - функция TWI Write (0xD0)). Далее, в пункте 5 в указателе байтов записывается 0 (TWI Write (0), указывая тем самым на первый регистр REG0 c которого начинается запись данных в ячейках модуля.
В пункте 6 в RG0 записывается значение секунд , а старший разряд этого регистра, который управляет включением/выключением модуля, устанавливается 1 (выключается модуль). Для этого используется функция TWI_Write (0x80).
В пунктах 7-12 в последующих регистрах записываются значения минут, часов, дня недели, число, месяц, год. При записи часов одновременно устанавливается 12-ти часовый режим занесением в 6 бит REG4 единицы ( пункт 8 ). Передача данных завершается формированием ведущим ( микроконтроллером) ”стопового” состояния (пункт 13, функция TWI_Stop ( ).
Далее выполняется повторное обращение к модулю с целью установки указателя адреса в нулевое состояние ( адрас первого регистра ) для подготовки модуля к чтению, а также включения модуля. В начале нового обращения микроконтроллер формирует стоповое состояние (пункт 14, функция TWI Start ( )),в пункте 15 выдается адрес модуля, как при предидущем обращении. В пункте 16 в указатель адреа записывается 0. В пункте 17 в регистр REG0 записывается 0 ( функция TWI_Write (0)). Так как при записи нулей старший бит REG0 обнуляется, модуль включается и начинает отсчитывать время. В пункте 18 формируется стоповое состояние и цикл обращения завершается.
Теперь рассмотрим программу на Си, с помощью которой микропроцессор считывает текущие значения времени с модуля и выводит на текстовый дисплей:
1. Unsigned charsec, min, hr, week day, day, mn,year;
2. Char*txt, tnum[4];
// установка связи с LCD модулем
3. sbitLCD_RSatPORTC2_bit;
4. sbitLCD_ENatPORTC3_bit;
5. sbitLCD_D4atPORTC4_bit;
6. sbitLCD_D5atPORTC5_bit;
7. sbitLCD_D6atPORTC6_bit;
8. sbitLCD_D7atPORTC7_bit;
9. sbitLCD_RS_Direction atDDC2_bit;
10. sbitLCD_EN_Direction atDDC3_bit;
11. sbitLCD_D4_Direction atDDC4_bit;
12. sbitLCD_D5_Direction atDDC5_bit;
13. sbitLCD_D6_Direction atDDC6_bit;
14. sbitLCD_D7_Direction atDDC7_bit;
//описание функции чтения времени и даты из модуля DS1307
15.voidread_Time (char *sec, char *min, char *hr, char *week_ day, char *day, char *mn, char *year) {
16. TWI Start ( ); // формирование ведущим стартового состояния, начало передачи
17. TWI Write (0xD0); // передача адреса модуля с флагом записи
18. TWI Write (0); // установка нуля в указателе адреса
19. TWI Stop ( ); // формирование состояние конца передачи
20. TWI Start ( ); // формирование состояния старта новой передачи
21. TWI Write (0xD1); // пересылка адреса модуля с флагом чтения
22. *sec= TWI_Read (1); // чтение значения секунд из REG0
23. *min= TWI_Read (1); // чтение минут из REG1
24. *hr= TWI_Read (1); // чтение часов из REG2
25. *week_day= TWI_Read (1); // чтение дня недели изх REG3
26. *day= TWI_Read (1); // чтение даты из REG 4
27. *mn= TWI_Read (1); // чтение месяца из REG5
28. *year= TWI_Read (1);// чтение года из REG6
29. TWI Stop ( ); // формирование стопового состояния
}
// описание функции преобразования полученных значений в символы
30. voidTransform_time (char *sec, char *min, char *hr, char *week_ day, char *day, char *mn, char *year) {
31. *sec= (( *sec & 0x70)>>4)*10 + (*sec & 0x0F);
32. *min= (( *min & 0x70)>>4)*10 + (*min & 0x0F);
33. *hr = (( *hr & 0x30)>>4)*10 + (*hr & 0x0F);
34. *week day = (* week_day & 0x07);
35. *day = (( *day & 0x30)>>4)*10 + (*day & 0x0F);
36. *mn = (( *mn & 0x10)>>4)* 10 + (* mn & 0x0F);
37. *year= ((* year & 0xF0)>>4)*10 + (*year & 0x0F);
}
// описание функции вывода значений на LCD
38. voidDisplay_Time (char sec, char min, char hr, char week_ day, char day, char mn, char year)
{
switch (week_day) {
case1: txt = “Sun”; break;
case2: txt = “Mon”; break;
case3: txt = “Tue”; break;
case4: txt = “Wed”; break;
case5: txt = “Thu”; break;
case6: txt = ”Fri” ; break;
case7: txt = “Sat”; break;
}
39. Lcd_Out (1,1,txt);
40. Lcd_Chr (1,6, (day/10) + 48);
41. Lcd_Chr (1,7, (day%10) + 48);
42. Lcd_Chr (1,9, (mn/10) + 48);
43. Lcd_Chr (1,10, (mn%10) + 48);
44. Lcd_Chr (1,14, (year/10) + 48);
45. Lcd_Chr (1,15, (year%10) +48);
46. Lcd_Chr (2,6, (hr/10) + 48);
47. Lcd_Chr (2,7, (hr%10) + 48);
48. Lcd_Chr (2,9, (min/10) + 48);
49. Lcd_Chr (2,10, (min%10) + 48);
50. Lcd_Chr (2,12, (sec/10) + 48);
51. Lcd_Chr (2,13, (sec%10) + 48);
}
// описание функции инициализации
52.voidInit_Main ( );{
53. Lcd_Init ( );
54. Lcd_Cmd (_LCD_CLEAR);
55. Lcd_Cmd (_LCD_CURSOR_OFF);
56. TWI_Init (100000);
57. Lcd_Chr (1,8,’.’);
58. Lcd_Chr (1,11,’.’);
59. txt= “ time: “ ;
60. Lcd_Out (2,1,txt);
61. Lcd_Chr (2,8,’ :’);
62. Lcd_Chr (2,11,’ :’);
63. txt= “2000”;
64. Lcd_Out (2,12, txt);
65. Lcd_Cmd ( _LCD_CURSOR_OFF);
}
66. voidmain( ) {
67.Init_main ( );
68. while (1) {
69.read_Time (&sec, &min, &hr, &week_ day, &day, &mn, &year);
70. Transform_time (&sec, &min, &hr, &week_ day, &day, &mn, &year);
71. Display_Time (sec, min, hr, week_ day, day, mn, year);
72. Delay_ms (1000);
}
}
В пунктах 1,2 представлены переменные и массив символов, используемых в программе . В пунктах 3-8 и 9-14 устанавливаются связи и направление передачи между выводами микроконтроллера и текстового дисплея, как это было выполнено в предидущих задачах.
С пункта 15 определяется функция чтения данных из модуля DS1307. В начале (пункты 16-19) в указателе адреса модуля RTC записывается адрес первого регистра памяти модуля, как это было выполнено в предидущей программе.
Далее выполняется последовательное считывание содержимых регимтров модуля (пункты 20-29). В соответствие с протоколом работы интерфейса TWI, в начале микроконтроллером формируется стартовое состояние ( пункт 20 ), за тем микроконтроллер выставляет по линии интерфейса адрес модуля с признаком считывания ( пункт 21, функция TWI Write (0xD1)) (байтовая константа в скобках функции 0xD1 содержит семиразрядный адрес модуля + одноразрядный флг считывания-1). .
В пунктах 22-28 считываются значения из последовательных регистров памяти модуляи заносятся в ячейки обозначены как *sec, *min, *hr, *week_ day, *day, *mn, *year . Передача завершается формированием стопового состояния ( пункт 29).
В пунктах 30-37 описывается функция преобразования полученных данных в двоичную систему. Как было сказано, время и календарь в модуле RTC представлены в двоично-десятеричной системе. Однако для преобразования в десятичные символы удобно их в начале представить в двлоичном формате. Для этого в старшей и млашей тетрадах данных наложением масок выделяются десятки и единицы, за тем содержимое старшей тетрады умножается на 10 ( присваивается вес 10) и суммиеуется с младшей тетрадой. Полученный результат является двоичным представлением двоично- десятичного числа.
В пунктах 38-51 описывается функция, выводящая полученные из модуля данные на текстовый дисплей. Параметрами этой функции являЮтся значения времени и календаря, считанные из модуля RTC и преобразованные в двоичный формат.
В начале определения функции оператором switchв переменную txt записывается текущий день недели, который выводится на дисплей командой . Lcd_Out (1,1,txt),использованной нами в предидущих задачах (пункт 39).
С пункта 40 начинается вывод на дисплей значений времени и календаря командой вывода символа. Например, команда Lcd_Chr (1,6, (day/10) + 48)выводит старший разряд значениа даты на первой строке с шестой позиции. 48 добавляется к полученному коду для преобразования в ASCII код, который используется длявывода символа на экран.
В пунктах 52-65 определяется функция инициализации TWI блока. В начале выполняется функция Lcd_Init ( ) , устанавливающая блок в исходное состояние ( пункт 53). Функцией Lcd_Cmd (_LCD_CLEAR)выполняется очистка экрана ( пункт 54). Далее выполняются функции вывода на LCD, которые нам известны из предидущих задач.
66 - 72 пункты представляют главную программу, которая предполагает последовательное выполнение описанных выше функций в бесконечном цикле while.
,
Дата добавления: 2016-12-27; просмотров: 2916;