Kuchynské minutky: Rozdiel medzi revíziami
Zo stránky SensorWiki
(6 medziľahlých úprav od rovnakého používateľa nie je zobrazených.) | |||
Riadok 34: | Riadok 34: | ||
<tabs> | <tabs> | ||
<tab name=" | <tab name="main.c"><source lang="c++" style="background: LightYellow;"> | ||
#include <avr/io.h> | #include <avr/io.h> | ||
#include "uart.h" | |||
#include <avr/interrupt.h> | |||
#include <util/delay.h> | |||
FILE uart_output = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE); | |||
FILE uart_input = FDEV_SETUP_STREAM(NULL, uart_getc, _FDEV_SETUP_READ); | |||
static volatile int vstup_minuty = 0; | |||
static volatile int vstup_sekundy = 0; | |||
static volatile int cas = 0; | |||
static volatile int vystup_min = 0; | |||
static volatile int vystup_sek = 0; | |||
static volatile int stop = 0; | |||
#define SW1 PD7 // tlacitko | |||
#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT)) | |||
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT)) | |||
enum states { Off, Down, On, Up }; // stavy tlacitka | |||
ISR (TIMER1_OVF_vect) | |||
{ | |||
TCNT1 = 0xC2F7; // nastavenie pocitadla | |||
if (cas>=0) | |||
{ | |||
cas--; | |||
} | |||
} | |||
void tone(int note, int delay) | |||
{ | |||
OCR0A = note; | |||
for (int i=1; i<=delay; i++) | |||
_delay_ms(1); | |||
} | |||
void hudba() // funkcia prehravania melodie | |||
{ | |||
int c = 78; | |||
int h = 104; | |||
int p = 0; | |||
tone(c,250); | |||
tone(p,50); | |||
tone(h,250); | |||
tone(p,250); | |||
} | |||
int main(void) | int main(void) | ||
{ | { | ||
uart_init(); | |||
stdout = &uart_output; // teraz funguje printf() | |||
while (1) | stdin = &uart_input; // teraz funguje scanf() | ||
{ | |||
/ | set_bit(PORTD,SW1); // zapnutie pull-up rezistora | ||
clear_bit(DDRD,SW1); // nastavenie pinu SW1 ako vstup | |||
enum states Tlacitko = Off; | |||
//************************** T1 ***********************// | |||
TCNT1 = 0xC2F7; | |||
TCCR1B = 0b00000101; // externy zdroj hodin na pin T1 reagujuci na nabeznu hranu | |||
// konfiguracia prerusovacieho systemu | |||
PCMSK2 |= (1<<PCINT21); | |||
PCICR |= (1<<PCIE2); | |||
sei(); // povolenie preruseni | |||
// pretecenie | |||
TIMSK1 = (1<<TOIE1); // povolenie pretecenia Timer 1 | |||
sei(); // povolenie preruseni | |||
//********************* hudba *************************// | |||
DDRD |= (1 << PD6); // port D.6 pin ako vystup | |||
TCCR0A = (1 << COM0A0) | (1 << WGM01); // Timer 0 v rezime CTC | |||
TCCR0B = (1 << CS02); // nastavenie preddelicky na 256 | |||
while(1) | |||
{ | |||
puts("Zadaj cas (min:sek)\r"); | |||
scanf("%d:%d",&vstup_minuty,&vstup_sekundy); // nacitanie casu | |||
cas = vstup_minuty * 60 + vstup_sekundy; // prepocitanie na sekundy | |||
while(cas>=0) | |||
{ | |||
vystup_min = cas / 60; | |||
vystup_sek = cas % 60; | |||
printf("%d:%d\r", vystup_min, vystup_sek); | |||
delay(1000); | |||
if(cas !=-1) | |||
{ | |||
printf(" \r"); | |||
} | |||
} | |||
stop = 0; | |||
while(stop == 0) | |||
{ | |||
hudba(); | |||
if ( (Tlacitko == Off) && bit_is_clear(PIND,SW1) ) | |||
{ | |||
Tlacitko = Down; | |||
} | |||
else if ( (Tlacitko == Down) && bit_is_clear(PIND,SW1) ) | |||
{ | |||
_delay_ms(10); | |||
if ( bit_is_clear(PIND,SW1) ) | |||
Tlacitko = On; | |||
} | |||
else if ( (Tlacitko == On) && bit_is_set(PIND,SW1) ) | |||
{ | |||
Tlacitko = Up; | |||
} | |||
else if ( (Tlacitko == Up) && bit_is_set(PIND,SW1) ) | |||
{ | |||
_delay_ms(10); | |||
if ( bit_is_set(PIND,SW1) ) | |||
Tlacitko = Off; | |||
} | |||
if(Tlacitko == Down) | |||
{ | |||
stop = 1; | |||
Tlacitko = Off; | |||
} | |||
} | |||
} | } | ||
return(0); | return(0); | ||
} | } | ||
</source></tab> | </source></tab> | ||
<tab name=" | <tab name="uart.c"><source lang="c++" style="background: LightYellow;"> | ||
#include <avr/io.h> | #include <avr/io.h> | ||
#include <util/delay.h> | |||
#include "uart.h" | |||
void uart_init( void ) | |||
{ | |||
// for different BAUD rate change the project settings, or uncomment | |||
// following two lines: | |||
// #undef BAUD // avoid compiler warning | |||
// #define BAUD 115200 | |||
#include <util/setbaud.h> // requires defined BAUD | |||
UBRR0H = UBRRH_VALUE; | |||
UBRR0L = UBRRL_VALUE; | |||
#if USE_2X // defined in setbaud.h | |||
UCSR0A |= (1 << U2X0); | |||
#else | |||
UCSR0A &= ~(1 << U2X0); | |||
#endif | |||
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */ | |||
UCSR0B = _BV(RXEN0) | _BV(TXEN0); /* Enable RX and TX */ | |||
} | |||
int uart_putc( char c, FILE *stream ) | |||
{ | |||
if (c == '\n') | |||
uart_putc('\r',stream); | |||
loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait until data register empty. */ | |||
UDR0 = c; | |||
return 0; | |||
} | |||
char uart_getc(void) | |||
{ | |||
//loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */ | |||
//return UDR0; | |||
while (!(UCSR0A & (1<<RXC0))); | |||
return UDR0; | |||
} | |||
void delay(int delay) // vlastna funkcia pre dlhsie casy | |||
{ | |||
for (int i=1; i<=delay; i++) | |||
_delay_ms(1); | |||
} | |||
</source></tab> | |||
<tab name="uart.h"><source lang="c++" style="background: LightYellow;"> | |||
#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT)) | |||
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT)) | |||
#ifndef UART_H_ | |||
#define UART_H_ | |||
#include <stdio.h> | |||
#define BAUD_PRESCALE (((F_CPU / (BAUDRATE * 16UL))) - 1) // vzorcek z datasheetu | |||
void hw_init( void ); | |||
void uart_init( void ); | |||
int uart_putc( char c, FILE *stream ); | |||
void uart_puts( const char *s ); | |||
char uart_getc( void ); | |||
void delay(int delay); | |||
#endif /* UART_H_ */ | |||
</source></tab> | </source></tab> | ||
</tabs> | </tabs> | ||
Zdrojový kód: [[Médiá:Ulejprojekt.zip|zdrojaky.zip]] | |||
=== Overenie === | |||
Na používanie treba zapojiť zariadenia podľa schémy vyššie. Na sériovú komunikáciu je potrebný niektorý terminálový program napr. PuTTY. | |||
* [https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html PuTTY download] | |||
[[Súbor: | [[Súbor:Aplikacia_Ulej.jpg|400px|thumb|center|Aplikácia.]] | ||
'''Video:''' | '''Video:''' | ||
<center><youtube> | <center><youtube>iCKPUbtynoA</youtube></center> | ||
[[Category:AVR]] [[Category:MIPS]] | [[Category:AVR]] [[Category:MIPS]] |
Aktuálna revízia z 17:34, 8. máj 2024
Záverečný projekt predmetu MIPS / LS2024 - Ján Ulej
Zadanie
Zostrojte kuchynské minútky. Cez sériovú linku načítajte čas. Po uplynutí času bzučiak zahrá melódiu.
Literatúra:
Analýza a opis riešenia
Kladný pól reproduktora (bzučiaka) som pripojil na mikroprocesor pin PD6. Ešte som medzi pin PD6 a kladný pól bzučiaka pripojil 220 ohm odpor ktorí slúži na odrušenie šumov ktoré potom vidno na sériovej komunikácii. Tlačidlo som pripojil tiež cez 220 ohm odpor na pin PD7.
Schéma zapojenia
Algoritmus a program
Použil som knižnicu <uart.h> kde som si dodefinoval funkcie aby mi fungovalo načítavanie a výpis cez sériovú linku. Na načítavanie som použil 'scanf' a na výpis 'printf'. Tiež som použil knižnice <avr/interrupt.h> na prerušenia a <until/delay.h> na oneskorenie. Premenné ktoré som použil v prerušení som zadefinoval ako static volatile. Vytvoril som si prerušenie kde sa mi odčítaval čas. Realizoval som to pomocou 16-bitového počítadla T1. Vytvoril som funkciu 'hudba()' v ktorej som zadefinoval frekvencie a dĺžku jednotlivých tónov. Na generovanie frekvencií na výstupe som použil počítadlo 'Timer0' v režime generátora frekvencie 'CTC'. V hlavnom programe som nastavil tlačidlo ako vstup a zapol pull-up rezistor. Na ukladanie stavu tlačidla som použil dátový typ Enumerate. V hlavnej slučke načítam pomocou sériovej komunikácie čas vo formáte minúty:sekundy. Následne minúty premením na sekundy. Pomocou 'printf' vypisujem čas tiež vo formáte minúty:sekundy. Po uplynutí zvoleného času je zavolaná funkcia 'hudba()'. Skončenie prehrávania hudby a opätovné načítanie času je zabezpečené zatlačením tlačidla.
#include <avr/io.h>
#include "uart.h"
#include <avr/interrupt.h>
#include <util/delay.h>
FILE uart_output = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE);
FILE uart_input = FDEV_SETUP_STREAM(NULL, uart_getc, _FDEV_SETUP_READ);
static volatile int vstup_minuty = 0;
static volatile int vstup_sekundy = 0;
static volatile int cas = 0;
static volatile int vystup_min = 0;
static volatile int vystup_sek = 0;
static volatile int stop = 0;
#define SW1 PD7 // tlacitko
#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
enum states { Off, Down, On, Up }; // stavy tlacitka
ISR (TIMER1_OVF_vect)
{
TCNT1 = 0xC2F7; // nastavenie pocitadla
if (cas>=0)
{
cas--;
}
}
void tone(int note, int delay)
{
OCR0A = note;
for (int i=1; i<=delay; i++)
_delay_ms(1);
}
void hudba() // funkcia prehravania melodie
{
int c = 78;
int h = 104;
int p = 0;
tone(c,250);
tone(p,50);
tone(h,250);
tone(p,250);
}
int main(void)
{
uart_init();
stdout = &uart_output; // teraz funguje printf()
stdin = &uart_input; // teraz funguje scanf()
set_bit(PORTD,SW1); // zapnutie pull-up rezistora
clear_bit(DDRD,SW1); // nastavenie pinu SW1 ako vstup
enum states Tlacitko = Off;
//************************** T1 ***********************//
TCNT1 = 0xC2F7;
TCCR1B = 0b00000101; // externy zdroj hodin na pin T1 reagujuci na nabeznu hranu
// konfiguracia prerusovacieho systemu
PCMSK2 |= (1<<PCINT21);
PCICR |= (1<<PCIE2);
sei(); // povolenie preruseni
// pretecenie
TIMSK1 = (1<<TOIE1); // povolenie pretecenia Timer 1
sei(); // povolenie preruseni
//********************* hudba *************************//
DDRD |= (1 << PD6); // port D.6 pin ako vystup
TCCR0A = (1 << COM0A0) | (1 << WGM01); // Timer 0 v rezime CTC
TCCR0B = (1 << CS02); // nastavenie preddelicky na 256
while(1)
{
puts("Zadaj cas (min:sek)\r");
scanf("%d:%d",&vstup_minuty,&vstup_sekundy); // nacitanie casu
cas = vstup_minuty * 60 + vstup_sekundy; // prepocitanie na sekundy
while(cas>=0)
{
vystup_min = cas / 60;
vystup_sek = cas % 60;
printf("%d:%d\r", vystup_min, vystup_sek);
delay(1000);
if(cas !=-1)
{
printf(" \r");
}
}
stop = 0;
while(stop == 0)
{
hudba();
if ( (Tlacitko == Off) && bit_is_clear(PIND,SW1) )
{
Tlacitko = Down;
}
else if ( (Tlacitko == Down) && bit_is_clear(PIND,SW1) )
{
_delay_ms(10);
if ( bit_is_clear(PIND,SW1) )
Tlacitko = On;
}
else if ( (Tlacitko == On) && bit_is_set(PIND,SW1) )
{
Tlacitko = Up;
}
else if ( (Tlacitko == Up) && bit_is_set(PIND,SW1) )
{
_delay_ms(10);
if ( bit_is_set(PIND,SW1) )
Tlacitko = Off;
}
if(Tlacitko == Down)
{
stop = 1;
Tlacitko = Off;
}
}
}
return(0);
}
#include <avr/io.h>
#include <util/delay.h>
#include "uart.h"
void uart_init( void )
{
// for different BAUD rate change the project settings, or uncomment
// following two lines:
// #undef BAUD // avoid compiler warning
// #define BAUD 115200
#include <util/setbaud.h> // requires defined BAUD
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
#if USE_2X // defined in setbaud.h
UCSR0A |= (1 << U2X0);
#else
UCSR0A &= ~(1 << U2X0);
#endif
UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); /* 8-bit data */
UCSR0B = _BV(RXEN0) | _BV(TXEN0); /* Enable RX and TX */
}
int uart_putc( char c, FILE *stream )
{
if (c == '\n')
uart_putc('\r',stream);
loop_until_bit_is_set(UCSR0A, UDRE0); /* Wait until data register empty. */
UDR0 = c;
return 0;
}
char uart_getc(void)
{
//loop_until_bit_is_set(UCSR0A, RXC0); /* Wait until data exists. */
//return UDR0;
while (!(UCSR0A & (1<<RXC0)));
return UDR0;
}
void delay(int delay) // vlastna funkcia pre dlhsie casy
{
for (int i=1; i<=delay; i++)
_delay_ms(1);
}
#define set_bit(ADDRESS,BIT) (ADDRESS |= (1<<BIT))
#define clear_bit(ADDRESS,BIT) (ADDRESS &= ~(1<<BIT))
#ifndef UART_H_
#define UART_H_
#include <stdio.h>
#define BAUD_PRESCALE (((F_CPU / (BAUDRATE * 16UL))) - 1) // vzorcek z datasheetu
void hw_init( void );
void uart_init( void );
int uart_putc( char c, FILE *stream );
void uart_puts( const char *s );
char uart_getc( void );
void delay(int delay);
#endif /* UART_H_ */
Zdrojový kód: zdrojaky.zip
Overenie
Na používanie treba zapojiť zariadenia podľa schémy vyššie. Na sériovú komunikáciu je potrebný niektorý terminálový program napr. PuTTY.
Video: