vassabi 0 22 марта, 2013 Опубликовано 22 марта, 2013 (изменено) · Жалоба Сильно не пинайте, на С перешел неделю назад, пишу в MPLAB X IDE 1.7 Как объявить sfr переменную в одном файле, а инициализировать в другом (например, первый файл библиотечный - lib.c, второй рабочий - main.c) Например, мне нужно чтобы lib.c работал с регистром PORTB. В lib.c я делаю объявление extern volatile unsigned int DATAPORT __attribute__ ((__sfr__)); Как мне теперь инициализировать ее в main.c? И еще вопрос, как делать объявление и инициализацию, в случае если нужно работать с переменной, которая ссылается на бит в sfr регистре? з.ы. Хелп в MPLAB X очень тяжелый для восприятия, по большей чати отправляет к ANSI стандарту С (литературу по С я курю параллельно) Изменено 22 марта, 2013 пользователем vassabi Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jack_avenger 4 24 марта, 2013 Опубликовано 24 марта, 2013 · Жалоба Обычно объявлять sfr есть необходимость только если компилятор из коробки не поддерживает выбранный чип. Судя по тому что у Вас PIC и среда MPLab - оба от одного производителя, то смею предположить что Вы что-то делаете не так. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vassabi 0 24 марта, 2013 Опубликовано 24 марта, 2013 · Жалоба .... смею предположить что Вы что-то делаете не так. Это тоже вполне допустимо :) Регистры sfr конечно же переопределять задача не стоит. Тут суть в чем: в файле lib.c лежит универсальный код, нпример реализован LCD, ему нужно работать с sfr (DB0...DB7, EN, RS...), каждый раз, когда этот файл используется (в другом приложении), править хеадер как-то не корректно (наверное). Посему в lib.c есть только объявление sfr переменной (что бы код компилился), а ее инициализация происходит уже в другом файле (e.g. main.c). Как-то так... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jack_avenger 4 24 марта, 2013 Опубликовано 24 марта, 2013 · Жалоба править хеадер как-то не корректно (наверное). Править хедер не стоит Сделайте что-то вроде следующего #define LCD_PORT PORTB и далее везде в модуле LCD работайте не напрямую, а через макрос LCD_PORT Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vassabi 0 24 марта, 2013 Опубликовано 24 марта, 2013 · Жалоба #define LCD_PORT PORTB и далее везде в модуле LCD работайте не напрямую, а через макрос LCD_PORT Ото ж, я так и делал, только если файлы лежат в разных проектах, то компилятор ее не видит (в данном случае lib.c прикручен к рабочему проекту как библиотека). Похоже это приколы этого компилятора или, что скорее всего, я еще не до конца разобрался... Вот только не понятно, все таки как extern переменную инициализировать не значением, а адресом, в данном случае sfr регистра. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jack_avenger 4 24 марта, 2013 Опубликовано 24 марта, 2013 · Жалоба Ото ж, я так и делал, только если файлы лежат в разных проектах, то компилятор ее не видит (в данном случае lib.c прикручен к рабочему проекту как библиотека). Похоже это приколы этого компилятора или, что скорее всего, я еще не до конца разобрался... Вот только не понятно, все таки как extern переменную инициализировать не значением, а адресом, в данном случае sfr регистра. Переменные extern инициализируются в месте их объявления (там где они без ключевого слова extern), а присваивать значения можно везде, где их видно. Чтоб инициализировать переменную адресом Вам нужно смотреть в сторону указателей Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vassabi 0 24 марта, 2013 Опубликовано 24 марта, 2013 (изменено) · Жалоба Чтоб инициализировать переменную адресом Вам нужно смотреть в сторону указателей С указателями понятно, но неужели нет стандартного решения... Т.е. если в одном файле она объявленя как extern volatile unsigned int DATAPORT __attribute__ ((__sfr__));, то в другом должно быть что-то типа volatile unsigned int DATAPORT __attribute__ ((__sfr__, __address__(0x200))); Так вот этот атрибут __address__(0x200)__ компилятор не понимает... Изменено 24 марта, 2013 пользователем vassabi Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jack_avenger 4 24 марта, 2013 Опубликовано 24 марта, 2013 · Жалоба С указателями понятно, но неужели нет стандартного решения... Т.е. если в одном файле она объявленя как extern volatile unsigned int DATAPORT __attribute__ ((__sfr__));, то в другом должно быть что-то типа volatile unsigned int DATAPORT __attribute__ ((__sfr__, __addr[0x200]__)); Так вот этот атрибут __addr[0x200]__ компилятор не понимает... С некоторыми упрощениями (насчет того что делает компилятор, а что линкер) можно сказать следующее: Еxtern говорит компилятору что эта переменная определена в другом модуле, таким образом он не выделяет под нее еще одну область памяти. И дописывая перед переменной extern Вы должны в точности переписать ее объявление в том виде, в котором она объявлена (там где без extern) за исключением пожалуй начального значения и включая ее адрес. Т.е. сделать таким образом код работающий с разными адресами не получится. Даже если компилятор скомпилирует все модули то потом ругнется линкер что типы переменных не совпадают. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vassabi 0 24 марта, 2013 Опубликовано 24 марта, 2013 (изменено) · Жалоба ...должны в точности переписать ее объявление в том виде, в котором она объявлена (там где без extern)... Да, это я в курсе... Походу, самый правильный вариант только через препроцессор... но тогда билиотечный файл не хочет ее видеть и не компилится... Изменено 24 марта, 2013 пользователем vassabi Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jack_avenger 4 24 марта, 2013 Опубликовано 24 марта, 2013 · Жалоба Да, это я в курсе... Походу, самый правильный вариант только через препроцессор... но тогда билиотечный файл не хочет ее видеть и не компилится... Что за библиотека? Ваша или Third party? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 24 марта, 2013 Опубликовано 24 марта, 2013 · Жалоба Походу, самый правильный вариант только через препроцессор... но тогда билиотечный файл не хочет ее видеть и не компилится... Вам обязательно чтоб библиотека была? Какой от этого профит? Может лучше исходники компилировать в каждом проекте? P.S. Как-то мало библиотеками приходилось пользоваться, потому не знаю будет ли работать такой вариант. В либе всю работу с портами делать через вызов функций. Сами функции определять в отдельном файле в соответсвии c реальным железом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vassabi 0 24 марта, 2013 Опубликовано 24 марта, 2013 (изменено) · Жалоба Вам обязательно чтоб библиотека была? Какой от этого профит? Может лучше исходники компилировать в каждом проекте?... Ну сейчас так и делаю, не без дела же сидеть :) В любом случае, спасибо! Думаю, что я просто еще не достаточно с IDE разобрался... ============== Хочу просто библиотеку отдельной сборкой держать, тут все таки есть свои плюсы, если код оптимизирован или откомпилен жирным дорогим компилятором в триал периоде ;) Потм трассировщик туда уже не лезет, от основного не отвлекает. Кста, а кто нибудь знает, существуют ли атрибуты функций, которые позволяют трассировщику туда не залазить в процессе отладки? Изменено 24 марта, 2013 пользователем vassabi Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jack_avenger 4 24 марта, 2013 Опубликовано 24 марта, 2013 · Жалоба Хочу просто библиотеку отдельной сборкой держать, тут все таки есть свои плюсы, если код оптимизирован или откомпилен жирным дорогим компилятором в триал периоде ;) Сомневаюсь что это оптимально. Если у процессора куча режимов косвенной адресации то еще прокатит, во всех остальных случаях лучше когда адреса переменных известны на этапе компиляции Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
vassabi 0 24 марта, 2013 Опубликовано 24 марта, 2013 (изменено) · Жалоба ....во всех остальных случаях лучше когда адреса переменных известны на этапе компиляции На этапе компиляции чего? Если речь о библиотеке и она откомпилена, то там адреса этой переменной не будет, она же extern. Если речь о компиляции основной задачи к которой зацеплена уже откомпиленая библиотека, то тут она (переменная) и пропишеться по адресу. Изменено 24 марта, 2013 пользователем vassabi Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jack_avenger 4 24 марта, 2013 Опубликовано 24 марта, 2013 · Жалоба Если речь о библиотеке и она откомпилена, то там адреса этой переменной не будет, она же extern. Будет код для доступа к ресурсу. Если адрес известен заранее, то команды получаются быстрее и короче в сравнении с вариантом когда сначала этот адрес надо вычислить. Хотя это не всем критично, я обращаю внимание на такие моменты только потому, что у моих приборов батарейное питание и желаемый срок работы от батареи - не менее 6 лет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться