Перейти к содержанию
    

Как правильно объявить extern для typedef?

Вот такая конструкция в 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

Так то работает, но ощущение избыточности кода. Да и править структуру, в случае чего, в двух файлах не хочется.

 

Как правильно и красиво сделать?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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. Хоть на несколько буковок и длиннее, но зато точно понятно, знаковый байт или беззнаковый. 

Изменено пользователем EdgeAligned

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 hours ago, EdgeAligned said:

Положите этот typedef в файл заголовочника и подключите его (файл) к файлу исходника и к остальным файлам, куда его надо подключать.

Уже так и сделал.

Как это обычно бывает - долго бьешься над проблемой, но как только задашь вопрос на форуме, еще до того как кто-то ответит, решение приходит само собой.

2 hours ago, EdgeAligned said:

Ну и освойте написание многофайловых проектов, чтобы не валить всё в один main.c.

Так у меня эта переменная только в main.c и stm32f1xx_it.c  используется. Проектик маленький, из-за 3-х функций еще какой-то файл создавать я не стал. А вообще так и делаю - отделяю функционал от распределения.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 4/9/2023 at 9:07 AM, MementoMori said:

Так у меня эта переменная только в main.c и stm32f1xx_it.c  используется. 

Напишите реализацию обработчика вашего прерывания в файле main.c

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

"Лучший" совет 🙂 Да, действительно, давайте свалим всё в один файл, пусть на три тыщщи строк, но в один.

Это называется "не решить проблему, а прибить костыль".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 4/9/2023 at 3:10 PM, EdgeAligned said:

"Лучший" совет 🙂 Да, действительно, давайте свалим всё в один файл, пусть на три тыщщи строк, но в один.

Это называется "не решить проблему, а прибить костыль".

Нет, надо утащить обработчик прерывания как можно дальше от периферии. Слоев за 20, а лучше за тридцать.

Разработчики микроконтроллеров стараются сделать обработчики прерываний с наименьшей задержкой, а программисты с ними нещадно 

борются, накладывая как можно больше слоев.

Например, есть UART. Пусть он описан в отдельном файле. И вместо того, чтобы обработчик приема сделать в этом же файле и чтобы он имел

прямой доступ к переменным и регистрам UART, надо утащить его и вызывать калл-бэки и к переменным обращаться через прослойки.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, dimka76 сказал:

Например, есть UART. Пусть он описан в отдельном файле. И вместо того, чтобы обработчик приема сделать в этом же файле и чтобы он имел

прямой доступ к переменным и регистрам UART,

Парсить входной поток UARTa в прерывании? Как по мне это не самой удачное решение... Что касается его регистров UART в прерывании - обычно обходятся от силы двумя, так что особо  способ обращения к ним на работу не влияет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Есть два подхода к программированию. Максимальная универсализация и переносимость, когда модули настолько самодостаточны, что могут быть перемещены без переделок. И максимальная экономичность, когда всё пишется только для конкретного проекта и внедрено в него до упора. А вот истина, она, как известно, посередине.

В конкретно именно рассматриваемом случае топикстартера структура tINFO_VAR и её переменная вообще не имеет отношения к периферии микроконтроллера и в принципе может быть вынесена на другой слой, её не обязательно внедрять в файлы, относящиеся к периферии микроконтроллера, смешивая разные уровни абстракции программы.

Выше я показывал текст, когда то, что относится к периферии микроконтроллера, выполняется "здесь и сейчас", а то, что является переносимым кодом, не связано с "регистрами". Это - и есть середина.

Изменено пользователем EdgeAligned

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 4/9/2023 at 6:47 PM, artemkad said:

Парсить входной поток UARTa в прерывании?

Где написано про парсить ?

 

On 4/9/2023 at 6:48 PM, EdgeAligned said:

В конкретно именно рассматриваемом случае топикстартера структура tINFO_VAR и её переменная вообще не имеет отношения к периферии микроконтроллера и в принципе может быть вынесена на другой слой, её не обязательно внедрять в файлы, относящиеся к периферии микроконтроллера, смешивая разные уровни абстракции программы.

Я писал не только про регистры периферии, а также про программные переменные того программного модуля, в котором работает обработчик прерывания. В моем примере - UART.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, dimka76 сказал:

Нет, надо утащить обработчик прерывания как можно дальше от периферии.

Идея такого подхода весьма банально - жестко отделить работу с железом от работы с данными в результате чего при смене железа изменения коснутся только того файла который работает с железом.

1 минуту назад, dimka76 сказал:

Где написано про парсить ?

Вот тут:

2 часа назад, dimka76 сказал:

обработчик приема

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 4/9/2023 at 6:59 PM, artemkad said:

Вот тут:

Где слово парсить ?

И что вы подразумеваете под словом парсить ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 минуты назад, dimka76 сказал:

И что вы подразумеваете под словом парсить ?

Разбор входного потока(в данном случае принимаемом UARTом) на лексемы или токены.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, dimka76 сказал:

В моем примере - UART.

Дак это - в ВАШЕМ примере 🙂 

Ну и я уже писал про два диаметрально разных подхода к написанию программы. Вы придерживаетесь принципа минимальной переносимости кода и минимального расслоения абстракций. Это не хорошо, и не плохо. Поэтому вовсе и не обязательно делать именно так, как вы. 

 

3 часа назад, dimka76 сказал:

Разработчики микроконтроллеров стараются ссделать обработчики прерываний с наименьшей задержкой, а программисты с ними нещадно борются, накладывая как можно больше слоев

В данном случае надбавка на вызов коллбека даже меньше времени входа в прерывание, поэтому более правильный подход к организации структуры программы не наносит заметного урона производительности микроконтроллера. Зато повышает производительность труда программиста 🙂 
Впрочем, допустимым считается и тот, и другой вариант, различаются они лишь степенью "завязанности" кода. В малых проектах высокая связанность кода не мешает, а в больших - создает трудноотслеживаемые переплетения.

Ну и кстати, про вышепоказанный пример с EXTI9_5. Как вы наверно замечали, существуют совмещенные вектора прерываний, такие как EXTI9_5, TIM1/TIM10. Как в этом случае будете разруливать ситуацию? Накидывать всё в одну кучу, в одно месиво?

Изменено пользователем EdgeAligned

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Друзья, ваш спор перешел в разряд "с какого конца разбивать яйцо, с острого или тупого".  Я решение выбрал, призываю вас не спорить.

 

У меня следующий вопрос.

А как бы мне передать структуру по 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 и это считается текстовой командой.  

Там сложностей не возникало. А вот со структурами как быть? Там ведь уже не используешь символы конца строки, ибо символы с этим кодом могут быть в структуре.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...