Нескольно простых вопросов о программировании AVR на Си.

Обсуждаем контроллеры компании Atmel.
Ответить
Открыл глаза
Сообщения: 40
Зарегистрирован: Пн июн 30, 2014 13:19:49
Откуда: Красногорск/Москва

Сообщение slonek »

ее результат - не логическая константа
Но с портом D она же работает... Как правильно записать эту строку?
Реклама
Опытный кот
Аватара пользователя
Сообщения: 760
Зарегистрирован: Сб окт 22, 2016 17:33:32
Откуда: кг

Сообщение Карбофос »

Код: Выделить всё

while (PINB&(1 << PB4)){}
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Она С портом D она работает только потому, что это PD0, а не другой пин. (1<<PD0) как раз равен 1, вот и "повезло".

Лучше сравнивать либо как выше Карбофос предложил, или:

Код: Выделить всё

while (PINB & (1 << PB4) == (1 << PB4)){}
Контактная информация:
Открыл глаза
Сообщения: 40
Зарегистрирован: Пн июн 30, 2014 13:19:49
Откуда: Красногорск/Москва

Сообщение slonek »

Спасибо!
А строку не нужно менять?

Код: Выделить всё

while ((PINB&(1 << PB4)) == 0){} // Ждем пока на выводе PB4 лог. 0
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Можно не менять, а можно короче записывать:

Код: Выделить всё

while (!(PINB & (1 << PB4)); // висим, пока на пине 0
while (PINB & (1 << PB4); // висим, пока на пине 1
Контактная информация:
Реклама
Открыл глаза
Сообщения: 40
Зарегистрирован: Пн июн 30, 2014 13:19:49
Откуда: Красногорск/Москва

Сообщение slonek »

Спасибо! Запустил смену светодиода по тактовой кнопке... ну и не только.
Вот полный говнокод:
Спойлер

Код: Выделить всё

#define F_CPU 9216000UL
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

int main()
{
	 CLKPR = (1 << CLKPCE);
	 CLKPR = (0 << CLKPCE) | (0 << CLKPS3) | (0 << CLKPS2) | (1 << CLKPS1) | (0 << CLKPS0);//Делим на 4
	
	DDRB= 0b01101110;
	PORTB=0b001011101;
	
	TCCR0A=0;
	TCCR0B=0;
	
	TCCR0A|= (1<<WGM01); //Выставляем режим CTC
	TCCR0A|= (1<<COM0A0); //Инвертируем значение OC0A по срабатыванию таймера.
	TCCR0B|= (1<<CS02);  //Ставим предделитель на значение 256. Запускаем генерацию
	
	OCR0A=134;
	
	TCCR1A = (1 << COM1A1) | (1 << WGM12) | (1 << WGM10); // Выставляем FAST PWM
	TCCR1B = (1 << CS12) | (1 << CS10); // Предделитель
	TCNT1=0;           // clear counter
	ICR1=23039;        // 100 Hz from 9216000/4 MHz clock
	
	TCCR1A=0b10000010; // non-inverting, fast PWM
	TCCR1B=0b00011001; // fast PWM, full speed
	
	OCR1A=20000;         // 86% strobe
				
 while(1) { 
 	  
 while (PINB&(1 << PB4)){} // Ждем пока на выводе PB4 лог. 1
 _delay_ms(50); // Задержка
 if ((PINB&(1 << PB6)) == 0) // Если на выводе PB0 лог. 0
 {
	 PORTB |= (1 << PB6); // Лог. 1 на выводе PB0
	 PORTB &= ~(1 << PB5); // Лог. 0 на выводе PB1
	OCR0A=134;
 }
 else
 {
	 PORTB &= ~(1 << PB6); // Лог. 0 на выводе PB0
	 PORTB |= (1 << PB5); // Лог. 1 на выводе PB1
	 OCR0A=99;
 }
 while (!(PINB & (1 << PB4))) // Ждем пока на выводе PDO лог. 0
 _delay_ms(50);}// Задержка


 if (PORTB &= ~(1 << PB0))
 {PORTB |= (1 << PB1);
	 _delay_ms(500);
 PORTB &= ~(1 << PB1);}  	
 } 
Самое противное, что не работают последние четыре строчки. Я не настоящий сварщик. Образумьте, подскажите, в чем ошибся.
Последний раз редактировалось slonek Ср ноя 17, 2021 00:55:15, всего редактировалось 1 раз.
Реклама
Опытный кот
Аватара пользователя
Сообщения: 760
Зарегистрирован: Сб окт 22, 2016 17:33:32
Откуда: кг

Сообщение Карбофос »

Код: Выделить всё

        if (!(PORTB & (1 << PB0)))
        {
            PORTB |= (1 << PB1);
            _delay_ms(500);
            PORTB &= ~(1 << PB1);
        }
    } // Задержка
Открыл глаза
Сообщения: 40
Зарегистрирован: Пн июн 30, 2014 13:19:49
Откуда: Красногорск/Москва

Сообщение slonek »

Чёт никак... :dont_know:
Нет реакции на кнопку.
Опытный кот
Аватара пользователя
Сообщения: 760
Зарегистрирован: Сб окт 22, 2016 17:33:32
Откуда: кг

Сообщение Карбофос »

Фигурная скобка.

Код: Выделить всё

} // Задержка
Надо так:

Код: Выделить всё

while (!(PINB & (1 << PB4))); // Ждем пока на выводе PDO лог. 0
_delay_ms(50);}// Задержка
Точка с запятой.
Открыл глаза
Сообщения: 40
Зарегистрирован: Пн июн 30, 2014 13:19:49
Откуда: Красногорск/Москва

Сообщение slonek »

Так у меня так и есть....
Это другая тактовая кнопка. Переключающая светодиоды и подающее высокое на PB1 - это разные кнопки. Их две.
Опытный кот
Аватара пользователя
Сообщения: 760
Зарегистрирован: Сб окт 22, 2016 17:33:32
Откуда: кг

Сообщение Карбофос »

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

И, вот такие конструкции

Код: Выделить всё

TCCR1A = 0b10000010; // non-inverting, fast PWM
TCCR1B = 0b00011001; // fast PWM, full speed
вы сами сможете их завтра понять?

Код: Выделить всё

    TCCR0A = 0;
    TCCR0B = 0;

    TCCR0A |= (1 << WGM01); //Выставляем режим CTC
    TCCR0A |= (1 << COM0A0); //Инвертируем значение OC0A по срабатыванию таймера.
    TCCR0B |= (1 << CS02); //Ставим предделитель на значение 256. Запускаем генерацию
Вот это что было?

Вот это

Код: Выделить всё

    CLKPR = (1 << CLKPCE);
    CLKPR = (0 << CLKPCE) | (0 << CLKPS3) | (0 << CLKPS2) | (1 << CLKPS1)
        | (0 << CLKPS0); //Делим на 4
к чему?
Вот это

Код: Выделить всё

    TCCR1A = (1 << COM1A1) | (1 << WGM12) | (1 << WGM10); // Выставляем FAST PWM
    TCCR1B = (1 << CS12) | (1 << CS10); // Предделитель
    TCNT1 = 0; // clear counter
    ICR1 = 23039; // 100 Hz from 9216000/4 MHz clock

    TCCR1A = 0b10000010; // non-inverting, fast PWM
    TCCR1B = 0b00011001; // fast PWM, full speed
тож что за писец?

Дальше не хочу смотреть.
Открыл глаза
Сообщения: 40
Зарегистрирован: Пн июн 30, 2014 13:19:49
Откуда: Красногорск/Москва

Сообщение slonek »

Просто словами опишите, где кнопки, и что хотите получить.
Иначе, получается разговор глухого с немым.
МК представляет собой два генератора. Один из них постоянно шарашит 100Гц на выводе OC1A (PB3).
Второй может выдавать 45 Гц и 33,33 Гц на выводе OC0A (PB2). Смена значения частоты производится нажатием кнопки (PB4). В зависимости от текущего значения частоты производится индикация на выводах PB5 или PB6.
Также, к выводу PB0 подключена вторая кнопка. При ее нажатии на выводе PB1 напряжение меняется от 0 до 5В на заданное время (500ms).
Друг Кота
Аватара пользователя
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)

Сообщение DX168B »

[uquote="slonek",url="/forum/viewtopic.php?p=4123649#p4123649"]Спасибо! Запустил смену светодиода по тактовой кнопке... ну и не только.
Вот полный говнокод:
***
Самое противное, что не работают последние четыре строчки. Я не настоящий сварщик. Образумьте, подскажите, в чем ошибся.[/uquote]
Эти что-ли?

Код: Выделить всё

if (PORTB &= ~(1 << PB0))
{
    PORTB |= (1 << PB1);
    _delay_ms(500);
    PORTB &= ~(1 << PB1);
} 
Так они и не будут работать. Вы в самом условии меняете бит PB0 в регистре PORTB, а не проверяете его.

Код: Выделить всё

if ( (PORTB & (1 << PB0)) != 0 ) // Сработает, если PB0 = 1. Если нужно наоборот, то писать нужно так: if ( (PORTB & (1 << PB0)) == 0 )
{
    PORTB |= (1 << PB1);
    _delay_ms(500);
    PORTB &= ~(1 << PB1);
} 

if ( (PORTB & (1 << PB0)) != 0 ) - Перевожу на человеческий:
1. Берем регистр PORTB.
2. Применяем к нему побитовое "И" со значением, полученным от выражения (1 << PB0), таким образом, отбрасывая все биты, кроме PB0
3. Если после пункта 2 у нас получилось не нулевое значение, то выполняем действия. А иначе, пропускаем их.

Ввиду того, что в выражении (1 << PB0) оба значения являются константами, то это выражение выполнит компилятор, а не микроконтроллер, и подставит готовый результат оператору "&" (PORTB & value), который выполнит уже сам микроконтроллер.
I am DX168B and this is my favourite forum on internet!
Контактная информация:
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18769
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

байт с четвертым битом, равным 1, имеет значение, не равное 1! результат наложения маски на байт надо проверять на 0: равно - бит сброшен, не равно - бит установлен.

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

Мой уютный бложик... заходите!
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 4468
Зарегистрирован: Вс янв 24, 2010 19:19:52
Откуда: Главный Улей России (Moscow)

Сообщение DX168B »

ARV такой вопрос по поводу этих макросов (bit_is_set / bit_is_clear). Они случайно не превращаются после компиляции в инструкции SBRC / SBRS для регистров РОН и SBIC / SBIS для регистров I/O?
I am DX168B and this is my favourite forum on internet!
Контактная информация:
OKF
Это не хвост, это антенна
Сообщения: 1430
Зарегистрирован: Вт июн 07, 2011 08:03:18

Сообщение OKF »

[uquote="ARV",url="/forum/viewtopic.php?p=4124350#p4124350"]а еще лучше пользоваться макросами bit_is_set и bit_is_clear[/uquote]
ARV, думаю, лучше говорить "А ВОТ МНЕ лучше/удобнее пользоваться..."
Или объяснить чем же лучше.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18769
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

для человека, не вполне понимающего, что X & (1<<3) никогда не может быть равно 1, однозначно лучше пользоваться готовыми макросами

Добавлено after 2 minutes 9 seconds:
DX168B писал(а):Они случайно не превращаются после компиляции
честно говоря, мне по барабану, во что они превращаются - хоть в тыкву... хотя предположу, что таки да, в эти ассемблерные конструкции (если аргументы однобайтовые, конечно)
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Открыл глаза
Сообщения: 40
Зарегистрирован: Пн июн 30, 2014 13:19:49
Откуда: Красногорск/Москва

Сообщение slonek »

Камрады! По совету DX168B испробовал два варианта. Итак:
При коде:

Код: Выделить всё

if ( (PORTB & (1 << PB0)) != 0 ) 
{
PORTB |= (1 << PB1);
_delay_ms(500);
PORTB &= ~(1 << PB1);
}
На кнопку PB0 реакции нет. Но при нажатии на кнопку PB4 вместе со сменой частоты (на PB3) и индикации на светодиодах (PB5 и PB6), включается PB1 на указанное время. Каждый раз при смене частоты (нажатии на PB4).

При коде

Код: Выделить всё

if ( (PORTB & (1 << PB0)) == 0 )
{
PORTB |= (1 << PB1);
_delay_ms(500);
PORTB &= ~(1 << PB1);
}
При нажатии на PB4 меняются частота и индикация. Реакции на кнопку PB0 нет. Индикация PB1 на кнопку PB4, в отличии от предыдущего случая, не реагирует.

Напомню. Есть кнопки. PB4 и PB0. PB4 меняет генерируемую частоту и индикацию на PB5, PB6. Кнопка PB0 должна на заданное время выдавать высокое на PB1.

Что хочу получить:
По нажатию на PB4 - меняется частота генерации, меняется индикация
По нажатию PB0 - на выходе PB1 подается высокое на заданное время.
Кнопки не зависимы друг от друга.

Полный говнокод выкладывал несколькими постами ранее.
Друг Кота
Аватара пользователя
Сообщения: 6296
Зарегистрирован: Пн ноя 22, 2010 00:57:15
Откуда: Ukraine

Сообщение FreshMan »

подскажите пожалуйста
почему команда

Код: Выделить всё

char str[] = "\0";
очищает строку

а команда

Код: Выделить всё

char *str = "\0";
НЕТ
Tell Me The Truth
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18769
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

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

Мой уютный бложик... заходите!
Контактная информация:
Ответить

Вернуться в «AVR»