реклама на сайте
подробности

 
 
> Ламерские вопросы по Си, перехожу с асма
Alt.F4
сообщение May 19 2012, 06:34
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



Добрый день.
Копаю интернет, но все как-то безуспешно.
Хочу написать функцию передачи строки по UART, работающую по прерыванию. Причем строка может быть как константа (храниться во флэш), так и переменная (храниться в СОЗУ).
Код
#define size_TX0     10
volatile static int8_t    count_TX0;//кол-во непереданных символов в буфере UART0
volatile static int8_t    index_TX0;//адресация в буфере передачи UART0
volatile static int8_t     bufferTX0[size_TX0];//массив - буфер передачи UART0
/*==============================*/
void send_UART0(char *string)
{
int8_t    i;
for(i=0;*string!='\0';i++)
    {
        bufferTX0[i]=(*string);    //сохраняем строку в буфер
        string++;
        count_TX0++;                //считаем символы
    }
index_TX0=0;                        //обнуляем адресацию в буфере
sbi(UCSR0B,UDRIE0);                    //запускаем прерывание
}
/*==============================*/
ISR(USART0_UDRE_vect)
{
    UDR0 = bufferTX0[index_TX0++];                // Берем данные из буффера.
    if(index_TX0==count_TX0)  cbi(UCSR0B,UDRIE0);    // Если все передали, то выкл.прерывание
}
/*==============================*/

Пишу send_UART0("12345");, но эти 12345 сохраняются в СОЗУ.
Вопрос: как передать в функцию строку, чтобы она сохранилась во флэш?
Спасибо.

Сообщение отредактировал Alt.F4 - May 19 2012, 06:36
Go to the top of the page
 
+Quote Post
3 страниц V   1 2 3 >  
Start new topic
Ответов (1 - 42)
Dog Pawlowa
сообщение May 19 2012, 07:19
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Если нужно флэш, то как-то так:
__flash char my_string[]="12345";
send_UART0(my_string);

Волшебное слово __flash зависит от компилятора.

Но с универсальной функцией придется еще пободаться.
Разберитесь с типом передаваемого указателя.


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
ReAl
сообщение May 19 2012, 07:54
Сообщение #3


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Хм... Я не силён в терминологии разряда «цветовой дифференциации штанов», но в моём понимании «ламер» означает человека, который не просто не знает чего-то (все чего-то не знают *) ), а и не желает разобраться и при этом ещё пробует учить других. «ламерский вопрос» при этом редкость и обычно сам он своим уровнем хорошо показывает, что в предыдущих своих сообщениях человек с умным видом рассуждал о том, чего совершенно не знает.
«нуб», в отличие от «ламера», хочет что-от узнать.
Один и тот же вопрос может быть «ламерским» или «чайниковским» в зависимости от того, кто его задал (от предистории).
Ну да не важно.


Судя по тому, что соседний вопрос был по AVR Studio, используется avr-gcc.
У него до версии 4.7 не поддерживаются разные пространства памяти и соответствующие модификаторы указателей (да и в 4.7, если я правильно понял, это есть в C frontend, но нет в C++).
Так что нужно использовать атрибут размещения из avr/pgmspace.h
Универсальную функцию написать можно, сначала придумав, как передавать признак ОЗУ/флеш.
Две специальных написать проще и результат не хуже. И это будет выглядеть как-то так:
CODE
#include <avr/pgmspace.h>

#define size_TX0 10

// беззнаковые счётчики и индексы дают код короче и быстрее
volatile static unt8_t count_TX0; //кол-во непереданных символов в буфере UART0
volatile static unt8_t index_TX0; //адресация в буфере передачи UART0
// char так char, какая нам разница, какой размер и знак у символов
volatile static char bufferTX0[size_TX0];//массив - буфер передачи UART0
...

void wait_UART0()
{
while (UCSR0B & (1<<UDRIE0)) {}
}

void start_UART0()
{
index_TX0 = 0;
UCSR0B |= (1<<UDRIE0);
}

// Строка из ОЗУ
void send_UART0(char *string)
{
char *dst = buffer_TX0;
char ch;

wait_UART0(); // надо ведь дождаться, пока уйдёт предыдущая строка

count_TX0 = 0;

// бесконечный цикл, тут прямо в условие действия затолкать для новичка возможно слишком уж нечитаемо выйдет
for (;;) {
ch = *string++;
// если достигнут конец строки или уже нет местя в буфере — выходим
if (ch == '\0' || ++count_TX0 >= size_TX0) break;
*dst++ = ch;
}

start_UART0();
}

...
// Строка из флеша.
// Увы, нормальной поддержки указатеелй во флеше нет, поэтому проще не обманывать себя
void send_UART0_P(unsigned string_address)
{
char *dst = buffer_TX0;
char ch;

wait_UART0();

count_TX0 = 0;

for (;;) {
ch = pgm_read_byte(string_address);
++string_address;
if ( ch == '\0' || ++count_TX0 >= size_TX0) break;
*dst++ = ch;
}

start_UART0();
}

...
send_UART0_P( PSTR("Temperature: ") ); // эта строка не попадёт в ОЗУ
char tmpbuf[size_TX0];
// к примеру, преобразовали в буфер число
send_UART0( tmpbuf );
send_UART0_P( PSTR("\r\n") ); // эта строка не попадёт в ОЗУ


____________
*) Не знать — не стыдно. Стыдно не хотеть узнать.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение May 19 2012, 20:32
Сообщение #4


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(Dog Pawlowa @ May 19 2012, 10:19) *
Но с универсальной функцией придется еще пободаться.

да, можно её и так боднуть:-)
http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gc...r-Builtins.html

Цитата(ReAl @ May 19 2012, 10:54) *
Универсальную функцию написать можно, сначала придумав, как передавать признак ОЗУ/флеш.
А зачем передавать, можно на ходу макрос разворачивать и определять PGM_P она или нет.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Alt.F4
сообщение May 20 2012, 11:17
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



Цитата
Две специальных написать проще и результат не хуже. И это будет выглядеть как-то так: ...
Спасибо большое!!! cheers.gif
У себя реализовал так:
Код
void  start_UART0_TX()
{
    index_TX0 = 0;            //обнуляем адресацию в буфере передачи
    sbi(UCSR0B,UDRIE0);        //запускаем прерывание
}
/*--------------------------*/
void send_UART0(char *string)
{
    u08    i;
    count_TX0 = 0;
    for(i=0;*string!='\0' && count_TX0<size_TX0;i++)
        {
            bufferTX0[i]=(*string++);    //сохраняем строку в буфер
            count_TX0++;                //считаем символы
        }
    start_UART0_TX();                    //запускаем прерывание
}

void send_UART0_P(const char *string)
{
    u08    i;
    count_TX0 = 0;
    for(i=0;pgm_read_byte(string)!='\0' && count_TX0<size_TX0;i++)
        {
            bufferTX0[i]=pgm_read_byte(string++);    //сохраняем строку в буфер
            count_TX0++;                            //считаем символы
        }
    start_UART0_TX();                                //запускаем прерывание
}
/*--------------------------*/
ISR(USART0_UDRE_vect)
{
    UDR0 = bufferTX0[index_TX0++];                    // Берем данные из буффера.
    if(index_TX0>=count_TX0)  cbi(UCSR0B,UDRIE0);    // Если все передали, то выкл.прерывание
}


Сообщение отредактировал Alt.F4 - May 20 2012, 11:21
Go to the top of the page
 
+Quote Post
defunct
сообщение May 21 2012, 00:33
Сообщение #6


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Строки наверное удобней выводить printf'ом. format str размещать во флеш, а %s - для вывода строк формируемых в run-time в ОЗУ...
WinAVR поддерживает макросы с переменным числом аргументов

Код
#define pgm_printf(x, ...) do {\
    static const char PROGMEM pgm_str[] = x;\
    char pgm_data_buf[sizeof(pgm_str)];\
    __pgm_strcpy( pgm_data_buf, pgm_str);\
    printf( pgm_data_buf, __VA_ARGS__);\
} while(0)

void __pgm_strcpy(char *dst, const char PROGMEM *str)
{
    do
    {
        *dst++ = *str;
    } while (*str++);
}


примеры использования:

pgm_printf("strlen(%s) = %u\n", "hello", strlen("hello"));
pgm_printf("x = %d\n", 123);
pgm_printf("addr_0x%x\n", 0x1000);
Go to the top of the page
 
+Quote Post
Alt.F4
сообщение May 23 2012, 03:11
Сообщение #7


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



Возник новый вопрос. Прочел, что хорошим тоном является при написании макросов, в том числе многострочных, заключать их в do{...}while(0)
Но вот беда, когда я заключаю в этот цикл while следующий макрос, он компилируется хрен знает каким образом.
Исходный вариант:
Код
#define check_temp(X)\
if(temp==X) {index_RX0++;break;}\
goto start_RX0;
В цикле while:
Код
#define check_temp(X)\
do{\
if(temp==X) {index_RX0++;break;}\
goto start_RX0;\
}while(0)
Макрос вставляю в case инструкции switch. В дизасемблере второй макрос выполняет два раза index_RX0+, затем джамп и перед ret обнуляет index_RX0!!!
Если do{...}while(0) убрать, то все работает как надо.
Что это может быть?
Спасибо.

Сообщение отредактировал Alt.F4 - May 23 2012, 03:12
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение May 23 2012, 05:48
Сообщение #8


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Alt.F4 @ May 23 2012, 06:11) *
Что это может быть?
Во втором случае break выходит из do{}while(), а не из case().

P.S. на будущее - заключайте X внутри макроса в скобки. В месте вызова он может оказаться не переменной, а выражением.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Alt.F4
сообщение May 23 2012, 06:15
Сообщение #9


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



Сергей Борщ, спасибо большое!!!
Go to the top of the page
 
+Quote Post
ReAl
сообщение May 23 2012, 10:31
Сообщение #10


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(defunct @ May 21 2012, 03:33) *
Строки наверное удобней выводить printf'ом. format str размещать во флеш, а %s - для вывода строк формируемых в run-time в ОЗУ...
WinAVR поддерживает макросы с переменным числом аргументов
А строки из флеша (в частности, выбранные по индексу или полученные как поле структуры) — форматом %S


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Alt.F4
сообщение Jun 2 2012, 15:11
Сообщение #11


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



Имеем массив в EEPROM и указатель на него:
Код
EEMEM char array[10];
unsigned int *addr_EE;
addr_EE = array;   <-- здесь компилятор ругается на несовпадение типов.
EEAR = addr_EE;
Подскажите пожалуйста, как правильно объявить указатель?
Спасибо.

Сообщение отредактировал Alt.F4 - Jun 2 2012, 15:14
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jun 2 2012, 15:27
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Alt.F4 @ Jun 2 2012, 18:11) *
Имеем массив в EEPROM и указатель на него:
Код
EEMEM char array[10];
unsigned int *addr_EE;
addr_EE = array;   <-- здесь компилятор ругается на несовпадение типов.
EEAR = addr_EE;
Подскажите пожалуйста, как правильно объявить указатель?
Спасибо.


Думаю что так:
Код
EEMEM char array[10];
EEMEM char *addr_EE;



или так можно:

Код
unsigned int addr_EE;
addr_EE = (unsigned int)array;
EEAR = addr_EE;

Go to the top of the page
 
+Quote Post
mempfis_
сообщение Jun 2 2012, 15:32
Сообщение #13


Профессионал
*****

Группа: Свой
Сообщений: 1 001
Регистрация: 27-06-06
Пользователь №: 18 409



Цитата(Alt.F4 @ Jun 2 2012, 18:11) *
Имеем массив в EEPROM и указатель на него:
Код
EEMEM char array[10];
unsigned int *addr_EE;
addr_EE = array;   <-- здесь компилятор ругается на несовпадение типов.
EEAR = addr_EE;
Подскажите пожалуйста, как правильно объявить указатель?
Спасибо.


У Вас array объявлен как EEMEM char а указатель на тип данных int.
Указатель должен соответсвовать типу данных или приводится к нему.
в IAR прокатила бы такая такая запись

Код
__eeprom char array[10];
char __eeprom *addr_EE;
addr_EE = array;



Go to the top of the page
 
+Quote Post
Alt.F4
сообщение Jun 2 2012, 15:42
Сообщение #14


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



Цитата
или так можно:
Код
unsigned int addr_EE;
addr_EE = (unsigned int)array;
EEAR = addr_EE;
Разницы от исходника компилятор не заметил, т.е. типы не совпадают.

Цитата
Думаю что так:
Код
EEMEM char array[10];
EEMEM char *addr_EE;
Если делать так, то варнинг несовпадения типов выскакивает уже напротив: EEAR = addr_EE;

Цитата
Указатель должен соответсвовать типу данных или приводится к нему.
Каким образом привести тип указателя, чтобы его значение можно было записать в EEAR и в тоже время в этот указатель можно записать адрес массива?

Сообщение отредактировал Alt.F4 - Jun 2 2012, 15:48
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Jun 2 2012, 16:02
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Alt.F4 @ Jun 2 2012, 18:42) *
Если делать так, то варнинг несовпадения типов выскакивает уже напротив: EEAR = addr_EE;адрес массива?

Тогда так:
Код
EEAR = (unsigned short)addr_EE;


Go to the top of the page
 
+Quote Post
Alt.F4
сообщение Jun 2 2012, 16:06
Сообщение #16


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



Цитата
EEAR = (unsigned short)addr_EE;
Варнинг исчез! Спасибо большое!

Сообщение отредактировал Alt.F4 - Jun 2 2012, 16:14
Go to the top of the page
 
+Quote Post
Alt.F4
сообщение Jun 3 2012, 12:55
Сообщение #17


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



Delete.

Сообщение отредактировал Alt.F4 - Jun 3 2012, 12:58
Go to the top of the page
 
+Quote Post
Alt.F4
сообщение Aug 6 2012, 09:58
Сообщение #18


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



Здравствуйте.
Столкнулся с новой проблемой, проклятый "undefined reference to" уже заманал.
Как avr-gcc подключает и компилирует вставки #include "ffff.h" мне видимо не понять.

В файле qqq.c стоит вызов функции с передачей в нее нескольких параметров, эта функция описана в www.c, а ее объявление в www.h
В qqq.c добавляю инклуд www.h с этой объявленной функцией.
Что ему не нравиться?
Спасибо.
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Aug 6 2012, 10:01
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Изложите проблему менее абстрактно: что именно написано в www.c, www.h, qqq.c и какое сообщение выдает дословно?
Go to the top of the page
 
+Quote Post
Alt.F4
сообщение Aug 6 2012, 10:14
Сообщение #20


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



aaarrr, ё-мана, это оказывается в Source Files (AVR Studio 4) надо добавлять все файлы с расширением *.c, я думал компилятор все сам подключит.
Блин, полдня убил зря angry.gif
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Aug 6 2012, 11:19
Сообщение #21


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(Alt.F4 @ Aug 6 2012, 13:58) *
Как avr-gcc подключает и компилирует вставки #include "ffff.h" мне видимо не понять.

Так же, как и любой другой компилятор.
Тупо вставляет содержимое подключаемого файла туда, где вы укажете директивой #include


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Aug 6 2012, 12:33
Сообщение #22


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Alt.F4 @ Aug 6 2012, 13:14) *
ё-мана, это оказывается в Source Files (AVR Studio 4) надо добавлять все файлы с расширением *.c, я думал компилятор все сам подключит.

Ы, откуда он (компилятор) узнает, что именно ему надо компилировать? Как раз-таки из содержимого файла проекта. Чистологика и никакого обману sm.gif
Есть люди, которые любят написать makefile типа раз и навсегда, в т.ч. предусмотреть, чтобы компилилось всё, что находится в папке проекта *.S, *.c, *.cpp
Лично мне такое не нравится, но их тоже понять можно: а нефиг посторонним исходникам делать в проекте! Так что выбирайте себе концепцию по душе.

Сообщение отредактировал _Pasha - Aug 6 2012, 12:35
Go to the top of the page
 
+Quote Post
maksimp
сообщение Aug 6 2012, 18:45
Сообщение #23


Местный
***

Группа: Участник
Сообщений: 313
Регистрация: 2-07-11
Пользователь №: 66 023



Цитата(_Pasha @ Aug 6 2012, 16:33) *
но их тоже понять можно: а нефиг посторонним исходникам делать в проекте!

Чтобы ограничить потери случайно испортив файл, часто делаю его копии в ту же папку. В проводнике "Копировать" и сразу "Вставить". В папке есть "www.c", "Копия www.c", "Копия (2) www.c" и т.д.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Aug 6 2012, 19:00
Сообщение #24


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (maksimp @ Aug 6 2012, 21:45) *
В проводнике "Копировать" и сразу "Вставить". В папке есть "www.c", "Копия www.c", "Копия (2) www.c" и т.д.
В Far-подобном файловом менеджере Shift-F6, End, _ Файл получает расширение .cpp_, все проблемы исключаются. Зато не нужно вручную прописывать в makefile каждый новый файл исходника - его достаточно просто создать. И Эклипса не путается при индексировании исходников.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
dxp
сообщение Aug 7 2012, 03:32
Сообщение #25


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



QUOTE (Сергей Борщ @ Aug 7 2012, 02:00) *
В Far-подобном файловом менеджере Shift-F6, End, _ Файл получает расширение .cpp_, все проблемы исключаются. Зато не нужно вручную прописывать в makefile каждый новый файл исходника - его достаточно просто создать.

+1!


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
AHTOXA
сообщение Aug 7 2012, 03:43
Сообщение #26


фанат дивана
******

Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684



Цитата(Сергей Борщ @ Aug 7 2012, 01:00) *
В Far-подобном файловом менеджере Shift-F6, End, _

Если копировать, то Shift+F5. Хотя зачем копировать, когда есть svn - не очень понятно.
А я для временного исключения файла из проекта делаю папку unused и перемещаю файл туда (эклипсе говорю, чтоб не трогала эту папку).


--------------------
Если бы я знал, что такое электричество...
Go to the top of the page
 
+Quote Post
Alt.F4
сообщение Oct 4 2012, 07:03
Сообщение #27


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



Подскажите, пожалуйста, как описать массив структур FontTable, все время ругается на несовместимость типа указателя?
Спасибо.
Код
typedef struct
{
    uint8_t      code;                 // код символа ASCII
    uint8_t *    index;                // указатель на массив символа
    uint8_t      width;                // ширина символа
} FontStruct;

const FontStruct FontTable[] = {
  {0x31, &font_0x31,6},
  {0x32, &font_0x32,6},
  {0x33, &font_0x33,6}}

/*---------------------------------------------------------------------------------*/
static const uint8_t font_0x31[6] PROGMEM = {0x00,0x81,0xff,0x80,0x00,0x00};
static const uint8_t font_0x32[6] PROGMEM = {0x82,0xc1,0xa1,0x91,0x8e,0x00};
static const uint8_t font_0x33[6] PROGMEM = {0x42,0x81,0x89,0x89,0x76,0x00};


Сообщение отредактировал Alt.F4 - Oct 4 2012, 07:51
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Oct 4 2012, 07:23
Сообщение #28


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(Alt.F4 @ Oct 4 2012, 11:03) *
Подскажите, пожалуйста, как описать массив структур FontTable, все время ругается на несовместимость типа указателя?
Спасибо.

Вот так:
Код
const FontStruct FontTable[] = {
  {0x31,  font_0x31,6},
  {0x32,  font_0x32,6},
  {0x33,  font_0x33,6}}

Имя массива - уже указатель.


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
Alt.F4
сообщение Oct 4 2012, 07:51
Сообщение #29


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



MrYuran, компилятор пишет: ../font.h:1362:3: warning: initialization from incompatible pointer type
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Oct 4 2012, 08:20
Сообщение #30


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Alt.F4 @ Oct 4 2012, 10:03) *
Подскажите, пожалуйста, как описать массив структур FontTable, все время ругается на несовместимость типа указателя?
Спасибо.

Потому что
Код
uint8_t *

- указатель на байт в ОЗУ,
а font_0x31
Код
PROGMEM

то есть во flash находится.
Go to the top of the page
 
+Quote Post
xemul
сообщение Oct 4 2012, 08:20
Сообщение #31



*****

Группа: Свой
Сообщений: 1 928
Регистрация: 11-07-06
Пользователь №: 18 731



Правильно пишет.
uint8_t * index
uint8_t font_0x31[6] PROGMEM
Go to the top of the page
 
+Quote Post
Alt.F4
сообщение Oct 4 2012, 08:28
Сообщение #32


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



А как тогда объявить указатель на массив во флэш?
з.ы. Ради интереса удалил PROGMEM, ничего не поменялось.
Пишет: ../font.h:1660:3: warning: initialization discards qualifiers from pointer target type

Добавлено:
Удалил "static const" перед uint8_t font_0x31[6] PROGMEM и варнинг пропал, но по прежнему выдает какую-то ошибку и она почему-то не отображается в билдере...

Добавлено еще раз:
Фув, наконец-то скомпилировалось. Вчера полдня и сегодня до обеда сходил с ума cranky.gif

Сообщение отредактировал Alt.F4 - Oct 4 2012, 08:43
Go to the top of the page
 
+Quote Post
MrYuran
сообщение Oct 4 2012, 08:37
Сообщение #33


Беспросветный оптимист
******

Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646



Цитата(Alt.F4 @ Oct 4 2012, 11:51) *
MrYuran, компилятор пишет: ../font.h:1362:3: warning: initialization from incompatible pointer type

Так это ж не ругается, так, под нос бухтит sm.gif

Может, так попробовать:
static const* uint8_t font_0x31 PROGMEM = {0x00,0x81,0xff,0x80,0x00,0x00};


--------------------
Программирование делится на системное и бессистемное. ©Моё :)
— а для кого-то БГ — это Bill Gilbert =)
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Oct 4 2012, 08:41
Сообщение #34


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Alt.F4 @ Oct 4 2012, 11:28) *
з.ы. Ради интереса удалил PROGMEM, ничего не поменялось.
Пишет: ../font.h:1660:3: warning: initialization discards qualifiers from pointer target type


Напишите так
Код
uint8_t font_0x31[6] = {0x00,0x81,0xff,0x80,0x00,0x00};
uint8_t font_0x32[6] = {0x82,0xc1,0xa1,0x91,0x8e,0x00};
uint8_t font_0x33[6] = {0x42,0x81,0x89,0x89,0x76,0x00};

const FontStruct FontTable[] = {
  {0x31,
  
  
  font_0x31,6},
  {0x32,
  font_0x32,6},
  {0x33,
  font_0x33,6}};


- без static const и без &.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Oct 4 2012, 12:02
Сообщение #35


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Код
typedef struct
{
  uint8_t        code;
  const uint8_t* index;       // указатель на КОНСТАНТНЫЙ массив (не хватало квалификатора const)
  uint8_t        width;
} FontStruct;

const FontStruct FontTable[] =
{
  {0x31, &font_0x31[0], 6},   // И тут тоже косяк был. Надо либо брать адрес нулевого элемента массива, либо просто имя массива без взятия адреса.
  {0x32, &font_0x32[0], 6},
  {0x33, &font_0x33[0], 6}
};

А в остальном у вас всё изначально правильно и static const к месту и PROGMEM.
Правда FontTable тоже во флешь можно разместить...


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Alt.F4
сообщение Oct 4 2012, 18:29
Сообщение #36


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



Цитата
Правда FontTable тоже во флешь можно разместить...
Да, попозже наверное так и сделаю, пока надоело бодаться с этим компилятором, придирается ко всяким мелочам.
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Oct 4 2012, 19:39
Сообщение #37


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(Alt.F4 @ Oct 4 2012, 21:29) *
Да, попозже наверное так и сделаю, пока надоело бодаться с этим компилятором, придирается ко всяким мелочам.

Я так понял, что const uint8_t * может и к flash, и к eeprom, и к озу обращаться?
Удобно, IAR так не позволяет.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Oct 5 2012, 05:47
Сообщение #38


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(_Артём_ @ Oct 4 2012, 23:39) *
Не совсем так. В avr-gcc const uint8_t* ptr при простом разыменовывании указателя всегда обращается к ОЗУ,
а чтобы читать из флеша или eeprom нужно через макросы мыкаться: pgm_read_byte(ptr) и eeprom_read_byte(ptr).
Что как раз не так удобно как в IAR.
Но и в avr-gcc 4.7.0 тоже появилась аналогичная IARу фича: ключевое слово __flash и теперь стало возможно
Код
const __flash uint8_t x1 = 33;
const __flash uint8_t x2 = 36;
const __flash uint8_t* ptr = &x1;
if (*ptr==x2)
{
    ...
}

Цитата(Alt.F4 @ Oct 4 2012, 22:29) *
пока надоело бодаться с этим компилятором, придирается ко всяким мелочам.
Это никакие не мелочи. Просто нужно один раз разобраться в теме и получать удовольствие от работы...
Для тренировки ответьте себе на следующий вопрос, чем отличаются следующие указатели:
Код
char* p1;
const char* p2;
char* const p3;
const char* const p4;


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
Alt.F4
сообщение Oct 5 2012, 09:47
Сообщение #39


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



Цитата
а чтобы читать из флеша или eeprom нужно через макросы мыкаться: pgm_read_byte(ptr) и eeprom_read_byte(ptr).
Миллионным перебором вариантов стал объявлять адрес для ЕЕ как void* adrr; sm.gif
А для чтения свой макрос написал (не знал, что есть eeprom_read_byte()):
Код
#define EE_read {\
cli();\
EEAR = (u16)addr++;\
sbi(EECR,EERE);\
temp = EEDR;\
EEAR = 0;\
sei();}


Цитата
Для тренировки ответьте себе на следующий вопрос, чем отличаются следующие указатели:
Вроде бы так:
char* p1; - переменный указатель на массив типа char
const char* p2; - указатель константа на массив типа char (хотя он все равно будет размещен в ОЗУ как и первый)
char* const p3; - тоже самое
const char* const p4; - тоже самое

Сообщение отредактировал Alt.F4 - Oct 5 2012, 09:47
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Oct 5 2012, 10:39
Сообщение #40


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(Alt.F4 @ Oct 5 2012, 13:47) *
Вроде бы так:
Нет не так. Отсюда и все проблемы..
char* p1; - указатель на char
const char* p2; - указатель на const char
char* const p3; - константный указатель на char
const char* const p4; - константный указатель на const char

Пока вы азы языка Си не поймёте, так и будете ходить по граблям, занимаясь подбором-перебором и изобретая очередные грабли.
Остановитесь, почитайте азы - сразу увидите как всё станет понятно и красиво.

Цитата(Alt.F4 @ Oct 5 2012, 13:47) *
А для чтения свой макрос написал (не знал, что есть eeprom_read_byte())
Зря... Достаточно
#include <avr/eeprom.h>
и в путь.
В avrlibc очень оптимально написано, что касается eeprom, да многое другое тоже.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Oct 5 2012, 12:05
Сообщение #41


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



.


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post
_Артём_
сообщение Oct 5 2012, 14:13
Сообщение #42


Гуру
******

Группа: Свой
Сообщений: 2 128
Регистрация: 21-05-06
Пользователь №: 17 322



Цитата(demiurg_spb @ Oct 5 2012, 08:47) *
Не совсем так. В avr-gcc const uint8_t* ptr при простом разыменовывании указателя всегда обращается к ОЗУ,
а чтобы читать из флеша или eeprom нужно через макросы мыкаться: pgm_read_byte(ptr) и eeprom_read_byte(ptr).

Сделал так:
Код
const uint8_t PROGMEM test[3]={1, 2, 4};
const uint8_t test2[3]={11,12,16};
const uint8_t * ptr;
volatile uint8_t test_copy[9];
__attribute__ ((section (".eeprom"))) const uint8_t  test3[3]={'A','B','m'};
int main()
{
    ptr=test;
    test_copy[0]=ptr[0];
    test_copy[1]=ptr[1];
    test_copy[2]=ptr[2];

    ptr=test2;
    test_copy[3]=ptr[0];
    test_copy[4]=ptr[1];
    test_copy[5]=ptr[2];

    ptr=test3;
    test_copy[6]=ptr[0];
    test_copy[7]=ptr[1];
    test_copy[8]=ptr[2];

Но похоже GCC просто соптимизировал чтение.
Если массивы объявить не как const, работать не будет.
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Oct 5 2012, 14:18
Сообщение #43


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Цитата(_Артём_ @ Oct 5 2012, 18:13) *
Да оптимизировал и не читал (constant propagation в действии).
Вы их (test1,2,3) как volatile const объявите или как extern из других единиц трансляции (не из main.c)...


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 26th July 2025 - 09:31
Рейтинг@Mail.ru


Страница сгенерированна за 0.01866 секунд с 7
ELECTRONIX ©2004-2016