MementoMori 4 8 апреля, 2023 Опубликовано 8 апреля, 2023 · Жалоба Вот такая конструкция в main.c typedef struct { int TimePosition; char WORK_STATE; char POWER_REGULATION_MODE; } tINFO_VAR; Хочу использовать переменную этого типа не только в main.с, но и в stm32f1xx_it.c Объявляю в main.c extern tINFO_VAR INFO_VAR; Казалось бы, в stm32f1xx_it.c нужно написать tINFO_VAR INFO_VAR; Однако не работает. Нужно повторно объявлять структуру и в главном файле и в stm32f1xx_it.c Так то работает, но ощущение избыточности кода. Да и править структуру, в случае чего, в двух файлах не хочется. Как правильно и красиво сделать? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Obam 38 8 апреля, 2023 Опубликовано 8 апреля, 2023 · Жалоба Вроде ж header-ы для этого придуманы... не? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 86 9 апреля, 2023 Опубликовано 9 апреля, 2023 (изменено) · Жалоба typedef не может объявляться с extern. Положите этот typedef в файл заголовочника и подключите его (файл) к файлу исходника и к остальным файлам, куда его надо подключать. Более разумно с точки зрения написания использовать в файле stm32f1xx_it.c в функции обработки прерывания только вызов функции-коллбэка. Вот так: void EXTI9_5_IRQHandler(void) { if(EXTI->PR & EXTI_PR_PR5) { EXTI->PR = EXTI_PR_PR5; Foo5_Callback(); } if(EXTI->PR & EXTI_PR_PR6) { EXTI->PR = EXTI_PR_PR6; Foo6_Callback(); } } в этом случае файл stm32f1xx_it.c избавлен от лишнего мусора и выполняет роль "распределителя". Сами вызываемые фукнции лежат в других файлах. Ну и освойте написание многофайловых проектов, чтобы не валить всё в один main.c. Аналогично, main.c в больших проектах выполняет только роль "распределителя" порядка работы. Да, и вместо char, int используйте локализованные версии uint8_t, int8_t, int32_t. Хоть на несколько буковок и длиннее, но зато точно понятно, знаковый байт или беззнаковый. Изменено 9 апреля, 2023 пользователем EdgeAligned Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MementoMori 4 9 апреля, 2023 Опубликовано 9 апреля, 2023 · Жалоба 2 hours ago, EdgeAligned said: Положите этот typedef в файл заголовочника и подключите его (файл) к файлу исходника и к остальным файлам, куда его надо подключать. Уже так и сделал. Как это обычно бывает - долго бьешься над проблемой, но как только задашь вопрос на форуме, еще до того как кто-то ответит, решение приходит само собой. 2 hours ago, EdgeAligned said: Ну и освойте написание многофайловых проектов, чтобы не валить всё в один main.c. Так у меня эта переменная только в main.c и stm32f1xx_it.c используется. Проектик маленький, из-за 3-х функций еще какой-то файл создавать я не стал. А вообще так и делаю - отделяю функционал от распределения. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 63 9 апреля, 2023 Опубликовано 9 апреля, 2023 · Жалоба On 4/9/2023 at 9:07 AM, MementoMori said: Так у меня эта переменная только в main.c и stm32f1xx_it.c используется. Напишите реализацию обработчика вашего прерывания в файле main.c Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 86 9 апреля, 2023 Опубликовано 9 апреля, 2023 · Жалоба "Лучший" совет 🙂 Да, действительно, давайте свалим всё в один файл, пусть на три тыщщи строк, но в один. Это называется "не решить проблему, а прибить костыль". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 63 9 апреля, 2023 Опубликовано 9 апреля, 2023 · Жалоба On 4/9/2023 at 3:10 PM, EdgeAligned said: "Лучший" совет 🙂 Да, действительно, давайте свалим всё в один файл, пусть на три тыщщи строк, но в один. Это называется "не решить проблему, а прибить костыль". Нет, надо утащить обработчик прерывания как можно дальше от периферии. Слоев за 20, а лучше за тридцать. Разработчики микроконтроллеров стараются сделать обработчики прерываний с наименьшей задержкой, а программисты с ними нещадно борются, накладывая как можно больше слоев. Например, есть UART. Пусть он описан в отдельном файле. И вместо того, чтобы обработчик приема сделать в этом же файле и чтобы он имел прямой доступ к переменным и регистрам UART, надо утащить его и вызывать калл-бэки и к переменным обращаться через прослойки. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
artemkad 92 9 апреля, 2023 Опубликовано 9 апреля, 2023 · Жалоба 2 часа назад, dimka76 сказал: Например, есть UART. Пусть он описан в отдельном файле. И вместо того, чтобы обработчик приема сделать в этом же файле и чтобы он имел прямой доступ к переменным и регистрам UART, Парсить входной поток UARTa в прерывании? Как по мне это не самой удачное решение... Что касается его регистров UART в прерывании - обычно обходятся от силы двумя, так что особо способ обращения к ним на работу не влияет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 86 9 апреля, 2023 Опубликовано 9 апреля, 2023 (изменено) · Жалоба Есть два подхода к программированию. Максимальная универсализация и переносимость, когда модули настолько самодостаточны, что могут быть перемещены без переделок. И максимальная экономичность, когда всё пишется только для конкретного проекта и внедрено в него до упора. А вот истина, она, как известно, посередине. В конкретно именно рассматриваемом случае топикстартера структура tINFO_VAR и её переменная вообще не имеет отношения к периферии микроконтроллера и в принципе может быть вынесена на другой слой, её не обязательно внедрять в файлы, относящиеся к периферии микроконтроллера, смешивая разные уровни абстракции программы. Выше я показывал текст, когда то, что относится к периферии микроконтроллера, выполняется "здесь и сейчас", а то, что является переносимым кодом, не связано с "регистрами". Это - и есть середина. Изменено 9 апреля, 2023 пользователем EdgeAligned Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 63 9 апреля, 2023 Опубликовано 9 апреля, 2023 · Жалоба On 4/9/2023 at 6:47 PM, artemkad said: Парсить входной поток UARTa в прерывании? Где написано про парсить ? On 4/9/2023 at 6:48 PM, EdgeAligned said: В конкретно именно рассматриваемом случае топикстартера структура tINFO_VAR и её переменная вообще не имеет отношения к периферии микроконтроллера и в принципе может быть вынесена на другой слой, её не обязательно внедрять в файлы, относящиеся к периферии микроконтроллера, смешивая разные уровни абстракции программы. Я писал не только про регистры периферии, а также про программные переменные того программного модуля, в котором работает обработчик прерывания. В моем примере - UART. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
artemkad 92 9 апреля, 2023 Опубликовано 9 апреля, 2023 · Жалоба 2 часа назад, dimka76 сказал: Нет, надо утащить обработчик прерывания как можно дальше от периферии. Идея такого подхода весьма банально - жестко отделить работу с железом от работы с данными в результате чего при смене железа изменения коснутся только того файла который работает с железом. 1 минуту назад, dimka76 сказал: Где написано про парсить ? Вот тут: 2 часа назад, dimka76 сказал: обработчик приема Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dimka76 63 9 апреля, 2023 Опубликовано 9 апреля, 2023 · Жалоба On 4/9/2023 at 6:59 PM, artemkad said: Вот тут: Где слово парсить ? И что вы подразумеваете под словом парсить ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
artemkad 92 9 апреля, 2023 Опубликовано 9 апреля, 2023 · Жалоба 3 минуты назад, dimka76 сказал: И что вы подразумеваете под словом парсить ? Разбор входного потока(в данном случае принимаемом UARTом) на лексемы или токены. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 86 9 апреля, 2023 Опубликовано 9 апреля, 2023 (изменено) · Жалоба 1 час назад, dimka76 сказал: В моем примере - UART. Дак это - в ВАШЕМ примере 🙂 Ну и я уже писал про два диаметрально разных подхода к написанию программы. Вы придерживаетесь принципа минимальной переносимости кода и минимального расслоения абстракций. Это не хорошо, и не плохо. Поэтому вовсе и не обязательно делать именно так, как вы. 3 часа назад, dimka76 сказал: Разработчики микроконтроллеров стараются ссделать обработчики прерываний с наименьшей задержкой, а программисты с ними нещадно борются, накладывая как можно больше слоев В данном случае надбавка на вызов коллбека даже меньше времени входа в прерывание, поэтому более правильный подход к организации структуры программы не наносит заметного урона производительности микроконтроллера. Зато повышает производительность труда программиста 🙂 Впрочем, допустимым считается и тот, и другой вариант, различаются они лишь степенью "завязанности" кода. В малых проектах высокая связанность кода не мешает, а в больших - создает трудноотслеживаемые переплетения. Ну и кстати, про вышепоказанный пример с EXTI9_5. Как вы наверно замечали, существуют совмещенные вектора прерываний, такие как EXTI9_5, TIM1/TIM10. Как в этом случае будете разруливать ситуацию? Накидывать всё в одну кучу, в одно месиво? Изменено 9 апреля, 2023 пользователем EdgeAligned 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MementoMori 4 9 апреля, 2023 Опубликовано 9 апреля, 2023 · Жалоба Друзья, ваш спор перешел в разряд "с какого конца разбивать яйцо, с острого или тупого". Я решение выбрал, призываю вас не спорить. У меня следующий вопрос. А как бы мне передать структуру по UART? Точнее, как передать, я представляю, беру указатель и по указателю передаю количество байт равное размеру структуры. Что-то вроде этого: void USART_Transmit_block( void *ptr, size_t size) { uint8_t *p = (uint8_t*)ptr; while(size--) USART_Transmit( *p++); } ... USART_Transmit_block((unsigned char*) &TX_Data, sizeof(TX_Data) ); А вот как быть с приемом? Там ведь как - если приходит 0x00, то это считается концом строки. А если в структуре есть байт 0x00? Как быть? Как синхронизировать начало посылки? У меня есть самопальный рабочий пример с передачей текстовых команд - в буфер принимаются байты, пока один из них не равен 0x0D. Как только этот байт ловится, читается все что принято после предыдущего байта 0x0D и это считается текстовой командой. Там сложностей не возникало. А вот со структурами как быть? Там ведь уже не используешь символы конца строки, ибо символы с этим кодом могут быть в структуре. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться