Форум РадиоКот https://radiokot.ru/forum/ |
|
Формирование случайной импульсной последовательности https://radiokot.ru/forum/viewtopic.php?f=58&t=150474 |
Страница 1 из 4 |
Автор: | SpeedFighter [ Сб дек 02, 2017 19:18:47 ] | |||
Заголовок сообщения: | Формирование случайной импульсной последовательности | |||
Здарова, ребята. Тут делаю небольшое устройство (пишу на сишке) на базе пичка (PIC18F1230). Его задачи: Спойлер1. По нажатию кнопки пуск - работать, по нажатию кнопки стоп - не работать.2. Формировать импульсы постоянной длительности со случайными задержками (импульс - 30 мкс, задержка от 100 мкс до 400 мс). 3. Работает - горит зеленый светодиот, не работает - красный. В ходе работы возникли следующие вопросы: 1. Как выбрать правильно МК под мою задачу? СпойлерКак минимум, я могу предположить, что МК должен нормально работать с импульсами, имеющими длительность 30 мкс. Но сейчас, как мне кажется, любой, даже самый дешевый МК может это.Вот я выбрал PIC18F1230, но что-то мне кажется, что это не совсем рационально, т.к. я использую функции в работе только те, которые есть в каждом пичке. 2. Где можно в даташите посмотреть требования к окружающим условиям и к источнику питания (я в английском слаб, хотел бы просто ключевые слова получить, если можно)? 3. Как сделать задержку на определенное время? СпойлерЧитал, что можно сделать задержку через циклы, но я не совсем понимаю, как приблизительно хотя бы прикинуть, сколько времени занимает выполнение одной пустой итерации цикла.Где-то читал, что цикл for выполняется за 3 такта, а частота моего внутреннего генератора вроде бы 4 МГц (Oscillator frequency), так вот, получается, что 1 итерация цикла задерживает работу на: t = 3/F = 3/(4*10^6) = 0,75 мкс. Я взял для уверенности 1 мкс. В итоге я потерпел фиаско, скажем, раз в 15 примерно. Прикладываю картинку выходного сигнала. Сигнал должен был длиться 15 мкс... ![]() 4. Как узнать, что кнопка нажата? 5. Является ли признаком быдло-кода использование оператора goto программировании МК на C? 6. Как правильно настроить биты конфигурации в МК (использую MPLAB X 4.05)? А то я фигню какую-то понастраивал. 7. Какой компилятор оптимальнее всего использовать для решения таких задач? И какие у него должны быть настройки? Прикладываю все важные файлы (проект в протосе, мплабе, изображение пичка) Картинка пичка: Спойлер![]() Код: СпойлерКод: /*#include <pic.h> // Библитека пичков #include <stdio.h>*/ #include <stdlib.h> //#include <pic18f1230.h> // Библиотека конкретного пичка #include <xc.h> // PIC18F1230 Configuration Bit Settings // 'C' source line config statements // CONFIG1H #pragma config OSC = RCIO // Oscillator (External RC oscillator, port function on RA6) #pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled) #pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled) // CONFIG2L #pragma config PWRT = OFF // Power-up Timer Enable bit (PWRT disabled) #pragma config BOR = BOHW // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled)) #pragma config BORV = 3 // Brown-out Reset Voltage bits (Minimum setting) // CONFIG2H #pragma config WDT = ON // Watchdog Timer Enable bit (WDT enabled) #pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768) // CONFIG3L #pragma config PWMPIN = OFF // PWM Output Pins Reset State Control bit (PWM outputs disabled upon Reset) #pragma config LPOL = HIGH // Low-Side Transistors Polarity bit (Even PWM Output Polarity Control bit) (PWM0, PWM2 and PWM4 are active-high (default)) #pragma config HPOL = HIGH // High Side Transistors Polarity bit (Odd PWM Output Polarity Control bit) (PWM1, PWM3 and PWM5 are active-high (default)) // CONFIG3H #pragma config FLTAMX = RA5 // FLTA Mux bit (FLTA input is muxed onto RA5) #pragma config T1OSCMX = LOW // T1OSO/T1CKI MUX bit (T1OSO/T1CKI pin resides on RB2) #pragma config MCLRE = ON // Master Clear Enable bit (MCLR pin enabled, RA5 input pin disabled) // CONFIG4L #pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable bit (Reset on stack overflow/underflow enabled) #pragma config BBSIZ = BB256 // Boot Block Size Select bits (256 Words (512 Bytes) Boot Block size) #pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled) // CONFIG5L #pragma config CP0 = OFF // Code Protection bit Block 0 (000400-0007FF) (Block 0 is not code-protected) #pragma config CP1 = OFF // Code Protection bit Block 1 (000800-000FFF) (Block 1 is not code-protected) // CONFIG5H #pragma config CPB = OFF // Code Protection bit (Boot Block Memory Area) (Boot Block is not code-protected) #pragma config CPD = OFF // Code Protection bit (Data EEPROM) (Data EEPROM is not code-protected) // CONFIG6L #pragma config WRT0 = OFF // Write Protection bit Block 0 (000400-0007FF) (Block 0 is not write-protected) #pragma config WRT1 = OFF // Write Protection bit Block 1 (000800-000FFF) (Block 1 is not write-protected) // CONFIG6H #pragma config WRTC = OFF // Write Protection bit (Configuration Registers) (Configuration registers are not write-protected) #pragma config WRTB = OFF // Write Protection bit (Boot Block Memory Area) (Boot Block is not write-protected) #pragma config WRTD = OFF // Write Protection bit (Data EEPROM) (Data EEPROM is not write-protected) // CONFIG7L #pragma config EBTR0 = OFF // Table Read Protection bit Block 0 (000400-0007FF) (Block 0 is not protected from table reads executed in other blocks) #pragma config EBTR1 = OFF // Table Read Protection bit Block 1 (000800-000FFF) (Block 1 is not protected from table reads executed in other blocks) // CONFIG7H #pragma config EBTRB = OFF // Table Read Protection bit (Boot Block Memory Area) (Boot Block is not protected from table reads executed in other blocks) // #pragma config statements should precede project file includes. // Use project enums instead of #define for ON and OFF. #define SIGNAL 30 // Длительность сигнала в мкс #define DELMIN 100 // Минимальное время задержки в мкс #define DELMAX 400000 // Максимальное время задержки в мкс void delay(int type); // Функция задержки void Prepare(void); // Функция подготовки МК int main() { Prepare(); // Запуск подготовки МК while(1) // Бесконечный цикл, основная задача МК { delay(0); // Задержка межуд сигналами TRISB = 0b00010000; // Подаем на выход лог. единицу delay(1); // Длительность сигнала TRISB = 0b00000000; // Выставляем лог. ноль } return 0; } void delay(int type) // Функция задержки { int N; // Локальная переменная для промежуточных присвоений if(type == 0) { N = DELMIN + rand() % DELMAX; // Формируем случайную задержку } else { N = SIGNAL; // Определяем длительность сигнала } for(int i = 0; i <= N; i++) {} // Держим заданный лог. уровень } // Подготовка МК void Prepare(void) { TRISA = 0b00000000; // Направление работы ножек порта А TRISB = 0b00010000; // Направление работы ножек порта В CMCON = 0x07; // Отключение компараторов PORTA = 0; // Очищаем порт А PORTB = 0; // Очищаем порт Б RBPU = 0; // Подтягивающие R (0-вкл, 1-выкл) }
|
Автор: | КРАМ [ Вс дек 03, 2017 00:42:08 ] |
Заголовок сообщения: | Re: Формирование случайной импульсной последовательности |
Задача действительно простая и может быть реализована практически на любом контроллере, желательно с модулем CCP (Capture-Compare-PWM). Этот модуль позволит аппаратно получать импульсы в 30 мкс. Но можно и без него, просто дергая ногой с программной задержкой в 30 мкс. Единственное, что Вы не сможете получить - True Random. Любая случайная функция будет ПСЕВДОслучайной, то есть иметь какой то интервал повторения. Узнать нажатие кнопки можно опросом порта и маскированием бита на котором висит кнопка. Опрос следует проводить с интервалом большим, чем время дребезга кнопки. Это позволит защититься от этого самого дребезга. Обычно хватает интервала 10...30 миллисекунд. Совершенно непонятно зачем Вам goto для такой задачи. И таки да, на Си этот оператор применять не следует без каких то совершенно безвыходных случаев (я таких не встречал). Температурный диапазон и требования к питанию указаны в разделе электрических параметров (в конце даташита). Факт того, что Вы их не нашли, означает, что Вы их и НЕ ПЫТАЛИСЬ искать. Достаточно посмотреть оглавление. Незнание английского тоже не аргумент, нынче гуглопереводчик доступен так же, как и сам гугол. Выбор Вами контроллера совершенно не обоснован. Ну разве только он единственный есть в наличии. Это очень старый МК и весьма дорогой. |
Автор: | vladlen-from-vrtp [ Вс дек 03, 2017 02:45:09 ] |
Заголовок сообщения: | Re: Формирование случайной импульсной последовательности |
... Единственное, что Вы не сможете получить - True Random. ... Не так давно решено и описано по ссылке в сообщении #593469 . |
Автор: | КРАМ [ Вс дек 03, 2017 05:00:55 ] |
Заголовок сообщения: | Re: Формирование случайной импульсной последовательности |
Это не решение. Это хуже, чем псевдослучайная функция. Патамушта случайная функция подразумевает на выходе белый шум в спектральном интервале квантования, а с WDT получится корреляция с питанием и температурой. А это совсем не случайные величины. То есть матожидание будет следовать за этими величинами. Если человек решает задачи криптографии, то простым будет генератор шума на стабилитроне и ОУ. Сигнал подаем на АЦП и имеем тот самый True Random. А если это типа" елочной гирлянды", то даже тупое повторение таблицы из 256 значений даст более чем отличный результат. |
Автор: | SpeedFighter [ Вс дек 03, 2017 06:52:37 ] |
Заголовок сообщения: | Re: Формирование случайной импульсной последовательности |
Задача действительно простая и может быть реализована практически на любом контроллере, желательно с модулем CCP (Capture-Compare-PWM). Этот модуль позволит аппаратно получать импульсы в 30 мкс. Но можно и без него, просто дергая ногой с программной задержкой в 30 мкс. Единственное, что Вы не сможете получить - True Random. Любая случайная функция будет ПСЕВДОслучайной, то есть иметь какой то интервал повторения. Узнать нажатие кнопки можно опросом порта и маскированием бита на котором висит кнопка. Опрос следует проводить с интервалом большим, чем время дребезга кнопки. Это позволит защититься от этого самого дребезга. Обычно хватает интервала 10...30 миллисекунд. Совершенно непонятно зачем Вам goto для такой задачи. И таки да, на Си этот оператор применять не следует без каких то совершенно безвыходных случаев (я таких не встречал). Температурный диапазон и требования к питанию указаны в разделе электрических параметров (в конце даташита). Факт того, что Вы их не нашли, означает, что Вы их и НЕ ПЫТАЛИСЬ искать. Достаточно посмотреть оглавление. Незнание английского тоже не аргумент, нынче гуглопереводчик доступен так же, как и сам гугол. Выбор Вами контроллера совершенно не обоснован. Ну разве только он единственный есть в наличии. Это очень старый МК и весьма дорогой. 1. Про рандом я знаю, что получаю псевдослучайное число. 2. Спасибо, некоторые нужные строчки в даташите нашел. 3. А какой тогда из современных и недорогих пичков (именно пичок хочу) можно взять? |
Автор: | КРАМ [ Вс дек 03, 2017 07:07:10 ] |
Заголовок сообщения: | Re: Формирование случайной импульсной последовательности |
3. Полагаю, что PIC12F1822 Вас устроит. Если кварцевая точность 30 мкс не нужна (1...2% разброса устроит), то можно еще понизить цену и взять PIC12F1501, а может и PIC10F322. Последний вообще в корпусе SOT23-6, что сделает устройство суперкомпактным. |
Автор: | SpeedFighter [ Вс дек 03, 2017 07:28:29 ] |
Заголовок сообщения: | Re: Формирование случайной импульсной последовательности |
Спасибо, 1-2% вполне устроят. Пока попробую на старом мк доделать полностью, а потом уже попробую на один из этих пичков перенести. Таки да, компактный пичок: Спойлер![]() ОПЪ: Как заставить работать такую строчку: Код: __delay_us(K); где: Код: int K = DELMIN + rand() % DELMAX; Компилятор на это ругается: main.c:5388: error: (800) undefined symbol "__delay$0" main.c:5393: error: (800) undefined symbol "__delay" Но такая строчка работает: Код: __delay_us(SIGNAL); // Длительность сигнала SIGNAL - через #define объявлен. Так же, задержка работает и при большИх значениях (400 000), хотя на форуме англоязычном говорили, что может из-за этого такая ошибка. |
Автор: | Аlex [ Вс дек 03, 2017 10:54:42 ] |
Заголовок сообщения: | Re: Формирование случайной импульсной последовательности |
__delay_us и __delay_ms - это не функции, а встроенные в компилятор макросы. По этому, переменную в них передавать нельзя. Если хотите с переменной, то пишите свою функцию. Но учтите, что частота процессора при этом должна быть достаточной, чтобы отработать 1 цикл в функции задержки за 1 us. |
Автор: | SpeedFighter [ Вс дек 03, 2017 14:12:27 ] |
Заголовок сообщения: | Re: Формирование случайной импульсной последовательности |
__delay_us и __delay_ms - это не функции, а встроенные в компилятор макросы. По этому, переменную в них передавать нельзя. Если хотите с переменной, то пишите свою функцию. Но учтите, что частота процессора при этом должна быть достаточной, чтобы отработать 1 цикл в функции задержки за 1 us. Вот проблема как раз в том, что я сам писал задержку через пустой цикл for, но увы, потерпел фиаско, слишком неточно. |
Автор: | КРАМ [ Вс дек 03, 2017 14:33:31 ] |
Заголовок сообщения: | Re: Формирование случайной импульсной последовательности |
точные задержки делают на таймере и прерываниях. |
Автор: | SpeedFighter [ Пн дек 04, 2017 20:48:15 ] |
Заголовок сообщения: | Re: Формирование случайной импульсной последовательности |
Я столкнулся ещё с одной неопределенностью. Как правильно назначить направление портов? Я сделал так и все работает*: Код: TRISA = 0b11111111; // Направление работы ножек порта А (вход) TRISB = 0b00000000; // Направление работы ножек порта В (выход) Под работает я понимаю, что на выходе получаю то, что хочу. Но в некоторых гайдах я встречал, что для входа наоборот, нужно ставить все нули, а для выхода - единицы. |
Автор: | КРАМ [ Вт дек 05, 2017 03:43:16 ] |
Заголовок сообщения: | Re: Формирование случайной импульсной последовательности |
TRISA/TRISB - означает Tri-state - третье состояние, то есть отключенное состояние ВЫХОДНОГО буфера. Таким образом, 1 в регистре TRIS означает чистый вход, а 0 - выход и вход одновременно (можно прочесть значение выхода). Не забывайте, что помимо ТRIS ногой управляет аналоговая функция этой ноги, если она присутствует. Включение аналоговой функции отключает цифровой вход. |
Автор: | 7seg [ Вт дек 05, 2017 04:49:49 ] |
Заголовок сообщения: | Re: Формирование случайной импульсной последовательности |
Как-то делал генератор случайных чисел . и за основу взял импульсы дребезга контактов вполне не плохо получается. |
Автор: | diplodok [ Вт дек 05, 2017 09:46:54 ] |
Заголовок сообщения: | Re: Формирование случайной импульсной последовательности |
Посмотри здесь. После получения случайного числа используй модуля ССР в режиме "сравнение установка выхода в 1/0" (compare set/clear output) для получения своей последователности. |
Автор: | SpeedFighter [ Вт дек 05, 2017 15:37:49 ] |
Заголовок сообщения: | Re: Формирование случайной импульсной последовательности |
Спасибо. А вот я что ещё прикинул: Есть функция srand(чиселка), которая выполняет инициализацию генератора случайных чисел rand(). С помощью неё я хочу и запустить псевдогенератор на пички, вставляя в srand предыдущее сгенерированное число. А первое число можно получить из rand(), например. |
Автор: | ARV [ Вт дек 05, 2017 19:59:33 ] |
Заголовок сообщения: | Re: Формирование случайной импульсной последовательности |
Первое число лично я получаю следующим образом: сразу после подачи питания (определяю по флагам), еще до того момента, когда Си очистит память статических переменных, подсчитываю CRC16 всей памяти, что доступна, ну или заметного её куска. И уже эту CRC использую в качестве стартового для srand. Так как после подачи питания RAM имеет случайное состояние, получается почти настоящая случайность. Во всяком случае получше srand(rand()), что вы предложили. |
Автор: | SpeedFighter [ Ср дек 06, 2017 21:16:12 ] | |||
Заголовок сообщения: | Re: Формирование случайной импульсной последовательности | |||
На PIC18F1230 я сделал, все работало, пусть и через костыли (не смог отключить АЦП на выводах RA0 и RA1, подключил к другим - все работало). На PIC10F322 - все не так гладко. Почему-то не загорается красный светодиод при отсутствии входных сигналов. Прикладываю схему из протоса и код. Код: СпойлерКод: // Подключение нужных библиотек #include <stdio.h> #include <stdlib.h> #include <xc.h> #define _XTAL_FREQ 8000000 // Тактовая частота 4 МГц #define SIGNAL 30 // Длительность сигнала в мкс #define DELMIN 100 // Максимальная задержка в мкс #define DELMAX 400000 // Максимальная задержка в мкс // PIC10F322 Configuration Bit Settings // 'C' source line config statements // CONFIG #pragma config FOSC = EC // Oscillator Selection bits (EC: CLKIN function enabled) #pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled) #pragma config WDTE = OFF // Watchdog Timer Enable (WDT enabled) #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled) #pragma config MCLRE = OFF // MCLR Pin Function Select bit (MCLR pin function is digital input, MCLR internally tied to VDD) #pragma config CP = ON // Code Protection bit (Program memory code protection is enabled) #pragma config LVP = ON // Low-Voltage Programming Enable (Low-voltage programming enabled) #pragma config LPBOR = ON // Brown-out Reset Selection bits (BOR enabled) #pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.) #pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off) // #pragma config statements should precede project file includes. // Use project enums instead of #define for ON and OFF. void Prepare(); // Функция подготовки МК int main() { Prepare(); // Запуск функции подготовки int K = 4; while(1) // Бесконечный цикл работы { if(RA3 == 1) // Проверка на нажатые кнопки { RA2 = 1; // Зажигаем зеленый светодиод srand(K); // Инициализация генератора случайных импульсов K = DELMIN + rand ()% DELMAX; // Присвоение псевдослучайного числа for(int i = 0; i <= K/60; i++) {} // Пустой цикл задержки //__delay_us(SIGNAL-4); // Определяем задержку RA1 = 1; // Подаем на выход лог. единицу __delay_us(SIGNAL-2); // Определяем длительность сигнала RA1 = 0; // Подаем на выход лог. ноль } else { RA2 = 0; // Зажигаем красный светодиод RA1 = 0; // На выход ставил лог. ноль } } return 0; } // Функция подготовки void Prepare() { TRISA = 0b1000; // Направление работы ножек порта А (вход) PORTA = 0b0000; // очищаем порт А } Схема: Спойлер![]()
|
Автор: | diplodok [ Ср дек 06, 2017 22:23:35 ] |
Заголовок сообщения: | Re: Формирование случайной импульсной последовательности |
Читаем документацию на 10F322 LVP = 1 - MCLR/Vpp pin is MCLP. Weak Pull-Up is enabled. Твой код не может определить 1 на входе. Там всегда есть 1. |
Автор: | КРАМ [ Чт дек 07, 2017 03:00:58 ] |
Заголовок сообщения: | Re: Формирование случайной импульсной последовательности |
Вообще непонятна история с двумя кнопками на одном входе. Что автор хотел получить? Впрочем, со светодиодами такая же история. Светодиоды нельзя будет погасить оба. |
Автор: | SpeedFighter [ Чт дек 07, 2017 05:07:25 ] |
Заголовок сообщения: | Re: Формирование случайной импульсной последовательности |
Читаем документацию на 10F322 LVP = 1 - MCLR/Vpp pin is MCLP. Weak Pull-Up is enabled. Твой код не может определить 1 на входе. Там всегда есть 1. А как убрать её? #pragma config LVP = OFF - не помогает. КРАМ писал(а): Вообще непонятна история с двумя кнопками на одном входе. Что автор хотел получить? Впрочем, со светодиодами такая же история. Светодиоды нельзя будет погасить оба. Нажатая кнопка включения - все работает. Не нажата кнопка включения или нажата кнопка выключения - МК не генерирует сигнал, только светодиод красный горит. На PIC18F1230 у меня все работало, тут же - нет. |
Страница 1 из 4 | Часовой пояс: UTC + 3 часа |
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |