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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

В своей теме я описывал, как поставить WinAVR посвежее и подключить к своему проекту, и даже снял видео в том числе про QtCreator.

Беглый взгляд на Ваш скриншот показывает, что линкер подключает в результирующий файл некий объектник gps_data_to_UART.o, который вообще-то в коде нигде не используется. Подозреваю, что у него большой размер, отсюда и результат. Вероятно, есть ещё какой-то файл gps_data_to_UART.c, который компилируется и линкуется в проект, хотя не используется.

P.S. Во вложении созданный мною шаблон для QtCreator для быстрого старта проекта.
Вложения
templates.7z
(4.73 КБ) 141 скачивание
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

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

Сообщение shads »

Попробую поставить чуть позже...

У меня еще один затык... (помоему AVRST+GCC сходит от меня сума... или я от него :shock: )
Пробую сделать массив структур. Каждая структура состоит из указателя на текст и нескольких параметров...
Типа такого:

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

PROGMEM uint8_t Txt1[] = {"text1"};   
PROGMEM uint8_t Txt2[] = {"TEXT2"};

PROGMEM struct{
   uint8_t *pTxt, UpLim, DnLim;
}Menu [] = {
   {Txt1,    1,2},
   {Txt2,   3,4}
};


Если получаю указатель так или так:

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

Menu[0].pTxt
Menu[1].pTxt
то все нормально, получаю указатель на соответствующее текстовое поле...


а если делаю так:
в глобальных переменных назначаю номер текущей структуры (или передаю в функцию параметром, не важно)

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

uint8_t shift = 0;
то чтение указателя на поле

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

Menu[shift ].pTxt
дает не предсказуемый результат.....



Вот пример в проте.
Если перед чтением указателя из структуры, еще раз присвоить значение смещению, то получаем в результате правильный адрес - 0х002C...
Если перед чтением закомментировать присваивание, (хотя оно выполнено глобально) получаем в результате 0x0000....
txt_struct.7z
(25.01 КБ) 216 скачиваний
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

Проверил код, немного исправил объявления структур, т.к. у меня не компилировалось (я всегда включаю директивы -Wall и -Werror у компилятора, чтобы все предупреждения компилятора обрабатывались как ошибки - это помогает поддерживать код более чистым):
Спойлер

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

#define F_CPU       8000000
#define UART_BAUD    9600
#include <avr/pgmspace.h>
#include <avr/io.h>

//----------
//тексты и структура
PROGMEM const uint8_t Txt1[] = {"text1"};
PROGMEM const uint8_t Txt2[] = {"TEXT2"};

PROGMEM const struct{
   const uint8_t *pTxt;
   uint8_t UpLim, DnLim;
}Menu[] = {
   {Txt1,    1,2},
   {Txt2,   3,4}
};

//----------
//Глобальные переменные
uint8_t MenuNum = 1;

//----------
//Передача байта по UART
void UartTransmByte (uint8_t byte)
{
   while (! (UCSRA & (1<<UDRE))){}         // Wait for empty transmit buffer
   UDR = byte;                        // Put data into buffer, sends the data
}

//передача int значения по UART
void UartTransmInt (uint16_t word)
{
   uint8_t temp;
   UartTransmByte ('0');
   UartTransmByte ('x');
   temp = (word>>12) & 0x0f;
   if (temp < 10)      UartTransmByte (temp + 0x30);
   else            UartTransmByte (temp + 0x37);
   temp = (word>>8) & 0x0f;
   if (temp < 10)      UartTransmByte (temp + 0x30);
   else            UartTransmByte (temp + 0x37);
   temp = (word>>4) & 0x0f;
   if (temp < 10)      UartTransmByte (temp + 0x30);
   else            UartTransmByte (temp + 0x37);
   temp = word & 0x0f;
   if (temp < 10)      UartTransmByte (temp + 0x30);
   else            UartTransmByte (temp + 0x37);
   UartTransmByte (',');
}

//----------
int main (void)
{
   //Настройка UART
   uint16_t BaudRateTemp = (F_CPU / UART_BAUD / 16 - 1);//скорость работы UART
   UBRRH = (BaudRateTemp>>8);            
   UBRRL =  BaudRateTemp;
   UCSRC = (1<<URSEL)|(1<<USBS)|         //2 стоп бита
         (1<<UCSZ1)|(1<<UCSZ0);         //формат посылки - 8 бит
   UCSRB = (0<<RXEN)|(1<<TXEN);         //разрешена передача

   MenuNum = 1;
   UartTransmInt ((uint16_t)Menu[MenuNum].pTxt);

   while (1){}
}
 
//----------

В терминал в Proteus выводится 0x002E, а если закомментировать строку MenuNum = 1 перед передачей в UART - то 0x002E. Т.е. работает код абсолютно одинаково в обоих случаях, как и ожидалось (то что разные значения - не важно, так как код разный, и в памяти всё это может в обоих случаях храниться по разным адресам).
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

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

Сообщение shads »

Выходит - компилятор (AVRStudio4.19 + toolchain) глючит!?...
Я даже в студии6 проверял, та же петрушка.....

Кстати у меня даже предупреждений никаких не было, все чисто...
Попробовал объявить структуру как вы - результат тот же...
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

прежде чем обвинять компилято, вы бы изучили как следует язык Си. что это за объявление строк с фигурными скобками?! вы учитываете, что строки у вас в PROGMEM, а в структуре указатель на гште8_е в ОЗУ? принципиально тут проблемы нет, но она может появиться в месте, где вы к этому указателю обращаетесь. ну и еще ряд замечаний - перечислять лень.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

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

Сообщение shads »

ARV писал(а):прежде чем обвинять компилято
Кстати, до сих пор я так и не встречал неадекватного поведения со стороны компилятора, все трудности решались открытием для себя определенных правил, соглашений си, анси и т.д..... так что самому не охота кого бы то ни было обвинять... тем более такого уважаемого оппонента как компилятор...
Но я для того и текст примера показал, чтобы мне указали на мой "очередной" косяк... Пока что правка объявлений в структуре и убирание фигурных скобок не помогли... Надеюсь на дальнейшие рекомендации :)....

ARV писал(а):вы бы изучили как следует язык Си. что это за объявление строк с фигурными скобками?!
и еще ряд замечаний - перечислять лень.
Вы бы лучше поднапряглись, да все таки посоветовали что то дельное... ато про фигурные скобки - как то не серьезно :)...

ARV писал(а):вы учитываете, что строки у вас в PROGMEM, а в структуре указатель на гште8_е в ОЗУ? принципиально тут проблемы нет, но она может появиться в месте, где вы к этому указателю обращаетесь.
А как по другому решить размещение массива структур в PROGMEM?
Вообще я думаю что указатель он и в африке указатель... не важно, с PROGMEM он записан, или без... думаю упоминание PROGMEM нужно только для того, чтобы компилятор мог контролировать правильность памяти, с которой будет работать указатель... Т.е. если указатель PROGMEM, а мы его используем чтобы работать с RAM, вот тут то и выскажется компилятор.....
Так что размещая в массиве указатель, который был объявлен с PROGMEM, компилятор об этом помнит, и дальше будет контролировать правильность используемой памяти...
В общем как ты и сказал -
принципиально тут проблемы нет
тем более у WiseLord работает... Наверное он свой компиль чем то прикармливает :)..... Вот только не хочет сказать... чем.....
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

Про хранение данных написано в мануале к avr-libc.

В любом случае, данные в такую структуру могут быть помещены только один раз, при компиляции программы и меняться они при её выполнении не могут. Отсюда и требования к объявлению таких данных как const.
UartTransmInt ((uint16_t)Menu[MenuNum].pTxt);
Здесь фактически аргумент функции UartTransmInt - это некий адрес в ОЗУ, а вовсе не значение, которое лежит в структуре в поле pTxt. В принципе, это передаваемое число может быть любым. Чтобы добраться до адреса, хранимого в flash-памяти, надо выполнить что-то вроде
UartTransmInt (pgm_read_word(&Menu[MenuNum].pTxt));


P.S. А строки, хранимые во Flash-памяти, объявлять надо как-то так:

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

static const uint8_t labelSTBY[]   PROGMEM = "Standby";
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

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

Сообщение shads »

WiseLord писал(а):Чтобы добраться до адреса, хранимого в flash-памяти, надо выполнить что-то вроде
UartTransmInt (pgm_read_word(&Menu[MenuNum].pTxt));
ВОТ!!! конечно же... как это я так протупил...

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

В общем извиняюсь за очередной балаган, который я тут развел :).....

(Хотя вопрос остался открытым, почему возвращаемый результат у меня в разных случаях был разный, хотя индекс по идее был всегда одинаковым (просто я его передавал разными способами))
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

Наверное, потому что при комментировании кода его размер уменьшался - это становился уже другой код - оптимизатор мог его сделать ещё более различным - функции располагались уже по другим адресам, и выводиться могло уже что-то другое.
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

shads писал(а):В общем извиняюсь за очередной балаган, который я тут развел :).....

балаган начинается с "фигурных скобочек", где не надо, а заканчивается тем, что
shads писал(а):указатель он и в африке указатель... не важно, с PROGMEM он записан, или без...
после чего начинаются чудеса.

поэтому я поднапрягаюсь и советую вам тщательно изучить Си, чтобы делать не тяп-ляп, а по правилам и с полным пониманием того, что делаешь. собственно, 90% моих советов только в этом и заключаются
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
shads
Опытный кот
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

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

Сообщение shads »

ARV писал(а):cоветую вам тщательно изучить Си, чтобы делать не тяп-ляп, а по правилам и с полным пониманием того, что делаешь. собственно, 90% моих советов только в этом и заключаются
Спасибо!!!
Именно этим сейчас и занимаюсь...
Я в принципе сразу сознался в своих грехах: viewtopic.php?p=2169843#p2169843
Но уже кой чего просветлело в голове :).... Так глядишь и C++ штурмовать начну :).....
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

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

Сообщение pokk »

Здравствуйте, подскажите как разместить в структуре строки разного размера. Компилятор CodeVisionAvr
есть такая структура меню

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

typedef  struct PROGMEM{
    void       *Next;
    void       *Previous;
    void       *Parent;
    void       *Child;
    unsigned char     OK;
    unsigned char     ESC;   
    unsigned char     ACTION_NEXT;
    unsigned char     ACTION_DOWN;      
    unsigned char  Text[41];
}  menuItem;

Сделал пару пунктов меню по смотрел подумал что избыточно выделять на текстовую часть 40 байт
Захотел сделать такое что бы при инициализации выделялось место ровно по текстовой части т.е при таком варианте:

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

menuItem        Null_Menu = {(void*)0, (void*)0, (void*)0, (void*)0,0,0,0,0, ""};  

выделилось в озу 8-9 байт на указатели а в текстовой части нечего не было (следующая переменная )

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

menuItem        Null_Menu2 = {(void*)0, (void*)0, (void*)0, (void*)0,0,0,0,0, "1234567"};  

а при таком варианте выделилось 8 байт на указатели и ещё массив со строкой "1234567"
Думал что вот такое изменение unsigned char Text[]; приведёт меня к желаемому результату но нет
после первой инициализации Null_Menu он создаёт массив нулевой размерностью и на все остальные строчки компилятор начинает ругаться "Error: ... included from: shaper.c: too many initializers"
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

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

Сообщение ARV »

попробуйте использовать указатель на строку char *Text;
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Аватара пользователя
GARMIN
Держит паяльник хвостом
Сообщения: 952
Зарегистрирован: Вс дек 02, 2012 16:58:33
Откуда: от туда
Контактная информация:

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

Сообщение GARMIN »

делай в структуре ссылку на текстовую строку, а строки объявляй отдельно.
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

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

Сообщение pokk »

Благодарю за помощь. С указателем на строку получилось.
Аватара пользователя
6Н23П
Открыл глаза
Сообщения: 72
Зарегистрирован: Вт июл 05, 2011 06:04:17
Откуда: барнаул

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

Сообщение 6Н23П »

здраствуйте
что означает конструкция

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

ADDRESS | 1
, где ADDRESS это допустим адрес микрухи.
например ADDRESS = 0b00000010, то получается что
0b00000010
0b00000001
__________
0b00000011 ?
Аватара пользователя
ua1arn
Встал на лапы
Сообщения: 81
Зарегистрирован: Вт май 08, 2012 23:15:45
Откуда: Санкт - Петербург

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

Сообщение ua1arn »

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

0b00000011 ?

Да.
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

Будь там ADDRESS |= 1 - это бы означало установку 0-го бита ADDRESS в 1.

А так - это всего лишь незавершённое логическое выражение, в результате которого получится некий промежуточный результат - число, равное ADDRESS с точностью до последнего бита, который будет равен 1. А что дальше с этим числом делается - мы не знаем.

Ну, как если бы спросить, что означает ADDRESS + 1.
Аватара пользователя
greenled
Родился
Сообщения: 6
Зарегистрирован: Чт май 17, 2012 12:49:55
Откуда: from nowhere

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

Сообщение greenled »

Доброго всем дня! Пишу тут прогу для МК с архитектурой 8051 на Си в Keil, увы, уровень владения языком невысок, но интересует такой вопрос: как ассоциировать с переменной какую-либо ячейку памяти данных? Делать ассемблерную вставку или можно как-то стандартными средствами кейловского си обойтись?
Аватара пользователя
Gudd-Head
Друг Кота
Сообщения: 20092
Зарегистрирован: Чт сен 18, 2008 12:27:21
Откуда: Столица Мира Санкт-Петербург

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

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

Аааа... зачем?
[ Всё дело не столько в вашей глупости, сколько в моей гениальности ] [ Правильно заданный вопрос содержит в себе половину ответа ]
Ответить

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