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

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

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

Author24 — интернет-сервис помощи студентам
Решил побаловаться и попробовать написать чего-нибудь на С++ под 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
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
06.12.2018, 15:08
Ответы с готовыми решениями:

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

[Вопрос] Перехват прерывания прямым доступом к вектору прерывания
Всех приветствую! В данный момент разбираюсь с обработкой аппаратного прерывания (прерывание...

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

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

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

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

Не по теме:

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

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

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

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

Добавлено через 1 минуту
Если не секрет, как решили изначальный вопрос ?
0
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
16.12.2018, 00:17  [ТС] 28
Void1509, в смысле а в чем вопрос? Вопрос решился вызовом конструкторов до main. И обрамлением обработчиков прерываний в extern "C". Это был опыт не более. У меня пока слишком ного библиотек написано а Си, чтобы я резко перешел на С++. Но некие удобства для себя я уже определил
0
5 / 5 / 0
Регистрация: 17.09.2018
Сообщений: 43
16.12.2018, 00:23 29
Вот ваш код в начале топика
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
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
16.12.2018, 00:28  [ТС] 30
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 31
Благодарю, понял, Вы инициализацию вынесли из конструктора.
0
874 / 535 / 175
Регистрация: 30.07.2015
Сообщений: 1,739
16.12.2018, 00:33  [ТС] 32
Void1509, для определния пинов и номера интерфейса тактирование особо не важно, и можно их вызвать до настройки системы тактирования, а вот проинициализировать можно и в main. Обычно в работе, точнее при изменениях в проекте перекидываются интерфейсы с одного на другой, дальнейшая их работа остается такой же
0
16.12.2018, 00:33
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
16.12.2018, 00:33
Помогаю со студенческими работами здесь

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

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

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

Строки в стиле C
Начал изучать C++, столкнулся с проблемой. Пользователь вводит строку, нужно вывести все возможные...

Строки в стиле С
Здравствуйте, задумался над одной штукой: можно ли просто написать char* s = &quot;stirng&quot;; или же...


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru