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

Си для 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-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 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 пользователей онлайн

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

    • Значит разряженную установил, или ИБП не исправный
    • Правильно ли я понял. Мне нужно взять где-то 12В (например, с лабораторного БП) и подать их на выход 12В моего сломанного БП через лампочку. Минусом на минус, плюсом на плюс? И тоже самое сделать с выходами 5В и 3.3В. И если в каком из этих случаев загорится лампочка, тогда с выходом есть проблема? Так, как написал @Armenn? Я уточнил в сообщении выше. Ибо не совсем понял, как это делать. 
    • Хочу сделать что-то вроде СВЧ-глушителя направленного действия.  1) Надо чтобы во время работы аппарат нельзя было выявить широкополосными радиосканерами (главная задача). 2) Чтобы максимум излучения достигло цели 3) Чтобы аппарат не мешал работе РЛС, GSM, WiFi и чтобы он вообще никому, кроме коптеров не мешал 4) Чтобы не сварить и не облучить себя и других людей Мне нужно для частоты 2200-2700 МГц (из СВЧ печи) Нужно чтобы он далеко бил. Если 2.5 ГГц попадет на поверхность какого-то большого объекта, то я не останусь незамеченным для радиосканеров и РЛС, а если их много в районе, то могут и определить направление даже если антенна направленная.  Допустим я возьму длинную трубу, обклею изнутри фольгой. Но по аналогии с фонарем. Если я обклею трубу фольгой и помещу вовнутрь фонарь, то какой бы длинной не была труба, на выходе будет расходящийся пучок, потому что лучи отражаются.  Но если я возьму черную трубу, то я получу более-менее узконаправленный луч. Но как на частоте 2.5 ГГц сделать из обычной трубы "черную" трубу?
    • Это касается именно тебя. Хотя... Поздно пить боржоми...  Давай, минусуй, двоечник. 
    • С ходу погружаться в регистры и ассемблер, пожалуй, перебором будет, но прочитать про распиновку, про различные функции каждого из выводов - не так уж и страшно. Иначе можно навсегда на уровне ардуино остаться - прошивать чужие коды без малейшего понимания, как оно работает.
    • Нет нельзя )  Вам я конечно не запрещаю. Не на этом этапе, может отпугнуть ) Например меня раздражает отсутствие схемы, хоть и без нее можно разобраться..
    • Не спешите, непонятно что подать... На 4-х контактном (три используются) я подаю переменку с вторички транса, постоянку (плюс) и общий (gnd). Что нужно поменять или дополнительно подключить?  А вот как? Тогда заведу на gnd доп проводок и попробую такой вариант. 
×
×
  • Создать...