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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
Chip115
Сверлит текстолит когтями
Сообщения: 1132
Зарегистрирован: Пт фев 16, 2007 14:18:20
Откуда: Новосибирск
Контактная информация:

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

Сообщение Chip115 »

blackx писал(а):Попробуйте увеличить размер стека.
Не помогло. Что еще может быть?
Теория — это когда все известно, но ничего не работает. Практика — это когда все работает, но никто не знает почему. Мы же объединяем теорию и практику: ничего не работает… и никто не знает почему!
© Альберт Эйнштейн
Реклама
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

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

Сообщение ibiza11 »

Приветствую всех участников форума!
Давно не обращался за помощью сюда... Заранее прошу прощения за много букв.
Ситуация: есть микроконтроллер с подключенным к нему графическим индикатором. Есть необходимость написать для этой сборки пользовательское многоуровневое меню.
Есть основной файл 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: Вопросы по С/С++ (СИ)

Сообщение Аlex »

Я бы завёл в menu.c структуру (т.к. она непосредственно относится к этому файлу) и в menu.h написал бы её прототип с квалификатором extern. Хотим иметь доступ к структуре - подключаем menu.h, не хотим - не подключаем :)
Другой вариант. Объявляем структуру в main.c и передаём её указатель через menu_refresh(...);.
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

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

Сообщение ibiza11 »

Приветствую, Alex!
Я склоняюсь больше к варианту со структурой в menu.c, так модуль становится законченным и независимым. только пока неясно, оригиналы параметров хранить там же или лучше отдельно? как считаете?
если отдельно - перерасход памяти в 2 раза) если там же - то модуль main без menu работать не сможет.

Если рассмотреть второй вариант, со структурой в main.c, то там нет проблемы с перерасходом памяти, но menu.c становится зависимым от main.c...

Хочется услышать того, кто это уже реализовывал) Пока вопрос открыт!
Ставим плюсы: )
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
Аlex
Модератор
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля
Контактная информация:

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

Сообщение Аlex »

оригиналы параметров хранить там же или лучше отдельно?
Там же и храните, а доступ к ним через extern.
Есть другой вариант, более правильный.
Создаёте файлы param.c и param.h, в param.c открываете доступ к работе с энергонезависимой памятью (eeprom, внешняя flash, SD-карта, винт :))) , ... ) и пишите основние функции работы с параметрами - чтение, обновление, запись, ... В param.h описываете все прототипы и создаёте тип-структуру. В param.c объявляете структуру с этим типом (это будет основная структура параметров), а в param.h объявляем её прототип с extern. Теперь, где хотим иметь доступ к основной структуре и функциям записи/чтения параметров - подключаем param.h.
Реклама
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

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

Сообщение ibiza11 »

:shock: почему я об этом до этого даже не подумал? вообще разумная идея! разрешает много конфликтов. Спасибо за идею!
Ставим плюсы: )
Реклама
Аватара пользователя
Chip115
Сверлит текстолит когтями
Сообщения: 1132
Зарегистрирован: Пт фев 16, 2007 14:18:20
Откуда: Новосибирск
Контактная информация:

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

Сообщение Chip115 »

В общем выяснилось что printf косячит работая в прерывании. Если вызывать из main, то все норм. Так вот. Мне через равные промежутки времени (напр. 1/2 сек.) требуется выводить значения тока, напруги и темпер. в юарт. Как это лучше сделать? Первое что пришло в голову - это создать класс, в котором будет массив и методы push, pop и print. В общем стек FIFO и метод, который будет пинать данные в УАПП. Если буфер не пустой, то выводим в уапп. Это норм. решение проблемы или можно более красиво выйти из ситуации?
Теория — это когда все известно, но ничего не работает. Практика — это когда все работает, но никто не знает почему. Мы же объединяем теорию и практику: ничего не работает… и никто не знает почему!
© Альберт Эйнштейн
Аватара пользователя
blackx
Говорящий с текстолитом
Сообщения: 1518
Зарегистрирован: Пт дек 28, 2012 21:56:46
Откуда: St. Petersburg

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

Сообщение blackx »

Так проблема то не в UART, а в printf(). Если printf() на два одинаковых вызова выдает разные результаты то проблема 100% с памятью. Прерывания вызываются в случайное время, оттого наблюдается такое недетерминированное поведение.

Возможные варианты решения:
1) перейти на целочисленные вычисления
2) переводить число в стоку с помощью функций типа ftoa() (если не включена в вашу реализацию libc - придется самому ее написать, готовые варианты можно найти в инете)
3) переводить число в стоку не в прерывании, а в основном теле программы. Вывод оставить как есть в прер-ии.
Изображение only pure true norwegian blackx Изображение
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

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

Сообщение pokk »

Здравствуйте, есть у меня функция чтения/передачи регистров W5100
формат такой первый бай это код чтения или записи 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: Вопросы по С/С++ (СИ)

Сообщение blackx »

Опишите, пожалуйста, подробнее, что вы передаете и принимаете, и в каком порядке.

Мне кажется, пытаться писать такую программу на основе конечного автомата было вашей ошибкой. Нарисуйте граф состояний со всеми переходами, и оцените насколько он получится сложным - сколько в нем будет связей между узлами, насколько количество связей окажется больше чем количество самих узлов, сколько циклов в графе получилось.
Насколько я вижу из исходной вашей функции, это будет только лишь несколько последовательных действий, выполняющихся всегда друг за другом. В таком случае применять конечный автомат абсолютно нецелесообразно. Его лучше заменить на набор разноуровневых функций, просто вызывающих друг друга.
Изображение only pure true norwegian blackx Изображение
pokk
Вымогатель припоя
Сообщения: 574
Зарегистрирован: Вт ноя 02, 2010 17:46:37

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

Сообщение pokk »

Опишите, пожалуйста, подробнее, что вы передаете и принимаете, и в каком порядке.
Одна команда чтения или записи состоит из передачи 4 байт
первый байт 0x0F (выбор команды чтения или записи)
второй байт старший байт адрес откуда надо считать.
третий байт младший байт адрес откуда надо считать.
четвёртый байт отправляем 0xFF(чтение) или данные .

После каждой отправки принимаем байт.

Его лучше заменить на набор разноуровневых функций, просто вызывающих друг друга.
Можно про это по подробнее ?
Насколько я вижу из исходной вашей функции, это будет только лишь несколько последовательных действий, выполняющихся всегда друг за другом.
Ага сколько бы я не рисовал получается именно это.
Основная задача избавится от

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

while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);       //53
сделать чего через if что бы дальнейшая часть программы выполнялась(другой модуль)
и без использования прерываний.
libixur
Родился
Сообщения: 2
Зарегистрирован: Чт дек 05, 2013 12:59:32

Re: AVR studio 4 в вопросах и ответах

Сообщение libixur »

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

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

Сообщение ibiza11 »

в UART

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

UDR = (PORTC & (1<<7));
в переменную

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

uint8_t tmp;
tmp = (PORTC & (1<<7));
Ставим плюсы: )
dzrkot
Открыл глаза
Сообщения: 75
Зарегистрирован: Чт авг 29, 2013 08:02:24

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

Сообщение dzrkot »

IDE - IAR , GNU GCC Compiler
чистый Си
Пытаюсь передать через указатель, компилятор ругается, если ставлю &, то нормально, но по идее я через & указываю на память где храниться чистый 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: Вопросы по С/С++ (СИ)

Сообщение BCluster »

Так а что нужно сделать собственно? Имеет смысл передавать указатель в двух случаях - нужно изменить передаваемый параметр либо передача указателя для работы с массивом.

Функция у вас принимает аргумент char*, что есть указатель. Т.е. адрес
Вы пытаетесь вместе char* передать char, т.е. значение, соответственно компилятор ругается
Если передавать с & - то передастся адрес вашей переменной, т.е. указатель
dzrkot
Открыл глаза
Сообщения: 75
Зарегистрирован: Чт авг 29, 2013 08:02:24

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

Сообщение dzrkot »

BCluster писал(а):Так а что нужно сделать собственно? Имеет смысл передавать указатель в двух случаях - нужно изменить передаваемый параметр либо передача указателя для работы с массивом.

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

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

Сообщение ibiza11 »

только в этом случае передается адрес вашей переменной, а не значение адреса, который хранится в ней.
чтобы передать в функцию значение адреса, нужно привести переменную к типу (char *)
Ставим плюсы: )
Аватара пользователя
BCluster
Собутыльник Кота
Сообщения: 2512
Зарегистрирован: Пн апр 06, 2009 19:33:29
Откуда: Молдова, Кишинев
Контактная информация:

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

Сообщение BCluster »

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

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

Сообщение pokk »

Здравствуйте заинтересовало меня как в define компилятор определяет переменную.
Ну т.е

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

#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 это типа параметр а во втором нет может к нему добавить какой-нибудь символ надо ?
Аватара пользователя
Kavka
Мудрый кот
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

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

Сообщение Kavka »

pokk, смутно соображаю, но кажется мне, что вам может быть полезно вот это
http://gcc.gnu.org/onlinedocs/cpp/Strin ... gification
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Ответить

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