Не помогло. Что еще может быть?blackx писал(а):Попробуйте увеличить размер стека.
Вопросы по С/С++ (СИ)
- Chip115
- Сверлит текстолит когтями
- Сообщения: 1132
- Зарегистрирован: Пт фев 16, 2007 14:18:20
- Откуда: Новосибирск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Теория — это когда все известно, но ничего не работает. Практика — это когда все работает, но никто не знает почему. Мы же объединяем теорию и практику: ничего не работает… и никто не знает почему!
© Альберт Эйнштейн
© Альберт Эйнштейн
- Реклама
- ibiza11
- Поставщик валерьянки для Кота
- Сообщения: 1900
- Зарегистрирован: Сб фев 21, 2009 13:11:40
- Откуда: Москва
Re: Вопросы по С/С++ (СИ)
Приветствую всех участников форума!
Давно не обращался за помощью сюда... Заранее прошу прощения за много букв.
Ситуация: есть микроконтроллер с подключенным к нему графическим индикатором. Есть необходимость написать для этой сборки пользовательское многоуровневое меню.
Есть основной файл main.c в котором собственно обрабатываются все события периферии, в котором должен быть реализован основной функционал. В идеале хочется из main.c вызывать некую функцию menu_refresh(...), которая будет выполнять все функции по отрисовке меню на дисплее.
Хочу отделить реализацию меню от этого файла, чтобы все не перемешивать.
Соответственно в файле menu.c описываю все пункты меню, надписи, графические примитивы. В этот файл подключаю драйвер дисплея для доступа к функциям отрисовки.
Загвоздка в том, файлу menu.c, нужно получать значения числовых параметров из основного файла main.c для последующего их отображения.
Параметров очень много!
К примеру пункт меню "Яркость дисплея : 100%" - требует значение яркости из основного файла, где он собственно и изменяется (функции изменения яркости естественно в другом модуле)
у меня сейчас два варианта:
1) завести в модуле menu.c глобальную структуру, в которой будут храниться копии параметров для отображения, а из main.с их изменять, инициализируя структуру при старте.
2) завести в модуле main.c глобальную структуру, в которой будут храниться параметры, а в menu.c передавать указатель на структуру, предварительно описав ее как extern.
Первый раз пишу такую громадину, хотелось бы знать как пишут ее остальные. Просьба прокомментировать, покритиковать мое решение, дать дельный совет по реализации. Вообще я в правильном направлении двигаюсь?
Давно не обращался за помощью сюда... Заранее прошу прощения за много букв.
Ситуация: есть микроконтроллер с подключенным к нему графическим индикатором. Есть необходимость написать для этой сборки пользовательское многоуровневое меню.
Есть основной файл main.c в котором собственно обрабатываются все события периферии, в котором должен быть реализован основной функционал. В идеале хочется из main.c вызывать некую функцию menu_refresh(...), которая будет выполнять все функции по отрисовке меню на дисплее.
Хочу отделить реализацию меню от этого файла, чтобы все не перемешивать.
Соответственно в файле menu.c описываю все пункты меню, надписи, графические примитивы. В этот файл подключаю драйвер дисплея для доступа к функциям отрисовки.
Загвоздка в том, файлу menu.c, нужно получать значения числовых параметров из основного файла main.c для последующего их отображения.
Параметров очень много!
К примеру пункт меню "Яркость дисплея : 100%" - требует значение яркости из основного файла, где он собственно и изменяется (функции изменения яркости естественно в другом модуле)
у меня сейчас два варианта:
1) завести в модуле menu.c глобальную структуру, в которой будут храниться копии параметров для отображения, а из main.с их изменять, инициализируя структуру при старте.
2) завести в модуле main.c глобальную структуру, в которой будут храниться параметры, а в menu.c передавать указатель на структуру, предварительно описав ее как extern.
Первый раз пишу такую громадину, хотелось бы знать как пишут ее остальные. Просьба прокомментировать, покритиковать мое решение, дать дельный совет по реализации. Вообще я в правильном направлении двигаюсь?
Ставим плюсы: )
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Я бы завёл в menu.c структуру (т.к. она непосредственно относится к этому файлу) и в menu.h написал бы её прототип с квалификатором extern. Хотим иметь доступ к структуре - подключаем menu.h, не хотим - не подключаем 
Другой вариант. Объявляем структуру в main.c и передаём её указатель через menu_refresh(...);.
Другой вариант. Объявляем структуру в main.c и передаём её указатель через menu_refresh(...);.
- ibiza11
- Поставщик валерьянки для Кота
- Сообщения: 1900
- Зарегистрирован: Сб фев 21, 2009 13:11:40
- Откуда: Москва
Re: Вопросы по С/С++ (СИ)
Приветствую, Alex!
Я склоняюсь больше к варианту со структурой в menu.c, так модуль становится законченным и независимым. только пока неясно, оригиналы параметров хранить там же или лучше отдельно? как считаете?
если отдельно - перерасход памяти в 2 раза) если там же - то модуль main без menu работать не сможет.
Если рассмотреть второй вариант, со структурой в main.c, то там нет проблемы с перерасходом памяти, но menu.c становится зависимым от main.c...
Хочется услышать того, кто это уже реализовывал) Пока вопрос открыт!
Я склоняюсь больше к варианту со структурой в menu.c, так модуль становится законченным и независимым. только пока неясно, оригиналы параметров хранить там же или лучше отдельно? как считаете?
если отдельно - перерасход памяти в 2 раза) если там же - то модуль main без menu работать не сможет.
Если рассмотреть второй вариант, со структурой в main.c, то там нет проблемы с перерасходом памяти, но menu.c становится зависимым от main.c...
Хочется услышать того, кто это уже реализовывал) Пока вопрос открыт!
Ставим плюсы: )
- Аlex
- Модератор
- Сообщения: 4614
- Зарегистрирован: Чт мар 18, 2010 23:09:57
- Откуда: Планета Земля
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Там же и храните, а доступ к ним через extern.оригиналы параметров хранить там же или лучше отдельно?
Есть другой вариант, более правильный.
Создаёте файлы param.c и param.h, в param.c открываете доступ к работе с энергонезависимой памятью (eeprom, внешняя flash, SD-карта, винт
- Реклама
- ibiza11
- Поставщик валерьянки для Кота
- Сообщения: 1900
- Зарегистрирован: Сб фев 21, 2009 13:11:40
- Откуда: Москва
Re: Вопросы по С/С++ (СИ)
Ставим плюсы: )
- Chip115
- Сверлит текстолит когтями
- Сообщения: 1132
- Зарегистрирован: Пт фев 16, 2007 14:18:20
- Откуда: Новосибирск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
В общем выяснилось что printf косячит работая в прерывании. Если вызывать из main, то все норм. Так вот. Мне через равные промежутки времени (напр. 1/2 сек.) требуется выводить значения тока, напруги и темпер. в юарт. Как это лучше сделать? Первое что пришло в голову - это создать класс, в котором будет массив и методы push, pop и print. В общем стек FIFO и метод, который будет пинать данные в УАПП. Если буфер не пустой, то выводим в уапп. Это норм. решение проблемы или можно более красиво выйти из ситуации?
Теория — это когда все известно, но ничего не работает. Практика — это когда все работает, но никто не знает почему. Мы же объединяем теорию и практику: ничего не работает… и никто не знает почему!
© Альберт Эйнштейн
© Альберт Эйнштейн
- blackx
- Говорящий с текстолитом
- Сообщения: 1518
- Зарегистрирован: Пт дек 28, 2012 21:56:46
- Откуда: St. Petersburg
Re: Вопросы по С/С++ (СИ)
Так проблема то не в UART, а в printf(). Если printf() на два одинаковых вызова выдает разные результаты то проблема 100% с памятью. Прерывания вызываются в случайное время, оттого наблюдается такое недетерминированное поведение.
Возможные варианты решения:
1) перейти на целочисленные вычисления
2) переводить число в стоку с помощью функций типа ftoa() (если не включена в вашу реализацию libc - придется самому ее написать, готовые варианты можно найти в инете)
3) переводить число в стоку не в прерывании, а в основном теле программы. Вывод оставить как есть в прер-ии.
Возможные варианты решения:
1) перейти на целочисленные вычисления
2) переводить число в стоку с помощью функций типа ftoa() (если не включена в вашу реализацию libc - придется самому ее написать, готовые варианты можно найти в инете)
3) переводить число в стоку не в прерывании, а в основном теле программы. Вывод оставить как есть в прер-ии.
only pure true norwegian blackx 
Re: Вопросы по С/С++ (СИ)
Здравствуйте, есть у меня функция чтения/передачи регистров W5100
формат такой первый бай это код чтения или записи 0F второй третий байт адрес 4 байт ff выталкиваем данные(чтение)
в принцепе тут 4 раза повторяюшийся код только с разными
Решил переделать программу по принципу конечного автомата. Соответственно функцию эту тоже видоизменить.
Выделил основные команды примерно получилось следующее. Если продолжать в том же духе то там надо ещё кучу подобных функций наделать. что мне не совсем нравится (путаница большая будет)
По этому у меня возник вопрос
1) Можно ли тут как-нибудь сделать что-то типа такого curr_state=resive(0x0F); И вообще как передавать параметры в функции
можно конечно через глобальные переменные но их будет сильно много.
Пока всё это писал придумал не большую иерархию из таблицы state_table вызывается глобальные функции типа CHIP_READ, CHIP_WRITE. А внутри CHIP_READ содержится ещё один массив из которого вызываются под функции send,resive.....
но пока не могу придумать как обойти без создания 8 функций
И вообще есть какое-нибудь более оптимальное решение?
Осознал проблему можно ли эти функции запихать в пассив ?
формат такой первый бай это код чтения или записи 0F второй третий байт адрес 4 байт ff выталкиваем данные(чтение)
в принцепе тут 4 раза повторяюшийся код только с разными
Спойлер
Код: Выделить всё
unsigned char CHIP_READ(unsigned int addr)
{
unsigned char temp[4];
GPIO_ResetBits(GPIOB, GPIO_Pin_12); //53
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET); //53
SPI_I2S_SendData (SPI2,0x0f); //53
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET); //35
temp[0]=SPI_I2S_ReceiveData(SPI2);
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET); //34
SPI_I2S_SendData (SPI2,((addr & 0xFF00) >> 8)); //14
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET); //35
temp[1]=SPI_I2S_ReceiveData(SPI2); //24
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData (SPI2,(addr & 0x00FF));
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
temp[2]=SPI_I2S_ReceiveData(SPI2);
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
SPI_I2S_SendData (SPI2,0xff);
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
temp[3]=SPI_I2S_ReceiveData(SPI2);
GPIO_SetBits(GPIOB, GPIO_Pin_12);
if(temp[0]==0x0&&temp[1]==0x01&&temp[2]==0x02){
return temp[3];
}
else {
GPIO_SetBits(GPIOD, GPIO_Pin_13); //зажечь
return 0;
}
}
Выделил основные команды примерно получилось следующее. Если продолжать в том же духе то там надо ещё кучу подобных функций наделать. что мне не совсем нравится (путаница большая будет)
Код: Выделить всё
void (*state_table[])() = {CHIP_READ,send, resive};
curr_state=CHIP_READ;
main()
{
while (1) {
state_table[curr_state]();
}
};
unsigned char CHIP_READ(unsigned int addr)
{
GPIO_ResetBits(GPIOB, GPIO_Pin_12);
curr_state=send;
}
void send(void){
if(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) != RESET){
SPI_I2S_SendData (SPI2,0x0f);
curr_state=resive;
}
}
void resive(void){
if(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) != RESET){
SPI_I2S_ReceiveData(SPI2)
curr_state=send2;
}1) Можно ли тут как-нибудь сделать что-то типа такого curr_state=resive(0x0F); И вообще как передавать параметры в функции
можно конечно через глобальные переменные но их будет сильно много.
Пока всё это писал придумал не большую иерархию из таблицы state_table вызывается глобальные функции типа CHIP_READ, CHIP_WRITE. А внутри CHIP_READ содержится ещё один массив из которого вызываются под функции send,resive.....
но пока не могу придумать как обойти без создания 8 функций
И вообще есть какое-нибудь более оптимальное решение?
Осознал проблему можно ли эти функции запихать в пассив ?
Код: Выделить всё
void test1(char data);
void test2(int data);
void test3(void );
void (*tab_test[])(void) = {test1,test2,test3};- blackx
- Говорящий с текстолитом
- Сообщения: 1518
- Зарегистрирован: Пт дек 28, 2012 21:56:46
- Откуда: St. Petersburg
Re: Вопросы по С/С++ (СИ)
Опишите, пожалуйста, подробнее, что вы передаете и принимаете, и в каком порядке.
Мне кажется, пытаться писать такую программу на основе конечного автомата было вашей ошибкой. Нарисуйте граф состояний со всеми переходами, и оцените насколько он получится сложным - сколько в нем будет связей между узлами, насколько количество связей окажется больше чем количество самих узлов, сколько циклов в графе получилось.
Насколько я вижу из исходной вашей функции, это будет только лишь несколько последовательных действий, выполняющихся всегда друг за другом. В таком случае применять конечный автомат абсолютно нецелесообразно. Его лучше заменить на набор разноуровневых функций, просто вызывающих друг друга.
Мне кажется, пытаться писать такую программу на основе конечного автомата было вашей ошибкой. Нарисуйте граф состояний со всеми переходами, и оцените насколько он получится сложным - сколько в нем будет связей между узлами, насколько количество связей окажется больше чем количество самих узлов, сколько циклов в графе получилось.
Насколько я вижу из исходной вашей функции, это будет только лишь несколько последовательных действий, выполняющихся всегда друг за другом. В таком случае применять конечный автомат абсолютно нецелесообразно. Его лучше заменить на набор разноуровневых функций, просто вызывающих друг друга.
only pure true norwegian blackx 
Re: Вопросы по С/С++ (СИ)
Одна команда чтения или записи состоит из передачи 4 байтОпишите, пожалуйста, подробнее, что вы передаете и принимаете, и в каком порядке.
первый байт 0x0F (выбор команды чтения или записи)
второй байт старший байт адрес откуда надо считать.
третий байт младший байт адрес откуда надо считать.
четвёртый байт отправляем 0xFF(чтение) или данные .
После каждой отправки принимаем байт.
Можно про это по подробнее ?Его лучше заменить на набор разноуровневых функций, просто вызывающих друг друга.
Ага сколько бы я не рисовал получается именно это.Насколько я вижу из исходной вашей функции, это будет только лишь несколько последовательных действий, выполняющихся всегда друг за другом.
Основная задача избавится от
Код: Выделить всё
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET); //53и без использования прерываний.
Re: AVR studio 4 в вопросах и ответах
Добрый день! Помоги пожалуйста. Есть контроллер ATmega32, пишу для него программу. Есть настроенный USART, как мне в него передать значение с определенного пина, к примеру PC7? Или как вобще получить значение пина в переменную?
- ibiza11
- Поставщик валерьянки для Кота
- Сообщения: 1900
- Зарегистрирован: Сб фев 21, 2009 13:11:40
- Откуда: Москва
Re: Вопросы по С/С++ (СИ)
в UARTв переменную
Код: Выделить всё
UDR = (PORTC & (1<<7));Код: Выделить всё
uint8_t tmp;
tmp = (PORTC & (1<<7));Ставим плюсы: )
Re: Вопросы по С/С++ (СИ)
IDE - IAR , GNU GCC Compiler
чистый Си
Пытаюсь передать через указатель, компилятор ругается, если ставлю &, то нормально, но по идее я через & указываю на память где храниться чистый 0x00 т.е. это неправильно ии так и надо и я ошибаюсь?
примерно так делаю
чистый Си
Пытаюсь передать через указатель, компилятор ругается, если ставлю &, то нормально, но по идее я через & указываю на память где храниться чистый 0x00 т.е. это неправильно ии так и надо и я ошибаюсь?
примерно так делаю
Код: Выделить всё
unsigned char adressMy=(0x00);
void getAdress(char* adress); // прототип
{
int main (void)
getAdress(adressMy);
}
void getAdress(char *adress)
{
// всякая разная всяка
}- BCluster
- Собутыльник Кота
- Сообщения: 2512
- Зарегистрирован: Пн апр 06, 2009 19:33:29
- Откуда: Молдова, Кишинев
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Так а что нужно сделать собственно? Имеет смысл передавать указатель в двух случаях - нужно изменить передаваемый параметр либо передача указателя для работы с массивом.
Функция у вас принимает аргумент char*, что есть указатель. Т.е. адрес
Вы пытаетесь вместе char* передать char, т.е. значение, соответственно компилятор ругается
Если передавать с & - то передастся адрес вашей переменной, т.е. указатель
Функция у вас принимает аргумент char*, что есть указатель. Т.е. адрес
Вы пытаетесь вместе char* передать char, т.е. значение, соответственно компилятор ругается
Если передавать с & - то передастся адрес вашей переменной, т.е. указатель
Re: Вопросы по С/С++ (СИ)
да спасибо я уже разобрался,просто на С++ сижу в основном там по ссылкам не думаю о таких вещахBCluster писал(а):Так а что нужно сделать собственно? Имеет смысл передавать указатель в двух случаях - нужно изменить передаваемый параметр либо передача указателя для работы с массивом.
Функция у вас принимает аргумент char*, что есть указатель. Т.е. адрес
Вы пытаетесь вместе char* передать char, т.е. значение, соответственно компилятор ругается
Если передавать с & - то передастся адрес вашей переменной, т.е. указатель
- ibiza11
- Поставщик валерьянки для Кота
- Сообщения: 1900
- Зарегистрирован: Сб фев 21, 2009 13:11:40
- Откуда: Москва
Re: Вопросы по С/С++ (СИ)
только в этом случае передается адрес вашей переменной, а не значение адреса, который хранится в ней.
чтобы передать в функцию значение адреса, нужно привести переменную к типу (char *)
чтобы передать в функцию значение адреса, нужно привести переменную к типу (char *)
Ставим плюсы: )
- BCluster
- Собутыльник Кота
- Сообщения: 2512
- Зарегистрирован: Пн апр 06, 2009 19:33:29
- Откуда: Молдова, Кишинев
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Приведенный вами код и в с++ вызовет ошибку компиляции
Re: Вопросы по С/С++ (СИ)
Здравствуйте заинтересовало меня как в define компилятор определяет переменную.
Ну т.е
так всё работает пишу
Но вот если добавить кавычки
nn уже не заменяется.
Вот и встал вопрос как он в первом случае понимал что nn это типа параметр а во втором нет может к нему добавить какой-нибудь символ надо ?
Ну т.е
Код: Выделить всё
#define SEND(nn) LEN=UTF_8(nn,mas);send(s,mas,LEN);Код: Выделить всё
SEND("варп") вместо этого ставится LEN=UTF_8("варп",mas);send(s,mas,LEN);Код: Выделить всё
#define SEND(nn) LEN=UTF_8("nn",mas);send(s,mas,LEN);nn уже не заменяется.
Вот и встал вопрос как он в первом случае понимал что nn это типа параметр а во втором нет может к нему добавить какой-нибудь символ надо ?
Re: Вопросы по С/С++ (СИ)
pokk, смутно соображаю, но кажется мне, что вам может быть полезно вот это
http://gcc.gnu.org/onlinedocs/cpp/Strin ... gification
http://gcc.gnu.org/onlinedocs/cpp/Strin ... gification
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)


