STM Урок 192. LL. STM32F1. ADC. Injected Once



Продолжаем работать с АЦП (ADC) контроллера STM32F1 с использованием библиотеки LL. Также работать мы пока будем с однократным преобразованием, но уже использовать мы будем не регулярные каналы, а инжектированые. Про данную группу я кратко говорил в предыдущих уроках, также мы её использовали давно на другом контроллере в уроке 19 и в уроке 20. Тем не менее напомню, что главное преимущество инжектированной группы каналов над регулярной в том, что для каждого канала существует свой регистр и нам не обязательно резко считать данные из регистра, чтобы они не затёрлись после конверсии одного канала, а лишь после этого приступать к конверсии другого.

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

На данном уроке мы воспользуемся обычным однократным преобразованием без последовательности, поэтому подключим мы только один канал, хотя схему мы оставим с прошлого урока, просто использоваться будет только один вход

 

 

С регистрами и их полями, используемыми для инжектированной группы, мы также знакомились в уроке 185, поэтому, думаю, мы сразу можем приступить к проекту урока, который был сделан из проекта того же урока с именем LL_ADC_REG_ONCE и назван LL_ADC_INJ_ONCE.

Откроем наш проект в Cube MX и в настройках ADC1 отключим регулярную группу, включим инжектированную, добавим только один канал, также время между выборками установим в 7,5 циклов

 

 

Сгенерируем проект для Keil, откроем его, настроим автоперезагрузку после прошивки, отключим оптимизацию, подключим к дереву проекта файлы lcd.c и i2c_user.c, откроем main.c и, наверно, не стоило бы вообще смотреть инициализацию ADC, которая сгенерировалась в Cube и я хотел всё это для экономии времени оставить на самостоятельный разбор, но не тут-то было. Как обычно, здесь не без сюрпризов, поэтому давайте всё-же глянем вот на этот участок функции MX_ADC1_Init

 

LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0};

 

Как мы видим, непонятно для чего здесь объявляется структура для регулярной группы, а не для инжекторной с именем LL_ADC_INJ_InitTypeDef.

А далее данная структура инициализируется и, соответственно, включаются все регистры также для настройки регулярных каналов

 

ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;

ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_DISABLE;

ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;

ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_SINGLE;

ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_NONE;

LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct);

 

 

Лишь настройки самого канала добавляются как положено — для инжектированной группы

 

LL_ADC_INJ_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_1);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_1, LL_ADC_SAMPLINGTIME_7CYCLES_5);
LL_ADC_INJ_SetOffset(ADC1, LL_ADC_REG_RANK_1, 0);

 

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

В связи со всем этим все настройки мы внесём самостоятельно в функции main(), в которой для начала, чтобы сбросить все регулярные настройки, применим деинициализацию периферии

 

 

А теперь настроим ADC на работу с инжектированной группой

 

 

Вот здесь изменим надпись

 

LCD_String("Jnjected Once");

 

 

В бесконечном цикле изменим имя вызываемой функции старта АЦП

 

LL_ADC_INJ_StartConversionSWStart(ADC1);

 

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

 

while (!LL_ADC_IsActiveFlag_JEOS(ADC1)) {}

LL_ADC_ClearFlag_JEOS(ADC1);

 

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

 

ADC_Data = LL_ADC_INJ_ReadConversionData12(ADC1, LL_ADC_INJ_RANK_1);

 

Если мы заглянем внутрь данной функции, то тем самым мы забираем сырые данные из регистра ADC1->JDR1.

Соберём код, прошьём контроллер и покрутим движок резистора, проследим, как будет изменяться результат в вольтах на дисплее

 

 

 

 

 

 

Итак, на данном уроке мы научились настраивать инжекторный канал АЦП, а также снимать с него показания.

Всем спасибо за внимание!

 

 

Предыдущий урок Программирование МК STM32 Следующий урок

 

Исходный код

 

 

Отладочную плату STM32F103C8T6 можно приобрести здесь STM32F103C8T6

Программатор недорогой можно купить здесь ST-Link V2

Дисплей LCD 16×2

Переходник I2C to LCD можно приобрести здесьI2C to LCD1602 2004

Логический анализатор 16 каналов можно приобрести здесь

 

 

Смотреть ВИДЕОУРОК в RuTube (нажмите на картинку)

STM LL. STM32F1. ADC. Injected Once

 

Смотреть ВИДЕОУРОК в YouTube (нажмите на картинку)

STM LL. STM32F1. ADC. Injected Once

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*