Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Друг Кота
Аватара пользователя
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Сообщение FreshMan »

WiseLord, благодарю !
оказывается, в эклипсе, в настройках проэкта, нужно просто добавить путь
Изображение Изображение
Tell Me The Truth
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 104
Зарегистрирован: Пн ноя 04, 2019 09:58:29
Откуда: г. Нижний Тагил Свердл. обл.

Сообщение Эйлер Леонард »

Доброго времени суток. Подключил библиотеку GPIO.h ссылка. Немного подрихтовал. Теперь работает с голым МК в AtmelStudio. Теперь задача - пины передавать в качестве параметра функции, ну и что либо там делать. Тип параметра, очевидно объект. По ссылке.. по указателю..
Спойлер/* ATiny85 */
#define F_CPU 8000000UL //
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "wiring.h"
#include "GPIO.h"

GPIO<BOARD::D3> led;

void My_function(/* параметр(ы) функции led, */){
// различные действия с led;
};

int main(void){

led.output();// пин на выход

while (1) {// мигание светодиодом
led = 1; // зажечь
_delay_ms(500);
led = 0; // погасить
_delay_ms(500);
}

}
Что-то совсем заклинило. Как экземпляр класса запихать параметром в функцию??
Реклама
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

Эйлер Леонард, какой там gcc?

Всегда можно сделать так:

Код: Выделить всё

template<typename T>
void foo(T pin) { pin.toggle(); }
Если доступен C++20, то можно написать концепт, типа такого:

Код: Выделить всё

template<typename T>
concept Pin = std::is_base_of_v<PinBase, T>;
Правда на AVR gcc обрезанный и я не уверен, что is_base_of_v там доступен, но можно заменить любой проверкой, в данном случае пин детектится по базовому классу. С концептом использование мало чем отличается, просто компилятор будет проверять, что передали действительно пин:

Код: Выделить всё

template<Pin T>
void foo(T pin) { pin.toggle(); }
Помимо этого есть auto:

Код: Выделить всё

void foo(auto pin) { pin.toggle(); }
Auto с концептом:

Код: Выделить всё

void foo(Pin auto pin) { pin.toggle(); }
Ну и чаще всего применяется чисто шаблонный вариант:

Код: Выделить всё

template<typename T>  //template<Pin T>
void foo() { T::toggle(); }
Но тогда пин обычно объявляют через using с которым генерится более эффективный код при отключенной оптимизации, что для AVR без отладчика не особо актуально:

Код: Выделить всё

using led = GPIO<BOARD::D3>;
Встал на лапы
Аватара пользователя
Сообщения: 104
Зарегистрирован: Пн ноя 04, 2019 09:58:29
Откуда: г. Нижний Тагил Свердл. обл.

Сообщение Эйлер Леонард »

Благодарю за отклик, буду вкуривать. Ох уж эти темплеты. :))

Добавлено after 39 minutes 48 seconds:
Заработало так:
Спойлер/* ATiny85 -std=c++14 */
#define F_CPU 8000000UL //
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "wiring.h"
#include "GPIO.h"

GPIO<BOARD::D3> led;

void foo0(auto pin) { pin=0; }
void foo1(auto pin) { pin=1; }

int main(void){

led.output();// пин на выход

while (1) {// мигание светодиодом

foo1(led);// зажечь
_delay_ms(500);
foo0(led);// погасить
_delay_ms(500);
}
}
Однако AtmelStydio подкрутил до -std=c++14
Ну всё, теперь с GPIO.h дела пойдут (даже полетят) :music:
Вложения
123.png
(35.5 КБ) 97 скачиваний
Реклама
Эиком - электронные компоненты и радиодетали
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

Да чего мелочиться, в gcc 11 уже -std=c++23 есть :)
Реклама
Друг Кота
Аватара пользователя
Сообщения: 7385
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Сообщение uldemir »

Помогите одну вещь. У меня в одном месте робот перестал двигаться и не могу понять почему. В процессе разбирательств, похоже, что оптимизатор съел команду. Потому как добавив одну команду для отладочной распечатки вдруг заработало.

И вот вопрос.

У меня не срабатывает команда:
Motor_Speed(-6000, -6000);

Эта функция делает следующее:

Код: Выделить всё

void Motor_Speed(int16_t left, int16_t right) {
	XstartL = left;
	XstartR = right;
}
Но дело в том, что XstartL/XstartR используются в функции, которая вызывается по прерыванию таймера. Но там они не модифицируются.

Код: Выделить всё

    ErrorL = XstartL - XprimeL;
    ErrorR = XstartR - XprimeR;
...
    if (XstartL == 0 && Left.Dir  == STOPPED) UIL = UL = 0, backlight |= FR_LEFT;
    if (XstartR == 0 && Right.Dir == STOPPED) UIR = UR = 0, backlight |= FR_RGHT;
Нужно ли эти две переменные объявлять как volatile или нет? сейчас они просто:

Код: Выделить всё

int XstartL  = 0, XstartR = 0;
Реклама
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18813
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

скорее надо обеспечить атомарность их модификации... из опыта могу сказать, что volatile сильно влияет на использование в главном цикле переменных, которые меняются в прерываниях, а если наоборот - то не влияет.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1590
Зарегистрирован: Вс июн 24, 2012 16:07:00
Откуда: Лен.Обл.

Сообщение da-nie »

Нужно ли эти две переменные объявлять как volatile или нет?
Нужно везде, где компилятор не сможет понять, что значение переменной может быть изменено вне функции. Иначе он с радостью способен "оптимизировать" код, предположив, что переменная не способна поменять своё значение.
Ну и запрет прерываний при изменении переменных нужен, конечно.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Контактная информация:
Это не хвост, это антенна
Сообщения: 1379
Зарегистрирован: Вт ноя 19, 2019 06:10:18

Сообщение tonyk »

da-nie писал(а):Ну и запрет прерываний при изменении переменных нужен, конечно.
Я бы сказал "обязательно", если этот код будет работать на 8-битном МК.
Друг Кота
Аватара пользователя
Сообщения: 7385
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Сообщение uldemir »

А если это MSP432 Cortex-M4F? Мне казалось, что запись 32 битного там поисходит разом и надобности запрещать прерывание нет. А то что левое колесо получит на 10 мс раньше правого - это ж мелочь.
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Дело не в битности переменной, а в том, что с ней происходит. Если она читается и модифицируется в разных потоках - пиши пропало, глюк обеспечен.
А volatile, ко всему прочему, может ещё и усугубить ситуацию. Т.к. он запретит компилятору всю оптимизацию для этой переменной. И обычный инкремент может превратиться в ЧМЗ. Грубо говоря, конечно.
Мудрый кот
Сообщения: 1856
Зарегистрирован: Вт авг 15, 2017 10:51:13

Сообщение jcxz »

[uquote="uldemir",url="/forum/viewtopic.php?p=4142289#p4142289"]Нужно ли эти две переменные объявлять как volatile или нет? сейчас они просто:

Код: Выделить всё

int XstartL  = 0, XstartR = 0;
[/uquote]Нужно. Более того - нужно запретить прерывания на время их записи (или иным образом обеспечить атомарность записи).

Добавлено after 1 minute 31 second:
[uquote="tonyk",url="/forum/viewtopic.php?p=4143025#p4143025"]
da-nie писал(а):Ну и запрет прерываний при изменении переменных нужен, конечно.
Я бы сказал "обязательно", если этот код будет работать на 8-битном МК.[/uquote]На 32-битном МК тоже - обязательно.

Добавлено after 12 minutes 32 seconds:
[uquote="uldemir",url="/forum/viewtopic.php?p=4143032#p4143032"]А если это MSP432 Cortex-M4F? Мне казалось, что запись 32 битного там поисходит разом и надобности запрещать прерывание нет. А то что левое колесо получит на 10 мс раньше правого - это ж мелочь.[/uquote]Так у вас там 2 записи 32-битных.

У вас внутри ISR одновременно используются обе этих переменные. А значит может быть ситуация, когда одно значение будет новым, другое - старым.
Конечно если для алгоритма это не существенно, то можно и забить. Но это может оказаться "выстрелом в ногу" в будущем. Когда забудете об этом и немного измените алгоритм.

PS: Неужто 3 команды на запрет/разрешение прерываний настолько критичны, что так пытаетесь их сэкономить???
PPS: Можно пойти и другим путём:

Код: Выделить всё

union {
  struct { u16 XstartL, XstartR; };
  u32 XstartL_XstartR;
} = {0, 0};
...
XstartL_XstartR = (u16)left | (u32)(u16)right << 16;
Здесь запись атомарна (на 32-битном МК), без запретов прерываний.
Друг Кота
Аватара пользователя
Сообщения: 7385
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Сообщение uldemir »

Ищё вопрос про волатильность. Как записать одной строчкой определение двух волатильных указателей. типа

Код: Выделить всё

uint8_t * volatile FRAM_send_ptr;
uint8_t * volatile FRAM_recv_ptr;
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Как то так, наверное :roll:

Код: Выделить всё

uint8_t * volatile FRAM_send_ptr, * volatile FRAM_recv_ptr;
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

Все будет так же как с обычными указателями:

Код: Выделить всё

uint8_t volatile *FRAM_send_ptr, *FRAM_recv_ptr;
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Как вариант:

Код: Выделить всё

typedef uint8_t * volatile      p_u8_volatile_t;

p_u8_volatile_t     FRAM_send_ptr, FRAM_recv_ptr;
:))

Добавлено after 4 minutes 40 seconds:
[uquote="Reflector",url="/forum/viewtopic.php?p=4147841#p4147841"]Все будет так же как с обычными указателями:

Код: Выделить всё

uint8_t volatile *FRAM_send_ptr, *FRAM_recv_ptr;
[/uquote]Мне кажется, или

Код: Выделить всё

uint8_t volatile *
и

Код: Выделить всё

uint8_t * volatile
немного разные вещи ? :roll:
Друг Кота
Аватара пользователя
Сообщения: 7385
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Сообщение uldemir »

Эта... тогда есть разница? У меня было

Код: Выделить всё

volatile uin8_t *FRAM_send_ptr, *FRAM_recv_ptr;
И эта штука не работала. Потом я вспомнил, что на эти грабли уже наступал... что нужно не указатель на волатильную переменную, а именно волатильный указатель.

Хм... только что проверил

Код: Выделить всё

uint8_t volatile *FRAM_send_ptr, *FRAM_recv_ptr;
- что-то не работает этот вариант.
Спойлер

Код: Выделить всё

Griever>fram_rdsr .
8C
Griever>0 fram_wrsr

Griever>fram_rdsr .
8C
Griever>
В статусный регистр FRAM 0 не записался.

А вариант

Код: Выделить всё

uint8_t * volatile FRAM_send_ptr, * volatile FRAM_recv_ptr;
отработал правильно.
Спойлер

Код: Выделить всё

Griever>fram_rdsr .
8C
Griever>0 fram_wrsr

Griever>fram_rdsr .
0
Griever>
нормально сбросились биты защиты от записи.
Модератор
Аватара пользователя
Сообщения: 4618
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Все спецификаторы, находящиеся до *, относятся к объекту, на который указывает указатель. А те, которые после *, - к самому указателю.

Код: Выделить всё

int const * ptr; // Указатель на константу
int * const ptr; // Константный указатель на переменную
int const * const ptr; // Указатель-константа на константу
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

Сообщение Reflector »

[uquote="Аlex",url="/forum/viewtopic.php?p=4147842#p4147842"]немного разные вещи ?[/uquote]
Конечно, я даже не обратил внимания, параллельно с багом борюсь :) В таком случае проще объявлять переменные отдельно и ничего не выдумывать...
Друг Кота
Аватара пользователя
Сообщения: 7385
Зарегистрирован: Пт авг 28, 2009 21:34:30
Откуда: 845-й км.

Сообщение uldemir »

Тогда что получается, что в строчке

Код: Выделить всё

uint8_t volatile *FRAM_send_ptr, *FRAM_recv_ptr;
обявляются два не волатильных указателя, только FRAM_send_ptr - указывает на волатильную переменную, а FRAM_recv_ptr - на обычную?
Ответить

Вернуться в «Разные вопросы по МК»