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 каналов можно приобрести здесь

 

 

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

 

STM LL. STM32F1. ADC. Injected Once

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

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

*