Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.57/7: Рейтинг темы: голосов - 7, средняя оценка - 4.57
 Аватар для _SayHello
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739

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

06.12.2018, 15:08. Показов 1933. Ответов 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
Ответ Создать тему
Новые блоги и статьи
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
Как ИИ начал спорить и врать (возможно почуяв опасность для себя от индустрии - уход от электроники).
Hrethgir 04.08.2026
Недельный диалог, на фоне событий с НПЗ. Да, из спирта можно получать бензин, и это не сложно. Но потом в схеме я решил избавиться от насоса, при этом полностью сделав контроль подачи спирта в. . .
Термопринтер QR701
Argus19 03.08.2026
Термопринтер QR701 Купил два термопринтера QR701. На сэлф-тесте написано: Language: PC936 (GB18030). Что означает, что принтеры могут печатать только латиницу и китайские иероглифы. Так же. . .
Создание формы заимствованного документа
Maks 03.08.2026
Задача: Необходимо создать собственную форму заимствованного документа. На форме должен быть реквизит "Покупатель", а также табличная часть со следующими реквизитами: - Расчетный счет покупателя. . .
Задача предоставления скидок покупателям
Maks 03.08.2026
Задача: В документе "Продажи" необходимо реализовать функционал предоставления скидок покупателям. Скидка должна автоматически рассчитываться и подставляться в соответствующее поле при выборе. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru