/gcc-STM32_ADS1256_ADC_driver

Драйвер АЦП: Микросхема ADS1256 [Texas Instruments] это Малошумящий 24-битный АЦП с SPI интерфейсом.

Primary LanguageCMIT LicenseMIT

"ADS1256" driver

Микросхема ADS1256 [Texas Instruments] это Малошумящий 24-битный АЦП с SPI интерфейсом.

Драйвер АЦП "ADS1256" реализован для архитектуры микроконтроллеров "STM32 Cortex-M" с использование низкоуровневых драйверов для SPI и EXTI из стандартного фреймворка "STM32CubeFW".

*К сожалению, в Интернете нашёл только любительские библиотеки (для Arduino) для работы с этим АЦП - поэтому ничего готового взять не удалось - пришлось создать свою версию Драйвера...*

Требования

Компилятор: GCC-совместимый (Keil, IAR)... Язык программирования "Си".

Эта версия Драйвера заточена по микроконтроллеры STM32 Cortex-M и фреймворк "STM32CubeFW".

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

Для организации низкоуровневой коммуникации по Шинам данных, Драйвер "ADC1256" использует фреймворк "STM32CubeFW". 
Из фреймворка "STM32CubeFW", используются HAL-драйверы для встроенной в микроконтроллер периферии (SPI и GPIO).
В частности, используются методы: 

1) GPIO: HAL_GPIO_ReadPin / HAL_GPIO_WritePin / HAL_GPIO_TogglePin;

2) SPI: HAL_SPI_Receive / HAL_SPI_Transmit, HAL_SPI_Receive_IT / HAL_SPI_Transmit_IT; 

3) Для реализации режима "потоковой конверсии" (DATAC) - Обработчики прерываний SPI и EXTI подключены через Callback-функции:

	HAL_SPI_TxRxCpltCallback()

	HAL_GPIO_EXTI_Callback()

	Подключённые в STUB-модуле: "ads1256_InterruptHandlersConnector.c"

Особенности и Ограничения драйвера

  1. В Драйвере реализованы высокоуровневые API-функции для КОНФИГУРАЦИИ почти всех параметров и РЕЖИМОВ микросхемы ADS1256.

     Единственное, что не реализовано: настройка и **управление Портами GPIO** микросхемы ADS1256 (их 4 шт.) - решено пока не реализовывать, поскольку это редкоиспользуемая фича.
    
  2. В Драйвере реализованы функции "Асинхронной Конвертации Данных" (режим DATAC, на прерываниях: "EXTI" по DRDY, и по "SPI").

     Но для работы этого продвинутого режима (DATAC) требуется обеспечить некоторые особенности аппаратной конфигурации (причём, это не ограничения данного Драйвера, а требования наследуемые из оригинального Datasheet на микросхему!) 
     Драйвер работает в предположении, что данные режимы обеспечены, в частности:
    
     SPI работает с "Full-Duplex Mode"; есть аппаратная шина DRDY; и др.
    
     Подробнее, эти требования расписаны в файле "ads1256.h" / в разделе "Потоковая конвертация: Асинхронное и неблокирующее..." / в комментарии "Требования и Ограничения".
    

    ПРИМЕЧАНИЕ:

     Если требования для обеспечения работы DATAC-режима не соблюдены - то "Асинхронная потоковая конвертация" запущена быть не может...
    
     Но, тем не менее, Драйвер АЦП всё ещё может ПОЛНОЦЕННО РАБОТАТЬ в режиме "одиночной финхронной выборки" и полностью доступны все API-методы для КОНФИГУРАЦИИ РЕЖИМОВ МИКРОСХЕМЫ.
    

    TESTING:

     Режим DATAC тестировался на максимальной скорости семплирования F_DATA=15000 SPS (в то время как абсолютный максимум для данной микросхемы = 30000 SPS), при скорости интерфейса F_SPI=562500 Гц.
    
     Результат: Периодический запрос Пакета данных (3байта) - вычитывается нормально. Запасы по таймингам есть. Но Скорость уже впритык.
    
  3. Реализован продвинутый модуль "ADS_STAT" - функции математической постобработки результатов конвертации: "усреднение скользящим окном", "конвертация кода АЦП в реальные единицы измерение (в т.ч. Калибровка)", "регистрация данных в Режиме потоковой конвертации".

     Замечу, что этот модуль реализует функцию "Регистратор данных", который является ключевым для "Режима потоковой конвертации". Без этой фунции невозможно использование режима DATAC! 
     Хотя, вы можете написать свою версию 1) функции "Регистратор данных" 2) и вообще весь модуль "математической постобработки" целиком... 
    
     Между Драйвером АЦП "ads1256.c" и модулем математической постобработки "adc_stat.c" - нет жёстких зависимостей! Эти модули могут эксплуатироваться раздельно - просто их API спроектированы таким образом, что удобно использовать вместе - сателлитные модули.
    

Также, вы можете использовать модуль математической постобработки "adc_stat.c" и с любым другим АЦП (например, встроенным в микроконтроллер).

  1. В API Драйвера - Не реализован возврат "Кода ошибки" при выполнении API-методов. Т.е. не реализован традиционный метод, подобный: ADS1256_API_GetLastError()...

     Таким образом, после запуска Setter-методов - не совсем понятно, принял ли АЦП новую команду или нет? 
     А может АЦП вообще "завис" или "отвалился от Шины"?
    

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

    Т.е. поскольку АЦП удалённый, то Setter-метод и сам не знает "принял ли АЦП очередную команду?.." 
    Для проверки реакции удалённого АЦП, по хорошему: каждому Setter-методу после отработки нужно было бы, каждый раз, вызывать парный ему Getter-метод и сверять возвращённый параметр с установленным ранее. 
    Но "Setter" и "Getter" методы реализованы "атомарно" (принята такая концепция) - каждый делает только свою функцию.

Рекомендую как метод:

    Если вам требуется достоверно убедиться, что АЦП принял устанавливаемый режим - то, после инициализации, вызовите серию Getter-методов самостоятельно, чтобы запросить текущий режим АЦП, и сверьте со своими установками.

    А в качестве "Keep alive / Ping" можете периодически вызывать метод: ADS1256_API_GetDeviceID()... Или, уж лучше сразу: ADS1256_API_ReadLastData(). Мне хватало последнего.

Советы по аппаратной реализации Шины связи с АЦП

Очень советую вам не игнорировать, а реализовать в аппаратной части "Шину CS" (Chip Select) - этот сигнал СТРОБИРУЕТ НАЧАЛО СЕССИИ КОММУНИКАЦИИ с АЦП. Таким образом, ПРЕПЯТСТВУЕТ СРЫВУ СИНХРЫ !!! Да, сигнал CS предназначен не только для управления несколькими "Ведомыми" по одной Шине, но и обеспечивает стабильность связи даже с Одним Ведомым.

    Без Строба по CS - Если по каким-то причинам (по причине НАНОСЕКУНДНОЙ ПОМЕХИ, конечно же) по шине SCLK пройдёт лишний фронт - то ВСЯ ДАЛЬНЕЙШАЯ КОММУНИКАЦИЯ с АЦП будет полностью похерена, до "сброса по питанию"! 
    (Будут просто идти мусорные данные от АЦП, а он вас "не услышит", поскольку все команды будет воспринимать со сдвигом на один бит... Наступал на эти грабли!)
    Таким образом, АЦП даже не воспримет команду RESET и повторную последовательность Инициализации - это будет уже бестолку.

    *Напомню: микросхема АЦП работает в режиме "Ведомого", а потому только слушает шину SCLK. И никакого альтернативного канала связи, чтобы сообщить микроконтроллеру о своём здоровье, не имеет - кроме как по Шине SPI. И если нарушается связь по SPI, то АЦП становится неуправляемым!*

    В какой-то мере, после срыва синхронизации, микроконтроллер мог бы восстановить работоспособность АЦП послав ему "Сигнал Сброс по внешней асинхронной аппаратной Шине /RESET" (есть такой вход у микросхемы).
    Но замечу, после "аппаратного Reset" - требуется полная переинициализация Микросхемы АЦП. Это долго. И сложно реализовывать алгоритм эвристической детекции, что "АЦП двинулся синхрой и несёт какой-то бред"... Не рекомендую этот путь!

    Гораздо лучше и эффективнее: ПЕРЕД КАЖДОЙ сессией коммуникации с АЦП (типа, "команда-ответ") - разрешать Шину сигналом "Chip Select" - при этом, каждый раз, микросхема АЦП переинициализирует только свой интерфейс SPI.
    После получения "ответа" от АЦП, сигнал CS возвращается в "пассивное состояние". Такая логика реализована в этом Драйвере. И такая логика рекомендована Datasheet.

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

Очень рекомендую сделать Подтяжки Шины, для самых критичных сигналов:

    **SCLK подтянуть к GND (подтяжкой 5K)**

    **/CS подтянуть к VDD (подтяжкой 5K)**

    *(Это очень важно, особенно в момент включения Питания: когда микроконтроллер ещё не проинициализирован и его Порты ввода/вывода находятся в высокоимпедансном состоянии - таким образом, Шина SPI полностью не управляема и по ней идёт всякий мусор от помех - и прямо в АЦП. Чтобы не случилось так, что Микроконтроллер проснётся, начнёт осознавать своё окружения - а АЦП уже "сдох", наловив мусорных данных, и уйдя в "глубокую залочку"...)*

    Подтяжка 5K может показаться великоватой, но такой номинал хорошо себя зарекомендовал в промышленной автоматике, в сильношумном окружении... Можете использовать номинал для подтяжек 5K..15K. (Меньше 15K не рекомендую использовать, в любом случае.)

Следующие Шины не столь критичны, здесь по желанию:

   DIN и DOUT подтягивать не нужно - АЦП "глух и нем" к ним, в случае отсутствия сигнала синхры.

   /RESET можно жестко подтянуть к VDD и не использовать (мне он непригодился)

Благодарности другим Авторам, материалы которых использовались

Помимо официального Datasheet: http://www.ti.com/product/ADS1256

Ориентировался на код других библиотек (любительских под Arduino):

supremeremixx @ http://www.cyberforum.ru/arm/thread2226883.html

Adien Akhmad @ https://github.com/adienakhmad/ADS1256

Flydroid @ https://github.com/Flydroid/ADS12xx-Library