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

Настройка портов в AVR

есть две строчки кода

 

DDRD = (0<<PD1)|(1<<PD0);

PORTD = (1<<PD1)|(0<<PD0);

 

что они делают? желательно как можно подробнее.

Я понимаю так: что в регистр DDRD записываем число получающееся после сдвига числа ноль влево на PD1, а также числа 1 влево на PD0. А так же операции ИЛИ между результатами двух этих операций. Но чему равны PD1 и PD0 непонятно.

Наверное я совсем ничего не понимаю в этом, подскажите пожалуйста.

 

к PD1 подключен пьезик

к PD0 подключена кнопка.

 

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


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

DDRD = (0<<PD1)|(1<<PD0);

PORTD = (1<<PD1)|(0<<PD0);

 

что они делают? желательно как можно подробнее.

к PD1 подключен пьезик

к PD0 подключена кнопка.

 

Запись DDRD = (0<<PD1)|(1<<PD0) сделает PD1 входом а PD0 выходом (кстати (0<<PD1) не имеет смысла).

Запись PORTD = (1<<PD1)|(0<<PD0) включит встроенный подтягивающий резистор на PD1 (т.к. как он настроен на вход), а на PD0 будет установлен уровень логического 0.

 

Теперь смотрим по настройкам.

PD1 сконфигурирован как вход с подтяжкой и к нему подключается "пьезик". Если "пьезик" это пищалка то никакого писка Вы нимкогда не услышите.

PD0 сконфигурирован как выход установленный в 0. Если на нём висит кнопка то что будет когда её нажмут? Если кнопка подтянута к напряжению питания то в целом ничего плохого, но если к 0 то может выгореть порт (хотя тут надо смотреть на схему для ясности).

 

IMHO настройки совсем не соответствуют тому, что Вы пытаетесь подключить к этим входам/выходам.

 

Запись DDRD = (0<<PD1)|(1<<PD0); делает такое: берёт 0 и сдвигает его на PD1 едениц влево (естественно в итоге получаем 0 поэтому запись не имеет смысла), потом берёт 1 и сдвигает на PD0 едениц влево (в итоге получаем число 0b00000001 что имеет смысл). Далее делает логическое OR 0 с числом 0b00000001 и полученный результат присваивается DDRD

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

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


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

Спасибо большое!

Пример заработал. Вот только не совсем понятна фраза как таковая "здвигаем на PD0 единиц"...

Чему изначально равно PD0? Или дело обстоит так, сначала выставляем на PD0 единицу, а потом уже работаем с ним?

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


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

Чему изначально равно PD0? Или дело обстоит так, сначала выставляем на PD0 единицу, а потом уже работаем с ним?

Обычно пины портов у AVR определяются в одном из хидеров, как НОМЕP этого пина:

#define PD0 0

#define PD1 1

#define PD2 2

......................

#define PD7 7

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

Запись типа 0<<PD2, хоть и численно равна нулю, но является наглядным способом указания того, что бит в маске порта, соответствующий пину PD2, равен нулю. Такая форма записи подразумевает, что определения пинов PD0-PD7 соответствуют номеру бита в байте. А чтобы запихнуть в данное место 0 или 1, их сдвигают влево операцией сдвига << на это же число двоичных разрядов.

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

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


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

В Си для задания битовых масок обычно пишут (стиль варируется)

DDRD = 
//(1<<PD7) |
//(1<<PD6) |
//(1<<PD5) |
//(1<<PD4) |
//(1<<PD3) |
//(1<<PD2) |
//(1<<PD1) |
(1<<PD0) |
0;

Студия не понимает такие фокусы, поэтому удобно писать

DDRD =  (0<<PD7) |(0<<PD6) |(0<<PD5) |(0<<PD4) |(0<<PD3) |(0<<PD2) |(0<<PD1) |(1<<PD0);

Особенно удобно, когда конфигурируешь переферию (типа SPI или UART), где биты имеют разные имена. Например SPI для Mega88

ldi    temp,(1<<SPIE)|(1<<SPE)|(0<<DORD)|(0<<MSTR)|(1<<CPOL)|(0<<CPHA)|(0<<SPR1)|(0<<SPR0)

Чтобы быстро переконфигурировать не вспоминая их корявых названий: в СИ достаточно закомментирова/раскомментировать строку, при таком способе записи поменять "0" на "1" или "1" на "0".

 

Заголовочники для МК как лежат в C:\Program Files\AVRStudio4\AvrAssembler2\Appnotes файлы типа m8def.inc (для Mega8) и tn2313def.inc (ATtiny2313). В них можно увидеть следующее

; ***** PORTD ************************

; PORTD - Data Register, Port D

.equ PORTD0 = 0 ;

.equ PD0 = 0 ; For compatibility

.equ PORTD1 = 1 ;

.equ PD1 = 1 ; For compatibility

.equ PORTD2 = 2 ;

.equ PD2 = 2 ; For compatibility

.equ PORTD3 = 3 ;

.equ PD3 = 3 ; For compatibility

.equ PORTD4 = 4 ;

.equ PD4 = 4 ; For compatibility

.equ PORTD5 = 5 ;

.equ PD5 = 5 ; For compatibility

.equ PORTD6 = 6 ;

.equ PD6 = 6 ; For compatibility

 

; DDRD

.equ DDD0 = 0 ;

.equ DDD1 = 1 ;

.equ DDD2 = 2 ;

.equ DDD3 = 3 ;

.equ DDD4 = 4 ;

.equ DDD5 = 5 ;

.equ DDD6 = 6 ;

 

По оформлению в своё время с коллегой "Сишником" долго дискутировал. Он также убеждал, что запись (0<<PD5) смысла не имеет и не стоит поэтому уродовать код B)

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


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

ldi temp,(1<<SPIE)|(1<<SPE)|(0<<DORD)|(0<<MSTR)|(1<<CPOL)|(0<<CPHA)|(0<<SPR1)|(0<<SPR0)

Скобки можно не писать функция (<<) имеет больший приоритет

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


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

2 ILYAUL

 

И как это будет выглядить со стороны ??

ldi temp, 1<<SPIE|1<<SPE|0<<DORD|0<<MSTR|1<<CPOL|0<<CPHA|0<<SPR1|0<<SPR0

 

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

 

Кроме краткости кода, должна присутсвовать его читабельность. И даже в большей степени чем кракость!

А скобки позволяют повысить читабельность кода

 

Например в книге Керигана/Ричи есть такой пример

char (*(*x[3]) ()) [5];

Но даже не новичку его будет трудно понять

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


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

2 ILYAUL

 

И как это будет выглядить со стороны ??

ldi temp, 1<<SPIE|1<<SPE|0<<DORD|0<<MSTR|1<<CPOL|0<<CPHA|0<<SPR1|0<<SPR0

Честно говоря , со временем привыкаешь , особенно если ещё не нужные нули убрать т.к. по умолчанию всё что не 1 установится в ноль

ldi temp, 1<<SPIE|1<<SPE|1<<CPOL

 

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


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

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

 

PORTx |= ( 1 << PINx ) | ( 1 << PINy ); // и т.д. - для "поднятия" пинов в единицу

PORTx &= ~( ( 1 << PINx ) | ( 1 << PINy ) ); // и т.д. - для соответственного "опускания" пинов в 0

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


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

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

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

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

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

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

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

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

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

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