Rotačný enkodér: Rozdiel medzi revíziami
Z SensorWiki
(→Algoritmus a program) |
(→Algoritmus a program) |
||
Riadok 37: | Riadok 37: | ||
#include <avr/interrupt.h> | #include <avr/interrupt.h> | ||
#include <util/delay.h> | #include <util/delay.h> | ||
− | |||
#define clk_pin PB3 | #define clk_pin PB3 | ||
Riadok 43: | Riadok 42: | ||
#define swt_pin PB5 | #define swt_pin PB5 | ||
− | |||
− | |||
volatile int counter = 0; | volatile int counter = 0; | ||
volatile bool buttonPressed = false; | volatile bool buttonPressed = false; | ||
− | |||
enum MenuState { MENU_MAIN, MENU_VALUE }; | enum MenuState { MENU_MAIN, MENU_VALUE }; | ||
volatile MenuState menuState = MENU_MAIN; | volatile MenuState menuState = MENU_MAIN; | ||
− | void initLCD() | + | void initLCD() { |
− | { | ||
− | |||
DDRD |= (1 << PD0) | (1 << PD1) | (1 << PD2) | (1 << PD3) | (1 << PD4) | (1 << PD5); | DDRD |= (1 << PD0) | (1 << PD1) | (1 << PD2) | (1 << PD3) | (1 << PD4) | (1 << PD5); | ||
− | |||
− | |||
PORTD = 0x20; | PORTD = 0x20; | ||
PORTD |= 0x04; | PORTD |= 0x04; | ||
PORTD &= ~0x04; | PORTD &= ~0x04; | ||
− | |||
− | |||
sendLCDCommand(0x28); | sendLCDCommand(0x28); | ||
− | |||
− | |||
sendLCDCommand(0x0C); | sendLCDCommand(0x0C); | ||
− | |||
− | |||
sendLCDCommand(0x01); | sendLCDCommand(0x01); | ||
− | + | DDRB &= ~((1 << clk_pin) | (1 << data_pin) | (1 << swt_pin)); | |
− | |||
− | DDRB &= ~(1 << clk_pin) | ||
PORTB |= (1 << clk_pin) | (1 << data_pin) | (1 << swt_pin); | PORTB |= (1 << clk_pin) | (1 << data_pin) | (1 << swt_pin); | ||
− | |||
− | |||
− | |||
} | } | ||
− | + | void sendLCDCommand(uint8_t command) { | |
− | void sendLCDCommand(uint8_t command) | ||
− | { | ||
PORTD = (command & 0xF0); | PORTD = (command & 0xF0); | ||
PORTD &= ~(1 << PD4); | PORTD &= ~(1 << PD4); | ||
Riadok 87: | Riadok 66: | ||
_delay_us(1); | _delay_us(1); | ||
PORTD &= ~(1 << PD5); | PORTD &= ~(1 << PD5); | ||
− | |||
PORTD = ((command << 4) & 0xF0); | PORTD = ((command << 4) & 0xF0); | ||
PORTD &= ~(1 << PD4); | PORTD &= ~(1 << PD4); | ||
Riadok 93: | Riadok 71: | ||
_delay_us(1); | _delay_us(1); | ||
PORTD &= ~(1 << PD5); | PORTD &= ~(1 << PD5); | ||
− | |||
_delay_us(40); | _delay_us(40); | ||
} | } | ||
− | + | void sendLCDData(uint8_t data) { | |
− | void sendLCDData(uint8_t data) | ||
− | { | ||
PORTD = (data & 0xF0); | PORTD = (data & 0xF0); | ||
PORTD |= (1 << PD4); | PORTD |= (1 << PD4); | ||
Riadok 105: | Riadok 80: | ||
_delay_us(1); | _delay_us(1); | ||
PORTD &= ~(1 << PD5); | PORTD &= ~(1 << PD5); | ||
− | |||
PORTD = ((data << 4) & 0xF0); | PORTD = ((data << 4) & 0xF0); | ||
PORTD |= (1 << PD4); | PORTD |= (1 << PD4); | ||
Riadok 111: | Riadok 85: | ||
_delay_us(1); | _delay_us(1); | ||
PORTD &= ~(1 << PD5); | PORTD &= ~(1 << PD5); | ||
− | |||
_delay_us(40); | _delay_us(40); | ||
} | } | ||
− | + | void updateCounterDisplay() { | |
− | void updateCounterDisplay() | + | sendLCDCommand(0x80 | 0x40); |
− | { | ||
− | sendLCDCommand(0x80 | 0x40); | ||
sendLCDData('P'); | sendLCDData('P'); | ||
sendLCDData('o'); | sendLCDData('o'); | ||
Riadok 128: | Riadok 99: | ||
sendLCDData('n'); | sendLCDData('n'); | ||
sendLCDData(':'); | sendLCDData(':'); | ||
− | + | sendLCDCommand(0x80 | 0x40 | 0x09); | |
− | sendLCDCommand(0x80 | 0x40 | 0x09); | ||
sendLCDData(' '); | sendLCDData(' '); | ||
sendLCDData(' '); | sendLCDData(' '); | ||
Riadok 138: | Riadok 108: | ||
sendLCDData(' '); | sendLCDData(' '); | ||
sendLCDData(' '); | sendLCDData(' '); | ||
− | + | sendLCDCommand(0x80 | 0x40 | 0x09); | |
− | sendLCDCommand(0x80 | 0x40 | 0x09); | ||
sendLCDData((counter / 100) + '0'); | sendLCDData((counter / 100) + '0'); | ||
sendLCDData(((counter / 10) % 10) + '0'); | sendLCDData(((counter / 10) % 10) + '0'); | ||
Riadok 145: | Riadok 114: | ||
} | } | ||
− | + | void handleMainMenu() { | |
− | void handleMainMenu() | + | if ((PINB & (1 << clk_pin)) != 0) { |
− | { | + | if ((PINB & (1 << data_pin)) != 0) { |
− | if ((PINB & (1 << clk_pin)) != | ||
− | |||
− | if ((PINB & (1 << data_pin)) != | ||
− | |||
counter++; | counter++; | ||
− | } | + | } else { |
− | |||
− | |||
counter--; | counter--; | ||
} | } | ||
Riadok 161: | Riadok 124: | ||
} | } | ||
− | + | if ((PINB & (1 << swt_pin)) == 0 && !buttonPressed) { | |
− | |||
− | if ((PINB & (1 << swt_pin)) == 0 && !buttonPressed) | ||
− | |||
buttonPressed = true; | buttonPressed = true; | ||
− | sendLCDCommand(0x01); | + | sendLCDCommand(0x01); |
sendLCDData('P'); | sendLCDData('P'); | ||
sendLCDData('r'); | sendLCDData('r'); | ||
Riadok 175: | Riadok 135: | ||
sendLCDData('d'); | sendLCDData('d'); | ||
_delay_ms(500); | _delay_ms(500); | ||
− | sendLCDCommand(0x01); | + | sendLCDCommand(0x01); |
menuState = MENU_VALUE; | menuState = MENU_VALUE; | ||
updateCounterDisplay(); | updateCounterDisplay(); | ||
− | } | + | } else if ((PINB & (1 << swt_pin)) != 0) { |
− | |||
− | |||
buttonPressed = false; | buttonPressed = false; | ||
} | } | ||
} | } | ||
− | + | void handleValueMenu() { | |
− | void handleValueMenu() | + | if ((PINB & (1 << clk_pin)) != 0) { |
− | { | + | if ((PINB & (1 << data_pin)) != 0) { |
− | if ((PINB & (1 << clk_pin)) != | ||
− | |||
− | if ((PINB & (1 << data_pin)) != | ||
− | |||
counter++; | counter++; | ||
− | } | + | } else { |
− | |||
− | |||
counter--; | counter--; | ||
} | } | ||
− | sendLCDCommand(0x80 | 0x40); | + | sendLCDCommand(0x80 | 0x40); |
sendLCDData('P'); | sendLCDData('P'); | ||
sendLCDData('o'); | sendLCDData('o'); | ||
Riadok 208: | Riadok 160: | ||
sendLCDData('n'); | sendLCDData('n'); | ||
sendLCDData(':'); | sendLCDData(':'); | ||
− | + | sendLCDCommand(0x80 | 0x40 | 0x09); | |
− | sendLCDCommand(0x80 | 0x40 | 0x09); | ||
sendLCDData((counter / 100) + '0'); | sendLCDData((counter / 100) + '0'); | ||
sendLCDData(((counter / 10) % 10) + '0'); | sendLCDData(((counter / 10) % 10) + '0'); | ||
Riadok 215: | Riadok 166: | ||
} | } | ||
− | + | if ((PINB & (1 << swt_pin)) == 0 && !buttonPressed) { | |
− | |||
− | if ((PINB & (1 << swt_pin)) == 0 && !buttonPressed) | ||
− | |||
menuState = MENU_MAIN; | menuState = MENU_MAIN; | ||
− | sendLCDCommand(0x01); | + | sendLCDCommand(0x01); |
sendLCDData('V'); | sendLCDData('V'); | ||
sendLCDData('a'); | sendLCDData('a'); | ||
Riadok 234: | Riadok 182: | ||
sendLCDData('e'); | sendLCDData('e'); | ||
sendLCDData('d'); | sendLCDData('d'); | ||
− | sendLCDCommand(0x80 | 0x40); | + | sendLCDCommand(0x80 | 0x40); |
sendLCDData(' '); | sendLCDData(' '); | ||
sendLCDData(' '); | sendLCDData(' '); | ||
Riadok 243: | Riadok 191: | ||
sendLCDData(' '); | sendLCDData(' '); | ||
sendLCDData(' '); | sendLCDData(' '); | ||
− | sendLCDCommand(0x01); | + | sendLCDCommand(0x01); |
sendLCDData(' '); | sendLCDData(' '); | ||
sendLCDData('R'); | sendLCDData('R'); | ||
Riadok 268: | Riadok 216: | ||
sendLCDData(' '); | sendLCDData(' '); | ||
updateCounterDisplay(); | updateCounterDisplay(); | ||
− | } | + | } else if ((PINB & (1 << swt_pin)) != 0) { |
− | |||
− | |||
buttonPressed = false; | buttonPressed = false; | ||
} | } | ||
} | } | ||
− | + | int main(void) { | |
− | int main(void) | ||
− | { | ||
initLCD(); | initLCD(); | ||
− | sei(); | + | sei(); |
− | while (1) | + | while (1) { |
− | + | switch (menuState) { | |
− | switch (menuState) | ||
− | |||
case MENU_MAIN: | case MENU_MAIN: | ||
handleMainMenu(); | handleMainMenu(); | ||
Riadok 295: | Riadok 237: | ||
} | } | ||
− | |||
− | |||
</source></tab> | </source></tab> |
Verzia zo dňa a času 15:52, 9. jún 2023
Záverečný projekt predmetu MIPS / LS2023 - Viktor Fos
Zadanie
Rotačný enkóder - vytvorime program pre zadávanie hodnoty nejakej veličiny na LCD displeji pomocou tohoto enkodéra. Jednoduché menu, výber hodnoty a zadávanie číselnej veličiny so zmenou nahor/nadol a potvrdenie stlačením.
Literatúra:
Analýza a opis riešenia
Najprv som podľa schémy zapojenia pripojil LCD displej a rotačný enkoder na dosku Arduino Uno.
Algoritmus a program
Algoritmus programu je....
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define clk_pin PB3
#define data_pin PB4
#define swt_pin PB5
volatile int counter = 0;
volatile bool buttonPressed = false;
enum MenuState { MENU_MAIN, MENU_VALUE };
volatile MenuState menuState = MENU_MAIN;
void initLCD() {
DDRD |= (1 << PD0) | (1 << PD1) | (1 << PD2) | (1 << PD3) | (1 << PD4) | (1 << PD5);
PORTD = 0x20;
PORTD |= 0x04;
PORTD &= ~0x04;
sendLCDCommand(0x28);
sendLCDCommand(0x0C);
sendLCDCommand(0x01);
DDRB &= ~((1 << clk_pin) | (1 << data_pin) | (1 << swt_pin));
PORTB |= (1 << clk_pin) | (1 << data_pin) | (1 << swt_pin);
}
void sendLCDCommand(uint8_t command) {
PORTD = (command & 0xF0);
PORTD &= ~(1 << PD4);
PORTD |= (1 << PD5);
_delay_us(1);
PORTD &= ~(1 << PD5);
PORTD = ((command << 4) & 0xF0);
PORTD &= ~(1 << PD4);
PORTD |= (1 << PD5);
_delay_us(1);
PORTD &= ~(1 << PD5);
_delay_us(40);
}
void sendLCDData(uint8_t data) {
PORTD = (data & 0xF0);
PORTD |= (1 << PD4);
PORTD |= (1 << PD5);
_delay_us(1);
PORTD &= ~(1 << PD5);
PORTD = ((data << 4) & 0xF0);
PORTD |= (1 << PD4);
PORTD |= (1 << PD5);
_delay_us(1);
PORTD &= ~(1 << PD5);
_delay_us(40);
}
void updateCounterDisplay() {
sendLCDCommand(0x80 | 0x40);
sendLCDData('P');
sendLCDData('o');
sendLCDData('s');
sendLCDData('i');
sendLCDData('t');
sendLCDData('i');
sendLCDData('o');
sendLCDData('n');
sendLCDData(':');
sendLCDCommand(0x80 | 0x40 | 0x09);
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDCommand(0x80 | 0x40 | 0x09);
sendLCDData((counter / 100) + '0');
sendLCDData(((counter / 10) % 10) + '0');
sendLCDData((counter % 10) + '0');
}
void handleMainMenu() {
if ((PINB & (1 << clk_pin)) != 0) {
if ((PINB & (1 << data_pin)) != 0) {
counter++;
} else {
counter--;
}
updateCounterDisplay();
}
if ((PINB & (1 << swt_pin)) == 0 && !buttonPressed) {
buttonPressed = true;
sendLCDCommand(0x01);
sendLCDData('P');
sendLCDData('r');
sendLCDData('e');
sendLCDData('s');
sendLCDData('s');
sendLCDData('e');
sendLCDData('d');
_delay_ms(500);
sendLCDCommand(0x01);
menuState = MENU_VALUE;
updateCounterDisplay();
} else if ((PINB & (1 << swt_pin)) != 0) {
buttonPressed = false;
}
}
void handleValueMenu() {
if ((PINB & (1 << clk_pin)) != 0) {
if ((PINB & (1 << data_pin)) != 0) {
counter++;
} else {
counter--;
}
sendLCDCommand(0x80 | 0x40);
sendLCDData('P');
sendLCDData('o');
sendLCDData('s');
sendLCDData('i');
sendLCDData('t');
sendLCDData('i');
sendLCDData('o');
sendLCDData('n');
sendLCDData(':');
sendLCDCommand(0x80 | 0x40 | 0x09);
sendLCDData((counter / 100) + '0');
sendLCDData(((counter / 10) % 10) + '0');
sendLCDData((counter % 10) + '0');
}
if ((PINB & (1 << swt_pin)) == 0 && !buttonPressed) {
menuState = MENU_MAIN;
sendLCDCommand(0x01);
sendLCDData('V');
sendLCDData('a');
sendLCDData('l');
sendLCDData('u');
sendLCDData('e');
sendLCDData(' ');
sendLCDData('e');
sendLCDData('n');
sendLCDData('t');
sendLCDData('e');
sendLCDData('r');
sendLCDData('e');
sendLCDData('d');
sendLCDCommand(0x80 | 0x40);
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDCommand(0x01);
sendLCDData(' ');
sendLCDData('R');
sendLCDData('o');
sendLCDData('t');
sendLCDData('a');
sendLCDData('r');
sendLCDData('y');
sendLCDData(' ');
sendLCDData('E');
sendLCDData('n');
sendLCDData('c');
sendLCDData('o');
sendLCDData('d');
sendLCDData('e');
sendLCDData('r');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
sendLCDData(' ');
updateCounterDisplay();
} else if ((PINB & (1 << swt_pin)) != 0) {
buttonPressed = false;
}
}
int main(void) {
initLCD();
sei();
while (1) {
switch (menuState) {
case MENU_MAIN:
handleMainMenu();
break;
case MENU_VALUE:
handleValueMenu();
break;
}
}
}
#include <avr/io.h>
void adc_init(void); // A/D converter initialization
unsigned int adc_read(char a_pin);
Pridajte sem aj zbalený kompletný projekt, napríklad takto (použite jednoznačné pomenovanie, nemôžeme mať na serveri 10x zdrojaky.zip:
Zdrojový kód: zdrojaky.zip
Overenie
Na používanie našej aplikácie stačia dve tlačítka a postup používania je opísaný v sekcii popis riešenia. Na konci uvádzame fotku záverečnej obrazovky pred resetom. Vypísaný je tu priemerný čas a najlepší čas.
Video:
Kľúčové slová 'Category', ktoré sú na konci stránky nemeňte.