И причём тут отрицательное число ?
Вопросы по С/С++ (СИ)
Что за знаковое число в целочисленной математике ?
И причём тут отрицательное число ?
И причём тут отрицательное число ?
- Реклама
надо 95 разделить на 50 и -95 разделить на 50 - все числа целые (а не натуральные). если просто поделить получается 1, так как остаток 45 отбрасывается. Но хочется получить 2. Так вот для +90 метод (90 + 25)/50 даст 2. Но для -90, к сожалению -1, потому как получается "округление" в положительную сторону, а хочется в абсолютную.
#define rnd_div(x, y) do ((x) < 0 ? -(-(x) + (y)/2) / (y) : ((x) + (y)/2) / (y); while 0
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Может, еще подскажете, это не совсем по C но около... Среда на базе эклипса. В данный момент это Simplicity Studio, но перед этим мучался с подобным под Code Compose Studio. Есть проект и есть проект. И я хочу чтобы несколько файлов с исходниками были общие. Примерно так:
т.е. файлы visualise должны быть общие, чтобы поправляя в одном проекте, эти же изменения были и во втором. Но файлы configuration.h - у проектов разные. Eclipse позволяет в проект добавить линки на файлы. Но, при компиляции проекта_2 есть две проблемы. Первая - другие файлы не видят файла visualise.h, упомянутого в #include. Ну хорошо, я могу в настройках проекта добавить этот путь и тогда видит. Но вторая проблема в том, что компилируя проект_2 файл visualise.c в команде #include "configuration.h" видит файл из проекта_1. Что тоже вроде как понятно - текущий каталог первый в поиске, но как правильно это сделать бы?
Код: Выделить всё
Project_1
visualise.c
visualise.h
configuration.h
Project_2
visualise.c -> Project_1/visualise.c
visualise.h -> Project_1/visualise.h
configuration.h
полные пути к включаемым файлам не помогают?
#include "\path]\dir1\config.h"
#include "\path]\dir1\config.h"
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
- Реклама
как? мне нужно, чтобы в одном проекте visualise.c взял один конфиг, а в другом проекте - другой. В предыдущий раз когда я имел <нецензурное слово> с таким извращением, все дефайны были определены в настройках проекта. Но хочется простого текстового файла - можно хоть комментарий написать, а то голова уже не та - забывать начинаю, что писал всего пару месяцев назад.
Впрочем, какой-то выход из положения нашел. Общие файлы запихнул в каталог common, а в настройках проекта сделал поиск инклюдов сначала в каталоге проекта, а потом в остальных местах.
Впрочем, какой-то выход из положения нашел. Общие файлы запихнул в каталог common, а в настройках проекта сделал поиск инклюдов сначала в каталоге проекта, а потом в остальных местах.
Пути должны быть относительными.
Относительно тех путей, которые уже есть в опциях компилятора
То есть, если, например есть такое: CFLAGS = ... -I /path/to/src/fonts ... - то нужно включать как #include <fonts.h>.
А если только CFLAGS = ... -I /path/to/src/ ... - то включается как #include <fonts/fonts.h>
Если в опциях компилятора оба пути перечислены, то можно по обоим вариантам.
Относительно тех путей, которые уже есть в опциях компилятора
То есть, если, например есть такое: CFLAGS = ... -I /path/to/src/fonts ... - то нужно включать как #include <fonts.h>.
А если только CFLAGS = ... -I /path/to/src/ ... - то включается как #include <fonts/fonts.h>
Если в опциях компилятора оба пути перечислены, то можно по обоим вариантам.
Tell Me The Truth
Доброго времени суток. Подключил библиотеку GPIO.h ссылка. Немного подрихтовал. Теперь работает с голым МК в AtmelStudio. Теперь задача - пины передавать в качестве параметра функции, ну и что либо там делать. Тип параметра, очевидно объект. По ссылке.. по указателю..
#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);
}
}Что-то совсем заклинило. Как экземпляр класса запихать параметром в функцию??
Спойлер
/* 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
Эйлер Леонард, какой там gcc?
Всегда можно сделать так:
Если доступен C++20, то можно написать концепт, типа такого:
Правда на AVR gcc обрезанный и я не уверен, что is_base_of_v там доступен, но можно заменить любой проверкой, в данном случае пин детектится по базовому классу. С концептом использование мало чем отличается, просто компилятор будет проверять, что передали действительно пин:
Помимо этого есть auto:
Auto с концептом:
Ну и чаще всего применяется чисто шаблонный вариант:
Но тогда пин обычно объявляют через using с которым генерится более эффективный код при отключенной оптимизации, что для AVR без отладчика не особо актуально:
Всегда можно сделать так:
Код: Выделить всё
template<typename T>
void foo(T pin) { pin.toggle(); }Код: Выделить всё
template<typename T>
concept Pin = std::is_base_of_v<PinBase, T>;Код: Выделить всё
template<Pin T>
void foo(T pin) { pin.toggle(); }Код: Выделить всё
void foo(auto pin) { pin.toggle(); }Код: Выделить всё
void foo(Pin auto pin) { pin.toggle(); }Код: Выделить всё
template<typename T> //template<Pin T>
void foo() { T::toggle(); }Код: Выделить всё
using led = GPIO<BOARD::D3>;Благодарю за отклик, буду вкуривать. Ох уж эти темплеты. 
Добавлено after 39 minutes 48 seconds:
Заработало так:
#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 дела пойдут (даже полетят)
Добавлено 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);
}
}
Ну всё, теперь с GPIO.h дела пойдут (даже полетят)
- Вложения
-
- 123.png
- (35.5 КБ) 78 скачиваний
- Сообщения: 2089
- Зарегистрирован: Вс июн 19, 2016 09:32:03
Помогите одну вещь. У меня в одном месте робот перестал двигаться и не могу понять почему. В процессе разбирательств, похоже, что оптимизатор съел команду. Потому как добавив одну команду для отладочной распечатки вдруг заработало.
И вот вопрос.
У меня не срабатывает команда:
Motor_Speed(-6000, -6000);
Эта функция делает следующее:
Но дело в том, что XstartL/XstartR используются в функции, которая вызывается по прерыванию таймера. Но там они не модифицируются.
Нужно ли эти две переменные объявлять как volatile или нет? сейчас они просто:
И вот вопрос.
У меня не срабатывает команда:
Motor_Speed(-6000, -6000);
Эта функция делает следующее:
Код: Выделить всё
void Motor_Speed(int16_t left, int16_t right) {
XstartL = left;
XstartR = right;
}Код: Выделить всё
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;
Код: Выделить всё
int XstartL = 0, XstartR = 0;скорее надо обеспечить атомарность их модификации... из опыта могу сказать, что volatile сильно влияет на использование в главном цикле переменных, которые меняются в прерываниях, а если наоборот - то не влияет.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
при взгляде на многих сверху ничего не меняется...
Мой уютный бложик... заходите!
Нужно везде, где компилятор не сможет понять, что значение переменной может быть изменено вне функции. Иначе он с радостью способен "оптимизировать" код, предположив, что переменная не способна поменять своё значение.Нужно ли эти две переменные объявлять как volatile или нет?
Ну и запрет прерываний при изменении переменных нужен, конечно.
И день и ночь в пути...
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
Мои программки: https://github.com/da-nie
Мои публикации: https://habr.com/ru/users/da-nie/posts/
Мои видео: https://www.youtube.com/channel/UCUroi3 ... 52g/videos
- Сообщения: 1339
- Зарегистрирован: Вт ноя 19, 2019 06:10:18
Я бы сказал "обязательно", если этот код будет работать на 8-битном МК.da-nie писал(а):Ну и запрет прерываний при изменении переменных нужен, конечно.
А если это MSP432 Cortex-M4F? Мне казалось, что запись 32 битного там поисходит разом и надобности запрещать прерывание нет. А то что левое колесо получит на 10 мс раньше правого - это ж мелочь.
Дело не в битности переменной, а в том, что с ней происходит. Если она читается и модифицируется в разных потоках - пиши пропало, глюк обеспечен.
А volatile, ко всему прочему, может ещё и усугубить ситуацию. Т.к. он запретит компилятору всю оптимизацию для этой переменной. И обычный инкремент может превратиться в ЧМЗ. Грубо говоря, конечно.
А volatile, ко всему прочему, может ещё и усугубить ситуацию. Т.к. он запретит компилятору всю оптимизацию для этой переменной. И обычный инкремент может превратиться в ЧМЗ. Грубо говоря, конечно.
- Сообщения: 1778
- Зарегистрирован: Вт авг 15, 2017 10:51:13
[uquote="uldemir",url="/forum/viewtopic.php?p=4142289#p4142289"]Нужно ли эти две переменные объявлять как volatile или нет? сейчас они просто:
[/uquote]Нужно. Более того - нужно запретить прерывания на время их записи (или иным образом обеспечить атомарность записи).
Добавлено after 1 minute 31 second:
[uquote="tonyk",url="/forum/viewtopic.php?p=4143025#p4143025"]
Добавлено 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: Можно пойти и другим путём:Здесь запись атомарна (на 32-битном МК), без запретов прерываний.
Код: Выделить всё
int XstartL = 0, XstartR = 0;Добавлено after 1 minute 31 second:
[uquote="tonyk",url="/forum/viewtopic.php?p=4143025#p4143025"]
Я бы сказал "обязательно", если этот код будет работать на 8-битном МК.[/uquote]На 32-битном МК тоже - обязательно.da-nie писал(а):Ну и запрет прерываний при изменении переменных нужен, конечно.
Добавлено 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;





