...очень круто...
Дальше можно не смотреть.
Не "видимо придётся", а так и нужно делать.видимо придется опрашивать от прерывания таймера эти биты.
service47 писал(а):Если под машиной состояний имеется ввиду флаг прерываний, устанавливаемый в единицу, когда происходит прерывание регистр EIFR биты INTF0 и INTF1:
опрос while(EIFR == 0b00000011)
то тут получается трудно нажать идеально одновременно обе кнопки чтобы запустился алгоритм, видимо придется опрашивать от прерывания таймера эти биты.
Код: Выделить всё
interrupt [TIM1_OVF] void timer1_ovf_isr(void){
//...
}
Код: Выделить всё
ISR(INT1_vect) //MINUS PIND3
{_delay_ms(200);
if (PIND3 <= 2,9) //(PIND3 <= 3) работает (PIND3 <= 2,95)
{s--;}
}
ISR(INT0_vect) //PLUS PIND2
{_delay_ms(200);
if (PIND2 >= 3) //(PIND2 >= 2,995) работает, а если (PIND2 >= 3) то не работает
{s++;}
}
DDRD=0x0C; //0b00001100
PORTD=0xff; // 0b11111111
Код: Выделить всё
#define F_CPU 1000000UL
#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>
#define COUNTDOWN 1
volatile char FLAG = 0;
volatile char s = 6; //Переменная цифры
volatile char a = 6;
volatile char b = 1; //Начальный сброс флага
volatile char c = 6;
volatile char j = 6; //Перескок через ШИМ
// массив знаков на индикатор
char digits[11] = {0b00111111, 0b00000110, 0b00011011, 0b00001111, 0b00100110, 0b00101101, 0b00111101, 0b00000111, 0b00111111, 0b00101111, 0b00101111}; // PORTC 0,1,2,3,4,5,6,7,8,9,x
char digita[11] = {0b00000000, 0b00000000, 0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000000, 0b00000001, 0b00000001, 0b00000001}; // PORTB
/******************************************************************/
#define ACT_BUTT_LEV 0 // Активный уровень нажатых кнопок
#define ACT_BUTT_LEV_2 0
//----------
#define PORT_BUTT_1 PIND // Порт кнопки №1
#define PIN_BUTT_1 2 // Номер бита порта кнопки №1
#define PORT_BUTT_2 PIND // Порт кнопки №2
#define PIN_BUTT_2 3 // Номер бита порта кнопки №2
//----------
#define PORT_LED_1 PORTB // Светики
#define DDR_LED_1 DDRB //
#define PIN_LED_1 2 //
#define PORT_LED_2 PORTB //
#define DDR_LED_2 DDRB //
#define PIN_LED_2 7 //
/******************************************************************/
/******************************************************************/
typedef struct{
unsigned cur: 1; // Текущее состояние
unsigned prev: 1; // Предыдущее состояние
unsigned down: 1; // Была нажата
unsigned up: 1; // Была отжата
}tButt;
volatile tButt mButt_1 = {0,!ACT_BUTT_LEV,0,0}; // Объявляем структуру mButt_1 для нашей кнопки и иним её.
typedef struct{
unsigned cur: 1; // Текущее состояние
unsigned prev: 1; // Предыдущее состояние
unsigned down: 1; // Была нажата
unsigned up: 1; // Была отжата
}tButt2;
volatile tButt2 mButt_2 = {0,!ACT_BUTT_LEV_2,0,0}; // Объявляем структуру mButt_2 для нашей кнопки и иним её.
/******************************************************************/
/******************************************************************/
ISR (TIMER1_OVF_vect) { s=3; //interrupt [TIM1_OVF] void timer1_ovf_isr(void){ //TIMER1_OVF_vect_num
static unsigned char cnt_ms_butt=20; // Счётчик для формирования периода в 20 мс.
TCNT1 -= 4000; // Перезапускаем таймер на 1 мс.
//----------//
if(!--cnt_ms_butt){ // Формируем 20-ти миллисек. периоды
cnt_ms_butt=20;
mButt_1.cur = (PORT_BUTT_1&(1<<PIN_BUTT_1))!=0; // Считываем текущее значение вывода.
// Дальше работаем с этим битом, т.к. порт может измениться в любой момент.
if((mButt_1.cur==ACT_BUTT_LEV) && (mButt_1.prev!=ACT_BUTT_LEV)) // Если текущее значение - "нажата" и предыдущее - "не нажата"
mButt_1.down = 1; // Устанавливаем флаг down
if((mButt_1.cur!=ACT_BUTT_LEV) && (mButt_1.prev==ACT_BUTT_LEV)) // Если текущее значение - "не нажата" и предыдущее - "нажата"
mButt_1.up = 1; // Устанавливаем флаг up
mButt_1.prev=mButt_1.cur; // Сохраняем текущее значение. Оно для следующего входа будет предыдущим
mButt_2.cur = (PORT_BUTT_2&(1<<PIN_BUTT_2))!=0; // Считываем текущее значение вывода.
if((mButt_2.cur==ACT_BUTT_LEV_2) && (mButt_2.prev!=ACT_BUTT_LEV_2)) // Если текущее значение - "нажата" и предыдущее - "не нажата"
mButt_2.down = 1; // Устанавливаем флаг down
if((mButt_2.cur!=ACT_BUTT_LEV_2) && (mButt_2.prev==ACT_BUTT_LEV_2)) // Если текущее значение - "не нажата" и предыдущее - "нажата"
mButt_2.up = 1; // Устанавливаем флаг up
mButt_2.prev=mButt_2.cur;
}
//----------//
}
/******************************************************************/
ISR(INT1_vect) //MINUS PIND3
{_delay_ms(200);
if (PIND3 >= 2) //(PIND3 <= 3) работает (PIND3 <= 2,95)
{s--;}
}
ISR(INT0_vect) //PLUS PIND2
{_delay_ms(200);
if (PIND2 >= 2,995) //(PIND2 >= 2,995) работает, а если (PIND2 >= 3) то не работает
{s++;}
}
void shim_start()
{
if (j==6)
{goto jstop;
}
// ASSR=0x00;
// // Установим биты COM1A1-COM1A0:0b10,означает сброс вывода канала A при сравнении Clear OC1A/OC1B on Compare Match, set OC1A/OC1B at BOTTOM (non-inverting mode), for Fast PWM. page135
// TCCR1A |= (1 << COM1A1)|(0 << COM1A0)|(0 << WGM11)|(1 << WGM10);
// // Установим биты WGM13-10:0b0101, согласно таблице это будет режим - Fast PWM, 8-bit, где верхний предел счета задается битом ICR1. page136
// TCCR1B |= (0 << WGM13)|(1 << WGM12)|(1 << CS12)|(0 << CS11)|(0 << CS10);
// // Битами CS12-10:0b100 задаем источник тактового сигнала для таймера МК, clkI/O/256 (From prescaler)=31250Hz. page137
// TCNT1 = 0x00; // начальная установка счетчика
// TIMSK1=0x00;
// ICR1 = 0x20; // задаем период ШИМ, здесь у нас число 255,
// // по формуле fPWM=fclk_I/O/N*(1+ICR1) вычисляем частоту ШИМ, она будет равна 8MHz/256(1+2)=10416Hz
// // для FR3706 надо 50000Hz, irlm0030 надо 16666Hz<
// OCR1A = 0x50; // начальный коэффициент заполнения ШИМ 0xC8=200, 0x50=1/3
jstop:
j=0;
}
int main(void)
{
DDRC=0x3f; //0b00111111 0-ввод 1-вывод
PORTC=0x00; //
DDRD=0x0C; //0b00001100
PORTD=0xff; // 0b11111111
DDRB=0xFF; //0b11000111 PB1(OC1A)-ШИМ DDRB=0xC7;
PORTB=0x00; //PORTB=0x00;
EICRA = (1<<ISC11) | (0<<ISC10) | (1<<ISC01) | (0<<ISC00); // настройка срабатывания прерываний The falling edge of INT1 generates an interrupt request
PCICR |= (1<<PCIE2) | (0<<PCIE1) | (0<<PCIE0);// разрешение прерываний PCINT23...16
PCMSK2=0b11000000; //разрешаем прерывание pcint23 pcint22
EIMSK=0b11000011; //разрешаем прерывание int0 и int1 - кнопка
MCUCR=0b00001111;// IVSEL, IVCE
sei(); //Глобальное разрешение прерываний
//Установка таймера0
//TCCR0A |= (0 << COM1A1)|(0 << COM1A0)|(1 << WGM01)|(0 << WGM00); //биты COM Normal port operation, OC0A disconnected, WGM T/C in CTC mode
//TCCR0B |= (0 << WGM02)|(0 << CS02)|(0 << CS01)|(1 << CS00); //биты CS fclk_I/O/1
//TCNT0=0x00;
//OCR0A=0x80;
//----------//
//TCCR0A=0x00; //TCCR0=0x00;
// TCCR0B=0x01; //TCCR0=0x00;
// TCNT0=0x00;
// Timer/Counter 1 initialization
TCCR1A=0x00; //для Compare Output Mode, non-PWM COM1A1/COM1B1=0 COM1A0/COM1B0=0 Normal port operation, OC1A/OC1B disconnected.
TCCR1B=0x01; //Waveform Generation Mode Bit Description WGM10-13=0 Normal //CS12-10=001 No prescaling
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
//OCR1AH=0x00;
//OCR1AL=0x00;
OCR1BH=0x00; //OCR1B compared with the counter value (TCNT1)
OCR1BL=0x00;
// Timer/Counter 2 initialization
//ASSR=0x00;
//TCCR2=0x00; //TCCR2=0x00;
//TCNT2=0x00;
//OCR2=0x00; //OCR2=0x00;
MCUCR=0x00;
//TIMSK0=0x04; //TIMSK=0x04;
TIMSK1=0x04; //TIMSK=0x04; //OCIE1B=1
//ACSR=0x80;
//SFIOR=0x00;
//----------//
while(1)
{
//----------//
if(mButt_1.up){ // Если кнопка была нажата -> отжата
mButt_1.up=0; // Сбрасываем флаг
PORT_LED_1 ^=(1<<PIN_LED_1); // Инвертируем светодиод №1
s++;
}
//----------//
if(mButt_1.down){ // Если кнопка была отжата -> нажата
mButt_1.down=0; // Сбрасываем флаг
PORT_LED_2 ^=(1<<PIN_LED_2); // Инвертируем светодиод №2
s++;
}
//----------//
//----------//
if(mButt_2.up){ // Если кнопка была нажата -> отжата
mButt_2.up=0; // Сбрасываем флаг
PORT_LED_1 ^=(1<<PIN_LED_1); // Инвертируем светодиод №1
s--;
}
//----------//
if(mButt_2.down){ // Если кнопка была отжата -> нажата
mButt_2.down=0; // Сбрасываем флаг
PORT_LED_2 ^=(1<<PIN_LED_2); // Инвертируем светодиод №2
s--;
}
//----------//
start:
if (b == 1)
{s=5;
FLAG &= ~ COUNTDOWN;
b++;
}
if (s > 9)
s--;
else if (s == 0)
s++;
if (FLAG == COUNTDOWN)
{
//cli();
char i = 0;
while (s > -1)
{
if (s > -1)
{
a = 5;
c = 5;
if (FLAG != COUNTDOWN)
{
goto start;
}
PORTB |= _BV(PB6); // чтобы мигала точка на индикаторе
_delay_ms(250);
PORTB &= ~_BV(PB6);
_delay_ms(250);
}
PORTC = digits[s];
PORTB = digita[s];
_delay_ms(500);
PORTB &= ~_BV(PB7); //Красный светодиод
_delay_ms(500);
PORTB |= _BV(PB7);
s--;
if (s == 0)
{
PORTC = digits[s];
PORTB = digita[s];
j=0;
shim_start();
PORTB &= ~_BV(PB2); //Зеленый светодиод
_delay_ms(250);
PORTB |= _BV(PB2);
_delay_ms(250);
}
i++;
if (i>=10)
{ICR1 = 0x00;
OCR1A = 0x00;}
}
sei();
FLAG &= ~ COUNTDOWN;
}
PORTC = digits[s];
PORTB = digita[s];
}
}Код: Выделить всё
DDRD=0x0C; //0b00001100
PORTD=0xff; // 0b11111111Какой кошмарservice47 писал(а):поставил нули реакции нет
service47 писал(а):DDRD=0x0C; //0b00001100 единичные биты это те две кнопки PIND2 и PIND3
Код: Выделить всё
#define F_CPU 1000000UL
#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/delay.h>
#define COUNTDOWN 1
volatile char FLAG = 0;
volatile char s = 6; //Переменная цифры
volatile char a = 6;
volatile char b = 1; //Начальный сброс флага
volatile char c = 6;
volatile char j = 6; //Перескок через ШИМ
// массив знаков на индикатор
char digits[11] = {0b00111111, 0b00000110, 0b00011011, 0b00001111, 0b00100110, 0b00101101, 0b00111101, 0b00000111, 0b00111111, 0b00101111, 0b00101111}; // PORTC 0,1,2,3,4,5,6,7,8,9,x
char digita[11] = {0b00000000, 0b00000000, 0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000001, 0b00000000, 0b00000001, 0b00000001, 0b00000001}; // PORTB
/******************************************************************/
#define ACT_BUTT_LEV 0 // Активный уровень нажатых кнопок
#define ACT_BUTT_LEV_2 0
//----------
#define PORT_BUTT_1 PIND // Порт кнопки №1
#define PIN_BUTT_1 2 // Номер бита порта кнопки №1
#define PORT_BUTT_2 PIND // Порт кнопки №2
#define PIN_BUTT_2 3 // Номер бита порта кнопки №2
//----------
#define PORT_LED_1 PORTB // Светики
#define DDR_LED_1 DDRB //
#define PIN_LED_1 2 //
#define PORT_LED_2 PORTB //
#define DDR_LED_2 DDRB //
#define PIN_LED_2 7 //
/******************************************************************/
/******************************************************************/
typedef struct{
unsigned cur: 1; // Текущее состояние
unsigned prev: 1; // Предыдущее состояние
unsigned down: 1; // Была нажата
unsigned up: 1; // Была отжата
}tButt;
volatile tButt mButt_1 = {0,!ACT_BUTT_LEV,0,0}; // Объявляем структуру mButt_1 для нашей кнопки и иним её.
typedef struct{
unsigned cur: 1; // Текущее состояние
unsigned prev: 1; // Предыдущее состояние
unsigned down: 1; // Была нажата
unsigned up: 1; // Была отжата
}tButt2;
volatile tButt2 mButt_2 = {0,!ACT_BUTT_LEV_2,0,0}; // Объявляем структуру mButt_2 для нашей кнопки и иним её.
/******************************************************************/
/******************************************************************/
ISR (TIMER1_OVF_vect) { s=3; //interrupt [TIM1_OVF] void timer1_ovf_isr(void){ //TIMER1_OVF_vect_num
static unsigned char cnt_ms_butt=20; // Счётчик для формирования периода в 20 мс.
TCNT1 -= 4000; // Перезапускаем таймер на 1 мс.
//----------//
if(!--cnt_ms_butt){ // Формируем 20-ти миллисек. периоды
cnt_ms_butt=20;
mButt_1.cur = (PORT_BUTT_1&(1<<PIN_BUTT_1))!=0; // Считываем текущее значение вывода.
// Дальше работаем с этим битом, т.к. порт может измениться в любой момент.
if((mButt_1.cur==ACT_BUTT_LEV) && (mButt_1.prev!=ACT_BUTT_LEV)) // Если текущее значение - "нажата" и предыдущее - "не нажата"
mButt_1.down = 1; // Устанавливаем флаг down
if((mButt_1.cur!=ACT_BUTT_LEV) && (mButt_1.prev==ACT_BUTT_LEV)) // Если текущее значение - "не нажата" и предыдущее - "нажата"
mButt_1.up = 1; // Устанавливаем флаг up
mButt_1.prev=mButt_1.cur; // Сохраняем текущее значение. Оно для следующего входа будет предыдущим
mButt_2.cur = (PORT_BUTT_2&(1<<PIN_BUTT_2))!=0; // Считываем текущее значение вывода.
if((mButt_2.cur==ACT_BUTT_LEV_2) && (mButt_2.prev!=ACT_BUTT_LEV_2)) // Если текущее значение - "нажата" и предыдущее - "не нажата"
mButt_2.down = 1; // Устанавливаем флаг down
if((mButt_2.cur!=ACT_BUTT_LEV_2) && (mButt_2.prev==ACT_BUTT_LEV_2)) // Если текущее значение - "не нажата" и предыдущее - "нажата"
mButt_2.up = 1; // Устанавливаем флаг up
mButt_2.prev=mButt_2.cur;
}
//----------//
}
/******************************************************************/
ISR(INT1_vect) //MINUS PIND3
{_delay_ms(200);
if (PIND3 == 3) //(PIND3 <= 3) работает (PIND3 <= 2,95) (PIND3 == 3)
{s--;}
}
ISR(INT0_vect) //PLUS PIND2
{_delay_ms(200);
if (PIND2 == 2) //(PIND2 == 2)(PIND2 >= 2,995) работает, а если (PIND2 >= 3) то не работает
{s++;}
}
void shim_start()
{
if (j==6)
{goto jstop;
}
// ASSR=0x00;
// // Установим биты COM1A1-COM1A0:0b10,означает сброс вывода канала A при сравнении Clear OC1A/OC1B on Compare Match, set OC1A/OC1B at BOTTOM (non-inverting mode), for Fast PWM. page135
// TCCR1A |= (1 << COM1A1)|(0 << COM1A0)|(0 << WGM11)|(1 << WGM10);
// // Установим биты WGM13-10:0b0101, согласно таблице это будет режим - Fast PWM, 8-bit, где верхний предел счета задается битом ICR1. page136
// TCCR1B |= (0 << WGM13)|(1 << WGM12)|(1 << CS12)|(0 << CS11)|(0 << CS10);
// // Битами CS12-10:0b100 задаем источник тактового сигнала для таймера МК, clkI/O/256 (From prescaler)=31250Hz. page137
// TCNT1 = 0x00; // начальная установка счетчика
// TIMSK1=0x00;
// ICR1 = 0x20; // задаем период ШИМ, здесь у нас число 255,
// // по формуле fPWM=fclk_I/O/N*(1+ICR1) вычисляем частоту ШИМ, она будет равна 8MHz/256(1+2)=10416Hz
// // для FR3706 надо 50000Hz, irlm0030 надо 16666Hz<
// OCR1A = 0x50; // начальный коэффициент заполнения ШИМ 0xC8=200, 0x50=1/3
jstop:
j=0;
}
int main(void)
{
DDRC=0x3f; //0b00111111 0-ввод 1-вывод
PORTC=0x00; //
DDRD=0x00; //0b00001100 DDRD=0x0C;
PORTD=0xff; // 0b11111111 PORTD=0xff;
DDRB=0xFF; //0b11000111 PB1(OC1A)-ШИМ DDRB=0xC7;
PORTB=0x00; //PORTB=0x00;
EICRA = (1<<ISC11) | (0<<ISC10) | (1<<ISC01) | (0<<ISC00); // настройка срабатывания прерываний The falling edge of INT1 generates an interrupt request
PCICR |= (1<<PCIE2) | (0<<PCIE1) | (0<<PCIE0);// разрешение прерываний PCINT23...16
PCMSK2=0b11000000; //разрешаем прерывание pcint23 pcint22
EIMSK=0b11000011; //разрешаем прерывание int0 и int1 - кнопка
MCUCR=0b00001111;// IVSEL, IVCE
sei(); //Глобальное разрешение прерываний
//Установка таймера0
//TCCR0A |= (0 << COM1A1)|(0 << COM1A0)|(1 << WGM01)|(0 << WGM00); //биты COM Normal port operation, OC0A disconnected, WGM T/C in CTC mode
//TCCR0B |= (0 << WGM02)|(0 << CS02)|(0 << CS01)|(1 << CS00); //биты CS fclk_I/O/1
//TCNT0=0x00;
//OCR0A=0x80;
//----------//
//TCCR0A=0x00; //TCCR0=0x00;
// TCCR0B=0x01; //TCCR0=0x00;
// TCNT0=0x00;
// Timer/Counter 1 initialization
TCCR1A=0x00; //для Compare Output Mode, non-PWM COM1A1/COM1B1=0 COM1A0/COM1B0=0 Normal port operation, OC1A/OC1B disconnected.
TCCR1B=0x01; //Waveform Generation Mode Bit Description WGM10-13=0 Normal //CS12-10=001 No prescaling
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
//OCR1AH=0x00;
//OCR1AL=0x00;
OCR1BH=0x00; //OCR1B compared with the counter value (TCNT1)
OCR1BL=0x00;
// Timer/Counter 2 initialization
//ASSR=0x00;
//TCCR2=0x00; //TCCR2=0x00;
//TCNT2=0x00;
//OCR2=0x00; //OCR2=0x00;
//MCUCR=0x00;
//TIMSK0=0x04; //TIMSK=0x04;
// TIMSK1=0x04; //TIMSK=0x04; //OCIE1B=1
//ACSR=0x80;
//SFIOR=0x00;
//----------//
while(1)
{
//if (PIND3 == 3) //(PIND3 == 3) работает если кнопка не нажата
//{s=8;}
//if (PIND2 == 2) //(PIND2 == 2) работает если кнопка не нажата
//{s=8;}
//----------//
if(mButt_1.up){ // Если кнопка была нажата -> отжата
mButt_1.up=0; // Сбрасываем флаг
PORT_LED_1 ^=(1<<PIN_LED_1); // Инвертируем светодиод №1
s++;
}
//----------//
if(mButt_1.down){ // Если кнопка была отжата -> нажата
mButt_1.down=0; // Сбрасываем флаг
PORT_LED_2 ^=(1<<PIN_LED_2); // Инвертируем светодиод №2
s++;
}
//----------//
//----------//
if(mButt_2.up){ // Если кнопка была нажата -> отжата
mButt_2.up=0; // Сбрасываем флаг
PORT_LED_1 ^=(1<<PIN_LED_1); // Инвертируем светодиод №1
s--;
}
//----------//
if(mButt_2.down){ // Если кнопка была отжата -> нажата
mButt_2.down=0; // Сбрасываем флаг
PORT_LED_2 ^=(1<<PIN_LED_2); // Инвертируем светодиод №2
s--;
}
//----------//
start:
if (b == 1)
{s=5;
FLAG &= ~ COUNTDOWN;
b++;
}
if (s > 9)
s--;
else if (s == 0)
s++;
if (FLAG == COUNTDOWN)
{
//cli();
char i = 0;
while (s > -1)
{
if (s > -1)
{
a = 5;
c = 5;
if (FLAG != COUNTDOWN)
{
goto start;
}
PORTB |= _BV(PB6); // чтобы мигала точка на индикаторе
_delay_ms(250);
PORTB &= ~_BV(PB6);
_delay_ms(250);
}
PORTC = digits[s];
PORTB = digita[s];
_delay_ms(500);
PORTB &= ~_BV(PB7); //Красный светодиод
_delay_ms(500);
PORTB |= _BV(PB7);
s--;
if (s == 0)
{
PORTC = digits[s];
PORTB = digita[s];
j=0;
shim_start();
PORTB &= ~_BV(PB2); //Зеленый светодиод
_delay_ms(250);
PORTB |= _BV(PB2);
_delay_ms(250);
}
i++;
if (i>=10)
{ICR1 = 0x00;
OCR1A = 0x00;}
}
sei();
FLAG &= ~ COUNTDOWN;
}
PORTC = digits[s];
PORTB = digita[s];
}
}
service47 писал(а):Нажимал в протеусе и на плате, но все работало с прошлой допотопной версией программы.
Код: Выделить всё
DDRD=0x00; //0b00001100 DDRD=0x0C;
PORTD=0xff; // 0b11111111 PORTD=0xff;
EICRA = (1<<ISC11) | (0<<ISC10) | (1<<ISC01) | (0<<ISC00); // настройка срабатывания прерываний The falling edge of INT1 generates an interrupt request
EIMSK=0b00000011; //разрешаем прерывание int0 и int1 - кнопка
sei(); //Глобальное разрешение прерываний