Altinkaya: турецкие корпуса для РЭА

Подключение часов реального времени DS1307 к микроконтроллеру STM8 через модуль I2C. Часть 1 - Особенности аппаратной части

STMicroelectronics STM8S003F3

- Одесса

Во многих приложениях процессы и события очень часто должны привязываться к астрономическому времени. Не оказалась исключением и моя экспериментальная система для выращивания рассады [1], в которой мне потребовалось включать и выключать фитолампы по определенному расписанию. Поскольку в микроконтроллерах STM8, выбранных в качестве аппаратной основы для ее реализации, модуль часов реального времени (Real Time Clock, RTC) отсутствовал, мне нужно было или реализовывать его самому, или использовать для этого внешние специализированные компоненты.

Выбираем схему BMS для заряда литий-железофосфатных (LiFePO4) аккумуляторов

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

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

Однако подключение ее к микроконтроллеру STM8 [2] оказалось не такой простой задачей, как пишут в статьях из серии «получение результата за 5 минут». Дело в том, что связка STM8 + DS1307 с использованием модуля I2C имеет ряд специфических особенностей, которые могут легко поставить в тупик человека, не знакомого с этими устройствами. Поэтому я искренне надеюсь, что, прочитав эту статью, люди, не знакомые с микросхемами RTC и STM8, смогут быстро повторить подобную схему.

Сразу обращу внимание, что материал статьи рассчитан на подготовленных специалистов, уже знающих, что такое микроконтроллеры, периферийные модули и прочие элементарные вещи. Хорошим дополнением к этой статье станут описание интерфейса I2C [3], техническая документация на выбранные микросхемы [2, 4], а также примеры работы с модулем I2C из библиотеки STM8S/A Standard Peripherals Library (StdPeriph_Lib) [5].

Аппаратная часть системы

Часы было решено сделать в виде отдельной платы, предоставляющей сведения о текущем времени по запросу внешнего (по отношению к плате) контроллера системы, поэтому ее принципиальная схема (Рисунок 1) во многом похожа на схемы других плат, одна из которых уже была рассмотрена в [1]. Основным элементом модуля является микроконтроллер DD1 (STM8S003F3P6), фактически выполняющий функцию «переводчика» команд, проходящих по системной шине, на язык, «понятный» микросхеме часов реального времени DD2 (DS1307). Микросхема DA2 (SP485) служит для преобразования уровней сигналов интерфейса RS-485, используемого для обмена данными между платами, в уровни, пригодные для использования модулем UART. Питание платы осуществляется напряжением 5 В, формируемым компенсационным стабилизатором DA1 из входного напряжения, которое может находиться в диапазоне от 7 В до 14 В.

Принципиальная схема платы часов.
Рисунок 1. Принципиальная схема платы часов.

Микросхема DS1307 требует для своей работы всего двух внешних компонентов: часового кварца ZQ1 с резонансной частотой 32.768 кГц и необязательного резервного источника питания GB1 с напряжением 2.0…3.5 В, в качестве которого удобно использовать 3-вольтовые литиевые батарейки CR2032. И хоть батарейка является необязательной – микросхема DS1307 может полноценно функционировать и без нее, – ее отсутствие делает бессмысленным весь замысел, ведь именно она позволяет часам работать после исчезновения напряжения VCC.

Обмен данными между микросхемами DD1 и DD2 происходит по интерфейсу I2C, поэтому DS1307 подключается к выводам 11 (информационный сигнал – SDA) и 12 (тактовый сигнал – SCL) микроконтроллера STM8S003F3P6, связанным с ее аппаратным модулем I2C. Резисторы R8 и R9 необходимы для формирования сигнала с высоким логическим уровнем на линиях SDA и SCL. К сожалению, использовать для этой цели встроенные подтягивающие резисторы портов PB4 и PB5 нельзя. Во-первых, они активны только при работе порта в режиме входа, а во-вторых, их поведение во время работы модуля I2C в технической документации не описано. Практика показала, что они, вероятнее всего, неактивны, поскольку при обрыве в цепи резистора R8 (из-за неправильной разводки печатной платы), обмен данными происходил с огромным количеством ошибок.

Работа DS1307 при напряжении питания 3.3 В

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

  • вывод VCC (основное напряжение питания) – 4.5…5.5 В;
  • вывод BAT (батарейка) – 2.0…3.5 В.

Проблема заключается в том, что недорогие версии программаторов ST-LINK могут не поддерживать работу микроконтроллеров, питающихся напряжением 5 В, хотя микросхемы STM8 могут функционировать при напряжении питания от 3.0 В до 5.5 В. Поэтому при наличии такого программатора во время загрузки и отладки программного обеспечения микросхемы DD1, DD2 и DA2 приходится питать напряжением 3.3 В, получаемым с контакта 1 разъема Х2. И если при таком напряжении проблем с работой приемопередатчика SP485 обычно не возникает, по крайней мере, при небольших расстояниях между платами, то алгоритм работы микросхемы DS1307 в этом режиме может отличаться от нормального.

При отсутствии батарейки GB1 микросхема DS1307, по крайней мере один ее тестовый экземпляр, при питании от источника с напряжением 3.3 В продемонстрировала полную работоспособность. Конечно, при отключении питания часы останавливались, а содержимое оперативной памяти уничтожалось, но для того, чтобы «почувствовать» эту микросхему и отладить программное обеспечение, этого вполне достаточно. Следует отметить, что после отключения питания разрушение информации в оперативной памяти микросхемы DS1307 происходит спустя несколько минут, хотя часы останавливаются сразу. Видимо, заряда, накопленного в фильтрующих конденсаторах и паразитных емкостях микросхемы, оказывается достаточно для сохранения содержимого ОЗУ в течение некоторого времени.

А вот при наличии батарейки и подаче на вывод VCC напряжения 3.3 В микросхема DS1307 перестает отвечать за запросы по интерфейсу I2C, хотя часы при этом продолжают работать и время не сбивается. О возможности такого поведения микросхем DS1307 нужно помнить, иначе во время отладки программного обеспечения можно потратить некоторое время на поиск несуществующей проблемы.

Организация программного обеспечения

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

  • обмен данными между STM8 и DS1307 по интерфейсу I2C;
  • обмен данными между STM8 и внешним контроллером по интерфейсу UART.

Из этих двух процессов более приоритетным является процесс обмена данными по интерфейсу UART, поскольку этот интерфейс более критичен к задержкам в обработке информации, чем I2C.

Особенности обмена данными по интерфейсу UART были подробно рассмотрены в [1]. Поскольку этот процесс более приоритетен, его обработка производится с помощью прерываний. А вот при обмене данными по интерфейсу I2C от использования прерываний было решено отказаться.

Дело в том, что модуль I2C микроконтроллеров STM8 имеет всего один вектор прерывания, в который «навалены» все события, генерируемые этим устройством, (Рисунок 2), поэтому, даже если анализировать только те флаги, которые могут быть подняты в режиме ведущего, обработчик уже получится достаточно сложным. Не следует забывать, что обмен данными по интерфейсу I2C намного сложнее, чем при использовании интерфейса UART, поэтому количество событий, генерируемых модулем I2C, в том числе и ошибок, значительно больше. Кроме того, модуль I2C может формировать одинаковые прерывания, например, завершение передачи стартового бита, совершенно в разные моменты сеанса обмена, поэтому при их обработке недостаточно просто проверить флаги – нужно еще понимать, как поступать на этом этапе обмена.

Организация прерываний модуля I2C микроконтроллеров STM8 [2].
Рисунок 2. Организация прерываний модуля I2C микроконтроллеров STM8 [2].

Если возложить эту нагрузку на обработчик прерывания, то есть риск надолго в нем «зависнуть», что приведет к ошибкам в работе UART. Поэтому было решено перенести обработку событий интерфейса I2C в общий программный поток.

В итоге основной цикл программы (main) получился следующим (Рисунок 3). Обработка запросов центрального процессора, передаваемых по интерфейсу UART, имеет более высокий приоритет, поэтому после приема пакета данных он должен быть обработан в первую очередь. Поскольку обработка пакета, в том числе и формирование ответа, может занять достаточно длительное время, эта операция (блок 3) была перенесена в общий поток для выполнения в фоновом режиме. Таким же образом выполняются и операции после отправки ответа центральному процессору (блок 5), например, перезагрузка микроконтроллера. Если же в данной итерации основного цикла нет ни команд, которые нужно обработать, ни команд, которые нужно выполнить, тогда происходит обработка событий, связанных с модулем I2C (блок 6).

Алгоритм основного цикла программы.
Рисунок 3. Алгоритм основного цикла программы.

Из-за достаточно большой сложности интерфейса I2C во многих рекомендациях по работе с модулем I2C, в том числе и в примерах из библиотеки StdPeriph_Lib, рекомендуется ориентироваться на обработку «событий» – определенной комбинации флагов в регистрах состояния модуля I2C (I2C_SR1, I2C_SR2 и I2C_SR3). Специально для этого в библиотеке StdPeriph_Lib присутствует специализированная функция I2C_CheckEvent, в которую передается константа типа I2C_Event_TypeDef с уже закодированной комбинацией проверяемых флагов (Таблица 1).

Таблица 1. Список констант I2C_Event_TypeDef с указанием проверяемых флагов [5]
Название константы Флаги регистра SR3 Флаги регистра SR1
DUALF
GENCALL
TRA
BUSY
MSL
TXE
RXNE
STOPF
ADD10
BTF
ADDR
SB
I2C_EVENT_MASTER_MODE_SELECT       1 1             1
I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED     1 1 1 1         1  
I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED       1 1           1  
I2C_EVENT_MASTER_MODE_ADDRESS10       1 1       1      
I2C_EVENT_MASTER_BYTE_RECEIVED       1 1   1          
I2C_EVENT_MASTER_BYTE_TRANSMITTING     1 1 1 1            
I2C_EVENT_MASTER_BYTE_TRANSMITTED     1 1 1 1       1    
I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED       1             1  
I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED     1 1   1         1  
I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED   1   1                
I2C_EVENT_SLAVE_BYTE_RECEIVED       1     1          
I2C_EVENT_SLAVE_STOP_DETECTED               1        
I2C_EVENT_SLAVE_BYTE_TRANSMITTED     1 1   1       1    
I2C_EVENT_SLAVE_BYTE_TRANSMITTING     1 1   1            

Для работы с модулем DS1307 была создана специализированная структура TDS1307, основные переменные которой приведены в Листинге 1. Главной переменной, определяющей текущий алгоритм обработки событий, связанных с модулем I2C, является переменная State – в зависимости от ее значения выполняются совершенно разные операции, поэтому она служит своеобразным переключателем алгоритмов.

Листинг 1. Описание структуры TDS1307

typedef struct
{
  uint8_t State;            // состояние обмена данными

  uint8_t Rx[BUFFER_SIZE];  // буфер передачи
  uint8_t Tx[BUFFER_SIZE];  // буфер приема

  bool HasDataToWrite;      // флаг наличия данных для записи

  int32_t Time;             // текущее время

  // служебные переменные
  uint8_t ByteCount;
  uint8_t ErrorCount;
  uint8_t PulseCount;
} TDS1307;

DS1307 содержит часы, календарь и 56 байт оперативной памяти. Вся информация, хранящаяся в этой микросхеме, находится в 64 регистрах, каждый из которых доступен для чтения и записи (Таблица 2). В этом проекте используются только часы, поэтому для обмена данными достаточно приемного (массив Rx) и передающего (массив Tx) буферов размером всего три байта (BUFFER_SIZE = 3).

Таблица 2. Регистры микросхемы DS1307
Адрес Бит 7 Бит 6 Бит 5 Бит 4 Бит 3 Бит 2 Бит 1 Бит 0 Содержимое
0x00 CH Десятки Единицы Секунды
0x01 0 Десятки Единицы Минуты
0x02 0 Десятки Единицы Часы
0x03 0 0 0 0 0 Единицы День недели
0x04 0 0 Десятки Единицы Число
0x05 0 0 0 Десятки Единицы Месяц
0x06 Десятки Единицы Год
0x07 OUT 0 0 SQWE 0 0 RS1 RS0 Настройки
0x08 – 0x3F Пользовательская информация ОЗУ

Формат хранения данных, используемый в микросхеме DS1307, является крайне неудобным для последующего использования. Поэтому в этом проекте было принято решение о его преобразовании. Время, передаваемое центральному процессору и принимаемое от него, хранится в 32-разрядной переменной Time, содержащей количество секунд, прошедших после полуночи (0…86399). Такой формат хранения времени позволяет проводить с ним простые операции сложения, вычитания и сравнения и упрощает настройку системы, например, с помощью персонального компьютера.

Флаг HasDataToWrite содержит информацию о том, что переменная Time была изменена контроллером системы по интерфейсу UART, что является эквивалентом того, что есть данные, предназначенные для записи в микросхему. Этот механизм используется для установки часов по интерфейсу UART.

Переменные ByteCount, ErrorCount и PulseCount являются служебными и используются на разных стадиях обмена данными. Их конкретное назначение станет понятным чуть позже.

Алгоритм подпрограммы обработки событий, связанных с микросхемой DS1307.
Рисунок 4. Алгоритм подпрограммы обработки событий, связанных
с микросхемой DS1307.

Общий алгоритм обработки событий, связанных с микросхемой DS1307 (блок 6 на Рисунке 3), реализованный в подпрограмме DS1307_Execute, выглядит следующим образом (Рисунок 4). При каждом вызове этой подпрограммы в первую очередь проверяются флаги ошибок модуля I2C, хранящиеся в его регистре SR2 (блоки 2 и 3). После этого производится проверка значения переменной State, и уже после этого выбирается один из блоков (5.1 – 5.N), в котором и происходит, собственно, обработка текущего события.

Проверка ошибок

Большинство флагов ошибок модуля I2C расположено в регистре SR2. Поскольку модуль I2C при работе с DS1307 используется только в режиме ведущего (Master), то и контролировать следует флаги ошибок, связанные с этим режимом. В первую очередь следует проверять флаг AF (Acknowledge Failure), свидетельствующий о том, что микросхема DS1307 не сформировала бит ACK, являющийся подтверждением приема информации (возможно информация до нее не доходит), и флаг ARLO (Arbitration Lost), сигнализирующий о том, что на шине I2C появился еще один ведущий. Поскольку появление еще одного ведущего в данной схеме принципиально невозможно, то установка бита ARLO (он устанавливается при обнаружении изменения сигнала на линии SDA при высоком уровне на линии SCL) свидетельствует о наличии проблем на аппаратном уровне, например, об обрыве в цепях подтягивающих резисторов. Вероятность установки флага OVR (Overrun), сигнализирующего о возможной потере принятых данных при работе в режиме ведущего, крайне мала. Тем не менее, установка этого флага может свидетельствовать о неправильной работе программы, поэтому лучше лишний раз перестраховаться.

Проверять флаги ошибок необходимо в обязательном порядке, поскольку их установка свидетельствует о наличии непредвиденных проблем. Если этого не делать, то программа может намертво «зависнуть» в ожидании события, которое уже никогда не наступит. Например, при случайной установке низкого уровня на линии SDA при высоком уровне на линии SCL из-за воздействия помехи поднимется флаг ARLO, что приведет к сбросу флага MSL (Master/Slave) в регистре SR3, что, в свою очередь, приведет к совершенно непредвиденному переводу модуля I2C из режима ведущего в режим ведомого (Slave). А поскольку все события, связанные с режимом ведущего, подразумевают проверку флага MSL (Таблица 1), это значит, что программа зависнет в ожидании завершения, например, окончания передачи байта, который уже никогда не будет передан из-за того, что модуль I2C прекратил передачу.

Алгоритм обработки ошибок может быть любым, в том числе и достаточно сложным. В этом проекте использовался самый простой подход, заключающийся в полной перезагрузке интерфейса I2C, поэтому при обнаружении ошибок переменной State присваивается начальное значение RESET_I2C (равное единице) (Листинг 2) и весь обмен данными начинается с самого начала. Обратите внимание, что проверку ошибок необходимо проводить только при активном модуле I2C, то есть, когда обмен данными с микросхемой DS1307 уже успешно прошел начальные этапы.

Листинг 2. Код обработки ошибок модуля I2C

if (P->State > READ_DATA)
{
  if (I2C->SR2 & (uint8_t)(I2C_FLAG_OVERRUNUNDERRUN
                         | I2C_FLAG_ARBITRATIONLOSS
                         | I2C_FLAG_ACKNOWLEDGEFAILURE))
  P->State = RESET_I2C;
}

Дополнительная информация

  1. А. Русу. Жонглируем прерываниями: особенности работы с модулем UART микроконтроллеров STM8
  2. STM8S Value line
  3. I2C Bus
  4. STM8S Series and STM8AF Series 8-bit microcontrollers. Reference Manual
  5. STM8S/A Standard Peripherals Library

Материалы по теме

  1. Datasheet Maxim DS1307
  2. Datasheet STMicroelectronics STM8S003F3
  3. Datasheet Texas Instruments LM1117
  4. Datasheet MaxLinear SP485

Окончание

Содержание цикла «Подключение часов реального времени DS1307 к микроконтроллеру STM8 через модуль I2C»

  1. Часть 1 - Особенности аппаратной части
  2. Часть 2 - Обмен данными с помощью модуля I2C
47 предложений от 23 поставщиков
Рабочее напряжение 3.3-5VHC-12 - радио модуль связи на базе чипа SI4438, работающий со стандартным Serial UART интерфейсом. Модуль поддерживает AT команды,...
ЗУМ-СМД
Россия
STM8S003F3P6
STMicroelectronics
4.35 ₽
STM8S003F3P6
STMicroelectronics
14 ₽
Romstore
Россия, Беларусь
STM8S003F3P6
111 ₽
ChipWorker
Весь мир
STM8S003F3P6
STMicroelectronics
121 ₽
Электронные компоненты. Бесплатная доставка по России
Для комментирования материалов с сайта и получения полного доступа к нашему форуму Вам необходимо зарегистрироваться.
Имя