Доброго времени суток! Есть ли возможно оптимизировать этот код? Прерывание срабатывает по одному из 4-х аппаратных таймеров. Один тик - одна точка измерения(АЦП) и формирование (задание для ШИМ) синусоиды выхода. Частота ШИМ модуляции 70...120 кГц (задаётся при калибровке), частота этого таймера высчитывается другой функцией в зависимости от требуемой частоты выходного сигнала. Быстрое прерывание: Код на Си: Код (C++): void FIQ_Handler (void) __irq { uint16_t lflag1; uint16_t *ldat_addr; uint16_t datadc; int16_t *lpw_addr; datadc = ADCDAT >> 16; lpw_addr = pw_addr; PWMA = *lpw_addr; lflag1 = flag1; if(lflag1 & _adc_start) //если измерение периода запущено { ldat_addr = dat_addr; *ldat_addr = datadc; ldat_addr++; if(!(ldat_addr < max_dat_addr)) //конец измерения для периода { ldat_addr = dat_addr_null; //начало в массиве для нового измерения lflag1 &= (~(_adc_start)); //измерение периода завершено } dat_addr = ldat_addr; } lpw_addr++; if(!(lpw_addr < max_pw_addr)) //конец периода сигнала { lpw_addr = &pw[0]; //новый адрес массива периода для ШИМ if(lflag1 & _adc_on) //если надо начать измерения { lflag1 |= _adc_start; //запуск измерения периода lflag1 &= (~(_adc_on)); //сброс команды "надо измерять" } } pw_addr = lpw_addr; flag1 = lflag1; T1CLRI = 0x01; } Где глобально определены: Код (C++): // signed short *pw_addr; signed short *pw_addr_nul; signed short *max_pw_addr // unsigned short *dat_addr; unsigned short *dat_addr_null; unsigned short *max_dat_addr; unsigned short *max_dat_addrI; unsigned short *dat_addr_nullI; unsigned short *max_dat_addrU; unsigned short *dat_addr_nullU; // uint16_t flag1; #define _adc_start 0x0001 //начало/конец измерения тока/напряжения #define _adc_on 0x0002 //включение измерения тока/напряжения сигнала uint16_t flag2; //#define _adc_t 0x0004 //измерение температуры //#define _adc_i 0x0008 //измерение тока //#define _adc_u 0x0010 //измерение напряжения //#define _DC_DC_On 0x0020 //состояние преобразователя напряжения (1 - включен) #define _f_int 0x0040 //флаг прерывания от FLASH #define _F_Calibrate 0x0080 //флаг калибровки //#define _set_sin 0x0100 //флаг пересчёта синусоиды #define _Pout_Err 0x0200 //перегрузка по мощности #define _OutCorr 0x0400 //флаг коррекции выхода #define _F_Work_On 0x0800 //устройство включено //#define _F_12_Err 0x1000 //ошибка напряжения питания устройства //#define _dac_set 0x2000 //задание на преобразователь установлено #define _Rerr 0x4000 //высокое сопротивление/обрыв #define _G_Draw 0x8000 //вывод заставки на экран Результат компиляции на ассемблере: Код (Text): ; generated by ARM C/C++ Compiler, 4.1 [Build 894] ; commandline ArmCC [--thumb --list --debug -c --asm --interleave -og_fiq.o --asm_dir=.\ --list_dir=.\ --depend=g_fiq.d --apcs=interwork -O0 -Otime -IC:\Keil_v4.54\ARM\RV31\Inc -IC:\Keil_v4.54\ARM\CMSIS\Include -IC:\Keil_v4.54\ARM\Inc\ADI -D__MICROLIB --omf_browse=g_fiq.crf G_Fiq.c] ARM AREA ||.text||, CODE, READONLY, ALIGN=2 FIQ_Handler PROC ;;;65 ;;;66 void FIQ_Handler (void) __irq 000000 e92d101f PUSH {r0-r4,r12} ;;;67 { ;;;68 uint16_t lflag1; ;;;69 uint16_t *ldat_addr; ;;;70 uint16_t datadc; ;;;71 int16_t *lpw_addr; ;;;72 datadc = ADCDAT >> 16; 000004 e59fc0a8 LDR r12,|L1.180| 000008 e59cc000 LDR r12,[r12,#0] 00000c e1a0382c LSR r3,r12,#16 ;;;73 lpw_addr = pw_addr; 000010 e59fc0a0 LDR r12,|L1.184| 000014 e59c2000 LDR r2,[r12,#0] ; pw_addr ;;;74 PWMA = *lpw_addr; 000018 e1d2c0f0 LDRSH r12,[r2,#0] 00001c e3a04000 MOV r4,#0 000020 e504c3ec STR r12,[r4,#-0x3ec] ;;;75 lflag1 = flag1; 000024 e59fc090 LDR r12,|L1.188| 000028 e1dc00b0 LDRH r0,[r12,#0] ; flag1 ;;;76 if(lflag1 & _adc_start) 00002c e3100001 TST r0,#1 000030 0a00000c BEQ |L1.104| ;;;77 { ;;;78 ldat_addr = dat_addr; 000034 e59fc084 LDR r12,|L1.192| 000038 e59c1000 LDR r1,[r12,#0] ; dat_addr ;;;79 *ldat_addr = datadc; 00003c e1c130b0 STRH r3,[r1,#0] ;;;80 ldat_addr++; 000040 e2811002 ADD r1,r1,#2 ;;;81 if(!(ldat_addr < max_dat_addr)) 000044 e59fc078 LDR r12,|L1.196| 000048 e59cc000 LDR r12,[r12,#0] ; max_dat_addr 00004c e151000c CMP r1,r12 000050 3a000002 BCC |L1.96| ;;;82 { ;;;83 ldat_addr = dat_addr_null; 000054 e59fc06c LDR r12,|L1.200| 000058 e59c1000 LDR r1,[r12,#0] ; dat_addr_null ;;;84 lflag1 &= (~(_adc_start)); 00005c e3c00001 BIC r0,r0,#1 |L1.96| ;;;85 } ;;;86 dat_addr = ldat_addr; 000060 e59fc058 LDR r12,|L1.192| 000064 e58c1000 STR r1,[r12,#0] ; dat_addr |L1.104| ;;;87 } ;;;88 lpw_addr++; 000068 e2822002 ADD r2,r2,#2 ;;;89 if(!(lpw_addr < max_pw_addr)) 00006c e59fc058 LDR r12,|L1.204| 000070 e59cc000 LDR r12,[r12,#0] ; max_pw_addr 000074 e152000c CMP r2,r12 000078 3a000004 BCC |L1.144| ;;;90 { ;;;91 lpw_addr = &pw[0]; 00007c e59f204c LDR r2,|L1.208| ;;;92 if(lflag1 & _adc_on) 000080 e3100002 TST r0,#2 000084 0a000001 BEQ |L1.144| ;;;93 { ;;;94 lflag1 |= _adc_start; 000088 e3800001 ORR r0,r0,#1 ;;;95 lflag1 &= (~(_adc_on)); 00008c e3c00002 BIC r0,r0,#2 |L1.144| ;;;96 } ;;;97 } ;;;98 pw_addr = lpw_addr; 000090 e59fc020 LDR r12,|L1.184| 000094 e58c2000 STR r2,[r12,#0] ; pw_addr ;;;99 flag1 = lflag1; 000098 e59fc01c LDR r12,|L1.188| 00009c e1cc00b0 STRH r0,[r12,#0] ; flag1 ;;;100 T1CLRI = 0x01; 0000a0 e3a0c001 MOV r12,#1 0000a4 e59f4028 LDR r4,|L1.212| 0000a8 e584c32c STR r12,[r4,#0x32c] ;;;101 } 0000ac e8bd101f POP {r0-r4,r12} 0000b0 e25ef004 SUBS pc,lr,#4 ;;;102 ENDP |L1.180| DCD 0xffff0510 |L1.184| DCD pw_addr |L1.188| DCD flag1 |L1.192| DCD dat_addr |L1.196| DCD max_dat_addr |L1.200| DCD dat_addr_null |L1.204| DCD max_pw_addr |L1.208| DCD ||pw|| |L1.212| DCD 0xffff0000 Смысл вот в чём: - Надо читать данные из АЦП быстро по прерыванию, размещать их в массив в теле функции определив новый адрес в массиве. - Надо брать данные из массива и записывать в регистр ШИМ быстро по прерыванию, определять новый адрес в месте массива. Данная функция читает данные измерения тока и напряжения в разные единицы времени... соответственно два разных массива. Массив для ШИМ един, он для формирования формы сигнала. Параметр flag1 - биты устанавливаются другой функцией другого прерывания обычного IRQ. Таким образом один период измеряется напряжение, другой период измеряется ток, и между ними напряжение питания и прочее через один многоканальный АЦП. Выбор каналов и запуск измерений в функции прерывания IRQ, всё синхронизировано битами параметра flag1. Смысл в том, что измерения могут стартовать только с началом периода выхода. В ШИМ данные записываются всегда согласно периоду выходного сигнала. Я вроде сделал минимальное количество обращений к памяти. Может есть место где ускорить? Как Вы думаете? Спасибо!
Всех приветствую - подскажите пожалуйста будет ли микросхема ch340c с внутренним кварцем работать также стабильно как с буквой G. Буду закладывать - экспериментировать некогда - СПАСИБО!
https://github.com/UnfinishedStuff/CH340C ".. Единственная проблема, с которой я столкнулся, это то, что требуется конденсатор 0,1 мкФ на выводе V3. У меня создалось впечатление, что это был выход 3v3, но хотя я не могу прочитать его описание в таблице данных CH340C, лист FT232 отмечает, что аналогичный конденсатор с их чипом необходим для обеспечения 3v3 для самого чипа для определенных функций. , так что, по-видимому, это также относится к CH340C. Без этого конденсатора ПК с Windows не распознает USB-устройство." ПС. Это перевод текста с сайта !
Спасибо - если светодиоды-индикаторы не нужны и общение будет между 5 вольтовой логикой, для чего 1.5кОм на линии передатчика в схеме предназначен? Лучше предусмотреть его?
Это называется - береженого бог бережет. Поставьте по резистору 1 ком в оба пина 2, 3. Если оставите цепи светодиодов - они должны стоять ЗА этими резисторами - ближе к разъёму. ПС. Переходник готовый - стОит копейки. Дороже по комплектующим будет. Полезного для проф. опыта, сборка этого девайса не принесет абсолютно.
нет мне надо юсб гнездо а не штекер - это во-первых, во - вторых без кварца и конденсаторов - плата меньше, стоимость 80 рублей для модулей - в рассыпухе - 35 рублей Переходник будет в составе устройства - на одной плате
В первых Ардуинах только такая и была. У меня работает. Скорее всего для стаховки видел такое—рекомендуют ставить на случай КЗ. От 300 ом до 1.5 ком. У меня работает и так.
Доброго времени суток! Вот это от скуки: Код (C++): /* вывод дампа *buf - начальный вдрес массива(структуры и др.) size - размер байта для вывода */ void outhex(uint8_t *buf, int size) { int cnt = 0, cnt2 = 0; printf("\n%04X: ",cnt); while(cnt < size) { if(!(cnt2 < 16)) { cnt2 = 0; printf("\n%04X: ",cnt); } printf("%02X ", (*(uint8_t*)(buf + cnt))); cnt2++; cnt++; } printf("\n"); } Результат (пример применения): Код (Text): 0000: 33 33 64 43 33 B7 14 46 00 00 00 00 00 00 00 00 0010: 33 B7 14 46 CD CC 4C CD 33 33 64 43 CD CC 4C C5 0020: 0A D7 23 3C AE 47 11 42 CD CC 4C 3D 66 66 86 3F 0030: 41 7D 00 00 7B 7B 00 00 1B 00 00 00 00 00 00 00 0040: 02 00 02 00 02 00 02 00 02 00 02 00 02 00 02 00 0050: 02 00 02 00 02 00 00 00 00 00 00 00 00 00 00 00 0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0070: 00 00 00 00 00 00 00 00 CD CC 4C CD CD CC 4C CD 0080: CD CC 4C C5 CD CC 4C C5 00 00 00 00 00 00 00 00 0090: 0A D7 23 3D 00 00 00 00 85 29 00 00 55 3B 00 00 00A0: 1B 00 00 00 00 00 01 00 02 00 02 00 02 00 02 00 00B0: 02 00 02 00 02 00 02 00 02 00 02 00 02 00 00 00 00C0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00D0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00E0: CD CC 4C CD CD CC 4C CD CD CC 4C C5 CD CC 4C C5 00F0: 00 00 00 00 00 00 00 00 0A D7 23 3D 00 00 00 00 0100: A8 77 00 00 72 72 00 00 1A 00 00 00 00 00 02 00 0110: 02 00 02 00 02 00 02 00 02 00 02 00 02 00 02 00 0120: 02 00 02 00 02 00 00 00 00 00 00 00 00 00 00 00 0130: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Кстати... может кто помнит как считается контрольная сумма в "Радио 86 РК" - дампы в журнале "Радио" сопровождались контрольной суммой.
Не очень уверен, но вроде бы примитивно - суммируются подряд байты, когда сумма превысила 255 - из нее эти 255 отнимают, и продолжают суммирование. Контрольная сумма - то что останется после байта, который последний перед байтом контрольной суммы.
да - берешь 5555 и/и с 4444 - потом отправляешь полученное - и на другом хвосте полученное с 4444 тоже через и/и и получаешь 5555
и где криптозащита? Например: автомобильная сигнализация. Такой подход приведёт к тому, что пакет открытия авто будет каждый раз одинаковым. Не надо ничего взламывать и расшифровывать - просто записать пакет, а затем его воспроизвести.
Это самый простейший вариант. Он расшифровывается на раз-два. Еще в 80-ых мне нравился однонаправленный вариант шифрования UNIX. То есть, зашифрованный пароль могут видеть все, в файле /etc/passwd Но данный файл доступен только для чтения всем, и для записи - root (системе). в /etc/passwd пароли хранились в зашифрованном виде, при вводе пароля пользователем, система шифровала его и сравнивала уже в зашифрованном виде с /etc/passwd. То есть алгоритм не предусматривал обратной расшифровки. Причем за шифрование отвечал crypt, исходники которого были открыты . Но подобрать... не реально, проще былыло подправить исходник crypt, перекомпилировать, и подменить, если был доступ на консоль, в однопользовательском режиме. А сейчас уже давно используется несимметричное шифрование!
рокки всё напутал. Кодировка - из другой области. Есть кодировка с потерей информации, есть без потери. Для этого используются кодеры/декодеры - сокращённо КОДЕК. Шифрование информации используется для её скрытия. Криптозащита - для невозможности подделки информации. Например, электронная подпись. Наипростейший случай - полином CRC. Но CRC - это не крипта.