Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: использование пойнтера в прерывании
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > MSP430
1921
Товарищи!
Подскажите, как можно в прерывании использовать ссылку на строку. В качестве входного параметра не получается - в С прерывания не имеют параметров.
Хотелось бы, чтобы работало примерно так: вызывается подпрограмма с входными параметрами void Prog1(char *P). Она настраивает чего-то и разрешает прерывания от UART. UART по прерываниям получает данные, которые должны складываться в String, на которую указывает P. Вопрос: как мне указать в обработчике прерывания эту вот ссылку? Что-то ничего у меня не получается...
MrYuran
В модуле с функциями для UART объявляете нужный указатель, с которым потом работает обработчик прерываний.
Ваша Prog1() заносит туда нужный адрес, в который сохраняется строка.
1921
Цитата(MrYuran @ Sep 29 2010, 15:58) *
static переменная?

Это как? Я пока до таких высот не дошёл.
MrYuran
Цитата(1921 @ Sep 29 2010, 17:01) *
Это как? Я пока до таких высот не дошёл.

Это в том смысле, если нужно было бы просто "помнить" некоторые данные между вызовами обработчика, то можно было бы внутри объявить статическую переменную, и она бы сохранялась после выхода из функции. Но поскольку вам нужно её изменять снаружи, то и объявлять её надо снаружи, иначе она будет не видна.
1921
Или подскажите, что вообще можно сделать с пойнтером. Как положить его значение в int и как произвольный int сделать пойнтером. Как-то в ассемблере с этим было попроще.
MrYuran
Цитата(1921 @ Sep 29 2010, 17:09) *
Или подскажите, что вообще можно сделать с пойнтером. Как положить его значение в int и как произвольный int сделать пойнтером. Как-то в ассемблере с этим было попроще.

Указатель хранит адрес. Тип указателя соответствует типу объекта, на который он ссылается.
Это вам учебники надо почитать.
Если я правильно понял, вы хотите присвоить указателю адрес какой-то переменной?
Так пожалуйста:
int *ptr; // объявили указатель на int

ptr = address; // теперь он указывает на ячейку с адресом address
ptr = &var1; // теперь он указывает на ячейку с переменной var1
var2 = *ptr; // присвоили переменной var2 значение ячейки, на которую ссылается ptr
1921
что не получается: Пойнтер *P объявлен глобально, но создаётся впечатление, что при выходе из подпрограмма void Prog(char *P) он разрушается, т.к. из другой подпрограммы (в данном случае из обработчика прерывания) он не виден. Чисто теоретически это выглядит так: все операции с *P, типа *(P+i), P[i] внутри процедуры транслируются в команды косвенной адресации без сохранения значения пойнтера в каком-либо регистре. И я никак не могу сохранить или получить адрес String в глобальную переменную типа int, которую внутри прерывания можно было бы (если вообще можно?) использовать как пойнтер.

Имеется ввиду, можно ли сделать что-то типа
int k;
chap *P;
k=P;
....
char i=*k
MrYuran
Цитата(1921 @ Sep 29 2010, 17:20) *
Чисто теоретически это выглядит так: все операции с *P, типа *(P+i), P[i] внутри процедуры транслируются в команды косвенной адресации без сохранения значения пойнтера в каком-либо регистре.

А почему бы и нет?
Если вы не модифицируете указатель, зачем его где-то сохранять?
Вы разыменовали указатель, получили значение, компилятор считает свою задачу выполненной.
1921
Я просто по пикам помню, там пойнтеры лежали в определённых регистрах, и к ним был свободный доступ (на ассемблере). Бери и делай с ними что хочешь. А любое значение, записанное в эти регистры, автоматически счиьтается пойнтером.
MrYuran
Цитата(1921 @ Sep 29 2010, 17:20) *
Имеется ввиду, можно ли сделать что-то типа
int k;
chap *P;
k=P;

Жирно выделенное вам компилятор сделать не позволит, т.к. это явное нарушение типов.
Если
char *k;
k=P;
то пожалуйста.
Можно, конечно, вывернуться через ж.. и написать k=(int)P; (а лучше unsigned int), но это неправильно.
То есть вы говорите компилятору: спокойно, я знаю, что делаю. И он съедает.
1921
Можно, конечно, вывернуться через ж.. и написать k=(int)P; (а лучше unsigned int), но это неправильно.
То есть вы говорите компилятору: спокойно, я знаю, что делаю. И он съедает.
[/quote]
Ну что же. Плохо! транслятор похоже вообще, оперирую с пойнтерами, в качестве выхода имеет только значение, лежащее по адресу. Неужели нет никакой возможности получить сам адрес той строки, на которую ссылается пойнтер, если мы передаём ссылку на неё? операции типа
char *P
char k
k=P идентичны k=P[0] и приводят к пересылке нулевого байта строки.
rezident
Я видимо как-то слабо улавливаю проблему, но если требуется передать указатель в функцию, в которой он изменяется так, чтобы после выхода из функции это изменение сохранилось, то передавать в функцию нужно не сам указатель, а указатель на указатель.
Код
void foo (int **pntr)
{ int *tmpPtr=*pntr; // tmpPtr теперь содержит адрес указателя, на который ссылается pntr
  ...
  tmpPtr++; // изменили tmpPtr
  ...
  *pntr=tmpPtr; // сохранили измененное значение указателя, адрес которого передавался через pntr
}

Как-то так примерно. laughing.gif
MrYuran
Цитата(1921 @ Sep 29 2010, 17:39) *
k=P идентичны k=P[0] и приводят к пересылке нулевого байта строки.

Не может такого быть.
Что за компилятор?
Как минимум, выругаться должен.
Hoksmur
Попробуйте задействовать модификатор volatile- должен обьяснять компилятору, что переменная может изменяться в любой момент, в том числе - не только программой (прерыванием как её частью). Соответственно - выделит место в памяти принудительно.
ih_
Цитата
...Неужели нет никакой возможности получить сам адрес той строки, на которую ссылается пойнтер...
поинтер и есть переменная, содержащая адрес
Код
// Работа #0 - "Инициализация"
typedef        unsigned char        byte;
// можно так
byte    myString[]="My string\n"; // это Ваша строка
// или так
byte    bigString[20]="My bigest string\n";    // и это Ваша строка больше

//typedef byte* pStr;
// это указатель на строку 'myString'
byte*        pMyString; // здесь мы будем хранить адрес строки 'myString'
// а это указатель на строку 'bigString'
byte*    pBigString;  // а здесь  адрес строки 'bigString'
// как Вы поняли размеры указателей одинаковы, и не зависят от длин строк

/ Теперь работа #1 - "Инициализация (поручение адресов переменных) указателей"
// получаем адрес строки 'mystring'
pMyString=&myString[0];    // обратите внимание на амперсанд (& - это амперсанд, оператор взятия адреса)
// получаем адрес строки 'bigString'
pBigString=&bigString[0]; // значение номера элемента массива может быть и не нулевым

// Теперь работа #2 - "Копирование указателей"
// получаем адрес пятого символа в строке 'bigString'
pBigString=&bigString[4];
// присваиваем указатель указателю
pMyString=pBigString; // теперь они оба являются одинаковыми ссылками на одну и туже строку 'igest string\n'

// Теперь работа #3 - "Присвоение значение через указатель"
// сначала берем адрес - это уже Вы умеете
pMyString=&myString[6];
// затем  присваиваем значение переменной, ссылкой на которую - есть указатель
*pMyString='O'; // теперь переменная 'mуString' содержит 'My strOng'
// обратите внимание на звездочку (* - звездочка, оператор взятия значения)
// а теперь присваиваем значению одной переменной, значение другой.
*pMyString=*pBigString;// Теперь  переменная 'mуString' снова содержит 'My string'

// Выводы:
// - все четыре примера это была относительная адресация, а пример от rezident, это косвенная адресация;
// - Си - это высокоуровневый ассемблер (при хорошем компиляторе :) ), только нужно немного перестроиться;

// Желаю настойчивости и удачи, тогда успех Вас не покинет! :);
Hoksmur
Цитата(ih_ @ Oct 26 2010, 21:10) *
поинтер и есть переменная, содержащая адрес
Код
// Работа #0 - "Инициализация"
typedef        unsigned char        byte;
// можно так
byte    myString[]="My string\n"; // это Ваша строка
// или так
byte    bigString[20]="My bigest string\n";    // и это Ваша строка больше

//typedef byte* pStr;
// это указатель на строку 'myString'
volatile byte*        pMyString; // здесь мы будем хранить адрес строки 'myString'
// а это указатель на строку 'bigString'
byte*    pBigString;  // а здесь  адрес строки 'bigString'
// как Вы поняли размеры указателей одинаковы, и не зависят от длин строк

Я хоть и не силён в Cях, но насколько знаю - размер указателей на любую строку одинаков, потому что она обявлена как массив char. Не в вводите народ в заблуждение. Если только не специфика реализации.

volatile - это про что я писал. Но я в указателях так до конца и не разобрался - возможно, этот модификатор неприменим к указателю. (Хотя - с чего бы это?)

Сергей Борщ
Цитата(Hoksmur @ Oct 27 2010, 05:37) *
Я хоть и не силён в Cях, но насколько знаю - размер указателей на любую строку одинаков, потому что она обявлена как массив char. Не в вводите народ в заблуждение.
А где вы увидели разный размер указателей?
Цитата(Hoksmur @ Oct 27 2010, 05:37) *
volatile - это про что я писал. Но я в указателях так до конца и не разобрался - возможно, этот модификатор неприменим к указателю. (Хотя - с чего бы это?)
Он применим не только к самому указателю, но и к объекту, на который указывает указатель. volatile char *, char * volatile и volatile char * volatile - три совершенно разных типа указателей. А разобраться нужно обязательно.
Хотя volatile к обсуждаемой теме никаким боком не относится.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.