1)При нажатии кнопки условно '1' - выводится 1-ый светодиод
2)После выполнения программы она останавливается и ждет следующее нажатие
2)При нажатии кнопки '2' - выводятся последовательно 1-ый и 2-ой и так до восьмой кнопки
Я новичок в этом
Если не один человек в двух ипостасях......Ivanoff-iv писал(а):ПС: Вы с Антон2342 не однокурсники?
Код: Выделить всё
#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/sfr_defs.h>
#include <avr/interrupt.h>
#include <util/delay.h>
/*********************************MACRO***********************************/
#define SET_BIT(port,bit) port|=(1<<bit)
#define CLR_BIT(port,bit) port&= ~(1<<bit)
#define INV_BIT(port,bit) port ^=(1<<bit)
#define BIT_IS_CLEAR(sfr,bit) (!(_SFR_BYTE(sfr) & _BV(bit)))
#define BIT_IS_SET(sfr,bit) (_SFR_BYTE(sfr) & _BV(bit))
/*****************************GLOBAL_DEFINE******************************/
#define VALUE_TCNT0 130
#define LED_PORT PORTB
/**************************SETING_DEFINE_BTN*****************************/
#define BTN_LOCK_TIME 10
#define BTN_LONG_TIME 200
#define BTN_PORT PORTD
#define BTN_DDR DDRD
#define BTN_PIN PIND
#define BTN_LINE_8 (1<<7)
#define BTN_LINE_7 (1<<6)
#define BTN_LINE_6 (1<<5)
#define BTN_LINE_5 (1<<4)
#define BTN_LINE_4 (1<<3)
#define BTN_LINE_3 (1<<2)
#define BTN_LINE_2 (1<<1)
#define BTN_LINE_1 (1<<0)
#define BTN_SHRT_BT1 (1<<0)
#define BTN_SHRT_BT2 (1<<1)
#define BTN_SHRT_BT3 (1<<2)
#define BTN_SHRT_BT4 (1<<3)
#define BTN_SHRT_BT5 (1<<4)
#define BTN_SHRT_BT6 (1<<5)
#define BTN_SHRT_BT7 (1<<6)
#define BTN_SHRT_BT8 (1<<7)
/************************************************************************/
struct UnionsBits
{
uint8_t B0:1;
uint8_t B1:1;
uint8_t B2:1;
uint8_t B3:1;
uint8_t B4:1;
uint8_t B5:1;
uint8_t B6:1;
uint8_t B7:1;
};
union Byte
{
uint8_t Byte;
struct UnionsBits Bits;
};
typedef struct {
union Byte Flag;
}BitUnion;
/**************************GLOBAL VARIABLE*******************************/
volatile uint8_t BtnFlags;
volatile uint8_t BtnMask = 0;
volatile BitUnion StatBt;
/************************************************************************/
void InitTimerZero()
{
TCCR0=(1<<CS01)|(1<<CS00);
TIMSK=(1<<TOIE0);
TCNT0=VALUE_TCNT0;
}
void InitBtn(void)
{
BTN_DDR &= ~(BTN_LINE_1|BTN_LINE_2|BTN_LINE_3|BTN_LINE_4|
BTN_LINE_5|BTN_LINE_6|BTN_LINE_7|BTN_LINE_8);
BTN_PORT |= (BTN_LINE_1|BTN_LINE_2|BTN_LINE_3|BTN_LINE_4|
BTN_LINE_5|BTN_LINE_6|BTN_LINE_7|BTN_LINE_8);
}
void Btn()
{
volatile uint8_t mask = 0;
static uint8_t BtnLockBit;
static uint8_t BtnLockCoun;
static uint8_t BtnLongCoun;
static uint8_t BtnLastState;
if(!(BTN_PIN & BTN_LINE_1)) mask = BTN_SHRT_BT1;
if(!(BTN_PIN & BTN_LINE_2)) mask = BTN_SHRT_BT2;
if(!(BTN_PIN & BTN_LINE_3)) mask = BTN_SHRT_BT3;
if(!(BTN_PIN & BTN_LINE_4)) mask = BTN_SHRT_BT4;
if(!(BTN_PIN & BTN_LINE_5)) mask = BTN_SHRT_BT5;
if(!(BTN_PIN & BTN_LINE_6)) mask = BTN_SHRT_BT6;
if(!(BTN_PIN & BTN_LINE_7)) mask = BTN_SHRT_BT7;
if(!(BTN_PIN & BTN_LINE_8)) mask = BTN_SHRT_BT8;
if (mask)
{
if (BtnLockCoun < BTN_LOCK_TIME) //клавиша нажата
{
BtnLockCoun++;
return; //защелка еще не дощитала - возврат
}
BtnLastState = mask;
BtnLockBit =1; //нажатие зафиксировано
if (BtnLongCoun >= (BTN_LONG_TIME)) return; //возврат, т.к. счетчик длинн нажат досчитал до максимума еще раньше
if (++BtnLongCoun >= (BTN_LONG_TIME))
{
BtnFlags |= (BtnLastState<<8); //счетчик досчитал до максимума - устанавливаем биты длинного нажатия
}
}
else
{ //клавиша отжата
if (BtnLockCoun)
{
BtnLockCoun --;
return; //защелка еще не обнулилась - возврат
}
if (! BtnLockBit) return; //СТАТИЧЕСКИЙ ВОЗВРАТ
BtnLockBit =0; //отжатие зафиксировано
if (BtnLongCoun < (BTN_LONG_TIME))
BtnFlags |= BtnLastState; //установка бита короткого нажатия
BtnLongCoun = 0; //сброс счетчика длительности нажатия
}
}
uint8_t BtnGet(void)
{
cli();
uint8_t temp = BtnFlags;
BtnFlags = 0;
sei();
return temp;
}
void BtnUpdate()
{
BtnMask=BtnGet();
switch(BtnMask)
{
case BTN_SHRT_BT1:
StatBt.Flag.Bits.B0=1;
break;
case BTN_SHRT_BT2:
StatBt.Flag.Bits.B1=1;
break;
case BTN_SHRT_BT3:
StatBt.Flag.Bits.B2=1;
break;
case BTN_SHRT_BT4:
StatBt.Flag.Bits.B3=1;
break;
case BTN_SHRT_BT5:
StatBt.Flag.Bits.B4=1;
break;
case BTN_SHRT_BT6:
StatBt.Flag.Bits.B5=1;
break;
case BTN_SHRT_BT7:
StatBt.Flag.Bits.B6=1;
break;
case BTN_SHRT_BT8:
StatBt.Flag.Bits.B7=1;
break;
default:
break;
}
}
uint8_t CountMs=0;
ISR(TIMER0_OVF_vect)
{
TCNT0=VALUE_TCNT0;
if (++CountMs >= 10)
{
Btn();
CountMs=0;
}
}
void Blink(uint8_t CountLed)
{
cli();
for(uint8_t temp=0;temp<CountLed;temp++)
{
SET_BIT(LED_PORT,temp);
_delay_ms(500);
}
LED_PORT=0x00;
StatBt.Flag.Byte=0;
CountLed=0;
sei();
}
int main(void)
{
DDRB=0xFF;
InitBtn();
InitTimerZero();
sei();
while(1)
{
BtnUpdate();
if (StatBt.Flag.Bits.B0) Blink(1);
if (StatBt.Flag.Bits.B1) Blink(2);
if (StatBt.Flag.Bits.B2) Blink(3);
if (StatBt.Flag.Bits.B3) Blink(4);
if (StatBt.Flag.Bits.B4) Blink(5);
if (StatBt.Flag.Bits.B5) Blink(6);
if (StatBt.Flag.Bits.B6) Blink(7);
if (StatBt.Flag.Bits.B7) Blink(8);
}
}
Код: Выделить всё
if(BIT_IS_CLEAR(BTN_PIN,0)) mask = BTN_SHRT_BT1;
if(BIT_IS_CLEAR(BTN_PIN,1)) mask = BTN_SHRT_BT2;
if(BIT_IS_CLEAR(BTN_PIN,2)) mask = BTN_SHRT_BT3;
if(BIT_IS_CLEAR(BTN_PIN,3)) mask = BTN_SHRT_BT4;
if(BIT_IS_CLEAR(BTN_PIN,4)) mask = BTN_SHRT_BT5;
if(BIT_IS_CLEAR(BTN_PIN,5)) mask = BTN_SHRT_BT6;
if(BIT_IS_CLEAR(BTN_PIN,6)) mask = BTN_SHRT_BT7;
if(BIT_IS_CLEAR(BTN_PIN,7)) mask = BTN_SHRT_BT8;
Код: Выделить всё
#include <avr/io.h>
#include <util/delay.h>
static uint8_t get_button_num(void){
uint8_t btn;
while(1){
// опрашиваем кнопки
btn = PIND;
if(btn != 0xFF){
// если хоть какая-то нажата
_delay_ms(15);
// после паузы для защиты от дребезга
if(btn == PIND){
// проверяем, что состояние кнопок не поменялось
// а затем вычисляем номер кнопки
switch(btn){
case 0b11111110: return 1;
case 0b11111101: return 2;
case 0b11111011: return 3;
case 0b11110111: return 4;
case 0b11101111: return 5;
case 0b11011111: return 6;
case 0b10111111: return 7;
case 0b01111111: return 8;
default:
// если нажато несколько кнопок - игнорируем
break;
}
}
}
}
}
int main(void){
uint8_t button;
uint8_t mask;
DDRB = 0xFF; // порт светодиодов, катоды на общий
PORTD = 0xFF; // кнопки на PORTD (замыкают на общий)
while(1){
// получаем номер нажатой кнопки
button = get_button_num();
// зажигаем поочередно светодиоды
mask = 1;
for(uint8_t i=0; i<button; i++){
PORTB = mask;
// каждые 0,5 сек
_delay_ms(500);
mask = (mask << 1) | 1;
}
// светодиоды горят еще 1 секунду, потом гаснут
_delay_ms(1000);
PORTB = 0;
}
}что именно по-вашему нечитабельно?7seg писал(а):ну это же не читабельно
с чего вдруг? данная форма записи констант определена расширением GNU. и она абсолютно наглядна для новичка.7seg писал(а):а вот за такое и по рукам надо
Код: Выделить всё
#include <mega8.h>
#include <delay.h>
#define PinButt (~PINB)
#define PortLed PORTD
#define AddLed PortLed=(PortLed<<1)|1
unsigned char ButtBuff=0;
void main(void)
{
PORTB=0xFF;
DDRB=0x00;
PORTD=0x00;
DDRD=0xFF;
while (1)
{
if (PortLed<ButtBuff) AddLed;
if ((PinButt)&&(PinButt!=ButtBuff))
{
ButtBuff=PinButt;
PortLed=0;
};
delay_ms(200);
}
}ARV писал(а):static uint8_t get_button_num(void)
спасибо.7seg писал(а):И да я видел вы умете писать красивый код
Код: Выделить всё
uint8_t myfunc(uint8_t v){
v^=v>>4;
return(0x6>>((v^(v>>2))&3)&1);
}мой тоже, но это его личные половые проблемы. если он настолько туп, что не замечает "безвыходность" функции, кроме как из switch-а с перебором всех комбинаций, то это меня не сильно волнует.goldenandy писал(а):Мой компилятор ругается, если функция не возвращает ничего....
В конце я бы дописал return 0;
а вот так я никогда не делаю. потому как вот этоIvanoff-iv писал(а):#define AddLed PortLed=(PortLed<<1)|1
с первого взгляда не может быть прочитао сразу без усилий. и со второго тоже. если не видеть первой цитаты, что можно сказать увиденной впервые второй? AddLed - это volatile переменная. почему вдруг надо СЧИТЫВАТЬ её по условию, не используя результат - абсолютно не понятно.Ivanoff-iv писал(а):if (PortLed<ButtBuff) AddLed;
Ivanoff-iv писал(а):а если я 2 кнопки разом нажму?
хоть триARV писал(а): default:
// если нажато несколько кнопок - игнорируем
break;
ага. чтобы это понять, мало увидеть ВТОРОЙ кусок кода (являющийся основной реализацией алгоритма), надо увидеть ПЕРВЫЙ. для конкретно этого "учебного" проекта ситуация не выглядит плхо, но если допустить на миг, что макрос определен "где-то" в другом файле-заголовке? все заголовки просматривать в поисках?Ivanoff-iv писал(а):AddLed - это не переменная, а процедура зажигания ещё одного светодиода
хоть три[/uquote] но из функции выйдет без "return"а...ARV писал(а): default:
// если нажато несколько кнопок - игнорируем
break;
с чего это оно из while(1) выйдет вообще?!Ivanoff-iv писал(а):но из функции выйдет без "return"а...
проблема решается гораздо проще: надо привести ваш макрос к виду макроса-функции без параметровIvanoff-iv писал(а):но переписывать тот код (с заглавными или вообще без макроса) на данный момент считаю излишним...
при // кнопки на PORTD (замыкают на общий)ARV писал(а):Код: Выделить всё
btn = PIND;
if(btn != 0){
// если хоть какая-то нажата