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

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

Сообщение WiseLord »

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

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

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

Сообщение 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 КБ) 217 скачиваний
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение 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. Т.е. работает код абсолютно одинаково в обоих случаях, как и ожидалось (то что разные значения - не важно, так как код разный, и в памяти всё это может в обоих случаях храниться по разным адресам).
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

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

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

Сообщение ARV »

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

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

Сообщение shads »

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

Сообщение 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";
Контактная информация:
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

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

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

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

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

Сообщение WiseLord »

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

Сообщение ARV »

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

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

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

Сообщение shads »

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

Сообщение 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
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18682
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

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

Сообщение GARMIN »

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

Сообщение pokk »

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

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

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

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

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

Сообщение ua1arn »

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

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

Сообщение WiseLord »

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

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

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

Сообщение greenled »

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

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

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

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