На первом уроке мы научились подавать напряжение ножкой микроконтроллера. Теперь нужно научиться управлять микроконтроллером без перепрошивки.
Зачем это нужно? Например, вы сделали часы на микроконтроллере, нужно выставить время, но очень не удобно каждый раз перепрошивать, когда собьется время. Намного удобнее пользоваться кнопками, например, одной менять часы, другой минуты.
Помните в первом уроке мы настраивали ножку как выход, т.е. мы могли ей подавать напряжение. Так вот, ножку можно настроить как вход. В таком режиме можно проверить есть ли на ней напряжение или нет.
Пример: создаем проект при помощи мастера проектов. Первую ногу настраиваем как выход, вторую как вход. При создании мастером проектов указываем, что ножка PB1 будет входом, на ней же включаем подтягивающий резистор, реализуется это так:
После создания проекта приведем код к такому виду:
#include <mega8.h> #include <delay.h> void main(void) { PORTB=0x02; DDRB=0x01; while (1) { if(PINB.1==0) { PORTB.0=1; delay_ms(100); PORTB.0=0; delay_ms(100); } }; } |
Как мы видим, по сравнению с первым уроком изменилась настройка порта
PORTB=0x02; DDRB=0x01; |
Подробнее о том что значат данные строки можно почитать тут
Также появилась новая строчка
if(PINB.1==0) {} |
данную строчку нужно читать так — если на ножке 1 порта В подключили землю (0 потенциал), то выполнить код в фигурных скобках. В нашем примере это код из первого урока. Если кнопка не замкнута, то ничего не делать. Промоделировать можно в Proteuse.
Вместо кнопки можно поставить датчик, реле и т.п., вместо светодиода — пищалку, получится сигнализация.
Архив с прошивкой и файлом протеуса доступен тут
Update1: Зачем нужна подтяжка порта?
У входа мк большое сопротивление, если будут течь даже микротоки вызванные помехами, то по закону Ома U=R*I это может привести к тому, что на входе появится лог 1. Чтобы не было таких проблем в AVR микроконтроллерах можно подключить ножку к плюсу питания, через подтягивающий резистор. В этом случае даже, логика работы меняется наоборот — но если появится помеха, нам это не важно, ведь у нас на входе уже логическая единица.
Почему подключение через резистор? Допустим мы подключили вход к плюсу напрямую без резистора. Когда кнопка сработает, она притянет вход к земле, поэтому на входе будет короткое замыкание между + и землей. Если же стоит резистор, то при замыкании кнопки с одной стороны он так и останется подключен к +, а со второй стороны на нем появится земля от кнопки. Через резистор потечет ток, но его величина будет не такой большой.
Update2: Добавлен тест, в котором вы можете проверить на сколько хорошо вы усвоили материал урока
Привет всем!
Возникли трудности в обработке переменной с плавающей точкой Float
есть простая менюшка в которой надо увиличивать-уменшать переменною но по непонятным причинам условия не работают(не уменш_не увил) прошу помощи у знающих
float VBmin;
////////////////////////////////////////////////////////////////////
void show_3()
{
//////////////////////////////////////////////////////////
if(PIND.6==0)
{
esc++;
delay_ms(200);
}
//////////////////////////////////////////////////////////
if(esc>>2)
{
esc=0;
lcd_gotoxy(0,1);
lcd_putsf(» «);
}
////////////////////////////////////////////////////////////
if(esc==1)
{
lcd_gotoxy(0,0);
lcd_putsf(«>»);
if(PIND.4==0)
{
VBmin++;
delay_ms(200);
}
if(VBmin>30) VBmin=0;
}
/////////////////////////////////////////////////////////////
if(esc==2)
{
lcd_gotoxy(0,0);
lcd_putsf(» «);
lcd_gotoxy(0,1);
lcd_putsf(«>»);
}
не понятно esc>>2 это у вас опечатка или ошибка в коде
Добрый день.
Помогите подправить код что бы работал 🙁
Уже 3 день ничего не получается (
1 кнопкам вкл. светодиод. а другвя выключает
При повторном нажатии например на кнопку включения.ничего не должно происходить
#include
#include
unsigned char blink = 0;
void main(void)
{
PORTB=0x02;
DDRB=0x01;
while (1)
if (PINB.1==1)
{ blink=1; }
if (PINB.3==1)
{ blink=0; }
if (blink)
{PORTB.0=1;
}
else { PORTB.0=0;
}
}
для такого кода ноги мк, которые идут к кнопке должны быть физически подтянуты к 0, через резистор.
Кстати говоря…
Если нога порта сконфигурирована как вход и подтянута к питанию, то вместо
if (PINB.1==0)
годнее писать просто
if (!PINB.1)
По сути ничего не меняется, но компилятор под такую конструкцию отжирает меньше памяти контроллера, иногда бывает критично, особенно при low level optimization.
А как сделать чтобы после отпускание кнопки светодиод горел еще минуту?
запустить таймер
Как подключить несколько независимых кнопок ?
Владимир От чего независимы Каждую кнопку можно настроить индеведуально
admin а как на Attiny 13 это сделать
абсолютно так же
добрый вечер
у меня ни как не получается записать в меню числа с точкой.
программа работает отлично, показания на LCD от 0,00 до 10,00
а в меню настраиваться только от 0 до 10
пожалуйста подскажите как исправить код
void menuChislo (void)
{
Max=alertMax;
Min=alertMin;
Hig=alertHig;
Low=alertLow;
Out1=alertOut1;
Out2=alertOut2;
Out3=alertOut3;
while(menu)
{
switch (editCount)
{
//——————OUT 1————————-
//—————-МАКСИМАЛЬНОЕ ЧИСЛО——————-
case 0:
if(PINC.2==0)
{
while
(PINC.2==0)
delay_ms(40);
Max++;
}
if(Max > 9)
{
Max = 9;
}
if(PINC.3==0)
{
while
(PINC.3==0)
delay_ms(40);
Max—;
}
if(Max = Max)
{
Min =Max-1;
}
if(PINC.3==0)
{
while
(PINC.3==0)
delay_ms(40);
Min—;
}
if(Min < 0)
{
Min = 0;
}
if(PINC.1==0)
{
while
(PINC.1==0)
delay_ms(40);
editCount++;
alertMin=Min;
chislo=1;
}
lcd_gotoxy(2,0);
lcd_puts("OUT1 LOW PRES");
lcd_gotoxy(5,1);
lcd_putchar((Min/1)%10+0x30);
lcd_putsf(" BAR");
chislo=1;
break;
если используется форматированный вывод, то в настройках проекта нужно выбрать, sprintf features float
добрый день
а можно по подробней пожалуйста
if(PINC.3==0)
{
while
(PINC.3==0)
delay_ms(40);
Max++
}
прибавляет целое число, а для проекта, для более точного контроля, желательно прибавлять и отнимать с десятыми
вопрос в том чтобы сделать это Max += 0.1?
добрый вечер
да, и чтоб на дисплее отображалось также, я пока не полностью понял как это сделать
если бы подробнее были описания таких тонкостей, то было бы замечательно
спасибо за Ваши уроки и Вашу помощь
Добрый день! Подскажите как реализовать например я портом ADC PORTС.0 измеряю напряжение 0-50в через делитель подходит минус к порту постоянно, как сделать чтобы при подачи минуса на порт PORTС.0 например выполнялся код? if(PINС.0==0)
{
PORTB.0=1;
delay_ms(100);
PORTB.0=0;
delay_ms(100);
}
Заранее благодарю!
#define OUT1 PORTB.0
#define OUT2 PORTA.0
#define OUT3 PORTA.1
#define IN1 PINB.1
#define IN2 PINB.2
#define IN3 PINA.7
unsigned char a, b, q=0;
void main(void)
{
#pragma optsize-
CLKPR=(1<<CLKPCE);
CLKPR=(0<<CLKPCE)|(0<<CLKPS3)|(0<<CLKPS2)|(0<<CLKPS1)|(0<5&&q==0)
{
q=1;
OUT1=1;
delay_ms(1000);
OUT1=0;
b=0;
}
if(IN1==1) b++;
if(IN1==1&&b>5&&q==1)
{
q=0;
b=0;
}
if(IN2==0) a++;
if(IN2==0&&a>5&&q==0)
{
q=1;
OUT1=1;
delay_ms(1000);
OUT1=0;
delay_ms(1000);
OUT1=1;
delay_ms(1000);
OUT1=0;
b=0;
}
if(IN2==1) b++;
if(IN2==1&&b>5&&q==1)
{
q=0;
b=0;
}
}
}
А как сделать, чтоб при нажатии и удержании кнопки IN1 светодиод моргнул один раз OUT1.При нажатии и кнопки IN2 светодиод моргнул два раза OUT1. Сильно не пинайте если что не так , только учусь.
Начало не скопировалось вот исправил.
while(1)
{
if(IN1==0) a++;
if(IN1==0&&a>5&&q==0)
{
q=1;
OUT1=1;
delay_ms(1000);
OUT1=0;
b=0;
}
if(IN1==1) b++;
if(IN1==1&&b>5&&q==1)
{
q=0;
b=0;
}
if(IN2==0) a++;
if(IN2==0&&a>5&&q==0)
{
q=1;
OUT1=1;
delay_ms(1000);
OUT1=0;
delay_ms(1000);
OUT1=1;
delay_ms(1000);
OUT1=0;
b=0;
}
if(IN2==1) b++;
if(IN2==1&&b>5&&q==1)
{
q=0;
b=0;
}
}
}
Здравствуйте нашел ваш ответ на вопрос подобный моему но не разобрал его
OldState=NewState;
{
TCNT1H=0×00;
TCNT1L=0×00;
}
мне тоже необходимо что бы i увеличивалось на 1 при каждом нажатии независимо от длительности импульса нажатия
всем привет подскажите как обрабатовать нажатие 8ми кнопок по очереди чтобы включались светодиоды например кнопка 1 вкл порт 2 и 3, кнопка 2 вкл порт 1 -3-4 ,кнопка 3 вкл порт 2и4
и тогда когда например 1-3-4 порты активны то остальные отключены и.т.п
пробовал через условие if две кнопки работают прекрасно как только добавляю остальные кнопки то прога работает не так как должно например какой нибудь из выходов может мигать или быть в 1 хотя должен быть в 0
А вообще лучше немного по другому подключать кнопку.Кроме резистора ёмкость нужно подключать.Пускай автор меня подправит.
с тюнькой 2313 Штотто не ппАлучается….
в чём может быть причина?
помогите !
как будет выглядеть код
1 вариант : нажал — включилось, ещё раз нажал — выключилось
2 вариант : 1 кнопкой жмём переключает в одну сторону, жмём вторую — переключает в другую?
Доброго времени суток! Уважаемый Админ подскажите пожалуйста. К примеру в какой не будь регистр записано 0b00001100 как из этого байта вытащить только один нужный бит, к примеру 3 тик ? с регистров портов получилось а как с других регистров или с переменной?
Спасибо за помощь!
Так же как и с другим числом. Сдвигаем число вправо, на нужное количество бит. Далее делаем логическое И с единицей, чтобы отсечь остальные разряды. Полученное число проверяем на ноль или единицу.
Спасибо за внимание к моему вопросу, а можно маленький пример? Нужно и переменной I которая содержит число 0b01001101 вытащить все биты по порядку и засунуть в 8 других переменных a ,s,d,f,g,h,f,z,x. Очень буду признателен за помощь, Спасибо. У вас отличный материал для обучения.
Я делал так. хотел узнать, как это можно сделать с помощью переменных а не свободного регистра .
#include
#include
unsigned char i,data;
// Timer2 overflow interrupt service routine
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
// Reinitialize Timer2 value
TCNT2=0x5F;
// Place your code here
ADCW=data;
PORTB.0=0;
i=ADCW.7;
PORTB.1=i;
PORTB.0=1;
delay_ms(10);
PORTB.0=0;
i=ADCW.6;
PORTB.1=i;
PORTB.0=1;
delay_ms(10);
PORTB.0=0;
i=ADCW.5;
PORTB.1=i;
PORTB.0=1;
delay_ms(10);
PORTB.0=0;
i=ADCW.4;
PORTB.1=i;
PORTB.0=1;
delay_ms(10);
PORTB.0=0;
i=ADCW.3;
PORTB.1=i;
PORTB.0=1;
delay_ms(10);
PORTB.0=0;
i=ADCW.2;
PORTB.1=i;
PORTB.0=1;
delay_ms(10);
PORTB.0=0;
i=ADCW.1;
PORTB.1=i;
PORTB.0=1;
delay_ms(10);
PORTB.0=0;
i=ADCW.0;
PORTB.1=i;
PORTB.0=1;
delay_ms(10);
PORTB.2=1;
delay_ms(10);
PORTB.2=0;
}
// Declare your global variables here
void main(void)
{
// Declare your local variables here
// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0xFF;
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTD=0x00;
DDRD=0x00;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
TCCR0=0x00;
TCNT0=0x00;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer1 Stopped
// Mode: Normal top=0xFFFF
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: 31,250 kHz
// Mode: Normal top=0xFF
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x06;
TCNT2=0x5F;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x40;
// USART initialization
// USART disabled
UCSRB=0x00;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
// ADC initialization
// ADC disabled
ADCSRA=0x00;
// SPI initialization
// SPI disabled
SPCR=0x00;
// TWI initialization
// TWI disabled
TWCR=0x00;
// Global enable interrupts
#asm(«sei»)
while (1)
{
// Place your code here
int v;
for(v=0;v<255;v++)
{
delay_ms(100);
data++;
}
}
}
int v = 0b1000;
int bit_n = 2;
int bit = (v >> bit_n) & 1;
Спасибо огромное!
все работает, но компилятор ругается на 2 строку
Error: C:\MK\mega8\test.c(23): invalid combination of type specifiers
версия 2.05
Все, разобрался Спасибо!
Друг подскажи пожалуйста а в codevisionavr есть библиотека для работы с st7735
не знаю, я codevision не пользовался очень давно