Jump to content

WinneR

Members
  • Content Count

    58
  • Joined

  • Last visited

Community Reputation

0 Обычный

About WinneR

  • Rank
    Осваивающийся

Информация

  • Город
    Екатеринбург

Электроника

  • Стаж в электронике
    3-5 лет
  • Сфера радиоэлектроники
    Светотехника

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Я конечно извиняюсь, но Вы пишите про 2 часа усиленного штудирования, а сами используйте delay. В 8 меге ещё 2 таймера есть! Зачем эта куча задержек??? Можно же функцию написать, которая раз в 10 меньше кода будет занимать.
  2. Я считаю, что да, flag2 вовсе можно не использовать. Я просто его добавил для обнуления переменной bcount. Сразу отвечу зачем. Для того если в если в момент нажатия кнопки значение переменной близко к её переполнению не произошло ничего непредвиденного. Вопрос то с ретурном, почему без него не работает? а с ним почти всё хорошо! Если бы я знал где проблема кроется....
  3. Итак проблему с кодом я частично решил)) Но есть нюанс, обнуление таймера происходит только при повторном нажатии кнопки сброса... почему так? этого я пока не пойму. И ещё вопрос специалистам, почему если не делать return в функции Button_state, она тупо не работает, таймер не стартует???? Вот сам код. #include "add.h" uint8_t NUM[12] = {63, 6, 91, 79, 102, 109, 125, 7, 127, 111, 57, 99}; // 9 0b01101111 // 0 1 2 3 4 5 6 7 8 9 C о volatile uint16_t bcount = 0; // счетчик для подавления дребезга uint16_t Timer_count = 0; // число для отсчёта таймером bool Timer_status = 0; // статус таймера volatile bool Timer_finished = 0; // завешение раблты таймера void read_encoder() { static bool a=0; if (!a) { if (Up0||Down0) { a=1; if (Up0) { if(!Timer_status) if (Timer_count<9999) Timer_count++; } if (Down0) { if(!Timer_status) if (Timer_count>0) Timer_count--; } } } if (Up1&&Down1) a = 0; } void Button_state(bool *lp, bool *sp) { static uint16_t smillis = 0; static uint8_t flag = 0; static uint8_t flag2 = 0; if(bit_is_clear(PINB,0)) { if(!flag2) {cli(); bcount=0; sei(); flag2=1;} if(!smillis) smillis = bcount; if(!flag && bcount-smillis > 500) { flag = 1; (*lp) = 1; } else (*lp) = 0; } if(smillis && !(bit_is_clear(PINB,0))) { if(bcount-smillis <= 500 && bcount-smillis > 20) (*sp) = 1; else (*sp) = 0; smillis = 0; flag = 0; } return 0; flag2 = 0; } ISR(TIMER2_OVF_vect) { if( Timer_status && Timer_count != 0) Timer_count--; if(Timer_count==0 && Timer_status) { if(Timer_status) Timer_status=0; PORTB |=_BV(1); } } ISR (TIMER0_OVF_vect) { bcount++; static uint8_t i=0; i=++i%5; if(i==0) { OFF(3); PORTD = NUM[N1]; ON(0); } if(i==1) { OFF(0); PORTD = NUM[N2]; ON(1); } if(i==2) { OFF(1); PORTD = NUM[N3]; ON(2); } if(i==3) { OFF(2); PORTD = NUM[N4]; ON(3); } } int main(void) { bool Long_press = 0; // длительное нажаие кнопки bool Short_press = 0; // корткое нажаие кнопки DDRD = 255; PORTD = 0; // разряды DDRC = 0b00001111; PORTC = 0; // сегменты, + - энкодера DDRB |=(1<<2) | (1<<1); // светодиоды, кнопка энкодера PORTB = 0b00000000; cli(); TIMSK |= (1 << TOIE0); TCCR0 |= (1<<CS01) | (1<<CS00); TCCR0 &= ~((1<<CS02)); // | (1<<CS00)); // без предделителя TCNT0 = 0; ASSR |= (1 << AS2); // Включаем асинхронный режим T2 TCNT2 = 0; // Сбрасываем регистр счета while(ASSR != (0b00001000)) asm ("nop"); // дожидаемся разрешения на запись TCCR2 = 0b00000101; // Предделитель на 128 TIMSK |= (1 << TOIE2); // Разрешаем прерывание по переполнению TIFR = 0; sei(); while (1) { read_encoder(); Button_state(&Long_press, &Short_press); separation(Timer_count); if(Short_press) if(!Timer_status) Timer_status = 1; // короткое нажатие, запуск таймера if(Long_press) { // длительное нажатие кнопки, обнуление срабатывания таймера if(Timer_count==0 && !Timer_status) { if(Timer_status) Timer_status=0; PORTB &=~_BV(1); } } } }
  4. Нее, неё я не кричу) Просто я хочу прописать основной функционал не в функции Button_state, а в основном цикле программы. Для этого мне нужно возвращать функцией значение переменных и работать уже с ними. Значение то возвращаются, но работает код некорректно. Вот в этом и проблема. Насчёт рабочего кода, скину вечером, как приду с работы.
  5. Я просто в контексте предложения не понял, что имеется ввиду. По поводу ошибки функция неоднократно использовалась мной и не только мной. Единственное, что я добавил, это обнуление переменной при нажатии кнопки. И ещё раз повторюсь ЕСЛИ РЕАЛИЗОВЫВАТЬ ТОТ ФУНКЦИОНАЛ, КОТОРЫЙ МНН НУЖЕН ВНУТРИ ЭТОЙ ФУНКЦИИ, ТО ВСЁ РАБОТАЕТ КАК ПОЛОЖЕНО.
  6. Я подавляю дребезг только кнопки энкодера и одновременно реализуется отслеживание длительного и короткого её нажатия. 0 таймер работает с частотой 125000 Гц, а 2 работает в асинхронном режиме от внешнего часового кварца. Попробовал uint8_t Button_state() { static uint16_t smillis = 0; static uint8_t flag = 0; static uint8_t flag2 = 0; if(bit_is_clear(PINB,0)) { if(!flag2) {cli(); bcount=0; sei(); flag2=1;} if(!smillis) smillis = bcount; if(!flag && bcount-smillis > 500) { flag = 1; //PORTB ^=_BV(1); return Long_press; } //else Long_press = 0 } if(smillis && !(bit_is_clear(PINB,0))) { if(bcount-smillis <= 500 && bcount-smillis > 20) return Short_press; //PORTB ^=_BV(2); //else Short_press = 0; smillis = 0; flag = 0; } flag2 = 0; } Не работает((в вайле просто пытаюсь инвертировать значение пина, светодиод тупо горит... while (1) { read_encoder(); Button_state(); separation(Timer_count); if(Long_press) PORTB ^=_BV(1); //if(Short_press) PORTB ^=_BV(2); } Интересней то, что если реализовывать весь функционал напрямую в функции Button_state(), то все работает как положено, но... функция есть функция, по моему мнению, она должна выполнять только свою работу.
  7. Нуу... Пишу как умею) Просто не весь функционал ещё реализован. Проблема в том, что я не могу вернуть из функции 2 значения, ни через глабальные переменные, ни через указатели, переданные в функцию в качестве аргументов, точнее они возвращаются, но работает это все некорректно. Что касается кода, тут всё , как я считаю, довольно просто. В функции read_encoder происходит считывание энкодера, соответственно прибавляется или уменьшается переменная Timer_count. Далее если нажать кнопку энкодера, значение которой считываеся функцией Button_state, значение переменной Timer_status меняется на противоположное(эта строчка не прописана в коде) и в обработчик прерываний 2 таймера начинается обратный отчёт. По завершении отчёта, также о обработчике инвертировалось значение светодиода, просто как индикация срабатывания таймера.
  8. Всех приветствую! Появилось немного времени поработать над кодом таймера. Вот код в мейне #include "add.h" uint8_t NUM[12] = {63, 6, 91, 79, 102, 109, 125, 7, 127, 111, 57, 99}; // 9 0b01101111 // 0 1 2 3 4 5 6 7 8 9 C о volatile uint16_t bcount = 0; // счетчик для подавления дребезга uint16_t Timer_count = 0; // число для отсчёта таймером bool Timer_status = 0; // статус таймера volatile bool Timer_finished = 0; // завешение раблты таймера bool Long_press = 0; // длительное нажаие кнопки bool Short_press = 0; // корткое нажаие кнопки void Button_state(); uint8_t read_encoder() { static bool a=0; uint8_t b=0; if (!a) { if (Up0||Down0) { a=1; if (Up0) { if(!Timer_status) if (Timer_count<9999) Timer_count++; } if (Down0) { if(!Timer_status) if (Timer_count>0) Timer_count--; } } } if (Up1&&Down1) a = 0; return b; } void Button_state() { static uint16_t smillis = 0; static uint8_t flag = 0; static uint8_t flag2 = 0; if(bit_is_clear(PINB,0)) { if(!flag2) {cli(); bcount=0; sei(); flag2=1;} if(!smillis) smillis = bcount; if(!flag && bcount-smillis > 500) { flag = 1; PORTB ^=_BV(1); } } if(smillis && !(bit_is_clear(PINB,0))) { if(bcount-smillis <= 500 && bcount-smillis > 20) PORTB ^=_BV(2);; smillis = 0; flag = 0; } return 0; flag2 = 0; } ISR(TIMER2_OVF_vect) { if( Timer_status && Timer_count != 0) { Timer_count--; //PORTB ^=_BV(2); } if(Timer_count==0 && Timer_status) { //Timer_finished = 1; if(Timer_status) Timer_status=0; //PORTB ^=_BV(1); } } ISR (TIMER0_OVF_vect) { bcount++; static uint8_t i=0; i=++i%5; if(i==0) { OFF(3); PORTD = NUM[N1]; ON(0); } if(i==1) { OFF(0); PORTD = NUM[N2]; ON(1); } if(i==2) { OFF(1); PORTD = NUM[N3]; ON(2); } if(i==3) { OFF(2); PORTD = NUM[N4]; ON(3); } } int main(void) { DDRD = 255; PORTD = 0; // разряды DDRC = 0b00001111; PORTC = 0; // сегменты, + - энкодера DDRB |=(1<<2) | (1<<1); // светодиоды, кнопка энкодера PORTB = 0b00000000; cli(); TIMSK |= (1 << TOIE0); TCCR0 |= (1<<CS01) | (1<<CS00); TCCR0 &= ~((1<<CS02)); // | (1<<CS00)); // без предделителя TCNT0 = 0; ASSR |= (1 << AS2); // Включаем асинхронный режим T2 TCNT2 = 0; // Сбрасываем регистр счета while(ASSR != (0b00001000)) asm ("nop"); // дожидаемся разрешения на запись TCCR2 = 0b00000101; // Предделитель на 128 TIMSK |= (1 << TOIE2); // Разрешаем прерывание по переполнению TIFR = 0; sei(); while (1) { read_encoder(); Button_state(); separation(Timer_count); //if(Long_press) PORTB ^=_BV(1); //if(Short_press) PORTB ^=_BV(2); } } Загвоздка вот в чем... Имеется функция Button_state, которая считывает длительное и короткое нажатие кнопки. Внутри функции все работает как положено. Но... мне хотелось прописать основную логику не в самой функции Button_state, а в основном цикле while. Недолго думая, создал 2 глобальные переменные Long_press и Short_press, в функции я просто присваиваю им 1 если выполнилось нужное действие. Вот так это безобразие выглядит... void Button_state() { static uint16_t smillis = 0; static uint8_t flag = 0; static uint8_t flag2 = 0; if(bit_is_clear(PINB,0)) { if(!flag2) {cli(); bcount=0; sei(); flag2=1;} if(!smillis) smillis = bcount; if(!flag && bcount-smillis > 500) { flag = 1; //PORTB ^=_BV(1); Long_press = 1; } else Long_press = 0; } if(smillis && !(bit_is_clear(PINB,0))) { if(bcount-smillis <= 500 && bcount-smillis > 20) Short_press = 1;//PORTB ^=_BV(2); else Short_press = 0; smillis = 0; flag = 0; } return 0; flag2 = 0; } Но к сожалению, работать эта конструкция не захотела, если в мейне просто попробовать включать и выключать светодиоды if(Long_press) PORTB ^=_BV(1); if(Short_press) PORTB ^=_BV(2); Ничего не получается индикатор мерцает(работу симулирую в протеусе) Светодиоды то включатся, то не включатся, короче херня полная. Ну ладно подумал я и решил попробовать передать в качестве аргументов в функцию адреса переменных Long_press и Short_press с помощью указателей, внутри функции с указателями работал точно по такому же принципу как и с глобальными переменными. Но, увы и при таком подходе результат я получил похожий на первый((( Подскажите люди добрые, что я делаю не так??????????
  9. На тему вольтметров куча видео, например это или вот это. Вроде там всё просто и понятно))
  10. @IMXO Большое спасибо за помощь! Сделал всё как Вы сказали и всё заработало. У меня ещё есть пара вопросов по этому коду, но это уже завтра, сегодня я уже всё.... Почитай вот эту тему, думаю станет более понятно как работает битовый сдвиг
  11. Спасибо! Вечером буду пробовать, о результатах отпишусь!
  12. Но тогда, как быть с main.cpp? Переименовать в с? Несовсем понятно с глобальным переменными. У меня переменные N1-N4 используются и в main.cpp и в add.с, в каком из файлов я могу присвоить им начальное значение, а в каком просто объявить?
  13. Про тайпдеф и дефайн я знаю, а вот про stdbool не знал. Спасибо! Вот вопрос, решит ли добавление проблему? Я уже писал в первом сообщении, что если функция не использует глобальных переменных, то все гуд. Соответственно я делаю вывод, что проблема в них. А может и нет... Т. Е попробовать вместо add. с создать add. cpp?
×
×
  • Create New...