MOZK12342
1

Состояние PORT не передается в PIN

20.05.2017, 22:30. Показов 7280. Ответов 40
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день!
Недавно я начал изучение программирования МК. Платформа Code vision, отладчик AVR studyo v.4.19. Микроконтройлер - ATMiko8.
Задача: настроить PORTB на ввод, подтянуть внутренними резисторами к +, схематически подключить кнопку на массу и все это дело считывать и выполнять действие.
Пишу код:
Инициализация
DDRB=0x00;
PORTB=0xFF;
после этого мне нужно проверить состояние кнопки, как я понимаю считывать состояние нужно из PINB. Проверяю условие:
if(PINB.0==0)
Отладчик всегда выполняет условие, т.к. PINB даже и не думал выставляться в единицы.
Настраиваю порт на вывод (DDRB=0xFF)(кликами мышки в отладчике), и PINB начинает принимать состояние PORTB следующим шагом при отладке, сбрасываю DDRB и снова PINB замирает.
Удивительно, что в Proteus все работает, но как работать с отладкой?

Программа тренировочная - ведет счет при нажатии кнопки

Код
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
void main(void)
{
unsykned char number[10]=
{
0x3f, //0
0x06, //1
0x5b, //2
0x4f, //3
0x66, //4
0x6d, //5
0x7d, //6
0x07, //7
0x7f, //8
0x6f  //9
};
unsykned char r=0;
unsykned char data[4]={0,0,0,0};
DDRB=0x00;
PORTB=0xFF;
DDRC=0x7F;
PORTC=0x00;
DDRD=0xFF;
PORTD=0x00;
ACSR=0x80;
while (1)
{
for(r=0;r<4;r++)
{
PORTD=number[data[r]];
PORTC=(1<<r);
delay_ms(1);
PORTD=0x00;
PORTC=0x00;
}
if(PINB.0==0)
{
if(data[0]<9) {data[0]++;}
else
{
data[0]=0;
if(data[1]<9) {data[1]++;}
else
{
data[1]=0;
if(data[2]<9) {data[2]++;}
else
{
data[2]=0;
if(data[3]<9) {data[3]++;}
else
{
data[3]=0;
}
}
}
}
}
}
}
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
20.05.2017, 22:30
Ответы с готовыми решениями:

Не устанавливается PIN после установки PORT в 1
Добрый день, я начинающий, учусь естественно с примеров. AVR Studyo 6.1. Схема простая, кнопка и...

Модернизация китайского 4 pin разветвителя: добавление поддержки PWM на 3 pin и 2 pin вентиляторах
Задача: переделка 3-х пинового вентилятора в 4-х пиновый с добавлением поддержки изменения оборотов...

Блок питания 8 pin или 4 pin и переходник на 8 pin?
Что лучше?или одинаково? Добавлено через 2 часа 30 минут CPU

Supermicro x9dbu работает на 8-pin + 8-pin без 4-pin
Добрый день, уважаемые. Пришла стойка с 2-мя серверами (вот счастье привалило...), до этого...

Какой артикул у разъема Apple ssd 6+12 pin и 7+17 pin
Добрый день! Кто может подсказать артикулы Apple разъемов для ssd дисков. Интересуют разъемы 6+12 и...

40
1 / 1 / 0
Регистрация: 28.03.2015
Сообщений: 94
14.01.2020, 11:23 21
Author24 — интернет-сервис помощи студентам
Нет, я ожидал что выход PIN изменит свое состояние на "высокий"одновременно с появлением высокого уровня на Port, так в самоучителе пишут, но это не произошло. Т.е. ожидаемое не совпало с увиденным. Кто косячит: я, букварь, или симулятор?
0
3881 / 2479 / 418
Регистрация: 09.09.2017
Сообщений: 10,862
14.01.2020, 12:13 22
Цитата Сообщение от mode2 Посмотреть сообщение
Нет, я ожидал что выход PIN изменит свое состояние на "высокий"одновременно с появлением высокого уровня на Port
Наличие задержки между чтением и записью описано где-то в даташите. С ходу, правда, не нашел, где именно.
Микроконтроллер - штука синхронная. Любой процесс происходит у него за один такт, и о том, что было между тактами, он не знает. Более того, любая физическая система обладает инерцией, то есть порт не может переключиться мгновенно, что на чтение, что на запись. Вот и получается, что на первом такте вы записываете в порт значение, и оно только начинает меняться. И тут же считываете его. А система-то инерционная, значение в порту измениться еще не успело.
Это на самом примитивном уровне.
Если хотите подробностей, почитайте еще что такое буферизация, конвейер выполнения. Да и общие знания по цифровой схемотехнике лишними не будут.

Добавлено через 6 минут
Все-таки нашел:
Цитата Сообщение от Даташит на ATmega8, глава I/O ports
Reading the Pin Value
Independent of the setting of Data Direction bit DDxn, the port pin can be read through the PINxn Register Bit. As shown in Figure 22, the PINxn Register bit and the preceding latch constitute a synchronizer. This is needed to avoid metastability if the physical pin changes value near the edge of the internal clock, but it also introduces a delay. Figure 23 shows a timing diagram of the synchronization when reading an externally applied pin value.
Цитата Сообщение от Евстифеев, глава 6.3 - Конфигурирование портов ввода-вывода
Состояние вывода микроконтроллера (независимо от установок бита DDxn) может быть получено путем чтения бита PINx регистра PIN*. При этом следует помнить, что между действительным изменением сигнала на выводе и изменением бита PINx существует задержка. Эта задержка вносится узлом синхронизации, состоящим, как показано на Рис. 6.1, из бита PINx и дополнительного триггера-защелки. Значение сигнала на выводе микроконтроллера фиксируется триггером-защелкой при НИЗКОМ уровне тактового сигнала и переписывается затем в бит РINx по нарастающему фронту тактового сигнала. Соответственно, величина задержки может составлять от 0.5 до 1.5 периодов системного тактового сигнала, как показано на Рис. 6.3, а.По этой же причине между операциями изменения и повторного считывания состояний вывода необходимо вставлять команду NOP. Поскольку команда OUT устанавливает сигнал «SYNC LATCH» в 1 по положительному фронту тактового сигнала, задержка в этом случае равна одному периоду тактового сигнала (Рис. 6.3, б).
1
1 / 1 / 0
Регистрация: 28.03.2015
Сообщений: 94
15.01.2020, 09:24 23
Укажу источник моих ожиданий, в нем, со слов автора, используется Atmel Studio 6 (я использую студию 4.19), и на скрине показывается что уровни PORT и PIN становятся высокими (оба) после выполнения команды PORTD = 0b00000001; Не только показывается, но и комментируется в тексте. В студии 4.19 добиться такого я не смог. В чем причина расхождения? В студии 6 изменили механизм, или ошибка в изложении материала? Кстати, автор иногда путает местами "правый" и "левый"
http://narodstream.ru/avr-urok... m-svetodi/
Миниатюры
Состояние PORT не передается в PIN  
0
3881 / 2479 / 418
Регистрация: 09.09.2017
Сообщений: 10,862
15.01.2020, 11:51 24
Самый надежный источник информации - даташит производителя.
Если чье-то высказывание противоречит даташиту, оно скорее всего неверное. Если сомнение остается, можно еще заглянуть в errata (перечень ошибок). Если и там нет, то, в лучшем случае, высказавший наткнулся на недокументированное или неопределенное поведение. Полагаться на него нельзя, но учитывать такую неоднозначность придется.
Так и в вашем случае: в одном месте пин переключается сразу, в другом через такт, а в реальности там довольно долгие переходные процессы, особенно если на ножке что-то висит.
Цитата Сообщение от mode2 Посмотреть сообщение
Кстати, автор иногда путает местами "правый" и "левый"
http://narodstream.ru/avr-urok... m-svetodi/
Когда увидел это: PORTD = 0b00000001; хотел сразу начать критиковать автора. Но нет, дальше он рассказывает о правильном использовании портов.
Из того, что я бегло проглядел по тексту, неплохой курс. Главное на видео не отвлекаться, без него проще.
Также рекомендую ознакомиться с курсом DiHalt'а, скажем, на изиэлектрониксе, да и на просторах интернета его можно найти.
.
Относительно портов и тому подобного: электроника не идеальна, после любого действия надо какое-то время переждать переходные процессы, чтобы потом считать не непонятный мусор, а хорошее стабильное состояние.
0
1 / 1 / 0
Регистрация: 28.03.2015
Сообщений: 94
15.01.2020, 18:45 25
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Из того, что я бегло проглядел по тексту, неплохой курс.
Несомненно у автора есть способности к изложению, написано живо. Но...вот этот абзац прокомментируйте, пожалуйста. Пояснение корректное, или в нем есть опечатки? Я пытался въедливо читать, но картина в голове не сложилась. Я не прошу объяснять выражение, только оценка абзаца на корректность поданного материала.

PORTD |= (1<<(PORTD0));
Первый непонятный оператор в данной команде — это сдвоенный оператор "|=". Такого рода операторов существует несколько. В данном случае сначала результат, который получится в правой части, сразу не присваивается переменной. которая находится в правой части, а складывается логически по "ИЛИ" со значением, хранящемся до этого в перменной, которая находится справа. Затем уже результат, полученный после применения данной логической операции, присваивается переменной, находящейся в правой части.
0
3881 / 2479 / 418
Регистрация: 09.09.2017
Сообщений: 10,862
16.01.2020, 09:07 26
x += y == x = x+y
x *= y == x = x*y
x |= y == x = x | y
x &=y == x = x & y
и т.д.
Цитата Сообщение от mode2 Посмотреть сообщение
Но...вот этот абзац прокомментируйте, пожалуйста
Похоже, автор немного увлекся объяснением, в результате напутал правую и левую части. С другой стороны, подобные операторы можно было и не объяснять в рамках курса контроллеров, поскольку они специфичный для языка Си в целом и рассматриваются в соответствующих учебниках.
Цитата Сообщение от mode2 Посмотреть сообщение
PORTD |= (1<<(PORTD0));
Эта запись вполне корректна, но лучше оформить как PORTD |= (1<<0);. Так оно и выглядит проще, и нет путаницы PORTD vs PORTD0. Еще можно записать как PORTD |= _BV(0);, но мне такая запись не нравится.
0
27 / 22 / 5
Регистрация: 31.01.2019
Сообщений: 98
21.01.2020, 23:56 27
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
PORTD |= (1<<0);.
Фууу =)
C++
1
PORTD |= 1;
Так красивЖе
0
3881 / 2479 / 418
Регистрация: 09.09.2017
Сообщений: 10,862
22.01.2020, 11:22 28
Цитата Сообщение от joogorden Посмотреть сообщение
Так красивЖе
Ничего подобного. Моя запись выглядит как установка бита. Ваша - как сложение с магическим числом.
0
27 / 22 / 5
Регистрация: 31.01.2019
Сообщений: 98
22.01.2020, 11:32 29
COKPOWEHEU, Вы серьёзно?
0
3881 / 2479 / 418
Регистрация: 09.09.2017
Сообщений: 10,862
22.01.2020, 12:42 30
joogorden, что поделать, не для всех очевидно, что при работе с отдельными битами лучше указывать именно отдельные биты, а не битовые маски.
Ну и учитывайте, что я комментировал пособие для начинающих. Им еще не рассказали, что вместо записи бита по номеру можно использовать именованные константы или целые макрофункции.
Запись вроде TIMSK |= (1<<TOIE1), конечно, еще лучше. Но ведь и для ее использования надо понимать, что TOIE1 это всего лишь чиселко, только поименованное.
0
27 / 22 / 5
Регистрация: 31.01.2019
Сообщений: 98
22.01.2020, 17:13 31
Для наглядности:
C++
1
    PORTD = PORTD | 0b00000001; //PD0=HIGH
А вообще это всё словоблудие. У всех представления о прекрасном индивидуальны =)
0
3881 / 2479 / 418
Регистрация: 09.09.2017
Сообщений: 10,862
22.01.2020, 18:14 32
Да, такой примитивный вариант в той статье разбирался. И, наверное, там расписано почему он не наглядный.
Для примера, какой код вы прочтете быстрее (прокомментируйте какие биты будут выставлены в каждом случае):
C
1
2
3
PORTD |= (1<<3);
PORTC |= 0b0010000;
PORTB |= 128;
А потом наступит веселье с перемещением устройства с одного вывода на другой. Например, потому что на том выводе UART вдруг понадобился, или просто плату развести проще.
0
27 / 22 / 5
Регистрация: 31.01.2019
Сообщений: 98
22.01.2020, 18:58 33
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
какой код вы прочтете быстрее
Естественно второй вариант =)
А ещё мне больше нравится такой вариант PORTB |= 0x80;

Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
А потом наступит веселье с перемещением устройства с одного вывода на другой. Например, потому что на том выводе UART вдруг понадобился, или просто плату развести проще.
А в чём веселье то, если такие вещи как выводы описываются в начале листинга в дефайнах?
0
3881 / 2479 / 418
Регистрация: 09.09.2017
Сообщений: 10,862
22.01.2020, 20:09 34
Вы не ответили какие биты там выставляются.
Впрочем, уже то, что вы не обратили на это внимания, намекает, что ошибку во второй записи вы не заметили.
0
27 / 22 / 5
Регистрация: 31.01.2019
Сообщений: 98
22.01.2020, 20:29 35
Забавно, не знал что мне тут тест устроили. Что то не заметил вопроса про где какие биты.
А вы как биты считаете? Нулевой бит у вас нулевой или первый? =)
Да ошибку не заметил, пока вы не написали. Но это не серьезная ошибка если биты считать с права и старшие не нужны. Компилятор скушает молча, а по второму варианту будет 0x10.
0
3881 / 2479 / 418
Регистрация: 09.09.2017
Сообщений: 10,862
23.01.2020, 11:02 36
Цитата Сообщение от joogorden Посмотреть сообщение
А вы как биты считаете? Нулевой бит у вас нулевой или первый? =)
Счет битов обычно начинается с нуля справа налево. Вспомните хотя бы порты PORTA0, PORTC4 и т.д.
Цитата Сообщение от joogorden Посмотреть сообщение
Да ошибку не заметил, пока вы не написали. Но это не серьезная ошибка если биты считать с права и старшие не нужны. Компилятор скушает молча
В том-то и проблема что компилятор скушает и даже предупреждения не выдаст. То есть пропустит потенциальную ошибку, когда человек хотел выставить 5-й бит, а выставлен будет 4-й. И сиди считай нолики. В записи же со сдвигами такой проблемы нет. А ведь битовые маски бывают и больше чем 8-битные.
Цитата Сообщение от joogorden Посмотреть сообщение
а по второму варианту будет 0x10
Сейчас-то, когда я рассказал про ошибку, уже неинтересно.
.
Ладно, предлагаю закончить спор о вкусе фломастеров
0
27 / 22 / 5
Регистрация: 31.01.2019
Сообщений: 98
23.01.2020, 13:41 37
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Счет битов обычно начинается с нуля справа налево. Вспомните хотя бы порты PORTA0, PORTC4 и т.д.
Это всем понятно. Вопрос возникнет у вас же если я вам отвечу на ваш же вопрос
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
(прокомментируйте какие биты будут выставлены в каждом случае):
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
PORTC |= 0b0010000
Так как в байте всего 8 бит логично нулевой бит посчитать первым, а седьмой восьмым. Ноль то это же ничего.
И если я вам отвечу пятый, вы скажете что я болван. Поэтому и написал 0x10 что бы не было таких вопросов.

Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Ладно, предлагаю закончить спор о вкусе фломастеров
Я с вами не спорю, а пишу что у других людей есть другие мнения отличные от ваших "истинных".
0
3881 / 2479 / 418
Регистрация: 09.09.2017
Сообщений: 10,862
23.01.2020, 14:52 38
Цитата Сообщение от joogorden Посмотреть сообщение
Так как в байте всего 8 бит логично нулевой бит посчитать первым, а седьмой восьмым.
Логично нулевой бит посчитать нулевым, а не первым. Мы же начали с управления портами в AVR. Да и абстрактные биты считаются так же.
А незначащие старшие нули вообще бессмысленно считать, их там бесконечно много.
Цитата Сообщение от joogorden Посмотреть сообщение
Я с вами не спорю, а пишу что у других людей есть другие мнения отличные от ваших "истинных".
Вы пытаетесь подменить понятия. Запись сдвигами обладает объективными преимуществами перед магическими числами, это не субъективное мнение.
Точно так же вынесение макросов обладает объективными преимуществами перед копипастом.
0
27 / 22 / 5
Регистрация: 31.01.2019
Сообщений: 98
23.01.2020, 16:44 39
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Логично нулевой бит посчитать нулевым, а не первым.
Это у него только наименование может быть например "D0" а по счету то он первый.

Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
А незначащие старшие нули вообще бессмысленно считать, их там бесконечно много.
То есть вы утверждаете что во втором вашем примере нет ошибки как вы ранее утверждали?

Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Запись сдвигами обладает объективными преимуществами перед магическими числами, это не субъективное мнение.
Я бы еще понял ваше утверждение, но в 26 посте что вы написали:
PORTD |= (1<<(PORTD0));
Эта запись вполне корректна, но лучше оформить как PORTD |= (1<<0);.

Вы имеете ввиду свой сдвиг единицы ноль раз?
0
2 / 2 / 0
Регистрация: 12.12.2019
Сообщений: 26
23.01.2020, 17:05 40
COKPOWEHEU, Вы грамотный человек. Но я не приветствую Ваше отношение к вопрошающим! Что за экспресс тесты? Ну и Вы же не "супермен" .)
Вы очень много пишете, очень много из написанного Вами очень интересно, но это не начальный уровень. Научитесь отвечать на вопрос прямо.) и не разводить холивар на 16 страниц форума из ничего!!
(ничего личного, просто я проникся Вашим "общением")
0
23.01.2020, 17:05
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.01.2020, 17:05
Помогаю со студенческими работами здесь

MSI Z77A-G45 подключение через 4-Pin + 4-Pin
Пару лет назад подключил MSI Z77A-G45 через 4-Pin + 4-Pin из-за того, что у меня нет 8-Pin...

Подключение питания 8 pin + 6 pin для GTX 760
Добрый день! Карта Asus GTX 760, доп питание 8 pin + 6 pin, имеется переходник 2 х 6 pin -&gt; 8...

Комп стартует от питания 4 pin, но при подключении 8 pin
Здравствуйте, уважаемые жители форума. блок питания: 450 W проц: Intel® Core™ i5-2310 (с...

Можно ли сунуть в rx 570 4gb только 6 pin, а не 8 pin?
Можно ли сунуть в rx 570 4gb только 6 pin, а не 8 pin? Будет все нормально?

Можно ли прицепить питание на процессор 4x pin когда на БП 8x pin
Можно ли прицепить питание на процессор У меня есть блок питания 24\8pin Как Вы поняли, 8pin это...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru