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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

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

Сообщение ibiza11 »

asteroid7 писал(а):Оно выводится в окно "Build". А настройки Tools->Options->Messages->Show Build стоит в All или Messages ?
:lol: везде полазил, а в Options самой среды разработки не залез))) получилось. ОГРОМНОЕ СПАСИБО, Asteroid7!!!! стояло значение "warnings", поставил "messages" - теперь сообщение выводится.
Если не затруднит, уточните, можно ли в этом сообщении выводить какие либо константы, объявленные заранее директивой #define?
Ставим плюсы: )
Аватара пользователя
asteroid7
Опытный кот
Сообщения: 703
Зарегистрирован: Вс янв 18, 2009 21:12:49

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

Сообщение asteroid7 »

Хочу выразить благодарность avreal и ARV. Заставили меня пересмотреть отношение к реализации критических секций на микроконтроллерах. Вопрос - "Почему зная об этом ты это не использовал?" - вогнал меня в небольшой ступор ) Мдаа, много думал...

Для GCC avreal класс критических секций привёл выше, а я приведу для IAR-a не подключая никаких хиадеров. Возможно, кому пригодится:

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

__intrinsic unsigned char __save_interrupt( void );
__intrinsic void  __restore_interrupt( unsigned char );
__intrinsic void __enable_interrupt(void);
__intrinsic void __disable_interrupt(void);

#ifdef __cplusplus

/* Class for controlling critical blocks */
class MUTEX
{
    public:
        MUTEX ()
        {
            __state = __save_interrupt();
            __disable_interrupt();
        }

        ~MUTEX ()
        {
            __restore_interrupt( __state );
        }
       
    private:
        unsigned char __state;
};

#endif

Реализация, как обычный локальный класс:

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

        //---critical block---
        MUTEX m;
        ...
Аватара пользователя
asteroid7
Опытный кот
Сообщения: 703
Зарегистрирован: Вс янв 18, 2009 21:12:49

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

Сообщение asteroid7 »

avreal писал(а):А вот пример, где логическая ошибка может быть для _любой_ архитектуры (хоть 128-битной), а предупреждения нет.

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

volatile char a;
volatile char b;
bool foo()
{
    char ta = a;
    return ta == b;
}


Не увидел в этом коде ошибки... Не затруднит Вас разъяснить этот момент.
Единственное, что бросается в глаза, это логическое "==" без скобок. Так это допускается стандартом.
Аватара пользователя
asteroid7
Опытный кот
Сообщения: 703
Зарегистрирован: Вс янв 18, 2009 21:12:49

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

Сообщение asteroid7 »

ibiza11 писал(а):Если не затруднит, уточните, можно ли в этом сообщении выводить какие либо константы, объявленные заранее директивой #define?
Только текст, заключённый в скобки, выводится. В PDF файле help->AVR C/C++ Compiler Reference Guide можно это уточнить.

Мне не удалось найти применению этой #pragma message диррективы.
Есть интереснее: #error. Она компиляцию останавливает. Удобно предкомпиляционные вычисления и наличие define-ов проверять. Например:

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

#if !defined(PIN_SELECT)
#       error "Не задана нога выборки чего то..."
#endif

#if UART_BUFFER < 300
#       error "Буфер маленький... Нужно не менее 300 байт..."
#endif
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

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

Сообщение ibiza11 »

asteroid7 писал(а):Только текст, заключённый в скобки, выводится. В PDF файле help->AVR C/C++ Compiler Reference Guide можно это уточнить.

Спасибо, Asteroid7, за ответ. Видимо остальным было влом отвечать. Я уже всю документацию перелопатил и очень много гуглил и яндексил:) действительно, я тоже не нашел как вывести константу, определенную директивой #define. Чтобы проверить какую то промежуточную константу приходится на этапе отладки добавлять в код строчки типа

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

#define A ((C+D)/B-D)
...
TCCR0=A;
а потом просматривать ассемблерный листинг в этом месте. Очень неудобно. Насчет #error и #warning я тоже уже знаю) в принципе и до этого знал)))) Только там тоже нельзя выводить объявленные константы. кстати #warning не останавливает компиляцию (логично, скажете Вы :) ).
А как Вы проверяете константы, расчет которых возлагаете на препроцессор?

P.S. может кому пригодится расчет значения регистра UBRR с округлением к ближайшему значению (для 16ти семплового приема):

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

enum{CPU_F_MHz=16};
enum{BAUD_RATE=115200}; // скорость обмена
enum{CUR_UBRR_10x=(CPU_F_MHz*10000000/16/BAUD_RATE-10)}; //константа для записи в регистр UBRR умноженная на 10
enum{A=((CUR_UBRR_10x-5)/10),B=(CUR_UBRR_10x/10),C=B-A}; //(НАЧАЛО)округление константы для записи в регистр UBRR
#if C==0x00
#define CUR_UBRR (A+1)
#else
#define CUR_UBRR B
#endif                                                   //(КОНЕЦ) округление константы для записи в регистр UABRR
...                                                      // значение UBRR находится в CUR_UBRR
UBRR=CUR_UBRR;


В аттаче добавил расчет UBRR в Excel.
Вложения
Расчет UBRR.xls
Расчет UBRR в Excel
(25 КБ) 244 скачивания
Ставим плюсы: )
Аватара пользователя
avreal
Опытный кот
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна
Контактная информация:

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

Сообщение avreal »

asteroid7 писал(а):Для GCC avreal класс критических секций привёл выше, а я приведу для IAR-a не подключая никаких хиадеров.
Собственно, я привёл класс критической секции из AVR/GCC порта операционной системы scmRTOS, написанной на С++.
Ваш пример можно сделать "несколько С++-нее", сделав сохранение состояния прерываний не присваиванием, а инициализацией.

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

MUTEX () :  __state( __save_interrupt() )
        {
            __disable_interrupt();
        }
Тогда он станет ещё более похожим на соответствующий класс AVR/IAR порта scmRTOS.

scmRTOS wiki http://scmrtos.sourceforge.net/ScmRTOS
Немного о ней у меня на сайте http://real.kiev.ua/scmRTOS — ссылки и подробное объяснение одного из примеров.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Аватара пользователя
avreal
Опытный кот
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна
Контактная информация:

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

Сообщение avreal »

asteroid7 писал(а):Не увидел в этом коде ошибки... Не затруднит Вас разъяснить этот момент.
Единственное, что бросается в глаза, это логическое "==" без скобок. Так это допускается стандартом.
А её и компилятор не видит :-)
Я ж говорю, он не догадывается ни о чём.
Тут может быть логическая ошибка, в точности та же, что и в Вашем примере про 8-битный контроллер и 16-битные данные.
Если переменные a и b меняются в прерывании вместе и должны обрабатываться согласованно (я привёл сравнение просто в качестве примера примитивной обработки), то их надо читать обязательно в общей критической секции в две временные переменные и только потом обрабатывать. Но компилятор об этом не знает, поэтому и не предупреждает. В отличие от прямого сравнения a == b, где он ворчит о возможной зависимости от порядка чтения.

Кстати, не всегда даже 16-битную переменную (имеются ввиду 8-битники, конечно), изменяемую в прерывании, обязательно читать в крит. секции. Пусть у нас есть таймаут, декрементируемый в прерывании до 0.

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

volatile uint16_t timeout;

some_ISR()
{
    if( timeout ) --timeout;
}

bool is_timeout_expired()
{
    return HIGH_BYTE( timeout ) == 0 && LOW_BYTE( timeout ) == 0;
}
Тут немного условно показано. И ISR без привязки к компилятору, и не показано само чтение. Можно timeout сделать объединением { uint16_t u; uint8_t b[2]; } и в макросах читать из байтовой части, можно в макросах обращаться по приведённому к (volatile uint8_t *) указателю со смещениями, не важно.
Важно то, что прерывание только декрементирует переменную и 0 уже не трогает.
СС++ для встроенного оператора &&) гарантирует, что вычисление операндов идёт слева направо с прекращением вычислений, когда результат уже ясен. Поэтому чтение сначала старшей части безопасно.
Старшая часть если уже стала 0, то при анализе младшей уже не поменяется.
А если ещё не 0, то младшая и не зачитывается.
Если за время сравнения с 0 старшей части младшая меняется — ну и ладно. Если к тому времени сама станет нулём — тем лучше, раньше узнаем об окончании таймаута :-)
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Аватара пользователя
avreal
Опытный кот
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна
Контактная информация:

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

Сообщение avreal »

ibiza11 писал(а):А как Вы проверяете константы, расчет которых возлагаете на препроцессор?
P.S. может кому пригодится расчет значения регистра UBRR с округлением к ближайшему значению (для 16ти семплового приема):
Я не смотрю глазами на сами константы. Если мне нужно проверить отклонение, то тогда из CURR_UBRR назад рассчитывается REAL_BAUD, потом

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

#define BAUD_THOUSANDTH   15 /* Отклонение 15 тысячных, 1.5% */
#define BAUD_LIMIT (BAUD_RATE * BAUD_THOUSANDTH / 1000)
#if (REAL_BAUD - BAUD_RATE) > BAUD_LIMIT || (REAL_BAUD - BAUD_RATE) < -BAUD_LIMIT
#error "Baudrate is out of range"
#endif
А округлять проще так:

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

#define DIV_ROUND(dividend, divider) ( (dividend + divider/2) / divider )
#define CUR_UBRR  DIV_ROUND( CPU_F_MHz*1000000/16, BAUD_RATE)
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
stas00n
Вымогатель припоя
Сообщения: 557
Зарегистрирован: Пн мар 23, 2009 04:03:45

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

Сообщение stas00n »

ibiza11 писал(а):
P.S. может кому пригодится расчет значения регистра UBRR с округлением к ближайшему значению (для 16ти семплового приема):


У меня адаптивная настройка "аналога" UBRR (в пиках он обзывается SPBRG) реализована так:

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

#define BAUDRATE            19200U
unsigned int      oscMeasuredValue = 31250;   //fosc = 128 * oscMeasuredValue; 31250*128=4000000
//....
unsigned int Get_Osc_Freq (void);
//....
oscMeasuredValue = Get_Osc_Freq();   //Измерение частоты
SPBRG   = ((oscMeasuredValue + (BAUDRATE/16)) / (BAUDRATE/8) - 1);

Сперва в программе измеряется тактовая частота внутреннего RC-генератора (в попугаях, дабы уложиться в двухбайтовую переменную), потом вычисляется нужное значение регистра c округлением.
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

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

Сообщение ibiza11 »

Спасибо за формулу округления:) что-то я совсем по сложному пути пошел)))) Вроде в школьном курсе алгебры была подобная формула? 8)
Ставим плюсы: )
Аватара пользователя
asteroid7
Опытный кот
Сообщения: 703
Зарегистрирован: Вс янв 18, 2009 21:12:49

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

Сообщение asteroid7 »

ibiza11 писал(а):Видимо остальным было влом отвечать.
На этом форуме единицы, кто использует IAR. Но, последние полгода интерес к нему увеличился )

ibiza11 писал(а):А как Вы проверяете константы, расчет которых возлагаете на препроцессор?
Например, проверка переполнения регистра OCR (8 бит) в качестве генерации меандра для разной частоты. Приведу утрированно, но смысл думаю будет понятен.

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

#define VAL_OCR( del, freq_hz ) ( ( QUARZ_FREQUENCY / ( del * freq_hz ) >> 1 ) - 1 )

//меандр для 1000 Hz
#define VAL_OCR_1000    VAL_OCR( 128ul, 1000ul )
//меандр для 2000 Hz
#define VAL_OCR_2000    VAL_OCR( 1ul, 2000ul )

#if VAL_OCR_1000 > 255
#error "1000 Hz - не влазит в байт. Нужно увеличить делитель"
#endif

#if VAL_OCR_2000 > 255
#error "2000 Hz - не влазит в байт. Нужно увеличить делитель"
#endif
Аватара пользователя
asteroid7
Опытный кот
Сообщения: 703
Зарегистрирован: Вс янв 18, 2009 21:12:49

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

Сообщение asteroid7 »

avreal писал(а):Ваш пример можно сделать "несколько С++-нее", сделав сохранение состояния прерываний не присваиванием, а инициализацией.
Согласен, Ваш вариант красивее.
Не то чтобы не доверяю, но навсякий случай перепроверил генерируемый код. Один в один.

avreal писал(а):А её и компилятор не видит Я ж говорю, он не догадывается ни о чём.Тут может быть логическая ошибка, в точности та же, что и в Вашем примере про 8-битный контроллер и 16-битные данные.Если переменные a и b меняются в прерывании вместе...
Так я и думал - затупил. Не проанализировал при обоюдном изменении. )
Аватара пользователя
O-LED
Мудрый кот
Сообщения: 1800
Зарегистрирован: Вт окт 05, 2010 01:08:57
Контактная информация:

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

Сообщение O-LED »

Знаю что элементарно, и даже как то делал раньше, но забыл как. :roll: Мне нужно 4 младших бита переменной типа unsigned int занести в 11,12,13,14 бит другой переменной типа unsigned long int (естественно не меняя остальных). Подскажите как.
KIT
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

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

Сообщение ibiza11 »

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

unsigned int a,b,c;
...
c=a&(0x000F); //копируем 4 младших бита из числа а, остальные обнуляем
c=(c<<11);//сдвигаем их до 14-11 битов
b=b&~(0x7800);//сбрасываем 14-11 биты в числе b (здесь ошибка была, забыл проинвертировать, сейчас поправил)
b=b|c;//копируем биты из числа с в число b
Последний раз редактировалось ibiza11 Пн янв 17, 2011 01:00:15, всего редактировалось 2 раза.
Ставим плюсы: )
Аватара пользователя
O-LED
Мудрый кот
Сообщения: 1800
Зарегистрирован: Вт окт 05, 2010 01:08:57
Контактная информация:

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

Сообщение O-LED »

ibiza11 Спасибо.
Точно, меня же интересуют 11-14 биты, а они входят в int переменную, значит можно просто с помощью двоичного ИЛИ сложит int и long int (предварительно сдвинув int) и получить желаемое.
KIT
dm211
Прорезались зубы
Сообщения: 208
Зарегистрирован: Вс дек 10, 2006 19:26:13

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

Сообщение dm211 »

Есть массив символов

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

unsigned char mass[]={"123456789"};
,как перекинуть символы на другой массив, чтобы было так-

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

unsigned char mass[]={"987654321"};
?
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

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

Сообщение ibiza11 »

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

unsigned char a[9]={1,2,3,4,5,6,7,8,9};
unsigned char b[9];
unsigned char i=0;
unsigned char j=8;
...
while (i<9)
{
   b[j]=a[i];
   i++;
   j--;
}
Ставим плюсы: )
dm211
Прорезались зубы
Сообщения: 208
Зарегистрирован: Вс дек 10, 2006 19:26:13

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

Сообщение dm211 »

ibiza11 , спасибо, проверил-работает.
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

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

Сообщение Gudd-Head »

dm211 писал(а):проверил-работает.

Гы, ещё бы оно не работало :)))
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Аватара пользователя
Кислый
Поставщик валерьянки для Кота
Сообщения: 2095
Зарегистрирован: Чт апр 08, 2010 18:50:01
Откуда: Краснодар
Контактная информация:

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

Сообщение Кислый »

кхе кхе.. может кто поделится кодом работы с LPT ( линухоподобный ) ?
в сети нашел только странный пример

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

#include <stdio.h>
#include <pthread.h>
#include <fcntl.h>

int main(int argc,char* argv[])
{
int val,port;
int fd;

if(argc<3){fprintf(stderr,"usage: %s port value\n",argv[0]); exit(1);}
if(sscanf(argv[1],"0x%x",&port) && sscanf(argv[2],"0x%x",&val))
{
fd=open("/dev/io",O_RDWR);
if(fd==-1){perror("open");exit(1);}
outb(port,val);
close(fd);
}
else
{fprintf(stderr,"port and value must be in hex format with 0x prefix\n"); exit(1);}

}


ругается на outb.

я опять затеял переписывать программу с паскаля )) я бы и так ею пользовался, но она не работает в wine
RETI ;рети-рети интеррапт, через шины данных тракт, через память, через порт, возвращайся в главный код
@hobbyelectronics
Ответить

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