Добрый день.
Изучаю прерывания, написал в CVAVR простейшую программу, которая по идее должна подавать логическую единицу на PB4 при изменении уровня на PB0. Только вот на PB4 всегда ноль. Ткните новичка носом. Ниже код:
/*******************************************************
This program was created by the
CodeWizardAVR V3.12 Advanced
Automatic Program Generator
© Copyright 1998-2014 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com
Project :
Version :
Date : 15.12.2015
Author :
Company :
Comments:
Chip type : ATtiny13A
AVR Core Clock frequency: 9,600000 MHz
Memory model : Tiny
External RAM size : 0
Data Stack size : 16
*******************************************************/
#include <tiny13a.h>
// Declare your global variables here
// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
// Place your code here
PORTB.4 = 1;
}
void main(void)
{
// Declare your local variables here
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE) | (0<<CLKPS3) | (0<<CLKPS2) | (0<<CLKPS1) | (0<<CLKPS0);
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
// Input/Output Ports initialization
// Port B initialization
// Function: Bit5=In Bit4=Out Bit3=In Bit2=In Bit1=In Bit0=In
DDRB=(0<<DDB5) | (1<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit5=0 Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
PORTB=(0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (1<<PORTB0);
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Normal top=0xFF
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=(0<<COM0A1) | (0<<COM0A0) | (0<<COM0B1) | (0<<COM0B0) | (0<<WGM01) | (0<<WGM00);
TCCR0B=(0<<WGM02) | (0<<CS02) | (0<<CS01) | (0<<CS00);
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;
// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=(0<<OCIE0B) | (0<<OCIE0A) | (0<<TOIE0);
// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Any change
// Interrupt on any change on pins PCINT0-5: Off
GIMSK=(1<<INT0) | (0<<PCIE);
MCUCR=(0<<ISC01) | (1<ISC00);
GIFR=(1<<INTF0) | (0<<PCIF);
// Analog Comparator initialization
// Analog Comparator: Off
// The Analog Comparator's positive input is
// connected to the AIN0 pin
// The Analog Comparator's negative input is
// connected to the AIN1 pin
ACSR=(1<<ACD) | (0<<ACBG) | (0<<ACO) | (0<<ACI) | (0<<ACIE) | (0<<ACIS1) | (0<<ACIS0);
ADCSRB=(0<<ACME);
// Digital input buffer on AIN0: On
// Digital input buffer on AIN1: On
DIDR0=(0<<AIN0D) | (0<<AIN1D);
// ADC initialization
// ADC disabled
ADCSRA=(0<<ADEN) | (0<<ADSC) | (0<<ADATE) | (0<<ADIF) | (0<<ADIE) | (0<<ADPS2) | (0<<ADPS1) | (0<<ADPS0);
// Global enable interrupts
#asm("sei")
while (1)
{
// Place your code here
}
}
Помогите разобраться с прерыванием на attiny13
- Реклама
- COKPOWEHEU
- Говорящий с текстолитом
- Сообщения: 1525
- Зарегистрирован: Чт июн 10, 2010 20:11:19
Re: Помогите разобраться с прерыванием на attiny13
Для начала отформатируйте код по-человечески.
Тег [СОDE] [/СОDE]
Отступы в начале каждой строки, выделяющие блоки кода
Уберите ненужные инициализации: вместо DDRB=(0<<DDB5) | (1<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0); достаточно было оставить DDRB = (1<<4); Инициализация таймера, компаратора, АЦП и прочего просто не нужна, зато занимает место и отвлекает от сути. Мусоные автогенерированные комментарии cvavr туда же.
Добавьте осмысленные комментарии.
.
Ну и как проверяли, в железе, протеусе или каком-то другом симуляторе? Какая схема подключения? Проверяли ли код пошагово?
PORTB=(0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (1<<PORTB0); Стоило бы записать как
PORTB = (1<<0); А, учитывая, что в ATtiny13 вывод INT0 висит на 6 ноге, PB1, совсем правильно было бы
PORTB = (1<<1);
Тег [СОDE] [/СОDE]
Отступы в начале каждой строки, выделяющие блоки кода
Уберите ненужные инициализации: вместо DDRB=(0<<DDB5) | (1<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0); достаточно было оставить DDRB = (1<<4); Инициализация таймера, компаратора, АЦП и прочего просто не нужна, зато занимает место и отвлекает от сути. Мусоные автогенерированные комментарии cvavr туда же.
Добавьте осмысленные комментарии.
.
Ну и как проверяли, в железе, протеусе или каком-то другом симуляторе? Какая схема подключения? Проверяли ли код пошагово?
PORTB=(0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (1<<PORTB0); Стоило бы записать как
PORTB = (1<<0); А, учитывая, что в ATtiny13 вывод INT0 висит на 6 ноге, PB1, совсем правильно было бы
PORTB = (1<<1);
Re: Помогите разобраться с прерыванием на attiny13
Я приношу свои извинения за оформление, выложил код целиком, не подумав. Вот, собственно, без воды:
COKPOWEHEU, спасибо, что "ткнули", я ступил, вместо PB1 "игрался" с PB0. Но все равно не так работает, как надо.
PB1 настроен на вход без подтяжек. Если на него подавать "-", то PB4 меняет состояние на противоположное, а вот если подавать "+",
то состояние PB4 не меняется. Правильно ли я понимаю, что, если INT0 настроен на любое изменение логического уровня, то при подаче "+" тоже должно генерироваться прерывание ? Тестирую в протеусе.
Если PB1 подтянуть резистором 10к к земле, то прерывание генерируется при подаче "+" на PB1, но перестает генерироваться при подаче "-".
С этим понятно.
Вообще, я пытаюсь портировать часть ардуиновской библиотеки RemoteSwitch, ее часть, касающуюся приема: RemoteReceiver. Но я в ней не нашел ничего про подтяжку к земле или питанию вывода, на который приходит сигнал с приемника, тогда получается, что он висит в Hi-Z состоянии.
Код: Выделить всё
#include <tiny13a.h>
interrupt [EXT_INT0] void ext_int0_isr(void)
{
PORTB.4 = !PORTB.4;
}
void main(void)
{
DDRB=(1<<DDB4);
GIMSK=(1<<INT0) | (0<<PCIE);
MCUCR=(0<<ISC01) | (1<ISC00);
GIFR=(1<<INTF0) | (0<<PCIF);
#asm("sei")
while (1) { }
}
PB1 настроен на вход без подтяжек. Если на него подавать "-", то PB4 меняет состояние на противоположное, а вот если подавать "+",
то состояние PB4 не меняется. Правильно ли я понимаю, что, если INT0 настроен на любое изменение логического уровня, то при подаче "+" тоже должно генерироваться прерывание ? Тестирую в протеусе.
Если PB1 подтянуть резистором 10к к земле, то прерывание генерируется при подаче "+" на PB1, но перестает генерироваться при подаче "-".
С этим понятно.
Вообще, я пытаюсь портировать часть ардуиновской библиотеки RemoteSwitch, ее часть, касающуюся приема: RemoteReceiver. Но я в ней не нашел ничего про подтяжку к земле или питанию вывода, на который приходит сигнал с приемника, тогда получается, что он висит в Hi-Z состоянии.
- COKPOWEHEU
- Говорящий с текстолитом
- Сообщения: 1525
- Зарегистрирован: Чт июн 10, 2010 20:11:19
Re: Помогите разобраться с прерыванием на attiny13
Пересобрал Ваш код под avr-gcc, поскольку cvavr не пользуюсь.:
Все работает как надо. Что может быть:
- Я не знаю cvavr, но в avr-gcc надо специально подключать <avr/interrupt> для использования прерываний. Без этого ругается и прерывания не работают.
- Подключил внутреннюю подтяжку на PB1, а кнопкой коммутирую этот вывод на землю. Можно было поставить внешнюю подтяжку либо переключатель земля-питание вместо простой кнопки. По идее эффект будет одинаков. Но вот если не сделать ничего из этого и просто коммутировать вывод на землю, нормально срабатывать оно не будет. Как сделано у вас - не знаю. Хорошо бы все-таки глянуть схему.
Не выдает ли cvavr дизассемблерный код? Хотелось бы на него взглянуть, есть ли разница с gcc-шным.
Кстати, если не ошибаюсь, ардуина использует avr-g++ (gcc C++), может проще его и изучать? Только без ардуинских библиотек, потому что, если я правильно помню, они заточены на ограниченный круг камней и крайне неоптимальны (вроде тупого ожидания передачи байта вместо использования прерываний).
Код: Выделить всё
#include <avr/io.h>
#include <avr/interrupt.h>
int main(){
DDRB=(1<<DDB4);
PORTB = (1<<1); //с подтяжкой все-таки удобнее
GIMSK=(1<<INT0) | (0<<PCIE);
MCUCR=(0<<ISC01) | (1<ISC00);
GIFR=(1<<INTF0) | (0<<PCIF);
asm("sei");
while (1) {
asm("nop"); //это чтобы можно было пройти отладчиком. Хоть какие-то команды в цикле, а то ему зацепиться не за что.
asm("nop");
}
}
ISR(INT0_vect){ //в avr-gcc прерывания обозначаются так
if(PORTB & (1<<4))PORTB &=~(1<<4);else PORTB |= (1<<4);
//можно было написать PORTB ^=(1<<4) но компилятор начинал творить фигню
}- Я не знаю cvavr, но в avr-gcc надо специально подключать <avr/interrupt> для использования прерываний. Без этого ругается и прерывания не работают.
- Подключил внутреннюю подтяжку на PB1, а кнопкой коммутирую этот вывод на землю. Можно было поставить внешнюю подтяжку либо переключатель земля-питание вместо простой кнопки. По идее эффект будет одинаков. Но вот если не сделать ничего из этого и просто коммутировать вывод на землю, нормально срабатывать оно не будет. Как сделано у вас - не знаю. Хорошо бы все-таки глянуть схему.
Не выдает ли cvavr дизассемблерный код? Хотелось бы на него взглянуть, есть ли разница с gcc-шным.
Кстати, если не ошибаюсь, ардуина использует avr-g++ (gcc C++), может проще его и изучать? Только без ардуинских библиотек, потому что, если я правильно помню, они заточены на ограниченный круг камней и крайне неоптимальны (вроде тупого ожидания передачи байта вместо использования прерываний).
Re: Помогите разобраться с прерыванием на attiny13
COKPOWEHEU
Большое спасибо еще раз, логика стала понятна. Схемы нет, я просто минимальную накидал в протеусе, чтобы понять логику работы. А вообще мне хотелось бы использовать 13-ю тиньку с китайским приемником 433 МГц (XY-MK-5V) и релюшкой, чтобы от китайского пульта включать/выключать реле. Собственно, собственно поэтому и потрошу ардуиновскую бибилиотеку RemoteSwitch. А так, собственно, тему можно закрывать.
Большое спасибо еще раз, логика стала понятна. Схемы нет, я просто минимальную накидал в протеусе, чтобы понять логику работы. А вообще мне хотелось бы использовать 13-ю тиньку с китайским приемником 433 МГц (XY-MK-5V) и релюшкой, чтобы от китайского пульта включать/выключать реле. Собственно, собственно поэтому и потрошу ардуиновскую бибилиотеку RemoteSwitch. А так, собственно, тему можно закрывать.
- Реклама

