допустимо все, что не запрещено. но чем больше написано, тем легче запутаться. не комментируя необходимость менять один байт двухбайтной переменной через указатель на двухбайтную переменную, я лично так не делал бы.
я бы поступил ровно так же, как выше: 1. объявил бы нужный мне тип 2. объявил бы указатель на него 3. присвоил бы этоу указателю нужный адрес (с преобразованием к void*) 4. работал бы с моим указателем без всяких извращений
Код:
int var; // переменная
typedef struct{ unsigned char lo; unsigned char hi; } lohi_type; // типа лохи, да :)))
lohi_type *ptr = (void*)&var; // вот это мой указатель на ту самую переменную
ptr->lo = 1; // меняем только младший байт переменной
ну или как- то так.
только многие вам скажут, что мой подход платформозависим: дескать, не во всех платформах младший байт следует первым в многобайтных переменных... но мне на это наплевать: я работаю только с такими платформами, где младший байт идет впереди
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Чёто я понять не могу в чём весь сырбор, если нужно обращаться к младшим и старшим байтам двухбайтовой переменной, и если вы пишете именно на mikroC, то там делается всё просто:
Код:
Example: d = 0x5678; tmp = Lo(d); // Equals 0x78
Lo(d) = 0xAA; // d equals 0x56AA ---------- d = 0x5678; tmp = Hi(d); // Equals 0x56
Hi(d) = 0xAA; // d equals 0xAA78
Так же можно и обращаться и к 4х байтной переменной. Так что читаем хелп к программе и не шлангуем
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Тут по подробнее, что за директива Да и зачем привязываться к абсолютным значениям, мне не совсем понятна, есть же константы А по поводу статического массива: int array[10]; // объявили, можно тут же и значения присвоить если надо t=array[i]; // обращение к элементу по индексу Вродеж всё просто, или я чего то недопонял в ваших тонких реализуемых мотивах
Directive absolute specifies the starting address in RAM for a variable. If the variable is multi-byte, higher bytes will be stored at the consecutive locations. Directive absolute is appended to declaration of a variable:
Код:
short x absolute 0x22; // Variable x will occupy 1 byte at address 0x22 int y absolute 0x23; // Variable y will occupy 2 bytes at addresses 0x23 and 0x24
Be careful when using the absolute directive, as you may overlap two variables by accident. For example:
Код:
char i absolute 0x33; // Variable i will occupy 1 byte at address 0x33 long jjjj absolute 0x30; // Variable will occupy 4 bytes at 0x30, 0x31, 0x32, 0x33; thus, // changing i changes jjjj highest byte at the same time, and vice versa
Наложение тех что объявлены через абсолют при ошибке понятны, а вот прочие переменные накладываются на абсолютные.
А про массив... Я там выше пропустил const
Код:
char a = 10; const unsigned int arr = {1 , &a}; p1 = *arr[1];
Если написать p1 = arr[1], то получим адрес переменной а. p1 = *arr[1], вызывает ошибку. p1 = *((char*)arr[1]), получим содержимое переменной а через статический указатель. Последнее вызывает сомнения в правильности написанного.
Ну теперь я начал понимать к чему вы клоните, я про абсолютные адреса переменных, но понять не могу для чего нужна такая жёсткая привязка. Допустим у нас есть массив 10, 50 да хоть 100 элементов, присвоили ему имя и обращаетесь к нему по имени и номеру(индексу) к конкретному элементу этого массива. Я никогда не задавался вопросом привязывать массив к определённому месту в оперативке, это же задача компилятора, да и язык С это язык высокого уровня, там такие мелочи обычно опускаются. По поводу жёсткой привязки это похоже на ход мыслей при написании на ассемблере. По поводу массива, вы почему то его насильно пытаетесь склонить к структуре. Структура может в себе содержать поля с разными типами переменных и в том числе и адрес. А массив это энное количество однотипных элементов, т.е. если вы объявили тип int то все элементы в массиве будет по 2 байта и типа int. Можно конечно поместить в этот массив адреса, если они имеют размер 2 байта. Пример массива: int arr[10]={0,1,2,3,4,5,6,7,8,9}; Если же нужно передать значение в функцию то просто передаём адрес массива, опять же не важно где он находиться в оперативной памяти.
Код:
int k; void fn(int *t)// какая то функция в которую передаётся указатель на переменную типа int { *t=3; //по адресу обращаемся к переменной }
void main() { k=2;
fn(&k); //получаем адрес k и передаём его в функцию, так же можно и адрес массива // здесь уже k=3 }
Цитата:
p1 = *arr[1], вызывает ошибку.
Ну всё логично, вы объявили массив как одномерный а пытаетесь обращаться как двухмерному массиву(одномерный массив это строка, а двухмерный это набор строк) Объявление двухмерного массива: int arr[2][3]={{1,2,3},{4,5,6}}; Или же: char[3][12]={{"Понедельник"},{"Вторник"},{"Среда"}};
А вот стёк в МК используется отдельно для основной программы и отдельно для прерываний? Или нельзя использовать call в прерываниях? Или MikroC учтёт вместе с сохранением контекста ещё и разные стёки? Используется MikroC PRO for 8051, AT89C4051. Заранее спасибо.
Стек (э), не стёк. Вызывать ПП из прерывания можно. Каждый вызов сопровождается записью адреса возвращения в стек, последовательно. При возвращении из ПП так же последовательно из стека извлекаются эти адреса.
_________________ Каждый имеет право на свое личное ошибочное мнение.
У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
Спасибо. А если нужно вызвать функцию только один раз, и то только для модульности и "красоты", то как можно заменить функцию и сэкономить память под стэк? Есть вроде вариант с дефайном и символом "/" в конце строки, но придется много "/" добавлять.
Стек высвобождается при возврате из функции. Вы же не планируете сидеть в ней вечно, верно? Заняли одну (верхнюю) позицию в стеке, зашли в ПП, сделали свое дело, при выходе забрали адрес из стека. Но если вы из этой функции полезете в другую (ещё одна позиция), а из той потом в следующую и еще, и ещё, то, в зависимости от глубины стека конкретного МК, имеете шанс переполнить его, т.е. потерять самый нижний в стопке адрес возврата.
_________________ Каждый имеет право на свое личное ошибочное мнение.
У меня было тяжелое детство - я до 14 лет смотрел черно-белый телевизор.
Да. Но у меня оперативки не хватает под стэк. Можно подсократить глубину. Есть функции вызываемые один раз. Нужно заменить их, оставив модульность и удобство. Какие бывают методы?
У меня почему-то требуется памяти под стэк на два байта больше чем рассчитано. На PUSH - 1 байт, в прерывании T0 нужно 7 PUSH = 7 байт. В основной программе 6 вложений, по 2 байта = 12 байт. В прерывании 3 вложения + само прерывание = 8 байт. Итого: 27 байт. Если свободно 27 байт то не работает (снаружи вообще нет никакой активности), но если добавить еще 2 свободных байта то все работает. Вопрос что я еще не учел? P.S. а Протэус вообще не заморачивается что памяти всего 128 байт, если превысить лимит, то без проблем выделит еще.
https://web.archive.org/web/20160421205 ... s/8051.htm Подскажите по скорости UART, что то не сходится. В табличках написано что скорость 19,2 кГц соответствует 0FDh в 8 битном таймере при (1/11,059 МГц)*12 машинного цикла. Т.е. таймер на 3 цикла = 3,26 мкс; а 19,2 кГц => 52,08 мкс весь период. 52,08/3,26 = 16 примерно.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 36
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения