ARV писал(а):может, надо после if фгурными скобочками обозначить условно-выполняемый блок с вашими портянками? кстати, сами портянки неплохо бы функциями сделать
в скобки убирал вылазит ошибка. в учебниках не нашел такого примера- этот if-else заключен в скобки другого if
почему компилятор ругается на: static void portyanka(void) --- ../main.c:130:14: error: invalid storage class for function 'portyanka'
зачем нужен класс static?
а на void portyanka(void) нет, чем они отличаются?
а вы скомпилируйте со static и без него и сравните размер кода.
static имеет смысл всегда указывать для функций и переменных, которые нужны только в пределах этого файла-модуля. если у вас однофайловый проект, значит, все функции делайте static
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 8000000UL
unsigned char test = 0;
void main(void)
{
//первые 4 вывода обоих портов выходы
DDRD = 0b00001111;
PORTD = 0b00001111;
DDRB = 0b00001111;
PORTB = 0b00001111;
TCCR0A = 0x00; //нормальный режим работы т/с0
TCCR0B |= (1 << CS01); //предделитель 256
TIMSK |= (1 << TOIE0); //разрешение прерывания по переполнению т/с0
sei(); //разрешение прерываний
while(1)
{
PORTD ^= (1 << PD0); //инверсия PD0 - проблема в этой строчке!
PORTB ^= (1 << PB0); //инверсия PB0
//приращение тестовой переменной
test++;
if (test == 255) test = 0;
}
}
ISR(TIMER0_OVF_vect) //прерывание по переполнению т/с0
{
PORTD ^= (1 << PD3); //инверсия PD3
}
Зачем оно? В основном цикле что-то делаем с переменными и выводами. В это время на PD3 должен генерироваться меандр. Если не обращаться к порту Д, все работает. Если сделать как в приведенном коде (с инверсией PD0), меандр превращается в это:
Как запись чего-то в порт (на другой вывод) может влиять на генератор в прерывании?
что есть PORTD ^= (1 << PD0); ?
1. считать порт в регистр
2. изменить в регистре бит
3. записать регистр в порт
догадайтесь, что будет, если между 1 и 2 или между 2 и 3 возникнет прерывание, которое выполняет аналогичные действия с этим же портом.
в Вашем случае простейший вариант - запретить прерывания на время выполнения этой строчки.
Понято, спасибо. В программе обращений к порту Д много, вокруг каждого запрет/разрешение втыкать - текст страшненький будет. Придется это дело в функцию запихать как-то , хех. Но, главное, грабли найдены.
правильный вариант - включить аппаратное дергание ножкой по таймеру.
еще вариант (плохой - непереносимость кода, не со всеми портами сработает):
не инвертировать бит, а устанавливать и очищать, что при включенной оптимизации сведется к одной инструкции sbi / cbi.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Попробовал оба варианта - второй, естественно, красивше.
Контроллер ATTiny2313. Смысл программы: собираем с порта Б сигналы, анализируем. При некоторых условиях выдаем соответствующие сигналы на порт Д. При этом на одном из выводов порта Д должен генерироваться меандр (примерно 2 кГц), который поступает на один из выводов порта Б. Наличие этого меандра - одно из условий, по которым выставляются сигналы порта Д. В общем, эта штука имитирует контроллер защит привода Arteh MDC2.
Вариант с прерываниями:
Спойлер
ISR(TIMER0_OVF_vect) //прерывание по переполнению т/с0
{
PIND = (1 << PD3); //инверсия PD3
}
СпойлерRTFM
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Или здесь тоже аппаратный хак сродни тому, как сбрасываются некоторые биты в ноль путём записи их в единицу (например, в АЦП, ADIF бит регистра ADCSRA)?
P.S. В интернете нагуглил цитату якобы из даташита
Writing a logic one to PINxn toggles the value of PORTxn, independent on the value of DDRxn.
, но в самих даташитах её не вижу.
P.P.S. В даташите на ATtiny2313 такое есть, на ATmega8, Atmega16 - нет.
Забавно... Прогуглив этот вопрос наткнулся на одно своего рода исследование:
У автора получился вариант с PORTx |= (1<<bit) самым быстрым. Вдвое быстрее чем запись в PINx.