допустимо все, что не запрещено. но чем больше написано, тем легче запутаться. не комментируя необходимость менять один байт двухбайтной переменной через указатель на двухбайтную переменную, я лично так не делал бы.
я бы поступил ровно так же, как выше: 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х байтной переменной. Так что читаем хелп к программе и не шлангуем
Использование модульных источников питания открытого типа широко распространено в современных устройствах. Присущие им компактность, гибкость в интеграции и высокая эффективность делают их отличным решением для систем промышленной автоматизации, телекоммуникационного оборудования, медицинской техники, устройств «умного дома» и прочих приложений. Рассмотрим подробнее характеристики и особенности трех самых популярных вариантов AC/DC-преобразователей MW открытого типа, подходящих для применения в промышленных устройствах - серий EPS, EPP и RPS представленных на Meanwell.market.
Тут по подробнее, что за директива Да и зачем привязываться к абсолютным значениям, мне не совсем понятна, есть же константы А по поводу статического массива: 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 примерно.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 43
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения