Вопросы по С/С++ (СИ)
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: Вопросы по С/С++ (СИ)
Представляете какой смачный многовариантный goto можно сделать с помощью оператора switch 
- Реклама
Re: Вопросы по С/С++ (СИ)
БИНГО!!!!!!!!!!!!!!!!!!!
ПаЛуЧиЛоСь.
Заработало как я хотел.
САМ!
САМ!
САМ! Сделал.
Надеюсь прилепился тот файл, с окончательной версией кода.
ПаЛуЧиЛоСь.
Заработало как я хотел.
САМ!
САМ!
САМ! Сделал.
Надеюсь прилепился тот файл, с окончательной версией кода.
- Вложения
-
- NewUnit.c
- (3.14 КБ) 279 скачиваний
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Кошмар.
Вот скажите, зачем Вам нужны такие паузы, когда вся система стоит колом?
Код: Выделить всё
Delay_ms(800) ; //пауза длиной 0.8 секRe: Вопросы по С/С++ (СИ)
Это как говорится "версия для радио". за эти 0.8 сек МК "дергает некоторыми своими ногами". Я сознательно убрал этот код что б вы не пытались его оптимизировать. А попытка оптимизации будет 100% Ваше мышление заточено под ужатие, оптимизацию-поиск изящных решений. А мне вполне достаточно такого вида как у меня. Объем кода очень маленький. Везде умещаюсь.
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Лучше попробуйте делать всё это не в основном цикле, а в прерывании.
Заведите аппаратный таймер, для удобства так, чтобы прерывания срабатывали раз в 1мс. Заведите 1 переменную - счётчик, и 2 переменную - событие.
В прерывании от таймера проверяйте, нажата ли кнопка. Если нажата, счётчик нажатий увеличивайте на 1. Если не нажата, счётчик обнуляйте.
При обнулении счётчика (отпускании кнопки) нужно проверить счётчик, если там больше 100 - значит это было полноценное короткое нажатие. Записываем это короткое нажатие в переменную-событие.
Если кнопка нажата долго, и счётчик досчитал до 600 - значит, в переменную-событие нужно записать информацию о длинном нажатии.
Больше ничего в прерывании делать не надо. Только считать и, при необходимости, обновлять переменную-событие.
В основном цикле программы никаких задержек не нужно. Просто в начале цикла вычитываем переменную событие, с обнулением. Если что-то было - выполняем, если ничего не было - ничего и не делаем.
Всё просто. И ни одной задержки, МК 99.9% времени работает в основном полезном цикле.
Заведите аппаратный таймер, для удобства так, чтобы прерывания срабатывали раз в 1мс. Заведите 1 переменную - счётчик, и 2 переменную - событие.
В прерывании от таймера проверяйте, нажата ли кнопка. Если нажата, счётчик нажатий увеличивайте на 1. Если не нажата, счётчик обнуляйте.
При обнулении счётчика (отпускании кнопки) нужно проверить счётчик, если там больше 100 - значит это было полноценное короткое нажатие. Записываем это короткое нажатие в переменную-событие.
Если кнопка нажата долго, и счётчик досчитал до 600 - значит, в переменную-событие нужно записать информацию о длинном нажатии.
Больше ничего в прерывании делать не надо. Только считать и, при необходимости, обновлять переменную-событие.
В основном цикле программы никаких задержек не нужно. Просто в начале цикла вычитываем переменную событие, с обнулением. Если что-то было - выполняем, если ничего не было - ничего и не делаем.
Всё просто. И ни одной задержки, МК 99.9% времени работает в основном полезном цикле.
- Реклама
Re: Вопросы по С/С++ (СИ)
Каждый должен заниматься своим делом. Это было для души.
Последний раз редактировалось Billi34 Пн сен 09, 2019 11:42:38, всего редактировалось 1 раз.
- WiseLord
- Друг Кота
- Сообщения: 4905
- Зарегистрирован: Чт апр 11, 2013 11:19:59
- Откуда: Минск
- Контактная информация:
Re: Вопросы по С/С++ (СИ)
Ну, если не нужен _понятный_ код, вдвое меньше по размеру и без задержек, в которых МК просто бесполезно висит - то дело хозяйское.
P.S. Вот упрощённый пример для понимания, как это должно работать:
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;
}
Re: Вопросы по С/С++ (СИ)
Я обязательно по изучаю Ваш пример. Уже появились идейки "нарастить" функционал программы.
Сопутствующий вопрос: это всё ещё на Си или уже С++? Будут ли работать операторы из вашего кода в моем компиляторе?
Re: Вопросы по С/С++ (СИ)
Доброго времени суток Коты. Объясните пожалуйста как работает МК в строчке кода if(PINC.B5&&!t) при значениях t ноль и единица. При значении ноль выполняются строки в {} скобках , при значении единица вроде бы не должны выполняться {} скобки, но они выполняются. PINC.B5 в обоих случаях равен единице.
подстановка ! t==1 ничего не поменяла.
Добавлено after 42 minutes 12 seconds:
Получается что !t при t равном единице не ноль. Как это исправить?
подстановка ! 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: Вопросы по С/С++ (СИ)
Billi34, не жалей скобок для расстановки приоритетов операций. На первых порах жить станет сильно легче.
Re: Вопросы по С/С++ (СИ)
"Какие ваши доказательства?"t равном единице не ноль.
Есть снимок регистра в симуляторе или отладчике?
Re: Вопросы по С/С++ (СИ)
Задолбался с инклюдами, нету понимания, гугл не помогает МЯУ!!!
Имею main.cpp в котором первой строчкой #include "main.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".
Имею main.cpp в котором первой строчкой #include "main.h".
Код: Выделить всё
//main.h
.
.// Всякие инклюды
.
#include "ds18b20.h"
.
.// Всякие инклюды
.
#include "PrintFunc.h" // В PrintFunc.cpp почему то не видится объявление из ds18b20.h !!!!!
.
.// Всякие инклюды
.В 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 скачиваний
Re: Вопросы по С/С++ (СИ)
[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, которые еще и компилируются в произвольном порядке.
#include тупо делает подстановку, т.е. содержимое хедеров добавится в .cpp и в конечном итоге останутся только main.cpp, PrintFunc.cpp и ds18b20.cpp, которые еще и компилируются в произвольном порядке.
Re: Вопросы по С/С++ (СИ)
[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 - каждый исходник компилируется изолировано.
Re: Вопросы по С/С++ (СИ)
Спасибо, когда то читал, но кажись только сейчас начал понимать, когда лбом побился )). Каждый .cpp пользуется только своим набором .h.
И тем не мене опять вопрос с почти теми-же участниками, кто то кого то не хочет видеть.
Функция print_SensorConf принимает ссылку на обьект класса, класс обьявлен в SensorConf.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"
Re: Вопросы по С/С++ (СИ)
целиком код покажите. В каком конкретно месте объявляется print_SensorConf при ругани? В этом случае компилятор считает сие переменной или полем класса, а не прототипом функции, о чем прямо и неоднозначно говорит.
Re: Вопросы по С/С++ (СИ)
Не собирается если функция print_SensorConf объявляется в PrintFunc.h как в листинге:
Объявление класса в SensorConf.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
*
* 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 скачивание
Re: Вопросы по С/С++ (СИ)
а какой конкретно исходник не собирается? Пытаюсь сам разгрести все цепочки инклудов, но тут какая-то совсем мешанина из разряда "так делать не надо")
Re: Вопросы по С/С++ (СИ)
Понимаю, что накосячил с подключением инклудов. Ругается на файл PrintFunc.h. Конкретно на строку void print_SensorConf(SensorConf &ptr);
- Вложения
-
- Safe_moonshine.png
- Скриншот
- (59.81 КБ) 149 скачиваний


