Я немного по-другому делаю: Так сложилось что, обычно, системный таймер всегда настраиваю на 1mS и, для дискретных мембранных кнопок, я выставляю время срабатывания 5mS и время отпускания 50mS. По программе - на каждую кнопку один счётчик + два бита ("кнопка нажата" и "факт нажатия"; последний - для передачи в подпрограмму обработки нажатия кнопок).
А что это дает? Если нужен системный таймер на 1 мс, то в его обработчике еще делается счетчик-делитель. В чем смысл разделять дребезг нажатия и дребезг отпускания? И зачем все это делать на каждую кнопку? А если это матрица?
Я правильно понял, мой пичок (PIC10F322) не поддерживает внешних прерываний (например, по нажатию кнопки)?
Неправильно. В этом контроллере есть ОДНО внешнее тактируемое прерывание (INT) и ЧЕТЫРЕ входа прерываний по изменению состояния порта (IOC). Тактируемое не вешают на кнопки. Оно никак не поможет с дребезгом. А IOC применяют для вывода контроллера из сна при нажатии кнопок.
Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества.
Заголовок сообщения: Re: Формирование случайной импульсной последовательности
Добавлено: Пн дек 11, 2017 19:05:13
Открыл глаза
Зарегистрирован: Вс май 28, 2017 19:07:32 Сообщений: 63
Рейтинг сообщения:0
Вот, пока сделал так, как понял, прерывание для опроса клавиш. Правильно ли? Если нет, то что именно неправильно?
Код: Спойлер
Код:
// Подключение нужных библиотек #include <stdio.h> // Стандартная библиотека ввода-вывода #include <stdlib.h> // Стандартная библиотека контроля #include <xc.h> // Специализированная библиотека XC8
// Параметры микроконтроллера #define _XTAL_FREQ 16000000 // Тактовая частота 4 МГц #define BOUNCE 15 // Время в мс для обработки дребезга #define CORRMIN 18 // Число итераций в цикле для задержки в 100 мкс #define CORRMAX 79998 // Число итераций в цикле для задержки в 400000 мкс // CORR - Correction factor
// Параметры сигнала #define SIGNAL 30 // Длительность сигнала в мкс
// Обознаение выводов и кнопок #define START RA2 // Кнопка ПУСК МК #define STOP RA3 // Кнопка СТОП МК #define LED RA0 // Вывод на светодиоды #define GREEN 1 // Сигнал для зеленого светодиода #define RED 0 // Сигнал для красного светодиода #define GENERATOR RA1 // Выход генератора
// Настройка МК #pragma config FOSC = INTOSC // Выбор генератора (внешний/внутренний) #pragma config BOREN = ON // Сброс при потере напряжения питания #pragma config WDTE = ON // Включение/выключение сторожевого таймера #pragma config PWRTE = OFF // Бит разрешения работы таймера включения (PWRTE) #pragma config MCLRE = OFF // Перезагрузка устройства через MCLR #pragma config CP = ON // Бит защиты #pragma config LVP = OFF // Низковольтное программирование #pragma config LPBOR = ON // Перезагрузка процессора при низкой мощности #pragma config BORV = LO // Выбор точки отключения (низкая/высокая) #pragma config WRT = OFF // Защита флеш памяти от записи
int main() // Главная функция { [b] TMR0=0; // Обнуление таймера TMR0[/b] // Объявление параметров конгруэнтного метода g_Random[0] = 1; g_Random[2] = 3; g_Random[3] = 5; Prepare(); // Запуск функции подготовки while(1) // Бесконечный цикл работы { if(g_bStat) // Проверка режима { LED = GREEN; // Включение зеленого светодиода (вкл МК) RandomDelay(); // Запуск функции случайной задержки GENERATOR = 1; // Выставляем лог. 1 на выход генератора __delay_us(SIGNAL); // Задерживаем лог. 1 на выходе GENERATOR = 0; // Обнуляем выход генератора } else { LED = RED; // Включение красного светодиода (выкл МК) } } return 0; }
// Функция подготовки void Prepare() { TRISA = 0b1100; // Направление работы ножек порта А (вход) PORTA = 0b0000; // Очистка порта A OSCCON = (1<<4)|(1<<5)|(1<<6); // Установка IRCF = '111' для частоты в 16 MHz WPUA&=~((1<<0)|(1<<1)|(1<<2)|(1<<3)); // Отключение WEAK PULL-UP ANSELA = 0; // Отключение аналоговой части }
void ButtonInterrupt isr(void) // Прерывание для опроса кнопок { [b]if(TMR0IF)[/b] // Проверка переполнения таймера { if(!START && STOP && !g_bStat) // Проверка на нажатие клавиши старт { __delay_ms(BOUNCE); // Обработка дребезга if(!START && STOP) // Обработка дребезга { g_bStat = 1; // Установка режима МК (вкл) } else { g_bStat = 0; // Установка режима МК (выкл) } } else if(START && !STOP && g_bStat) // Проверка на нажатие клавиши стоп { __delay_ms(BOUNCE); // Обработка дребезга if(START && !STOP) // Обработка дребезга { g_bStat = 0; // Установка режима МК (выкл) } } else if(!START && !STOP && g_bStat) // Защита от дурака { __delay_ms(BOUNCE); // Обработка дребезга if(!START && !STOP) // Обработка дребезга { g_bStat = 0; // Установка режима МК (выкл) } } [b]TMR0IF = 0; // Cбрасываем флаг о переполнении[/b] } }
Вот, НО! Вопрос заключается в том, а как правильно сделать прерывание раз в 10-30 мс? Как рассуждаю я:
0. Я настроил тактовую частоту генератора на 16 МГц в OSCCON . 1. Таймер TMR0 настроен при этом на 8 МГц 2. При такой частоте, таймер переполнится за 256*(1/8) = 32 мкс 3. Мало, нужно получить 20-30 мс, но я же не смогу получить её, даже с предделителем в 256. 4. Вывод - нужно понижать тактовую частоту в OSCCON до 4х МГц, но не хотелось бы.
Как быть?
Вот скрин из даташита, кому интересно:
Спойлер
Как сделать случайную задержку, т.е. чтобы таймер считал до числа N, которое было определено ранее?
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
В чем смысл разделять дребезг нажатия и дребезг отпускания? И зачем все это делать на каждую кнопку? А если это матрица?
Кнопка, для пользователя, должна сработать максимально быстро, но не с "первого пичка" (который может оказаться импульсной помехой), а собственно "дребезг" я убираю на отпускании кнопки. Для каждой кнопки: Почти во всех моих изделиях есть возможность входа в некоторые функции по нажатию (и удержанию) нескольких кнопок в определённой последовательности (по аналогии с Ctrl+Alt+Del). Матричная клавиатура отличается от дискретных кнопок только способом опроса кнопок. Подавление "дребезга" остаётся прежним. Естественно, если по условию, в любой момент времени может быть нажата только одна кнопка - тогда всё намного проще... ----------
SpeedFighter писал(а):
Как быть?
Не забывайте, что на таймеры подаётся FOSC/4. С Timer0 максимальное время 16,384mS (FOSC/4/256/256) при тактовой 16MHz. У PIC10F322 есть ещё Timer2, с которого вы можете получить чуть более 65mS (65,536mS) при тактовой 16MHz.
SpeedFighter писал(а):
чтобы таймер считал до числа N
Таймер всегда даст прерывание при переходе на "0". Перефразируйте задачу: "Надо записать в таймер стартовое значение".
Но я, честно говоря, не понял, в чем преимущество таймера для опроса кнопок в ДАННОЙ программе. А вот преимущество задержки через таймеры - я вижу, но как сделать задержку от 100 мкс до 400 мс, если таймер TMR2 может только до 65 мс задерживать?
Преимущество в "прозрачности" такого алгоритма для остального кода. И отличной переносимости в практически в ЛЮБОЙ код. Делать нужно сразу правильно. Про задержки. Таймер генерирует лишь МИНИМАЛЬНЫЙ ДИСКРЕТ времени, а остальное реализуется ПРОГРАММНЫМ счетчиком ВНУТРИ ОБРАБОТЧИКА прерываний от таймера.
Но я, честно говоря, не понял, в чем преимущество таймера для опроса кнопок в ДАННОЙ программе. А вот преимущество задержки через таймеры - я вижу, но как сделать задержку от 100 мкс до 400 мс, если таймер TMR2 может только до 65 мс задерживать?
Преимущество в "прозрачности" такого алгоритма для остального кода. И отличной переносимости в практически в ЛЮБОЙ код. Делать нужно сразу правильно. Про задержки. Таймер генерирует лишь МИНИМАЛЬНЫЙ ДИСКРЕТ времени, а остальное реализуется ПРОГРАММНЫМ счетчиком ВНУТРИ ОБРАБОТЧИКА прерываний от таймера.
Насчет опроса кнопок: 1. После выполнения функции прерывания, микроконтроллер вернется на какой этап? С того момента, на котором прервался? Даже если был в цикле? 2. Если сделать глобальную переменную и в обработчике прерываний сделать присваивание этой переменной какого-либо числа, то сохранится ли в ней значение?
Насчет опроса кнопок: 1. После выполнения функции прерывания, микроконтроллер вернется на какой этап? С того момента, на котором прервался? Даже если был в цикле? 2. Если сделать глобальную переменную и в обработчике прерываний сделать присваивание этой переменной какого-либо числа, то сохранится ли в ней значение?
1. При выходе из обработчика программа попадет на следующую после прерванной команду. То есть для основного кода прерывания как бы не существуют, при их исполнении выполнение основного кода замирает, а затем восстанавливается ровно с того места на котором произошла остановка. 2. Глобальная переменная измененная в прерывании останется измененной. Но есть несколько другая опасность. Компилятор может проигнорировать часть исходного кода основного цикла, если увидит, что переменная в основном цикле не модифицируется, а так же может произойти ошибка при чтении переменной в основном цикле, если ее разрядность выше разрядности контроллера (прерывание может произойти между чтениями младшей и старшей частями переменной). Поэтому все глобальные переменные, которые модифицируются в прерывании должны при объявлении иметь квалификатор volatile перед типом, например volatile int count; Это позволит компилятору избежать генерации ошибочного кода.
Какую тему не возьми, все в итоге сведется либо к политике, либо к кнопкам, либо к обсуждению крутости ARM. ведь про случайную последовательность тема же была, при чем тут кнопки, прерывания, DMA?!
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Про ДМА разговор не идет. По крайней мере тут. Про прерывания и кнопки разговор идет ровно потому, что автор реализует свое устройство посредством КНОПОК. Про случайную последовательность уже все разобрали. Правила форума не ограничивают круг обсуждаемых вопросов в топике формулировкой заголовка. Тема обсуждения вольна уходить В ЛЮБУЮ ТЕХНИЧЕСКУЮ СТОРОНУ.
Какую тему не возьми, все в итоге сведется либо к политике, либо к кнопкам, либо к обсуждению крутости ARM. ведь про случайную последовательность тема же была, при чем тут кнопки, прерывания, DMA?!
Все просто, стареешь вот и брюзжишь. Делом займись , всяко веселей будет..
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 9
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения