dlinyj: (Default)
[personal profile] dlinyj
расстрелянного генерала разбирая свой код, который писал пол года назад. Небольшой опус.

Много хороших советов по хорошему стилю программирования водится в интернетах, так же несколько хороших уроков преподал мне камрад [livejournal.com profile] maddev , за что ему отдельное большое спасибо. Единственное, что я не следую его совету не использовать глобальные переменные, ибо не знаю как от них отказаться. Ведь флаги нужны, а без них никуда.

В общем, тоже дам один. Ковыряю тут свой код, примерно как ребёнок ковыряет говно палочкой. И вижу там такую конструкцию:
...
//Тут некоторая мелкая процедурка в коде, например приём символов по UART
if (некое условие)
{
...
//*****************************************************
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!		
PORTA=0xFF; //НИКОГДА ТАК НЕ ДЕЛАТЬ!!!!!!
//*****************************************************
...
} 


Хотел подсветить код, но не нашёл где. Сайт http://tohtml.com/c/ , где я делал это внезапно сломался на этом коде


Это было сделано в момент отладки, чтобы мигать светодиодом. А байт записывается, чтобы не думать на какой ноге порта висит светодиод. Так делать нельзя никогда!!! Лучше сделать во первых дефайн определяющий порт, дефайн определяющий ногу, и менять состояние только ОДНОГО пина!
В результате после написания программы я благополучно забыл об этой адовой конструкции, и уже было собирался переносить код в другой проект, как обнаружил этот капец.

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

Date: 2012-06-19 02:20 pm (UTC)
From: [identity profile] dlinyj.livejournal.com
Ни то и не другое, это микроконтроллер AVR и порт А.

Date: 2012-06-19 02:31 pm (UTC)
From: [identity profile] juunitaki.livejournal.com
Если доступ к глобальным переменным делать через функции, они перестанут быть глобальными переменными. Типа так:

flag.h:
extern int my_global_flag; // объявление

inline int flag_is_set() {
return (my_global_flag == 1);
}

inline void flag_set() {
my_global_flag = 1;
}

inline void flag_clear() {
my_global_flag = 0;
}
...

flag.c:
int my_global_flag; // определение

1. В любой момент можно вставить отладку и отследить изменение глобальной переменной.
2. inline компилятор вставляет по месту при оптимизации. то есть нет потерь быстродействия на вызов функции.

PS: пусть камрады меня поправят, если я гоню. ;)

Date: 2012-06-19 03:02 pm (UTC)
From: [identity profile] mbr.livejournal.com
1. так же точно можно сделать брекпоинт на обращении к области памяти
2. если это не static inline, и вызов из другого .с, компилятор может спокойно положить на этот инлайн.

Date: 2012-06-19 03:06 pm (UTC)
From: [identity profile] mbr.livejournal.com
для эмбеда и с - глобальные переменные не столь уж страшны. Для плюсов же наоборот считается дурным тоном использовать дефайны. Вместо них - константы - меньше вероятность ошибки из-за забытой скобки препроцессора.

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

Date: 2012-06-19 03:13 pm (UTC)
From: [identity profile] tnt23.livejournal.com
Да и за PORTA тоже надо убивать лопатой :)


#define MY_PORT PORTA
#define MY_DIR DDRA
#define MY_IN PINA


И дальше оперировать ими.

Date: 2012-06-19 03:15 pm (UTC)
From: [identity profile] juunitaki.livejournal.com
1. ok, отладка - не единственная цель разбиения программы на функции.
2. inline-функции в h-файле.

Date: 2012-06-19 03:36 pm (UTC)
From: [identity profile] maddev.livejournal.com
С глобальными переменными вполне себе классическая ситуация: важно понимать область их применимости, а не тупо использовать/не использовать.

Date: 2012-06-19 04:28 pm (UTC)
From: [identity profile] mbr.livejournal.com
кстати да, плюсую

Date: 2012-06-19 07:35 pm (UTC)
From: [identity profile] dlinyj.livejournal.com
А что плюсовать, когда в посте я об этом сказал

Date: 2012-06-19 07:35 pm (UTC)
From: [identity profile] dlinyj.livejournal.com
По моему вы невнимательно читаете мой пост, я об этом сказал:

>>Лучше сделать во первых дефайн определяющий порт, дефайн определяющий ногу, и менять состояние только ОДНОГО пина!

Date: 2012-06-19 07:43 pm (UTC)
From: [identity profile] dlinyj.livejournal.com
Какие есть рекомендации по использованию/неприменению?

Date: 2012-06-19 07:49 pm (UTC)
From: [identity profile] di-halt.livejournal.com
Ими тоже оперировать не нужно, а нужно рядом воткнуть дефайн который будет делать то, что нужно. Типо

LED_ON
LED_OFF

SPI_SEND_BYTE

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

Date: 2012-06-20 07:27 am (UTC)
From: [identity profile] dlinyj.livejournal.com
Ди, может ты мне тогда сможешь помочь.


У меня по УАПП приходят четырёхбайтовые комманды, формата два байта комманда, и два байта номер:
Например
ON01 - включить релюшку первую
или
RD12 - прочитать состояние 12 релюшки

Есть комманды, которые применимы ко всем релюшкам, типа:

OAOA - выключить все релюшки.

Фишка в том, что номера релюх по сути должны быть не привязаны к номерам портов. Как наиболее оптимально сделать разбор этих комманд, и включать релюшку именно с этим номером?

Комманды микроконтроллеру:

ON ** - On ** switch
OF ** - Off ** switch
OA OA - Off All Switch
RD ** - Read status switch
RA RA - Read status ALL switch
HS HS - Signal the presence - просто запрос присутствия, есть ответ присутствия.

У меня реализована ещё проверка по таймауту, что если не принято было всё в течении определённого времени, то приёмка обнуляется и выдаётся ошибка. Но конструкция вышла аховая.

Date: 2012-06-20 11:10 am (UTC)
From: [identity profile] tnt23.livejournal.com
Увы мне! я стормозил!!

Date: 2012-06-20 04:33 pm (UTC)
From: [identity profile] gorl.livejournal.com
Серег, есть очень крутая книжка по тому как писать надо и как не надо.
Называется "Совершенный код" Макконнелла. Каждому программисту строго рекомендую читать.
Как правильно кто-то говорил: написать хороший код и написать плохой код занимает одно и то же время.

Date: 2012-06-20 04:36 pm (UTC)
From: [identity profile] gorl.livejournal.com
Кстати, а что за задачи, что нельзя обойтись без глобальных переменных? Множественные точки входа?

Date: 2012-06-20 05:12 pm (UTC)
From: [identity profile] arkamax.livejournal.com
Есть еще более общий совет - никогда не вешать затычек. Если приходится так делать - всегда помечать их заранее выбранным маркером, и при КАЖДОМ релизе делать поиск по всему проекту на эти маркеры. Еще более жесткий вариант - никогда ничего не коммитить с маркерами. Мы же пользуемся code versioning, да? Да? :)

Date: 2012-06-20 06:02 pm (UTC)
From: [identity profile] di-halt.livejournal.com
Заведи такие шняги

#define Relay1_ON {Relay1PORT |=1<<relay_bit1; Relay1DDR |=1<<relay_bit1}while(0) #define Relay1_OFF {Relay1PORT &=~(1<<relay_bit1); Relay1DDR |=1<<relay_bit1}while(0) и юзай их в свое удовольствие. Надо будет поменять - они все у тебя в одной куче. Взял и поменял.

Date: 2012-06-20 06:03 pm (UTC)
From: [identity profile] di-halt.livejournal.com
Да любой флаговый автомат. Там же куча параллельных событий, им надо как то обмениваться друг с другом сообщениями.

Date: 2012-06-21 05:17 am (UTC)
From: [identity profile] dlinyj.livejournal.com
Расшифруй как это юзать, или дай пруф, где можно почитать

Date: 2012-06-21 05:21 am (UTC)
From: [identity profile] dlinyj.livejournal.com
Спасибо за ссылку, качаю. В айпад кину, буду читать в метро.

Date: 2012-06-21 05:23 am (UTC)
From: [identity profile] dlinyj.livejournal.com
Суть в то, что у тебя происходит прерывание, и ты в программе не знаешь что оно произошло. Надо каким-то образом сообщить головной программе, что как минимум было прерывание. Как максимум передать какие-то данные (например была передана последовательность байт). Если в прерывании будут вызываться множество сторонних функций, то это замедлит работу всей программы. У словиях контроллера, когда у тебя частота работы несколько мегагерц - это критично.

Date: 2012-06-21 05:24 am (UTC)
From: [identity profile] dlinyj.livejournal.com
>> Мы же пользуемся code versioning, да? Да? :)

К сожалению нет, даже гитхаб не юзаем :)

Date: 2012-06-21 07:08 am (UTC)
From: [identity profile] di-halt.livejournal.com
Не тупи. Это обычный дефайн, только ЖЖ форматирование похерил.

Я просто загнал несколько команд в пустой while, чтобы юзать их как макрос.

Date: 2012-06-21 03:33 pm (UTC)
From: [identity profile] arkamax.livejournal.com
Блин... Слушай, уже без шуток - поставь TortoiseSVN или если под линями - хоть command line SVN, и подними где-нибудь SVN сервер (хоть на той же машине, если совсем все плохо с хостингом). По опыту - спасет от многих проблем, даже если ты работаешь один. Такое дело - если что-то напортачил в коде, то всегда можно откатиться назад, причем к любому состоянию, и посмотреть, что было изменено перед тем, как начало глючить. Спасало не раз, проверено.

Date: 2012-06-21 03:36 pm (UTC)
From: [identity profile] dlinyj.livejournal.com
Я знаю, что изобрёл велосипед, но я просто делаю сам версионность проектов с папками. И сохраняю в разные папки. Папки храню в дропбоксе.


Впрочем, надо просто курнуть гитхаб

Date: 2012-06-21 05:53 pm (UTC)
From: [identity profile] arkamax.livejournal.com
А diff? Задолбаться же можно.

January 2026

S M T W T F S
    123
456 78910
11121314151617
18192021222324
25262728293031

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 22nd, 2026 11:39 am
Powered by Dreamwidth Studios