Разговоры на технические темы

Тема в разделе "Флудилка", создана пользователем Igor68, 1 апр 2021.

  1. Airbus

    Airbus Радиохулиган Модератор

    Я тоже;)
     
  2. Igor68

    Igor68 Гуру

    Доброго времени суток! Есть ли возможно оптимизировать этот код?
    Прерывание срабатывает по одному из 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. Смысл в том, что измерения могут стартовать только с началом периода выхода. В ШИМ данные записываются всегда согласно периоду выходного сигнала.
    Я вроде сделал минимальное количество обращений к памяти. Может есть место где ускорить? Как Вы думаете?
    Спасибо!
     
    Последнее редактирование: 7 апр 2021
  3. Рокки1945

    Рокки1945 Гуру

    Всех приветствую - подскажите пожалуйста будет ли микросхема ch340c с внутренним кварцем работать также стабильно как с буквой G.
    Буду закладывать - экспериментировать некогда - СПАСИБО!
     
  4. Ariadna-on-Line

    Ariadna-on-Line Гуру

    https://github.com/UnfinishedStuff/CH340C
    ".. Единственная проблема, с которой я столкнулся, это то, что требуется конденсатор 0,1 мкФ на выводе V3. У меня создалось впечатление, что это был выход 3v3, но хотя я не могу прочитать его описание в таблице данных CH340C, лист FT232 отмечает, что аналогичный конденсатор с их чипом необходим для обеспечения 3v3 для самого чипа для определенных функций. , так что, по-видимому, это также относится к CH340C. Без этого конденсатора ПК с Windows не распознает USB-устройство."
    ПС. Это перевод текста с сайта !
     
    Последнее редактирование: 16 апр 2021
    Рокки1945 нравится это.
  5. Рокки1945

    Рокки1945 Гуру

    Спасибо - если светодиоды-индикаторы не нужны и общение будет между 5 вольтовой логикой, для чего 1.5кОм на линии передатчика в схеме предназначен? Лучше предусмотреть его?
    Снимок.PNG
     
    Последнее редактирование модератором: 16 апр 2021
  6. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Это называется - береженого бог бережет. Поставьте по резистору 1 ком в оба пина 2, 3. Если оставите цепи светодиодов - они должны стоять ЗА этими резисторами - ближе к разъёму.
    ПС. Переходник готовый - стОит копейки. Дороже по комплектующим будет. Полезного для проф. опыта, сборка этого девайса не принесет абсолютно.
     
    Последнее редактирование: 16 апр 2021
    Рокки1945 нравится это.
  7. Рокки1945

    Рокки1945 Гуру

    нет мне надо юсб гнездо а не штекер - это во-первых, во - вторых без кварца и конденсаторов - плата меньше, стоимость 80 рублей для модулей - в рассыпухе - 35 рублей
    Переходник будет в составе устройства - на одной плате
     
  8. Airbus

    Airbus Радиохулиган Модератор

    В первых Ардуинах только такая и была. У меня работает.
    Скорее всего для стаховки видел такое—рекомендуют ставить на случай КЗ. От 300 ом до 1.5 ком. У меня работает и так.
     
    Рокки1945 нравится это.
  9. Рокки1945

    Рокки1945 Гуру

    Всем спасибо за оперативный фидбек - теперь появилась уверенность в своих действиях.
     
  10. Igor68

    Igor68 Гуру

    Доброго времени суток!

    Вот это от скуки:
    Код (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 РК" - дампы в журнале "Радио" сопровождались контрольной суммой.
     
  11. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Не очень уверен, но вроде бы примитивно - суммируются подряд байты, когда сумма превысила 255 - из нее эти 255 отнимают, и продолжают суммирование. Контрольная сумма - то что останется после байта, который последний перед байтом контрольной суммы.
     
    Последнее редактирование: 7 июн 2021
  12. Igor68

    Igor68 Гуру

    И это выглядит как двухбайтное значение? Точно помню что она имела размер 2 байта.
     
  13. Рокки1945

    Рокки1945 Гуру

    а ты знаешь что вся криптазащита - стоит на исключающем или?
     
  14. Un_ka

    Un_ka Гуру

    XOR ?
     
  15. Рокки1945

    Рокки1945 Гуру

    да - берешь 5555 и/и с 4444 - потом отправляешь полученное - и на другом хвосте полученное с 4444 тоже через и/и и получаешь 5555
     
  16. parovoZZ

    parovoZZ Гуру

    и где криптозащита?
    Например: автомобильная сигнализация. Такой подход приведёт к тому, что пакет открытия авто будет каждый раз одинаковым. Не надо ничего взламывать и расшифровывать - просто записать пакет, а затем его воспроизвести.
     
  17. ZAZ-965

    ZAZ-965 Гуру

    Кто на ком стоял? Один из столпов криптографии - сложность нахождения больших простых чисел.
     
  18. Рокки1945

    Рокки1945 Гуру

    Хорошо - но и/и в кодировке используется.
     
  19. SergeiL

    SergeiL Оракул Модератор

    Это самый простейший вариант. Он расшифровывается на раз-два.

    Еще в 80-ых мне нравился однонаправленный вариант шифрования UNIX.
    То есть, зашифрованный пароль могут видеть все, в файле /etc/passwd
    Но данный файл доступен только для чтения всем, и для записи - root (системе).
    в /etc/passwd пароли хранились в зашифрованном виде, при вводе пароля пользователем, система шифровала его и сравнивала уже в зашифрованном виде с /etc/passwd. То есть алгоритм не предусматривал обратной расшифровки. Причем за шифрование отвечал crypt, исходники которого были открыты ;). Но подобрать... не реально, проще былыло подправить исходник crypt, перекомпилировать, и подменить, если был доступ на консоль, в однопользовательском режиме. ;)
    А сейчас уже давно используется несимметричное шифрование!
     
    Рокки1945 нравится это.
  20. parovoZZ

    parovoZZ Гуру

    рокки всё напутал.
    Кодировка - из другой области. Есть кодировка с потерей информации, есть без потери. Для этого используются кодеры/декодеры - сокращённо КОДЕК.
    Шифрование информации используется для её скрытия.
    Криптозащита - для невозможности подделки информации. Например, электронная подпись. Наипростейший случай - полином CRC. Но CRC - это не крипта.
     
    Un_ka и Рокки1945 нравится это.