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

Си для AVR. Пытаюсь разобраться в структуре кода.


mosfetx

Рекомендуемые сообщения

Всем привет. Снова взялся за Си. Прошлые попытки провалились. Если не найду ответа в гугл или здесь, вопросы буду писать в эту тему

Вопрос в следующем.

#define F_CPU 8000000
#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
	unsigned char i=0;
    DDRD = 0xFF;
	PORTD = 0x00;
    while (1) 
    {
		for ( i=0; i<=7; i++ )
		{
			PORTD = (1<<i);
			_delay_ms(500);
		}
		
		for ( i=0; i<=7; i++ )
		{
			PORTD = ~(1<<i);
			_delay_ms(500);
		}
		
    }
}

Во втором цикле for, как я понимаю должно быть так.в момент входа в цикл PORTD все биты нули. И при выполнении строки PORTD = ~(1<<i); ни чего не должно происходить.

так как запись нуля в ноль ни чего не произойдёт. Но как только доходит до этой строки все биты PORTD выставляются в единицы. И потом начинает тухнуть один светодиод с сдвигом влево.

Объясните пожалуйста почему так. Вроде это побитовые операции, 

 

Изменено пользователем mosfetx
Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

12 минут назад, mosfetx сказал:

Объясните пожалуйста почему так

i=1  PORTD = ~(1<<1)  в двоичном 00000001 сдвигаем на 1, получаем 00000010, побитово инвертируем, в порт пишется 11111101

i=12 PORTD = ~(1<<2)  в двоичном 00000001 сдвигаем на 2, получаем 00000100, инвертируем, в порт пишется 11111011

Ну и так далее. Так что все правильно работает, не трожь :) 

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

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Выбираем схему BMS для заряда литий-железофосфатных (LiFePO4) аккумуляторов

Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

24 минуты назад, mosfetx сказал:

То есть чтобы не происходило инвертирование всех битов мне надо писать PORTD &= ~(1<<i);?

Конструкция (1<<i) дает байт с 1 в бите с номером i.  Побитовое отрицание ~ дает байт с единицами и нулем в бите i.

Да, сброс одного бита i  PORTD = PORTD & ( ~(1<<i) )  или кратко  PORTD &= ~(1<<i)

Установка одного бита i  PORTD = PORT  |  (1<<i) или кратко PORTD | =  (1<<i)

Но в вашем коде тоже все правильно, сначала бежит 1 от 0 до7 бита, потом так же бежит 0 при остальных битах в единице.

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

10 часов назад, mosfetx сказал:

for ( i=0; i<=7; i++ ) { PORTD = (1<<i); _delay_ms(500); }

Довольно неоптимальная конструкция, скорее всего компилятор для (1<<i) тоже организует цикл. Вот так гораздо лучше:

for(uint8_t i=1; i; i<<1){
  PORTD = i;
  _delay_ms(500);
}

 Соответственно, во втором варианте надо лишь инвертировать i перед вывoдом в порт: PORTD = ~i;

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

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

Учу по урокам с этого сайта http://narodstream.ru/avr-urok-7-knopka/.

Встретил там такие предложения.

Цитата

Можно пойти на хитрость и применить вот такую конструкцию PINB&0b00000001.

Данная конструкция нам и проверит нулевой бит. То есть если в регистре PINB также будет 1 в нулевом его бите,

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

Наверное он имел ввиду if(!(PINB&0b00000001)?

и ещё я вообще не понял что он тут имеет ввиду

Цитата

То есть если ни с чем не сравнивать в условии результат, то условие эквивалентно сравниванием с нулём, только наоборот

. Для истинности результат должен быть ненулевым — (результат!=0).

Возможно глупые вопросы но я должен все понимать чтоб двигаться дальше.

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

Не знаю, что там за уроки, но правильно так: всё, что не ноль, эквивалентно истине. Поэтому (a) и (a != 0) абсолютно эквивалентны в качестве условия в if и других местах, где требуется.

Главное, не думать, что истина всегда эквивалентна 1.

То есть (PINB & 1) и (PINB & 2) совсем не то же самое, что (PINB & 1) == 1 и (PINB & 2) == 1

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

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

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

Во-вторых, суффикс UL означает, что число следует рассматривать, как unsigned long, а суффикс L - как просто long. Это необходимо потому, что в Си по умолчанию (т.е. без суффиксов) все числа имеют размерность int, а значит, бОльшее число туда может влезть не полностью, что приведет к загадочным результатам вычислений. В последних версиях (стандартов Си или компиляторов?) это вроде как уже немного скорректировано, но я бы на это не стал надеяться, и рекомендовл бы продолжать использовать суффиксы явно.

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

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

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

05.12.2019 в 22:14, mosfetx сказал:

Вопрос в следующем.

Лучше всего вам создать консольный проект на компьютере и запустить эту вашу функцию в дебаге, закоментировав апаратнозависимые хидера и переопределив апаратнозависимые функции и переменные-регистры.Например так:

unsigned char PORTD ;

_delay_ms(short val)

{

printf("delay for %d ms, PORTD=0x%x;\n",val, PORTD);

}

На все вопросы вам ответит компилятор, все остальное от лукавого!

05.12.2019 в 22:14, mosfetx сказал:

Объясните пожалуйста почему так. Вроде это побитовые операции, 

unsigned char PORTD ;
void _delay_ms(short val) 
{ 
	printf("delay for %d ms, PORTD=0x%x;\n",val, PORTD); 
  static int debugCnt = 0;
  if(debugCnt++ > 20) exit(0);
}

во так без дебага можно посмотреть что с портом Д происходит на С-ях.

Можно сделать все! Но чем больше можно, тем больше нельзя!

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

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

. Определение тактовой частоты должно задаваться в makefile или в свойствах проекта вцелом, а не в индивидуальных исходниках.

А зачем вообще в коде задавать значение тактовой ? что оно нам даст ? тактовая же определяется во фьюзах и задается при прошивке отдельно.

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

27 минут назад, E_C_C сказал:

А зачем вообще в коде задавать значение тактовой ? что оно нам даст ?

значения констант для задержек, вы думаете, на основании чего считаются? Вообще все что связано с временем требует значение тактовой частоты.

Можно сделать все! Но чем больше можно, тем больше нельзя!

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

2 минуты назад, ruhi сказал:

вы думаете, на основании чего считаются?

Это понятно.Так же если нужно сделать одинаковые временные интервалы при переносе проекта на разные чипы , с разными тактовыми. Но вот в плане вопроса ТС , он ничего не портирует , код пишется под атмегу 8 с 8мгц тактовой , зачем нужен дефайн ? Не проще один раз посчитать значение делителя и значение таймера и записать их.

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

59 минут назад, E_C_C сказал:

Не проще один раз посчитать значение делителя и значение таймера и записать их.

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

В программировании любая простота обязательно оборачиавется проблемами: либо до какого-то события, либо после него: мы или мучаемся над изучением/осваиванием чего-либо, либо мучаемся потом, отлавливая ошибки. Какие проблемы решать лучше - каждый сам выбирает для себя.

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

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

45 минут назад, ARV сказал:

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

И сразу возникает вопрос - каков критерий "правильного"  кода?

Оптимальность ,т.е .скорость выполнения и нетребовательность к ресурсам железа ? Удобство в понимании другими ? удобство в написании для себя ?, а может изящество , или изощренность в решении задачи ?

К примеру - операцию деления  на любую степень двойки можно заменить сдвигом , это будет быстрее , но не так очевидно. И каждый автор учебника или курса предлагает своё видение , говоря что именно так и правильно. 

в уроках "народ стрим" , на которые ссылается топикстартер, проект разбит на  библиотеки и содержит много дефайнов , да это удобно, для программиста . А для начинающего создает сложности,  т.к .  нет наглядности , разумеется это моё ИМХО и я ни разу не претендую на авторитетное мнение.  

Изменено пользователем E_C_C
Ссылка на комментарий
Поделиться на другие сайты

Даже ребенка в игре с кубиками учат, что при строительстве пирамидки снизу должны быть кубики побольше, а выше - поменьше. То есть объясняют порядок, которого следует придерживаться. Так и в программировании: если придерживаться порядка, то будет легче.

Разумеется, если руки не дрожат и есть опыт, можно построить пирамиду и наоборот6 снизу маленький и тонкий, а на нем огромная куча больших и толстых. Но все это развалится от малешего толчка. Так и в программировании: если делать как-нибудь, оно вполне может работать, и даже будет скорее всего работать, но буквально до первой попытки что-то изменить.

При программировании на Си вопрос оптимальности - надуманный вопрос. В огромном количестве случаев любая "оптимизация вручную" (пример с делением) наверняка в конечном итоге проиграет оптимизации, которую устроит компилятор. Но даже если это и не так - необходимости в столь тонкой оптимизации почти никогда не встречается в любительских проектах: производительность современных микроконтроллеров настолько высока, что экономить на делении, заменяя его сдвигами, нет никакого смысла.

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

Есть большая и толстая книга:

71AE90J735L%5B1%5D.gif

или в переводе на русский

Alen_Golub__Verevka_dostatochnoj_dliny_c

Прочесть которую необходимо каждому, кто вознамерился заниматься программирвоанием хотя бы раз в неделю. Хорошо прочищает голову, освобождая от всяких вопросов типа "а нужно ли?".

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

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

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

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

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

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

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

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

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

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...