Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739

Прерывания в стиле С++

06.12.2018, 15:08. Показов 2016. Ответов 31
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Решил побаловаться и попробовать написать чего-нибудь на С++ под stm32. Чисто ради любопытства, накорябал класс Led (хотя наверное можно было накидать класс Output, а от него наследоваться =)).
типа того
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#ifndef LEDS_H_INCLUDED
#define LEDS_H_INCLUDED
 
#include "stm32f30x_gpio.h"
#include "stm32f30x_rcc.h"
 
#define LED_RESET   0
#define LED_SET     1
 
 
class Led
{
private:
    GPIO_TypeDef * LED_PORT;
    uint32_t LED_PIN;
    uint8_t State;
public:
    explicit Led(GPIO_TypeDef * port, uint32_t pin, uint8_t state = LED_RESET);
 
    void Set();
    void Reset();
    void Toogle();
    uint8_t GetState();
};
 
#endif /* LEDS_H_INCLUDED */


Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
Led::Led(GPIO_TypeDef * port, uint32_t pin, uint8_t state)
{
    LED_PORT = port;
    LED_PIN = pin;
 
    if(port == GPIOA)
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
    else if(LED_PORT == GPIOB)
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
    else if(LED_PORT == GPIOC)
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
    else if(LED_PORT == GPIOD)
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);
    else if(LED_PORT == GPIOE)
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE);
    else if(LED_PORT == GPIOF)
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOF, ENABLE);
 
    GPIO_InitTypeDef gpio;
 
    gpio.GPIO_Pin = LED_PIN;
    gpio.GPIO_Speed = GPIO_Speed_2MHz;
    gpio.GPIO_Mode = GPIO_Mode_OUT;
    gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(LED_PORT, &gpio);
 
    if(state == LED_SET)
    {
        GPIO_SetBits(LED_PORT, LED_PIN);
        State = LED_SET;
    }
    else
    {
        GPIO_ResetBits(LED_PORT, LED_PIN);
        State = LED_RESET;
    }
}
 
void Led::Set()
{
    GPIO_SetBits(LED_PORT, LED_PIN);
    State = LED_SET;
}
 
void Led::Reset()
{
    GPIO_ResetBits(LED_PORT, LED_PIN);
    State = LED_RESET;
}
 
void Led::Toogle()
{
    LED_PORT->ODR ^= LED_PIN;
    if(State)
        State = LED_RESET;
    else
        State = LED_SET;
}
 
uint8_t Led::GetState()
{
    return State;
}


Так вот, прикольно, и мне понравилось. Все работает. Но возник вопрос, как например поморгать светодиодом в обработчике прерываний? Если мы объявим объекты в main их будет не видно в обработчиках.
Будучи явно уверенным, что глобально объект объявить нельзя, сделал так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "Leds.h"
 
Led LED1(GPIOE, GPIO_Pin_12);
Led LED2(GPIOE, GPIO_Pin_13);
 
int main(void)
{
    SystemInit();
 
    while(1)
    {
        for(uint32_t i = 0; i < 0xFFFFF; i++){};
        LED1.Toogle();
        LED2.Toogle();
    }
}
И оно заработало. Хотя я почему то был уверен, что функции до main вызывать нельзя и компилятор ругаться будет. Проверил в Qt действительно, и там на вызов перед main не ругается.
Может кто уже с этим разбирался, подскажите как правильно, и чем черевата такая писанина?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
06.12.2018, 15:08
Ответы с готовыми решениями:

C++ в функциональном стиле: как писать в стиле C#/LINQ (без дополнительных библиотек)?
Как писать в стиле C#/LINQ (без дополнительных библиотек)? Вот, допустим, есть простейшая задача: ввести число n, ввести n групп чисел, в...

[Вопрос] Перехват прерывания прямым доступом к вектору прерывания
Всех приветствую! В данный момент разбираюсь с обработкой аппаратного прерывания (прерывание таймера 08h и 1Ch, -//- клавиатуры 09h). ...

Вычислить адрес вектора прерывания по номеру прерывания.
17. По заданному номеру прерывания (13 h) вычислите логические адреса хранения исходных адресов обработчиков прерывания в таблице векторов....

31
 Аватар для Voland_
1983 / 1276 / 131
Регистрация: 04.01.2010
Сообщений: 4,607
15.12.2018, 23:01
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Void1509 Посмотреть сообщение
вы утверждали, что операции сдвига - тяжеловесны.
я акцентировал внимание на том, что они тяжеловесны в случае не константного сдвига, а по регистру:
Цитата Сообщение от Voland_ Посмотреть сообщение
структуры динамического сдвига занимают много места и времени в коде
но, в общем, я вижу что в кортексе это не проблема.
Цитата Сообщение от Void1509 Посмотреть сообщение
Сравнивать AVR и ARM - это как сотовый начала 90-х и современный телефон. В смысле и то, и то электроника.

Не по теме:

:). ну ок, вообще-то это вы слишком далеко их разнесли. И то и то имеет право на жизнь, так что вполне нормально сравнивать то, где существует обсужденная фича.

0
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
15.12.2018, 23:18  [ТС]
Void1509, это все конечно приятно и лампово один светодиод один пин один порт. Я тоже так думал когда писал первый проект. Потом светодиодов стало 20 в том же проекте. Потом эти светодиоды перекинули совсем на другие пины. И так далее. Если бы всегда было все статично то вопросов бы не было. А так мне надо одну структуру переопределить и все. А можно и на ходу переделать структуру через интерфейс какой нибудь и сохранить в епроме
0
5 / 5 / 0
Регистрация: 17.09.2018
Сообщений: 43
15.12.2018, 23:38
Боюсь в проблеме которую вы описали - С++ бессилен. Это проблема чисто организационного порядка и никакими средами программирования к сожалению не решается. Заказчик, если его не ставить в рамки договором и техзаданием, имеет неограниченный ассортимент всяческих хотелок и учесть их все просто не возможно.
0
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
16.12.2018, 00:01  [ТС]
Void1509, борьба и идет за упрощение своей работы
0
5 / 5 / 0
Регистрация: 17.09.2018
Сообщений: 43
16.12.2018, 00:10
Как видите, простота есть критерия субъективная. Вам проще через класс описать, мне - дефайном. Но мой способ не генерирует лишний код.

Добавлено через 5 минут
Аж любопытно стало - глянуть на проект на С++. На каком уровне происходит вызов конструкторов в коде ТСа ? На уровне инициализации секции .init ?
0
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
16.12.2018, 00:10  [ТС]
Void1509, но ваш способ не позволяет поменять пин на ходу. не меняя прошивки.

А вообще изначальный вопрос исчерпан. Уже не по теме обсуждение.
0
5 / 5 / 0
Регистрация: 17.09.2018
Сообщений: 43
16.12.2018, 00:14
Цитата Сообщение от _SayHello Посмотреть сообщение
но ваш способ не позволяет поменять пин на ходу. не меняя прошивки.
Ну, да. К этому и стремился - все что можно - определить на уровне компиляции, а не исполнения.

Добавлено через 1 минуту
Если не секрет, как решили изначальный вопрос ?
0
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
16.12.2018, 00:17  [ТС]
Void1509, в смысле а в чем вопрос? Вопрос решился вызовом конструкторов до main. И обрамлением обработчиков прерываний в extern "C". Это был опыт не более. У меня пока слишком ного библиотек написано а Си, чтобы я резко перешел на С++. Но некие удобства для себя я уже определил
0
5 / 5 / 0
Регистрация: 17.09.2018
Сообщений: 43
16.12.2018, 00:23
Вот ваш код в начале топика
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "Leds.h"
 
Led LED1(GPIOE, GPIO_Pin_12);
Led LED2(GPIOE, GPIO_Pin_13);
 
int main(void)
{
    SystemInit();
 
    while(1)
    {
        for(uint32_t i = 0; i < 0xFFFFF; i++){};
        LED1.Toogle();
        LED2.Toogle();
    }
}
в данном коде конструкторы объектов класса Led вызываются до SystemInit(); Вопрос в том - как вы разрешили данную коллизию ?
0
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
16.12.2018, 00:28  [ТС]
Void1509, а, если вы про это то вот самый простой вариант
Цитата Сообщение от _SayHello Посмотреть сообщение
Меня это тоже смутило, на светодиодах это не особо критично, на периферии сложнее уже неприятно. Можно конечно решить, таким образом. Оставить конструктор таким:
C
1
2
3
4
5
Led::Led(GPIO_TypeDef * port, uint32_t pin)
{
* * LED_PORT = port;
* * LED_PIN = pin;
}
И вызывать его до main. И добавить метод:
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void Led::Init(uint8_t State)
{
* * if(port == GPIOA)
* * * * RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
* * else if(LED_PORT == GPIOB)
* * * * RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
* * else if(LED_PORT == GPIOC)
* * * * RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
* * else if(LED_PORT == GPIOD)
* * * * RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);
* * else if(LED_PORT == GPIOE)
* * * * RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOE, ENABLE);
* * else if(LED_PORT == GPIOF)
* * * * RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOF, ENABLE);
GPIO_InitTypeDef gpio;
gpio.GPIO_Pin = LED_PIN;
* * gpio.GPIO_Speed = GPIO_Speed_2MHz;
* * gpio.GPIO_Mode = GPIO_Mode_OUT;
* * gpio.GPIO_PuPd = GPIO_PuPd_NOPULL;
* * GPIO_Init(LED_PORT, &gpio);
if(state == LED_SET)
* * {
* * * * GPIO_SetBits(LED_PORT, LED_PIN);
* * * * State = LED_SET;
* * }
* * else
* * {
* * * * GPIO_ResetBits(LED_PORT, LED_PIN);
* * * * State = LED_RESET;
* * } * *
}
И вызывать его в main
1
5 / 5 / 0
Регистрация: 17.09.2018
Сообщений: 43
16.12.2018, 00:32
Благодарю, понял, Вы инициализацию вынесли из конструктора.
0
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
16.12.2018, 00:33  [ТС]
Void1509, для определния пинов и номера интерфейса тактирование особо не важно, и можно их вызвать до настройки системы тактирования, а вот проинициализировать можно и в main. Обычно в работе, точнее при изменениях в проекте перекидываются интерфейсы с одного на другой, дальнейшая их работа остается такой же
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
16.12.2018, 00:33

Вызов прерывания в обработке прерывания
В программе,нажатие кнопки вызывает прерывание,в котором оно обрабатывается.Попутно в обработке этого прерывания запускается таймер по...

макропроцессор в стиле с
Реализуйте простой макропроцессор в стиле С, использующий директивы #include и #define. Входной файл содержит исходный текст, выходной –...

ToolBar в стиле XP
Я пока работаю на VB6. Машинка слабовата, да и дистрибутивы меньше получаются. Но охота, чтб приложения современно выглядели. Допустим хочу...

О стиле программирования
Я это знаю. Но я указал, что принято явным образом присваивать начальное значение. Посмотрите все примеры задач на BASIC в литературе. ...

Алгоритм в стиле с++
Есть txt файл в котором примерно 400 К строк. Нужно пройтись по всем строкам и записать в новый файл только те строки в которых есть слово...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
32
Ответ Создать тему
Опции темы

Новые блоги и статьи
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть не большие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru