Перейти к содержимому

#3. Разработка источника импульсного питания с PFC на TL494 + STM32 by #DarthMuxa

Параметры ИИП:

  1. Входное напряжение – 145-265В;
  2. Выходное напряжение –  до 60В;
  3. Выходной номинальный ток – 10А
  4. Применение изолятора в цепях управления и измерений;
  5. Возможность работы с МК (на STM32) и без МК

План разработки:

  1. Изучение технической документации оборудования — 01.10.2019 — 31.10.2019 гг.

2. Разработка схемы ИИП — 01.10.2019 — 31.10.2019 гг.

2.1. Разбивка на компоненты и части

Часть 1 — Корректор коэффициента мощности. Схема из Datasheet. Расчет с сайта производителя (onsemiconductor)

Часть 2 — Полумост — Трансформатор — выпрямитель — выход
UPD: вместо мостового выпрямления — однополярное со средней точкой. Исправил сопротивление Затвор — Исток. Добавил усилитель токового шунта. Исправил регулирование напряжения. LC фильтр вызывает вопросы.

Часть 3 — TL494 + Adum + Ir .
UPD: Пробую KiCad, ошибки указанные поправил (ПС: Спасибо большое за наводящие вопросы).
UPD2: Начал вникать в обратную связь TL, и способы регулирования.
UPD3: Исправил регулирование по току и напряжению. Подправил управление верхним ключом.

Часть 4 — Питание IR (15В/1А), TL (15В/1А) , МК(5В/1А) и Вентилятор (12В/0.2А). Конструктор на сайте жалуется на «Напряжение сток-исток близко к пробивному.«

2.2. Изучение даташитов

Схема 2 части собрана из даташитов на IR2110, adum1400-1402, & tl494…
UPD: Поскольку в схемы были ошибки, перечитал даташиты

UPD2: Добавились L4805 и PC817. Почитал datasheet и на них

2.3. Установка и изучение программ разработки

Установлен Proteus 8.

UPD: Для черчения схем выбрал KiCad, потому что Open Source. KiCad — крутая штука.

2.4. Документирование всех этапов

3. Сборка ИИП — 01.11.2019 — 30.11.2019 гг.

3.1. Подбор компонентов для платы.
Заказал:
КР1114ЕУ4 ШИМ-контроллер (Tl494);
IR2110PBF 500 В/2А [DIP-14];
ADUM1402ARWZ [SO-16W];
N87, ETD49 (т.к. следующий размер в 2 раза дороже), Сердечник ферритовый

Расчет ИТ в программе «старичка». Выпрямление выбрал мостовое, потому что в полном расчете, при однополярном или двухполярном выпрямление, выходит предупреждение, о недостаточном размере сердечника.
Другой расчет с более согласованными параметрами от PFC(в таблице не они, а значения по умолчанию, недоглядел), и всё-таки «однополярной схемой со средней точкой». Еще присмотрюсь, если этот вариант окажется интереснее заменю схему «Часть 2»

3.2. Изучение программ разводки плат.

KiCad

3.3. Изучение принципов и правил разводки печатных плат.

3.4. Разведение и трассировка платы в программе.

3.5. Травление платы и пайка компонентов.

3.6. Документирование всех этапов

4. Отладка ИИП — 01.12.2019 — 31.12.2019 гг.

4.1. Настройка и отладка платы.

4.2. Работа с осциллографом.

4.3. Документирование всех этапов

5. Изучение МК и программирования — 09.01.2020 — >

Проект Регулирования по току и напряжению в Proteus

Для понимания процессов регулирования проект операционного усилителя в Proteus.

5.1 Работа с микроконтроллером STM32F103C6 В Proteus.

Цель: создать симуляцию работы дисплея и STM в Proteus. В процессе понять,
— как включить и настроить Pin’ы МК,
— как включить дисплей,
— как послать информацию в дисплей,
— научиться напрямую через регистры управлять МК
— понять как работать с программой в Proteus

Предисловие.

Прежде чем начать работать с МК. Составим представление о структуре документа, в котором мы будем писать программу.
Документ можно условно разделить на части: начало документа — это #include подключение заголовочных файлов (с расширением .h) библиотек, будь то HALL, StdPL да даже CMSIS имеет подключаемую библиотеку «stm32f10x.h».
После можно объявить глобальные переменные

Также до начала основной функции можно объявить директивы #define — они в дальнейшем будут подменять одно значение другим. Например, как я понял запись в HALL «GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP» при помощи подключаемого файла stm32f1xx_hall_gpio.h в котором директивами переводится в понятный ядру язык, что пин будет работать в режиме выход пуш-пул.

Далее в документе объявляется основная функция «int main (void)» все записи что будут после этой строки и до строки while(1) будут выполняться единожды при запуске программы. То что будет в { } while станет выполняться по циклу всё время, пока не настанет сброс или прерывание.
ну и самое главное: каждое «предложение» кода заканчивается «;» . а каждая функция описывается в { }.

Пример мигание светодиодом. и много других примеров . Чтобы просмотреть код открывайте файл main.c

1. Подготовка

1.1 STM, Proteus и LED Blink запуск базового примера Proteus.
Для знакомства с STM, я рекомендую воспользоваться примерами. Чтобы открыть пример «мигание светодиодом» нажмите в Proteus: «File -> Open Sample Project» из предложенного списка Category выберите «VSM for Cortex M3». В правой таблице с результатами найдите «STM32F103 Blink LED (using STMCubeMX)».

Что бы открыть код и познакомиться с ним. Нажмите правой кнопкой по STM, в появившемся меню нам нужен самый нижний пункт «Edit Source Code» (Proteus должен быть с расширением VSM Studio).

При работе с кодом вы можете столкнуться с проблемой в виде отсутствия Компилятора. Что бы решить её, во вкладке «Source Code» (закладка Proteus, где находится код вашей программы, или программы примера) в меню System выберите пункт Compilers Configuration и выполните проверку, скорее всего нужный Вам компилятор будет отсутствовать (я использовал GCC for ARM). Что бы установить его, в перечне нажмите кнопку Download.

При загрузке из интернета, также может возникнуть проблема, в связи с неверным путём к файлу: по завершению загрузки появлялась ошибка, что файл «yagarto-bu-2.23.1_gcc-4.7.2-c-c++_nl-1.20.0_gdb-7.5.1_eabi_20121222» отсутствует. Поэтому, я скачал этот файл с сайта производителя (приложу его в конце абзаца), и поместил по указанному пути: C:\Program Files (x86)\Labcenter Electronics\Proteus 8 Professional\Downloads. После выполнил проверку установленных компиляторов, и напротив пункта «GCC for ARM» уже значилось «YES».

1.2 Настраиваем STM и Blink под наши нужды
Теперь мы можем менять код из Proteus LED blink, и перекомпилировать его. Но для начала заменим модель из примера STM32F103R6 на свою STM32F103C6, добавим дисплей LM016L из библиотеки Proteus. в библиотеку, можно попасть например так: ПКМ -> Place -> Component -> From Libraries

Подключим дисплей. Соединим VSS с землей, VDD с питанием, на VEE через потенциометр подадим от 0,2 до 0,7 V, что бы регулировать контрастность. RW можно посадить на землю (этот пин отвечает за передачу данных из дисплея в STM, нам этого не нужно и там всегда будет 0). Остальные RS, E, D7-D0 сажаем на любые пины STM. Я подключил их на PA0-PA7 и PA15-PA13.

В STM, нам нужно изменить конфигурацию пинов РА на OUTPUT_PP (выход PUSH-PUL) Для этого в коде примера находим участок Configuration GPIO pins РА0-РА15. Меняем строчку GPIO_InitStruct.Mode заменяя ANALOG на OUTPUT_PP;. Добавляем строчку GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;, что бы сообщить МК о низкой частоте их работы.
Я включил все пины РА, но нам нужны не все, и вы можете из перечня удалить не нужные.

2. Знания для дальнейшей работы

2.1 Изучение дисплея. Из DataSheet на дисплей нам понадобятся две таблички:

Команды которые понимает дисплей и соответствующие им значения битов. А также время, которое нужно для выполнения команд
таблица символов и значения их битов. сверху в строке — старшие 4 бита. слева в столбце — младшие 4.

Ещё один важный момент дисплея, это pin Е. Он отвечает за передачу байта, который сформирован из 8 битов D0-D7, бита RS и бита RW. Передача осуществляется так:
— подаём на пины RS, R/W, DB7 – DB0 – нужные сигналы, соответствующие нашей команде.
— подаём единицу на вывод Е.
— ждём минимум 150 нс
— подаём нуль на вывод Е.

2.1 Изучение STM и Reference-manual. Поскольку в примере были инициализированы pin РС13, и несколько PA с помощью библиотеки HAL. мы ещё не знаем как инициализировать pin.

Итак, как бы мы инициализировали пин PC13 отвечающий за светодиод и аналогично ему PA0-PA15, через регистры RCSIS. Для этого в Reference-manual посмотрим следующую таблицу:

Из вышеприведенного изображения мы можем узнать всё что нужно. А именно, что пара битов 20 и 21 — отвечает за настройку pin PA..PC13: вход или выход с различной скоростью. То есть, что бы сделать порт PC13 выходом со скоростью 10МГц нам нужно записать в бит 21 — 0, а в 20 — 1. .
Биты 22 и 23 — отвечают за точную настройку входа или выхода. Так как мы уже выбрали режим ВЫХОД 10МГц, то при значениях в битах 22 = 0 и 23 = 0, мы получим что pin 13 будет push-pull выход со скоростью 10МГЦ.

А когда pin настроен и подключен к дисплею. Мы будем формировать на соответствующей ножке либо высокий сигнал 1, либо низкий 0. Для этого мы воспользуемся ещё одной таблицей:

Из этой таблицы мы можем узнать, что биты с 16 по 31 — это биты сбрасывающие в 0 соответствующий pin. Например 29 бит, сбрасывает в 0 pin 13. А биты с 0 по 15 — это биты устанавливающие 1 в соответствующий пин. Например 13 бит, устанавливает 1 на пине 13.

3. Начинаем собирать проект

Итак. STM настроена. Дисплей изучен. И мы можем начинать писать приветствие с помощью нашего дисплея.

3.1 Что бы дисплей начал выводить текст, его нужно инициализировать. Инициализация состоит из таких этапов:
1- выбрать разрядность 8 бит или 4-бит (при 4 битной разрядность код передается в 2 этапа по 4 младшим пинам D0-D4 сначала первых четыре бита кода, затем последние четыре бита) У нас, передача осуществляется восьмью битами.
2 — выключить дисплей
3 — очистить дисплей, установить курсор в нулевую позицию
4 — задать настройки: сдвигать «экран» запрещено, курсор сдвигать вправо.
5 — Включить дисплей. С настройками: с курсором/без курсора. с мигающим курсором

На кусочке кода видно как записывать SET или сбрасывать RESET байт (ниже таблица BSRR).

// устанавливаем разрядность 8 бит
GPIOA->BSRR = (1 << 31); //0 бит на PIN15 А соответствующий ноге RS передача команды GPIOA->BSRR = (1 << 30); //0 Сбросить бит на PIN14 А соответствующий ноге RW дисплея GPIOA->BSRR = (1 << 23); //0 Сбросить бит на PIN7 А соответствующий ноге D7 дисплея GPIOA->BSRR = (1 << 22); //0 Сбросить бит на PIN6 А соответствующий ноге D6 дисплея GPIOA->BSRR = (1 << 5); //1 Сбросить бит на PIN5 А соответствующий ноге D5 дисплея GPIOA->BSRR = (1 << 4); //1 Сбросить бит на PIN4 А соответствующий ноге D4 дисплея GPIOA->BSRR = (1 << 3); //1 Записать бит на PIN3 А соответствующий ноге D3 дисплея GPIOA->BSRR = (1 << 18); //0 Записать бит на PIN2 А соответствующий ноге D2 дисплея GPIOA->BSRR = (1 << 17); //0 Записать бит на PIN1 А соответствующий ноге D1 дисплея GPIOA->BSRR = (1 << 16); //0 Записать бит на PIN0 А соответствующий ноге D0 дисплея
// задержка перед битом E (не забыть в переменных в начале кода объявить переменную int i)
for( i = 0; i <= 16000; i++ );
GPIOA->BSRR = (1 << 13); // бит на E дисплея что бы передать данные
for( i = 0; i <= 40000; i++ );
GPIOA->BSRR = (1 << 29); // Сбросить бит на Е, что бы закончить передачу данных
for( i = 0; i <= 24000; i++ );

// выкл дисплей
GPIOA->BSRR = (1 << 31); //0 бит на PIN15 А соответствующий ноге RS передача команды GPIOA->BSRR = (1 << 30); //0 Сбросить бит на PIN14 А соответствующий ноге RW дисплея GPIOA->BSRR = (1 << 23); //0 Сбросить бит на PIN7 А соответствующий ноге D7 дисплея GPIOA->BSRR = (1 << 22); //0 Сбросить бит на PIN6 А соответствующий ноге D6 дисплея GPIOA->BSRR = (1 << 21); //0 Сбросить бит на PIN5 А соответствующий ноге D5 дисплея GPIOA->BSRR = (1 << 20); //0 Сбросить бит на PIN4 А соответствующий ноге D4 дисплея GPIOA->BSRR = (1 << 3); //1 Записать бит на PIN3 А соответствующий ноге D3 дисплея GPIOA->BSRR = (1 << 18); //0 Записать бит на PIN2 А соответствующий ноге D2 дисплея GPIOA->BSRR = (1 << 17); //0 Записать бит на PIN1 А соответствующий ноге D1 дисплея GPIOA->BSRR = (1 << 16); //0 Записать бит на PIN0 А соответствующий ноге D0 дисплея
// задержка перед битом E (не забыть в переменных в начале кода объявить переменную int i)
for( i = 0; i <= 16000; i++ );
GPIOA->BSRR = (1 << 13); // бит на E дисплея что бы передать данные
for( i = 0; i <= 40000; i++ );
GPIOA->BSRR = (1 << 29); // Сбросить бит на Е, что бы закончить передачу данных
for( i = 0; i <= 24000; i++ );

// сброс дисплей и ставим в 0 курсор
GPIOA->BSRR = (1 << 31); //0 бит на PIN15 А соответствующий ноге RS передача команды GPIOA->BSRR = (1 << 30); //0 Сбросить бит на PIN14 А соответствующий ноге RW дисплея GPIOA->BSRR = (1 << 23); //0 Сбросить бит на PIN7 А соответствующий ноге D7 дисплея GPIOA->BSRR = (1 << 22); //0 Сбросить бит на PIN6 А соответствующий ноге D6 дисплея GPIOA->BSRR = (1 << 21); //0 Сбросить бит на PIN5 А соответствующий ноге D5 дисплея GPIOA->BSRR = (1 << 20); //0 Сбросить бит на PIN4 А соответствующий ноге D4 дисплея GPIOA->BSRR = (1 << 19); //0 Записать бит на PIN3 А соответствующий ноге D3 дисплея GPIOA->BSRR = (1 << 18); //0 Записать бит на PIN2 А соответствующий ноге D2 дисплея GPIOA->BSRR = (1 << 17); //0 Записать бит на PIN1 А соответствующий ноге D1 дисплея GPIOA->BSRR = (1 << 0); //1 Записать бит на PIN0 А соответствующий ноге D0 дисплея
// задержка перед битом E (не забыть в переменных в начале кода объявить переменную int i)
for( i = 0; i <= 16000; i++ );
GPIOA->BSRR = (1 << 13); // бит на E дисплея что бы передать данные
for( i = 0; i <= 40000; i++ );
GPIOA->BSRR = (1 << 29); // Сбросить бит на Е, что бы закончить передачу данных
for( i = 0; i <= 24000; i++ );

// установки: сдвиг экрана запрещён, курсор сдвигается вправо
GPIOA->BSRR = (1 << 31); //0 бит на PIN15 А соответствующий ноге RS передача команды GPIOA->BSRR = (1 << 30); //0 Сбросить бит на PIN14 А соответствующий ноге RW дисплея GPIOA->BSRR = (1 << 23); //0 Сбросить бит на PIN7 А соответствующий ноге D7 дисплея GPIOA->BSRR = (1 << 22); //0 Сбросить бит на PIN6 А соответствующий ноге D6 дисплея GPIOA->BSRR = (1 << 21); //0 Сбросить бит на PIN5 А соответствующий ноге D5 дисплея GPIOA->BSRR = (1 << 20); //0 Сбросить бит на PIN4 А соответствующий ноге D4 дисплея GPIOA->BSRR = (1 << 19); //0 Записать бит на PIN3 А соответствующий ноге D3 дисплея GPIOA->BSRR = (1 << 2); //1 Записать бит на PIN2 А соответствующий ноге D2 дисплея GPIOA->BSRR = (1 << 1); //1 Записать бит на PIN1 А соответствующий ноге D1 дисплея GPIOA->BSRR = (1 << 16); //0 Записать бит на PIN0 А соответствующий ноге D0 дисплея
// задержка перед битом E (не забыть в переменных в начале кода объявить переменную int i)
for( i = 0; i <= 16000; i++ );
GPIOA->BSRR = (1 << 13); // бит на E дисплея что бы передать данные
for( i = 0; i <= 40000; i++ );
GPIOA->BSRR = (1 << 29); // Сбросить бит на Е, что бы закончить передачу данных
for( i = 0; i <= 24000; i++ );

// Вкл Дисплей без курсора
GPIOA->BSRR = (1 << 31); //0 бит на PIN15 А соответствующий ноге RS передача команды GPIOA->BSRR = (1 << 30); //0 Сбросить бит на PIN14 А соответствующий ноге RW дисплея GPIOA->BSRR = (1 << 23); //0 Сбросить бит на PIN7 А соответствующий ноге D7 дисплея GPIOA->BSRR = (1 << 22); //0 Сбросить бит на PIN6 А соответствующий ноге D6 дисплея GPIOA->BSRR = (1 << 21); //0 Сбросить бит на PIN5 А соответствующий ноге D5 дисплея GPIOA->BSRR = (1 << 20); //0 Сбросить бит на PIN4 А соответствующий ноге D4 дисплея GPIOA->BSRR = (1 << 3); //1 Записать бит на PIN3 А соответствующий ноге D3 дисплея GPIOA->BSRR = (1 << 2); //1 Записать бит на PIN2 А соответствующий ноге D2 дисплея GPIOA->BSRR = (1 << 1); //1 Записать бит на PIN1 А соответствующий ноге D1 дисплея GPIOA->BSRR = (1 << 16); //0 Записать бит на PIN0 А соответствующий ноге D0 дисплея
// задержка перед битом E (не забыть в переменных в начале кода объявить переменную int i)
for( i = 0; i <= 16000; i++ );
GPIOA->BSRR = (1 << 13); // бит на E дисплея что бы передать данные
for( i = 0; i <= 40000; i++ );
GPIOA->BSRR = (1 << 29); // Сбросить бит на Е, что бы закончить передачу данных
for( i = 0; i <= 24000; i++ );

В побитовом управлении дисплеем важно ещё раз отметить, что бит RS отвечает за: 0 — отправить в дисплей команду (например вышеперечисленные в инициализации) или 1 — отправить данные (например букву)
RW — бит отвечающий за чтение, пока он нам не нужен.
E — это бит «передачи». Он работает следующим образом: когда код отправлен в дисплей (первые 10 строчек кода), коротковременно (по datasheet 150 нс, но в примере дольше) на пин Е дисплея подается единица. После того как на Е — снова 0, дисплей выполняет команду, или выводит текст.

Выводы. В вышеприведенном примере к Proteus есть ошибка, связанная с тем, что изначально void писался только под стирание дисплея, но в процессе изучения, появления ошибок, в тестовых целях основной код так и остался в void Cleare. Еще одна ошибка в том, что я пока не понимаю, как работает частота кристалла, и соответственно как точно отсчитывать время. т.к установлены библиотеки HAL в качестве задержки времени можно не мотать циклы, а пользоваться функцией HAL_Delay(150);

5.2 Работа с микроконтроллером STM32F103C8. Keil v5 и дисплей Sharp

Цель: — познакомиться со средой разработки для STM Keil v5
— узнать что такое библиотека, как устанавливать сторонние библиотеки, и какие стандартные библиотеки должны быть подключены при создании проекта на примере дисплея sharp c контроллером HD44780A00 и библиотеки к нему.
— написать самостоятельный код, с пониманием каждой строчки

1. Подготовка

1.1 Keil
Скачать кейл можно с официального сайта. Это среда разработки для STM распространяется условно бесплатно. При превышение кодом 32 кБ, необходимо купить полную версию. Для наших нужд 32 кБ более чем достаточно.
1.2 STM и Display

STM32F103C8 продаётся в популярном китайском магазине. Ещё нам понадобиться ST-Link и Display, которые продаются там же.
1.3 Библиотеки
В Keil уже должна быть библиотека стандартной периферии STM. Но если вым интересно подробнее почитать, то скачать её можно с официального сайта STM.
Так же нам нужна библиотека для нашего дисплея на чипе hd44780. а также библиотека для простой печати текста. В меню «загрузки» нашего сайта уже есть библиотека для дисплея.
Ниже архив, в котором всё что нужно для дисплея.

2. Создаём проект.
2.1 Итак, запускаем Keil. Прежде чем создать наш проект нам нужно добавить наш МК в список девайсов Keil. Для этого в панели меню, нажимаем Project -> Manage -> Pack Installer.
И в левом окне, в закладке Devices ищем и выбираем наш МК.
Теперь в правом окне в закладке Packs, нам нужно обновить до последних все CMSIS драйвера (зеленые ромбы на скриншоте)

Теперь создаём новый uProject: в панели меню, нажимаем Project -> New uVision Project. Нам предлагают выбрать папку, и название для файла. Будет очень удобно, если для каждого проекта у Вас будет своя папка.
Таким образом, пользуясь всеми рекомендациями:
— создаём папку со всеми нашими проектами, например: STM
— создаём папку под наш конкретный проект: Display
— создаём файл проекта: Display
— в открывшемся окне Select Device for Target ищем и выбираем наш МК STM32F103C8

GPIO в пункте Device -лишний, выберем GPIO в StdPeriph Devices

В появившемся окне менеджере, мы выбираем необходимые в нашем проекте библиотеки. Это:
CORE — расшифровка всех регистров ядра. То с помощью чего мы писали код, прошлого урока. База. Прямая связь с Reference Manual. Это библиотека нужна всегда.
Device- StdPeriph Drivers:
RCC — библиотеки для подключения портов, чтобы включить тактирование портов. GPIO — Библиотека для подключения портов. А Framework — нужен всегда при подключении библиотек стандартной периферии.
Очень хорошая особенность в данной настройке состоит в том, что, если например вы хотите добавить, какую-либо библиотеку, но где-то раньше не подключили то с чьей помощью должна работать эта библиотека, менеджер проектов подсветит выбранный пункт желтым и подскажет что нужно добавить.

2.1 Добавляем нашу библиотеку LCD
Для начала перестроим немного структуру нашего проекта.

Нажмем правой кнопкой по папке Source Group 1 и выберем пункт Manage Project Items…

В открывшемся окне мы можем разбить весь проект по удобным нам папкам. Переименовать группы, и с помощью отмеченного значка создать новые. Создадим группу LCD (или Library или как Вам нравится). Теперь выделим эту группу и в крайнем правом окне добавим все файлы из архива библиотеки: это hd44780.h, hd44780.с, bcd.h, bcd.с. (если каких-то файлов не будет видно, поменяйте тип файлов)
Для того что бы библиотека заработала нормально и нам не пришлось в начале кода писать #include «полный путь к файлу». Укажем путь к этим файлам:

И раз уж мы вошли в меню Option for Target. Выполним настройку keil, как в статье #4. А именно: в закладке Debug выберем ST-Link Debugger, и настраиваем его, добавляя пункт во flash download: «Reset and Run».
2.2 Создаём главный исполняющий файл.
Для этого, нажмем правой кнопкой по папке Source Group. и выберем пункт Add New Item to Group. в появившемся окне выберем С File (.c) и дадим ему имя, например «main»
Теперь у нас готово всё, что касается программной части.

3. Собираем макет.

3.1 ST-Link + STM
Что бы прошить stm32f103 да и любую другую stm мы пользуемся отладчиком ST-Link. Его мы просто вставляем в usb порт, а наш Keil с ним мы уже познакомили, так что после нажатия Build а затем Load. Наш код через st-link в виде машинного кода направится в нашу STM.
Для этого мы должны соединить вывод ST-LINK с выводами STM:

3.2 Дисплей
DataSheet на дисплей. Из него мы можем узнать, что дисплей питается от 5 В. и его распиновку

В моём дисплее используется шлейф, и чтобы понять его распиновку я вызвонил первый (то есть Vss) и последний (то есть Vss подсветки) пин. Так же при подключении, для экономии «ножек» будем пользоваться только 4 пина передачи данных DB7-DB4.
Обратите внимание, что дисплей питается от 5 В ещё раз. и заметьте, что к STM у нас подходит только 3.3 В, так что, хотя на плате есть вывод 5В, на нем нет этого напряжения (замерьте для точности, вдруг их только у меня нет?). В общем 5 В возьмём с отладчика ST-Link.

4. Пишем программу

Хороший сайт рассказывающий о STM с 0: https://catethysis.ru/

4.1 То что мы уже знаем

// подключаем директивы наших библиотек, которые нам нужны в данном коде.
#include «hd44780.h»
#include «bcd.h»
#include «stm32f10x.h»

Цитата с сайта: «Препроцессор потом заменит все наши include, подставляя вместо них содержимое указанного файла. Этот процесс проходит рекурсивно, начиная с .c–файла и заходя в каждый встреченный #include .h, и если в .h–файле тоже встретились директивы #include — препроцессор зайдёт и в них. Получается такое дерево инклудов. Обратите внимание: он не обрабатывает ситуацию двойного включения инклудов, т.е. один и тот же .h-файл может включиться несколько раз, если он указан в #include в нескольких местах проекта. Такую ситуацию нужно обрабатывать дефайнами.»

int main (void) // основная функция
{
lcd_init (); //инициализируем дисплей
while(1) //бесконечный цикл нашего кода
{
lcd_set_xy(0,0); // устанавливаем курсор в 1 строку 1 символ
lcd_out(«Hello»); // выводим текст Hello
lcd_set_xy(7,1); //устанавливаем курсор в 2 строку 7 символ
delay(500); //задержка времени
lcd_out(«world»); //пишем World
delay(2000); //ждём 2 секунды
lcd_clear(); //очищаем дисплей
delay(500);
} //закрыли цикл while
}//закрыли функцию main

Прежде чем закончить наш код, написав заключительную функцию, мы должны подробно разобрать этот участок кода, для того что бы понять, так как же всё-таки работает библиотека.
Итак, как написано в цитате с сайта Препроцессор проходит по всем файлам .c проекта, при этом удаляет все наши комментарии за «//» и в таких /* ссс */. Распаковывает по иерархии все #include. Потом совершает все подстановки. И в конце концов направляет в компилятор один цельный файл.
Так вот, зная как работает препроцессор, мы знаем как будет работать наш основной код.

Итак, всё начинается с lcd_init(); Эта функция расписана в файле hd44780.c . Откроем его и разберемся с этой функцией

Участок кода, отправляющий 0011 в дисплей, затем высылаем вторую часть. В итоге в дисплее формируется инициализирующая его последовательность команд, как в прошлой статье.
Однако, как функция узнала на какие пины STM посылать 1 или 0, ведь у STM нет пинов DB? ответ на это вопрос находится в файле hd44780.h

Кстати, обратите внимание что вначале этого файла мы подключаем стандартную библиотеку. И т.к. с этого файла начинается наш код, то файл «stm32f10x.h» уже знаком компилятору. Значит, можно сделать следующее. Во-первых, начать include с файла stm32f10x.h. А во-вторых, закомментировать include в файле hd44780.h.

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


void delay(uint32_t ms)
{
volatile uint32_t nCount; // объявляем переменную, она может меняться в любое время
RCC_ClocksTypeDef RCC_Clocks; // Подключаем внутренние часы ???
RCC_GetClocksFreq (&RCC_Clocks); // запрашиваем частоту тиков
nCount=(RCC_Clocks.HCLK_Frequency/10000)*ms; // присваиваем переменной значение, которое делим на 10000 и получаем число равное 1 мс
for (; nCount!=0; nCount—); // мотаем циклы
}

Вывод.

Код закончен. нажимаем Build. по завершению получаем отчёт:

И мы можем загружать его. кнопкой Load. Перед этим еще раз проверяем настройку Keil, а именно Debug — ST-Link

18 комментариев для “#3. Разработка источника импульсного питания с PFC на TL494 + STM32 by #DarthMuxa”

  1. По-моему я начинаю понимать ошибку. Итак. Номинал подобран неверно, нужно будет пересчитать так чтобы дальше в адум пошло 5В. При 100 Ом на коллекторах TL Нужно эмиттеры подтянуть к земле 200 Ом, верно?
    Дальше ошибка в питании логики Ir, у меня 15 там, а нужно 5, оно?

    1. Во-первых, да, верно, ты подаёшь 15В от TL494 на 5В-вход ADUM1402, что не есть правильно и допустимо. Как вариант, можно использовать соответствующие делители напряжения. Сопротивления порядка 100 Ом использовать можно, но нецелесообразно, так как линия низкоточная, а ток в этом случае через цепочку будет идти сравнительно большой, вполне подойдёт делитель из резисторов порядка кОм, например 1 кОм и 2 кОм, либо выше.
      Во-вторых, у IR2110 есть специальный вход питания для цифровой части — Vdd — его необходимо посадить на 5В, которыми запитывается ADUM1402 на соответствующей стороне, этим ты обеспечишь согласование уровней от ADUM1402 до IR2110.

  2. Господа! В схеме с 494 все резисторы, кроме R и Rt, применены неверно.
    Питание 2110 и 1412 организуйте по-нормальному, а не через делители напряжения.
    Сделайте так же, как в схеме:

  3. Предложение:
    Разместить 494 и драйвер 2110 на высокой стороне с контролем тока, как в схеме:

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

    Причем ток лучше ограничивать на высокой стороне, а не отключать преобразователь, как на вышеописанной схеме. Вот примерный вариант как ограничивать перегрузку по току:

  4. Прежде всего, мне очень стыдно за ошибки. Это только мои, у ребят со связкой IR и TL все хорошо.
    По поводу готовых решений. Я не знаю, насколько правильно отходить от ТЗ.

    1. Я подумал, что, т.к Uобр от мах60 В после трансформатора и выпрямителя, то TL так же нужно защитить. Но PC817 действительно не нужно, ведь есть же адум, и там как раз есть 2 канала в «другую сторону»

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