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

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

Представляете какой смачный многовариантный goto можно сделать с помощью оператора switch :)
Реклама
Аватара пользователя
Billi34
Открыл глаза
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

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

Сообщение Billi34 »

БИНГО!!!!!!!!!!!!!!!!!!!
ПаЛуЧиЛоСь.
Заработало как я хотел.
8) 8) 8) 8) 8) 8) 8)

САМ!
САМ!
САМ! Сделал.
Надеюсь прилепился тот файл, с окончательной версией кода.
Вложения
NewUnit.c
(3.14 КБ) 279 скачиваний
Реклама
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

Кошмар.

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

 Delay_ms(800) ;  //пауза длиной 0.8 сек
Вот скажите, зачем Вам нужны такие паузы, когда вся система стоит колом?
Аватара пользователя
Billi34
Открыл глаза
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

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

Сообщение Billi34 »

Это как говорится "версия для радио". за эти 0.8 сек МК "дергает некоторыми своими ногами". Я сознательно убрал этот код что б вы не пытались его оптимизировать. А попытка оптимизации будет 100% Ваше мышление заточено под ужатие, оптимизацию-поиск изящных решений. А мне вполне достаточно такого вида как у меня. Объем кода очень маленький. Везде умещаюсь.
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

Лучше попробуйте делать всё это не в основном цикле, а в прерывании.

Заведите аппаратный таймер, для удобства так, чтобы прерывания срабатывали раз в 1мс. Заведите 1 переменную - счётчик, и 2 переменную - событие.

В прерывании от таймера проверяйте, нажата ли кнопка. Если нажата, счётчик нажатий увеличивайте на 1. Если не нажата, счётчик обнуляйте.

При обнулении счётчика (отпускании кнопки) нужно проверить счётчик, если там больше 100 - значит это было полноценное короткое нажатие. Записываем это короткое нажатие в переменную-событие.

Если кнопка нажата долго, и счётчик досчитал до 600 - значит, в переменную-событие нужно записать информацию о длинном нажатии.

Больше ничего в прерывании делать не надо. Только считать и, при необходимости, обновлять переменную-событие.

В основном цикле программы никаких задержек не нужно. Просто в начале цикла вычитываем переменную событие, с обнулением. Если что-то было - выполняем, если ничего не было - ничего и не делаем.

Всё просто. И ни одной задержки, МК 99.9% времени работает в основном полезном цикле.
Реклама
Аватара пользователя
Billi34
Открыл глаза
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

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

Сообщение Billi34 »

Каждый должен заниматься своим делом. Это было для души.
Последний раз редактировалось Billi34 Пн сен 09, 2019 11:42:38, всего редактировалось 1 раз.
Реклама
Аватара пользователя
WiseLord
Друг Кота
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск
Контактная информация:

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

Сообщение WiseLord »

Ну, если не нужен _понятный_ код, вдвое меньше по размеру и без задержек, в которых МК просто бесполезно висит - то дело хозяйское.

P.S. Вот упрощённый пример для понимания, как это должно работать:
Спойлер

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

// Кнопки
#define BTN0    PIND.B0
#define BTN1    PIND.B1

// События
#define EVT_NO          0
#define EVT_BTN0        0x01            // 00000001
#define EVT_BTN1        0x02            // 00000010
#define EVT_BTN0_LONG   (EVT_BTN0 << 4) // 00010000
#define EVT_BTN1_LONG   (EVT_BTN1 << 4) // 00100000

// Длительность нажатий
#define LONG_PRESS      600
#define SHORT_PRESS     100

static volatile uint8_t event = EVT_NO;  // Переменная для хранения события

void isr_timer(void)  // Аппаратное прерывание от таймера, каждые 1мс
{
    static uint16_t btnCounter = 0; // Cчётчик нажатий
    static uint8_t btnPrev = 0;     // Предыдущее нажатие

    uint8_t btnNow = 0;

    // Опрашиваем кнопки
    if (!BTN0)              // нажата кнопка 0
        btnNow |= EVT_BTN0;
    if (!BTN1)              // нажата кнопка 1
        btnNow |= EVT_BTN1;

    if (btnNow) {               // Если кнопка нажата
        if (btnNow == btnPrev) {    // если это всё та же кнопка
            btnCounter++;           // просто наращиваем счётчик
            if (btnCounter == LONG_PRESS) {
                event = (btnNow << 4);      // сохраняем "длинное" событие
            }
        } else {
            btnPrev = btnNow;           // кнопка сменилась, запоминаем
        }
    } else {
        if (btnCounter > SHORT_PRESS && btnCounter < LONG_PRESS) {
            event = btnNow;     // короткое нажатие - сохраняем событие
        }
        btnCounter = 0; // сбрасываем счётчик
    }
}

uint8_t getEvent(void)
{
    uint8_t ret = event;    // значение для возврата
    event = 0;              // событие "забрали", можно обнулять

    return ret;
}

int main(void)
{
    // настраиваем порты
    // ...
    // настраиваем таймер на прерывания раз в 1мс
    // ..
    // поехали...

    uint8_t evt;

    while (1) {
        evt = getEvent();

        switch (evt) {
        case EVT_BTN0:
            // обрабатываем короткое нажатие кнопки 0
            break;
        case EVT_BTN1:
            // обрабатываем короткое нажатие кнопки 1
            break;
        case EVT_BTN0_LONG:
            // обрабатываем длинное нажатие кнопки 0
            break;
        case EVT_BTN1_LONG:
            // обрабатываем длинное нажатие кнопки 1
            break;
        }
    }

    return 0;
}
Аватара пользователя
Billi34
Открыл глаза
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

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

Сообщение Billi34 »

:) Спасибо.
Я обязательно по изучаю Ваш пример. Уже появились идейки "нарастить" функционал программы.
Сопутствующий вопрос: это всё ещё на Си или уже С++? Будут ли работать операторы из вашего кода в моем компиляторе?
Аватара пользователя
Billi34
Открыл глаза
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

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

Сообщение Billi34 »

Доброго времени суток Коты. Объясните пожалуйста как работает МК в строчке кода if(PINC.B5&&!t) при значениях t ноль и единица. При значении ноль выполняются строки в {} скобках , при значении единица вроде бы не должны выполняться {} скобки, но они выполняются. PINC.B5 в обоих случаях равен единице.

подстановка ! t==1 ничего не поменяла.

Добавлено after 42 minutes 12 seconds:
Получается что !t при t равном единице не ноль. Как это исправить?
Аватара пользователя
ПростоНуб
Собутыльник Кота
Сообщения: 2723
Зарегистрирован: Пт сен 07, 2018 20:20:02
Откуда: деревня в Тульской губернии

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

Сообщение ПростоНуб »

Billi34, !t при t не равном нулю всегда ложь. Так что, раз у Вас выражение if истинно, то t не равно нулю. Покажите весь код.
Аватара пользователя
VladislavS
Собутыльник Кота
Сообщения: 2562
Зарегистрирован: Вт май 01, 2018 19:44:47

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

Сообщение VladislavS »

Billi34, не жалей скобок для расстановки приоритетов операций. На первых порах жить станет сильно легче.
Аватара пользователя
smalcom
Встал на лапы
Сообщения: 128
Зарегистрирован: Пн фев 08, 2016 10:57:14

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

Сообщение smalcom »

t равном единице не ноль.
"Какие ваши доказательства?"
Есть снимок регистра в симуляторе или отладчике?
Аватара пользователя
FeCat
Прорезались зубы
Сообщения: 211
Зарегистрирован: Пт окт 21, 2011 14:39:31

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

Сообщение FeCat »

Задолбался с инклюдами, нету понимания, гугл не помогает МЯУ!!! :cry:
Имею main.cpp в котором первой строчкой #include "main.h".

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

//main.h 
.
.// Всякие инклюды
.
#include "ds18b20.h"
.
.// Всякие инклюды
.
#include "PrintFunc.h"	//	В PrintFunc.cpp почему то не видится объявление из ds18b20.h !!!!!
.
.// Всякие инклюды
.
В ds18b20.h соответственно обьявление класса ds18b20.
В PrintFunc.cpp первой строчкой #include "PrintFunc.h", но в PrintFunc.cpp почему то не видится обьявление класса ds18b20 ('ds18b20' has not been declared) из ds18b20.h хотя он обьявлен раньше.
Если в PrintFunc.h подключить ds18b20.h, то всё видится, но как так то? Ведь в main.h "#include "ds18b20.h" стоит раньше "#include "PrintFunc.h".
Вложения
Safe_moonshine_1.zip
Проект целиком Atmel Studio 7.0
(76.92 КБ) 200 скачиваний
Reflector
Поставщик валерьянки для Кота
Сообщения: 2089
Зарегистрирован: Вс июн 19, 2016 09:32:03

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

Сообщение Reflector »

[uquote="FeCat",url="/forum/viewtopic.php?p=3704784#p3704784"]Если в PrintFunc.h подключить ds18b20.h, то всё видится, но как так то? Ведь в main.h "#include "ds18b20.h" стоит раньше "#include "PrintFunc.h".[/uquote]
#include тупо делает подстановку, т.е. содержимое хедеров добавится в .cpp и в конечном итоге останутся только main.cpp, PrintFunc.cpp и ds18b20.cpp, которые еще и компилируются в произвольном порядке.
arkhnchul
Друг Кота
Сообщения: 3092
Зарегистрирован: Пн апр 06, 2015 11:01:53
Откуда: москва, уфа

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

Сообщение arkhnchul »

[uquote="FeCat",url="/forum/viewtopic.php?p=3704784#p3704784"]Если в PrintFunc.h подключить ds18b20.h, то всё видится, но как так то? Ведь в main.h "#include "ds18b20.h" стоит раньше "#include "PrintFunc.h".[/uquote]вот так то. Когда компилятор собирает PrintFunc.cpp, он совершенно ничего не знает о main.cpp - каждый исходник компилируется изолировано.
Аватара пользователя
FeCat
Прорезались зубы
Сообщения: 211
Зарегистрирован: Пт окт 21, 2011 14:39:31

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

Сообщение FeCat »

Спасибо, когда то читал, но кажись только сейчас начал понимать, когда лбом побился )). Каждый .cpp пользуется только своим набором .h.
И тем не мене опять вопрос с почти теми-же участниками, кто то кого то не хочет видеть.

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

//PrintFunc.h

#include "SensorConf.h" // Если внутри объявить "void print_SensorConf(SensorConf &ptr);" после объявления класса "SensorConf" то всё нормально собирается.
.
.
.
void print_SensorConf(SensorConf &ptr); // Ругается - "variable or field 'print_SensorConf' declared void", 
                                                           // "'SensorConf' was not declared in this scope"
                                                           // "'ptr' was not declared in this scope"
Функция print_SensorConf принимает ссылку на обьект класса, класс обьявлен в SensorConf.h.
arkhnchul
Друг Кота
Сообщения: 3092
Зарегистрирован: Пн апр 06, 2015 11:01:53
Откуда: москва, уфа

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

Сообщение arkhnchul »

целиком код покажите. В каком конкретно месте объявляется print_SensorConf при ругани? В этом случае компилятор считает сие переменной или полем класса, а не прототипом функции, о чем прямо и неоднозначно говорит.
Аватара пользователя
FeCat
Прорезались зубы
Сообщения: 211
Зарегистрирован: Пт окт 21, 2011 14:39:31

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

Сообщение FeCat »

Не собирается если функция print_SensorConf объявляется в PrintFunc.h как в листинге:
Спойлер

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

/*
 * PrintFunc.h
 *
 * Created: 21.09.2019 16:11:05
 *  Author: Admin
 */ 

#ifndef PRINTFUNC_H_
#define PRINTFUNC_H_

//#include "main.h"

#include "stdint.h"
#include "SensorConf.h"	//	Если void print_SensorConf(SensorConf &ptr); - прописать внутри то всё собирается
	
void print_ads1115_value(uint16_t val);
void print_ADC_value(uint16_t val);
void print_Freg100(uint16_t val);
void print_ds18b20_val(int16_t &t);

void print_SensorConf(SensorConf &ptr);		//	Так не собирается

#endif /* PRINTFUNC_H_ */
Объявление класса в SensorConf.h.
Спойлер

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

/* 
* SensorConf.h
*
* Created: 27.04.2019 20:44:02
* Author: Admin
*/

#ifndef SensorConf_h_
#define SensorConf_h_ 



#include <stdint.h>
//#include "pin_macros.h"
//#include "menu.h"
#include "global_vars.h"

//#include "PinDefs.h"

typedef struct{
	bool		DS18B20_Enable;				//	1	<DS18B * ON/OFF>	Вкл/Откл датчика
	uint8_t		Alarm_1_Enable;				//	2	<Alarm 1 ON/OFF>	Разрешение сигнала тревоги 1
	uint8_t		Alarm_1_ifUpTemperature;	//	3	<Alarm 1 if >/<>	Настройка тревоги 1 по превышению(или равно) или понижению(или равно)
	int16_t		Alarm_1_TemperatureVal;		//	4	<Alarm 1 set tC>	Уставка тревоги 1 по температуре
	uint8_t		Action_1_Namber;			//	5	<Choice1 action>	Номер действия для первого аларма
	uint8_t		Alarm_2_Enable;				//	6	<Alarm 2 ON/OFF>	Разрешение сигнала тревоги 2
	uint8_t		Alarm_2_ifUpTemperature;	//	7	<Alarm 1 if >/<>	Настройка тревоги 1 по превышению(или равно) или понижению(или равно)
	int16_t		Alarm_2_TemperatureVal;		//	8	<Alarm 2 set tC>	Уставка тревоги 1 по температуре
	uint8_t		Action_2_Namber;			//	9	<Choice2 action>	Номер действия для второго аларма
	uint8_t		Action_Sensor_ERROR;		//	10
} EEstruct;

using SensorConfEEPROM = EEstruct;

class SensorConf
{
//variables
public:
	public:
	
	SensorConfEEPROM		Conf;						// Настройки в ОЗУ, сохраняемые во шлэше
	
	bool					Check_Alarm(void);			//	Проверка значений датчиков на уставки тревоги. true - тревога.
	unsigned int			AlarmActionsStatus;			//	При алармах тут выставляем флаги.
	bool					AlarmFlag;					//	При любом аларме выставляем флаг, сбрасывается только вручную.
	const signed int		*TValue;					//	Указатель на температуру.
	const bool				*TValueCRC;					//	Указатель на CRC температуры, true-верная.
	
	static bool				SC_eepromERROR;				//	Если при включении eeprom прочти с ошибкой
	unsigned char MenuN;								// номер функцию меню
	
/*
uint8_t		Alarm_1_Enable_EEPROM			EEMEM = 0;
uint8_t		Alarm_1_ifUpTemperature_EEPROM	EEMEM = 1;
uint16_t	Alarm_1_TemperatureVal_EEPROM	EEMEM = (30<<4);
uint8_t		Action_1_Namber_EEPROM			EEMEM = 0;
uint8_t		Alarm_2_Enable_EEPROM			EEMEM = 0;
uint8_t		Alarm_2_ifUpTemperature_EEPROM	EEMEM = 0;
uint16_t	Alarm_2_TemperatureVal_EEPROM	EEMEM = (25<<4);
uint8_t		Action_2_Namber_EEPROM			EEMEM = 0;
uint8_t		Action_Sensor_ERROR_EEPROM		EEMEM = 0;*/

private:
	SensorConfEEPROM *SC_eeprom;					// Указатель на структуру флэша где будем сохранять настройки
	SensorConfEEPROM *SC_eepromXOR;					// Указатель на структуру флэша где будем сохранять XOR настроек
	void menu_1(void);	//	Вкл/откл датчика
	void menu_2(void);	//	<Alarm 1 ON/OFF>	Разрешение сигнала тревоги 1
	void menu_3(void);	//	<Alarm 1 if >/<>	Настройка тревоги 1 по превышению(или равно) или понижению(или равно)
	void menu_4(void);	//	<Alarm 1 set tC>	Уставка тревоги 1 по температуре
	void menu_5(void);	//	<Choice action >	Номер действия для первого аларма
	void menu_6(void);	//	<Alarm 2 ON/OFF>	Разрешение сигнала тревоги 2
	void menu_7(void);	//	<Alarm 1 if >/<>	Настройка тревоги 1 по превышению(или равно) или понижению(или равно)
	void menu_8(void);	//	<Alarm 2 set tC>	Уставка тревоги 1 по температуре
	void menu_9(void);	//	<Choice2 action>	Номер действия для второго аларма
	void menu_10(void);	//	<Sens ERROR act>
	void menu_0(void);
	char RW_EEPROM(bool a=0);	//	true - сохранение, false - восстановление настроек. Возврат 0 если была ошибка.
	
public:
	
	void ToDefoult(void);	//	Сброс к настройкам по умолчанию.
	void menu_start(void);
	
	//void (SensorConf::*Menu[10])(void);	// нулевая и последняя функция в массиве будут выводить в корневое меню
	using FP = void(SensorConf::*) ();
	FP Menu[12]	=	{	&SensorConf::menu_0,
						&SensorConf::menu_1,
						&SensorConf::menu_2,
						&SensorConf::menu_3,
						&SensorConf::menu_4,
						&SensorConf::menu_5,
						&SensorConf::menu_6,
						&SensorConf::menu_7,
						&SensorConf::menu_8,
						&SensorConf::menu_9,
						&SensorConf::menu_10,
						&SensorConf::menu_0};
	
	
	unsigned char Sensor_number;		// Номер датчика
		
protected:
private:
	// Можно сделать статическим...
	void CheckButtonAndSwitchMenu(void);	//	Переключение меню от кнопок LEFT-RIGHT

//functions
public:
	SensorConf(const int*, const bool*, SensorConfEEPROM *eeprom, SensorConfEEPROM *SC_eepromXOR, unsigned char SN);
	SensorConf();
	~SensorConf();
protected:
private:
	SensorConf( const SensorConf &c );
	SensorConf& operator=( const SensorConf &c );

}; //SensorConf


#ifdef MAIN
	#define _Ex
#else
	#define _Ex extern

	_Ex SensorConfEEPROM EEMEM SensorConfEEPROM_1;
	_Ex SensorConfEEPROM EEMEM SensorConfEEPROM_2;
	_Ex SensorConfEEPROM EEMEM SensorConfEEPROM_3;
	_Ex SensorConfEEPROM EEMEM SensorConfEEPROM_4;
	_Ex SensorConfEEPROM EEMEM SensorConfEEPROM_5;

	_Ex SensorConfEEPROM EEMEM SensorConfEEPROM_XOR_1;	// Для контроля целостности
	_Ex SensorConfEEPROM EEMEM SensorConfEEPROM_XOR_2;
	_Ex SensorConfEEPROM EEMEM SensorConfEEPROM_XOR_3;
	_Ex SensorConfEEPROM EEMEM SensorConfEEPROM_XOR_4;
	_Ex SensorConfEEPROM EEMEM SensorConfEEPROM_XOR_5;

	_Ex SensorConfEEPROM SensorConfDefoult;	//	Дефолтные настройки

	_Ex SensorConf SensorConf_1;	// DS18B20_1
	_Ex SensorConf SensorConf_2;	// DS18B20_2
	_Ex SensorConf SensorConf_3;	// DS18B20_3
	_Ex SensorConf SensorConf_4;	// DS18B20_4
	_Ex SensorConf SensorConf_5;	// DS18B20_5

#endif


//void print_SensorConf(SensorConf &ptr);	//	Если раскомментировать, и закомментировать в PrintFunc.h то собирается



#endif /*SensorConf_h_*/
Вложения
Safe_moonshine_1.zip
Проект целиком, как есть. Atmel Studio 7.0
(180.58 КБ) 201 скачивание
arkhnchul
Друг Кота
Сообщения: 3092
Зарегистрирован: Пн апр 06, 2015 11:01:53
Откуда: москва, уфа

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

Сообщение arkhnchul »

а какой конкретно исходник не собирается? Пытаюсь сам разгрести все цепочки инклудов, но тут какая-то совсем мешанина из разряда "так делать не надо")
Аватара пользователя
FeCat
Прорезались зубы
Сообщения: 211
Зарегистрирован: Пт окт 21, 2011 14:39:31

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

Сообщение FeCat »

Понимаю, что накосячил с подключением инклудов. Ругается на файл PrintFunc.h. Конкретно на строку void print_SensorConf(SensorConf &ptr);
Вложения
Safe_moonshine.png
Скриншот
(59.81 КБ) 149 скачиваний
Ответить

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