Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить

Re: Котуинко

Пт мар 29, 2024 22:09:58

ИГРЫ С ВЕКТОРАМИ
(по мотивам viewtopic.php?p=4561359#p4561359)
Весьма обычный прием...
Допустим есть в начальном месте размеченное изготовителем поле для команд переходов...
тут вектор сброса на своем месте по умолчанию:
Код:
;
; "irq_pavr.txt" файл описания поля векторов прерываний
;
.cseg
.org 0x000
irq_res:
rjmp init ; переход к началу программы инициализации системы
; - - - - - - - - - - - - - - - - - - - - - - - - - - -
; блок размещения векторов активных прерываний
; .org OC0Aaddr
; irq_t0:
; rjmp timers_bum ; steps
; - - - - - - - - - - - - - - - - - - - - - - - - - - -


Теперь где-то в удобном месте ставим второй вектор сброса. Полнейшая "творческая отсебятина" в вопросе где те вектора ставить. Допустим так:
Код:
.cseg
.org 0x200
init:
rjmp real_init

а далее собственно у нас или тот real_init будет выполняться или в той же ячейке расположенная новая команда перехода на иную точку входа в программу (перепрошитая "обманщиком" при помощи SPM (или еще попакостнее с использованием возможностей IJMPов :facepalm: :o ))...
Даже если исходная таблица закрыта для перезаписи локами, то "самодельная вторичная" может располагаться как нам нравится (где удобнее).
Собственно при прерывании (аппаратном сбросе) у нас срабатывает тандем из двух команд :
первый переход по команде, размещенной в классической ячейке таблицы векторов
rjmp init
и затем уже второй - на нужную в данный момент программу (из нашей "полной отсебятинки"):
rjmp real_init
или
IJMP ; по адресу, находящемуся в Z
хотя... никто не запрещал ставить IJMP и в "стандартную" таблицу векторов... УПС... это я точно прозевал... (В MCS51 такой приятненькой команды к сожалению нету) :oops:
Я брал пример на скору руку с шаблона асма тинек - но там в принципе любые команды переходов вместо rjmp name сгодятся.
Что JMP по фиксированному адресу, что еще поизворотливее (у АВРок) IJMP по содержимому Z регистра.
Понятно что это потеря быстродействия - лишняя команда - зато возможности достаточно заморочливые.
Второе - сама SPM не знает где чего лежит - но автор такого приема прекрасно знает разметку памяти своего творения посему параметры то уж задаст и для бутлоадера (при начальной прошивке) и для прикладной программы.
8)

Re: Котуинко

Пт мар 29, 2024 23:00:03

я говорил о совсем другом.
меня интересуют не те переходы, как

.org 0x200
init:
rjmp real_init

а интересует, чтобы прерывание, например, по таймеру

.org OC0Aaddr
rjmp irq_t0

работало в области загрузчика.
а конкретно я говорил про приемо-передатчик, и соответственно, мне нужно, чтобы работал такой код

.org URXCaddr ; адрес прерывания USART, Rx Complete
rjmp USART_Rx_Complete ; прием готов
nop
rjmp USART_Tx_Complete ; передача готова

в области загрузчика.
и как я уже там сказал, по установленному биту IVSEL у меня не происходит перенос таблицы векторов в загрузочную область, а продолжает работать таблица на своем прежнем месте, начиная с нулевого адрема.

Re: Котуинко

Пт мар 29, 2024 23:07:04

А что мешает сделать простой переход в область адресов загрузчика из "стандартной"?
Привязка к аппаратной поддержке совсем не обязательна.
Просто делаем свой раздел в защищенной области к которому обращаются команды указателей адреса перехода из основного раздела " по умолчанию"...
Исходная таблица "по умолчанию" будет обслуживать переходы на вновь созданную, но не средствами аппаратной поддержки, а средствами программной поддержки автором программы.
Мы же вторичные (целевые) указатели можем размещать где угодно. Другое дело, что при написании целевой программы нужно учитывать параметры разметки бутлоадера - знать адреса размещения векторов по листингу бутлоадера и задавать их затем вручную при написании целевой программы.
Но это уже стандартная специфика для комплекта базового бутлоадера с набором минимальных общих функций и целевой программы, которая может как пользоваться подпрограммами бутлоадера (прием/передача, типовые преобразования и т.п.) так и своими аналогами таких же подпрограмм.
Это привычнее с оперативно подгружаемыми программами на самоделке с единой общей базой. Меняем модуль аппаратного расширения и загружаем соответствующую этому аппаратному модулю прикладную часть программы. А в самой "мамке" сидит только базовый загрузчик и утилиты управления аппаратным ядром устройства.
Некоторая аналогия ПК - сначала запускается биос аппаратной части, затем программа пользователя, которая также использует и ресурсы биос и ресурсы собственные, которые можно модифицировать при необходимости.
Отличие только в режиме модификации ячеек памяти программ - для ОЗУ мгновенная запись, по флеш ПЗУ требуется некоторое время и спецпроцедуры для перезаписи.
8)
По конкретике...
Допустим я взял мегу8а...
Оставил исходную таблицу векторов на своем месте...
А прикладные вектора хочу разместить в области бутлоадера (на всякий случай беру бутлоадер максимального размера)...
Т.е. у меня область бутлоадера от 0хС00 и далее...
ставлю вот такой добавок в дефайне (m8adef.inc):

Спойлер
Код:
; ***** my INTERRUPT VECTORS ************************************************

; причем софтовая таблица может иметь и другие адреса начального размещения внутри области бутлоадера
; а не только самые первые (от FOURTHBOOTSTART)

.equ   INT0addr_r = FOURTHBOOTSTART + 0x0001   ; External Interrupt Request 0
.equ   INT1addr_r = FOURTHBOOTSTART + 0x0002   ; External Interrupt Request 1
.equ   OC2addr_r   = FOURTHBOOTSTART + 0x0003   ; Timer/Counter2 Compare Match
.equ   OVF2addr_r = FOURTHBOOTSTART + 0x0004   ; Timer/Counter2 Overflow
.equ   ICP1addr_r = FOURTHBOOTSTART + 0x0005   ; Timer/Counter1 Capture Event
.equ   OC1Aaddr_r = FOURTHBOOTSTART + 0x0006   ; Timer/Counter1 Compare Match A
.equ   OC1Baddr_r = FOURTHBOOTSTART + 0x0007   ; Timer/Counter1 Compare Match B
.equ   OVF1addr_r = FOURTHBOOTSTART + 0x0008   ; Timer/Counter1 Overflow
.equ   OVF0addr_r = FOURTHBOOTSTART + 0x0009   ; Timer/Counter0 Overflow
.equ   SPIaddr_r   = FOURTHBOOTSTART + 0x000a   ; Serial Transfer Complete
.equ   URXCaddr_r = FOURTHBOOTSTART + 0x000b   ; USART, Rx Complete
.equ   UDREaddr_r = FOURTHBOOTSTART + 0x000c   ; USART Data Register Empty
.equ   UTXCaddr_r = FOURTHBOOTSTART + 0x000d   ; USART, Tx Complete
.equ   ADCCaddr_r = FOURTHBOOTSTART + 0x000e   ; ADC Conversion Complete
.equ   ERDYaddr_r = FOURTHBOOTSTART + 0x000f   ; EEPROM Ready
.equ   ACIaddr_r   = FOURTHBOOTSTART + 0x0010   ; Analog Comparator
.equ   TWIaddr_r   = FOURTHBOOTSTART + 0x0011   ; 2-wire Serial Interface
.equ   SPMRaddr_r = FOURTHBOOTSTART + 0x0012   ; Store Program Memory Ready

; .equ   INT_VECTORS_SIZE   = 19   ; size in words

А в своей программе ставлю сначала

Код:
   .org 0x0000
 INT0addr: jmp INT0addr_r   ; External Interrupt Request 0
 INT1addr: jmp INT1addr_r   ; External Interrupt Request 1
 OC2addr:   jmp OC2addr_r   ; Timer/Counter2 Compare Match
 OVF2addr: jmp OVF2addr_r   ; Timer/Counter2 Overflow
 ICP1addr: jmp ICP1addr_r   ; Timer/Counter1 Capture Event
 OC1Aaddr: jmp OC1Aaddr_r   ; Timer/Counter1 Compare Match A
 OC1Baddr: jmp OC1Baddr_r   ; Timer/Counter1 Compare Match B
 OVF1addr: jmp OVF1addr_r   ; Timer/Counter1 Overflow
 OVF0addr: jmp OVF0addr_r   ; Timer/Counter0 Overflow
 SPIaddr:   jmp SPIaddr_r   ; Serial Transfer Complete
 URXCaddr: jmp URXCaddr_r   ; USART, Rx Complete
 UDREaddr: jmp UDREaddr_r   ; USART Data Register Empty
 UTXCaddr: jmp UTXCaddr_r   ; USART, Tx Complete
 ADCCaddr: jmp ADCCaddr_r   ; ADC Conversion Complete
 ERDYaddr: jmp ERDYaddr_r   ; EEPROM Ready
 ACIaddr: jmp ACIaddr_r   ; Analog Comparator
 TWIaddr: jmp TWIaddr_r   ; 2-wire Serial Interface
 SPMRaddr: jmp SPMRaddr_r   ; Store Program Memory Ready

; далее текст программы при необходимости
.................................
; теперь область бутлоадера:

  .org FOURTHBOOTSTART ; или иная область внутри области ПЗУ бутлоадера - это софт, а не аппаратная разметка***
INT0addr_r: jmp my_INT0   ; External Interrupt Request 0
INT1addr_r: jmp my_INT1   ; External Interrupt Request 1
OC2addr_r: jmp my_OC2   ; Timer/Counter2 Compare Match
OVF2addr_r: jmp my_OVF2   ; Timer/Counter2 Overflow
ICP1addr_r: jmp my_ICP1   ; Timer/Counter1 Capture Event
OC1Aaddr_r: jmp my_OC1A   ; Timer/Counter1 Compare Match A
OC1Baddr_r: jmp my_OC1B   ; Timer/Counter1 Compare Match B
OVF1addr_r: jmp my_OVF1   ; Timer/Counter1 Overflow
OVF0addr_r: jmp my_OVF0   ; Timer/Counter0 Overflow
SPIaddr_r: jmp my_SPI   ; Serial Transfer Complete
URXCaddr_r: jmp my_URXC   ; USART, Rx Complete
UDREaddr_r: jmp my_UDRE   ; USART Data Register Empty
UTXCaddr_r: jmp my_UTXC   ; USART, Tx Complete
ADCCaddr_r: jmp my_ADCC   ;   ; ADC Conversion Complete
ERDYaddr_r: jmp my_ERDY   ;   ; EEPROM Ready
ACIaddr_r: jmp my_ACI   ; Analog Comparator
TWIaddr_r: jmp my_TWI   ; 2-wire Serial Interface
SPMRaddr_r: jmp my_SPMR   ; Store Program Memory Ready

; далее сам бутлоадер с соответствующими подпрограммами:
.....................................


my_INT0: reti   ; External Interrupt Request 0
my_INT1: reti   ; External Interrupt Request 1
my_OC2: reti   ; Timer/Counter2 Compare Match
my_OVF2: reti   ; Timer/Counter2 Overflow
my_ICP1: reti   ; Timer/Counter1 Capture Event
my_OC1A: reti   ; Timer/Counter1 Compare Match A
my_OC1B: reti   ; Timer/Counter1 Compare Match B
my_OVF1: reti   ; Timer/Counter1 Overflow
my_OVF0: reti   ; Timer/Counter0 Overflow
my_SPI: reti   ; Serial Transfer Complete
my_URXC: reti   ; USART, Rx Complete
my_UDRE: reti   ; USART Data Register Empty
my_UTXC: reti   ; USART, Tx Complete
my_ADCC: reti   ;   ; ADC Conversion Complete
my_ERDY: reti   ;   ; EEPROM Ready
my_ACI: reti   ; Analog Comparator
my_TWI: reti   ; 2-wire Serial Interface
my_SPMR: reti   ; Store Program Memory Ready

В принципе... если у меня есть несколько вариантов на один вектор
обработки и несколько подпрограмм требующих быстрого переключения...
Тогда где-нибудь храню адреса тех подпрограмм а по точке вектора
ставлю:

Код:
URXCaddr_r: ijmp   ; USART, Rx Complete
UDREaddr_r: ijmp   ; USART Data Register Empty
UTXCaddr_r: ijmp   ; USART, Tx Complete


при этом надо позаботиться о предварительной загрузке прикладных адресов
в Z регистр, что обеспечит возможность запуска нескольких вариантов
подпрограмм для каждого из прерываний.

для аппаратной поддержки возможны и "обратные" варианты - когда основная
таблица в бутлоадере, а "софтовая" в любом месте прикладной программы.
:tea:

Re: Котуинко

Сб мар 30, 2024 08:42:35

а мне нужен, как раз, аппаратный перенос таблицы векторов.
ну вот смотри.
записываем в МК бутлоадер. вся остальная память, начиная с нулевого адреса, до бутлоадера чистая.
а мне нужно, чтобы работали прерывания, когда с нулевого адреса таблица не заполнена.
к примеру, я пишу:

.org SECONDBOOTSTART
rjmp nachalo

.org URXCaddr + SECONDBOOTSTART ; адрес прерывания USART, Rx Complete
rjmp USART_Rx_Complete ; прием готов
nop
rjmp USART_Tx_Complete ; передача готова

nachalo:
ldi R26, 1<<IVCE
out GICR, R26
ldi R26, 1<<IVSEL
out GICR, R26

таким образом, я прописываю нужные вектора со смещением на начало и делаю перенос таблицы в область бутлоадера.
ранее, когда я это пробовал сделать, видимо, я допустил какую-то ошибку и у меня не происходил перенос таблицы векторов.
вчера вечером сделал тестовый текст, и тоже допустил, видимо, эту же ошибку, и у меня перенос не работал.
а сейчас с утра нашел ошибку и исправил. и теперь у меня прекрасно работают прием и передача по новым векторам в области загрузчика.
проверил - связь с компом теперь работает замечательно.
правда, мне уже это не надо, так как я уже в загрузчике обошелся без прерываний и сделал программный анализ флага RXC на приеме и анализ флага UDRE при передаче.
получилось, что я сам был виноват и зря тебя напрягал с вопросами. но все равно спасибо за потраченное на меня время.

Re: Котуинко

Сб мар 30, 2024 09:49:36

А почему не как обычно?
Код:
nachalo:
   ldi R26, 1<<IVCE
   out GICR, R26

   SBR   R26,1<<IVSEL
;  ldi R26, 1<<IVSEL
   out GICR, R26

Re: Котуинко

Сб мар 30, 2024 10:07:58

а потому, что в даташите сказано, что при записи IVSEL нужно установить IVCE в ноль.
и даже там есть такой пример.

Re: Котуинко

Сб мар 30, 2024 10:12:01

К сожалению я на АВРках с бутом и самопрограммированием пока не практиковался...
Посему еще один нюанс упустил...

Касается он бит BLB02:01 и BLB12:11...
Судя по документации той же меги8А с их помощью проводится защита от исполнения подпрограмм обслуживания прерываний, расположенных в "чужой" относительно основной таблицы прерываний области.
Таблица векторов в области памяти целевой программы.
Защита от доступа к целевой программе со стороны подпрограмм обработчиков прерываний, расположенных в области бутлоадера выполняют BLB12:11
Если защита включена, то адрес перехода, размещенный в таблице векторов которая находится в области адресов целевой программы, и указывающий на область бутлоадера будет игнорироваться т. е. подпрограмма - обработчик, размещенная в области бутлоадера и рассчитанная на исполнение как часть вызова из целевой программы не запустится.

Аналогично действуют и биты BLB02:01 — только по отношению бутлоадера.
Если основная таблица в области бутлоадера и в ней адресован обработчик из области целевой программы то такой обработчик будет блокирован.

Однако... предполагаю что...
Аппаратные средства отслеживают только адрес в основной таблице векторов... и то при его явном указании в команде (требует проверки вариант с IJMP вместо JMP addr).

Теоретически если в той же области, где расположена основная таблица сделать дополнительную таблицу-обманку и уже из нее вызывать «чужеродный» обработчик вполне вероятен вариант исполнения. "Подставной вектор" то уже будет "в своей" для защит области...
Однако это предположение надо практическим тестом проверить...
Пока в планах у меня такая проверка не стоит, но интересненько...
:roll:

Re: Котуинко

Сб мар 30, 2024 11:03:57

я про все локи уже давно прочитал в даташите.
все твои дополнительные таблицы не являются аппаратными. все равно переходы на обработчики прерываний будут делаться из основной аппаратной таблицы.
я вот что подумал, что при переходе из загрузчика в приложение сначала перемещенную таблицу нужно вернуть на свое место с нулевого адреса, а уж потом сделать переход на нулевой адрес.

Re: Котуинко

Сб мар 30, 2024 13:14:30

Вопрос как опознается блокировка.
Т. Е. Какой базовый принцип.
Ведь запрета на обращение к простым подпрограммами из "чужой области" блокировка не ставит.
Иначе были бы блокированы и подпрограммы с вызывающим CALL/JMP ADR а в даташитах про то ни слова.
Посему запрет блокировки касается только фиксированных ячеек области векторов прерываний.
В других ячейках контроль адреса не проводится.
Предположим, что при установленной защите в ячейке с вектором стоит адрес передачи управления в свою же область адресного пространства. Для системы защиты это разрешенный переход (и начало обработки прерывания)... А уже там стоит вторая переадресация "в запретную зону". Вот такой вариант в принципе вполне возможен.
Проверку и без бутлоадера можно попробовать сделать... Чисто из " спортивна интересу"...
:roll:

Re: Котуинко

Вт апр 02, 2024 19:13:09

Прикупил жирну адуринку...
mega2560 pro... Вроде бы и неплохая базовая платка -относительно малогабаритная...
Только вот пригляделся -
а на всего этого монстра с количеством под 70 линий
ВСЕГО ТРИ КОНТАКТА "ОБЩИЙ"(GND)!!!
https://img.radiokot.ru/files/20529/3eugnlk41u.jpg
Как-то уж совсем неудобственно, особо при заявленном выходном токе стабилизаторов до 800мА...
Для сигналов и силовых обратный проводок один (максимум два) на всю платку...
ПЕЧАЛЬКА однако...
:(

Re: Котуинко

Чт апр 04, 2024 09:17:33

а сигналы, тем более, силовые и должны в одну точку сходиться, так что все нормально.

Re: Котуинко

Чт апр 04, 2024 09:54:06

Так не факт, что на платке общий слой...
Силовые и сигнальные что от источника питания, что от нагрузок/источников сигнала и все в один контакть...
хотя бы еще парочку поставили... Силовые то можно и через "общий +" затянуть. Мне больше интерес был для подключения параллельного ОЗУ (23я серия похоже таки из области фантастики по местным условиям).
Ну да и на том... сойдет... Все равно пока "на отлежку" в кащеев сундук.
:sleep:

Re: Котуинко

Сб апр 06, 2024 21:27:49

А вот посмотрите,какая шняга интересная.
https://forum.cxem.net/index.php?/topic ... nt=3938993
Можно же перенести прошивку (дизассемблировать,т.к исходника не дал) на другой МК ?
например мега8 ? их у меня полно,а тини44 нет.

Re: Котуинко

Вс апр 07, 2024 00:04:49

При наличии документации на те RW1990 можно под любой МК программу сделать...
Да и в сети полно всяких самоделок на разных АВРкахи адуринах...
:roll:
Кстати... Для программирования далласов можно использовать аппаратную начинку DS2480...
"...
Supports 12V EPROM Programming and
Stiff 5V Pullup for Crypto iButton, Sensors
and EEPROM
..."
DS2480b_new.pdf
(409.69 KiB) Скачиваний: 5

8)
Последний раз редактировалось BOB51 Вс апр 07, 2024 08:52:00, всего редактировалось 1 раз.

Re: Котуинко

Вс апр 07, 2024 07:45:31

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

Накропал вот такой код для Ардуины:

#include <EEPROM.h>

int address = 0; // Переменная для хранения адреса
byte value1 = B00001111; // Переменная для хранения значения 1
byte value2 = B10101010; // Переменная для хранения значения 2

void setup() {
Serial.begin(115200);

EEPROM.put(address, value1); // Записать значение value1 в ячейку с адресом 0

address += 1; // Корректируем адрес

EEPROM.put(address, value2); // Записать значение value2 в ячейку с адресом 1

// Обнуляем переменные
address = 0;
byte value1 = 0;
byte value2 = 0;

// Получаем данные из EEPROM
EEPROM.get(address, value1);
address += 1; // Корректируем адрес
EEPROM.get(address, value2);
Serial.println( value1, BIN); // Вывести полученное значение 1
Serial.println( value2, BIN); // Вывести полученное значение 2
}
void loop() {}

В результате выполнения кода:
Монитор СОМ порта выдаёт:

07:40:53.677 -> 1111
07:40:53.677 -> 10101010

Почему вместо положенного байта 00001111 монитор показывает 1111?

Re: Котуинко

Вс апр 07, 2024 08:47:22

Так что положили, то и получили.
Значения переменных как были так и остались
Относительно "пропавших лидирующих нулей" - это особенности вывода на печать (функции обработчика перекодировки опции BIN, HEX в print) - аналогия гашения старших незначащих нулей на разнообразных индикаторах.
Для контроля можете выставить HEX - хотя и там "лидирующий нуль" может не воспроизводиться если формат отличается от 0xNN.
8)

Re: Котуинко

Вс апр 07, 2024 08:57:32

Относительно "пропавших лидирующих нулей" - это особенности вывода на печать

Так это что, это он всегда будет и справа и слева в байте нули обрезать как ему вздумается?
Но тогда ещё вопрос. Реальный код будет чтение из массива и запись байт в порты (У Ардуины 2560 можно байты сразу целиком в порты выводить) Я собираюсь потом этот прочитанный байт 00001111 в порт выводить, он мне его в порт как выведет? Где окажется младший бит если нулей нет?

Re: Котуинко

Вс апр 07, 2024 09:03:41

Нет проблем, он отправится туда, где ему место по весу битов.

Re: Котуинко

Вс апр 07, 2024 09:09:24

Вот код при чтении байт из массива:

#include <avr/io.h>
#include <EEPROM.h>

byte EEMEM dataArray_addr[16];
void setup() {
Serial.begin(115200);

// объявляем массив
byte dataArray[16] = {B00000001, B00000010, B00000100, B00001000,
B00010000, B00100000, B01000000, B10000000,
B01111111, B10111111, B11011111, B11101111,
B11110111, B11111011, B11111101, B11111110};
//
EEPROM.put((byte)&dataArray_addr, dataArray);
// объявляем откуда будем читать
byte dataArray_read[16];
// читаем точно так же, как писали
EEPROM.get((byte)&dataArray_addr, dataArray_read);
EEPROM[0] += 1;
// проверяем данные
Serial.println(dataArray_read[0], BIN);
Serial.println(dataArray_read[1], BIN);
Serial.println(dataArray_read[2], BIN);
Serial.println(dataArray_read[3], BIN);
Serial.println(dataArray_read[4], BIN);
Serial.println(dataArray_read[5], BIN);
Serial.println(dataArray_read[6], BIN);
Serial.println(dataArray_read[7], BIN);
Serial.println(dataArray_read[8]), BIN;
Serial.println(dataArray_read[9]), BIN;
Serial.println(dataArray_read[10], BIN);
Serial.println(dataArray_read[11], BIN);
Serial.println(dataArray_read[12], BIN);
Serial.println(dataArray_read[13], BIN);
Serial.println(dataArray_read[14], BIN);
Serial.println(dataArray_read[15], BIN);
}
void loop() {}

Здесь монитор СОМ порта показывает дичь вообще полную:

09:04:58.892 -> 1
09:04:58.892 -> 10
09:04:58.892 -> 100
09:04:58.892 -> 1000
09:04:58.892 -> 10000
09:04:58.892 -> 100000
09:04:58.892 -> 1000000
09:04:58.892 -> 10000000
09:04:58.892 -> 127
09:04:58.892 -> 191
09:04:58.892 -> 11011111
09:04:58.892 -> 11101111
09:04:58.892 -> 11110111
09:04:58.892 -> 11111011
09:04:58.892 -> 11111101
09:04:58.892 -> 11111110

Откуда взялись значения 127 и 191?
Я ни разу не программист, но дело и не в программировании вовсе, я просто не понимаю как он всё это интерпретирует при выводе данных.

Re: Котуинко

Вс апр 07, 2024 09:11:52

При печать старшие биты, равные 0, не отображаются.
СпойлерМожете организовать собственный "правильной" печать. Код немного длинный, но все для теста.
Напр.:
Код:
  value1 = EEPROM.get(address, value1);

  Serial.print("0b");
 
  if (value1 < 128)
    Serial.print('0');
   
  if (value1 < 64)
    Serial.print('0');
   
  if (value1 < 32)
    Serial.print('0');
   
  if (value1 < 16)
    Serial.print('0');
   
  if (value1 < 8)
    Serial.print('0');
   
  if (value1 < 4)
    Serial.print('0');
   
  if (value1 < 2)
    Serial.print('0');
   
  if (value1 < 1)
    Serial.print('0');

  Serial.println(value1, BIN);

---
...
Откуда взялись значения 127 и 191?

Перепутали две строки выше. Поместите BIN в скобки.
Последний раз редактировалось veso74 Вс апр 07, 2024 09:15:26, всего редактировалось 2 раз(а).
Ответить