Vzorové riešenie MIPS 2026: Rozdiel medzi revíziami
Zo stránky SensorWiki
Vytvorená stránka „Vzorové riešenie MIPS 2026 Praktická časť skúšky z predmetu MIPS / LS2026 - '''Richard Balogh''' == Zadanie == Dostali ste neznámu elektronickú súčiastku spolu s jej datasheet-om. Vašou úlohou je z datasheetu zistiť, o aký snímač ide, identifikovať jeho vývody a navrhnúť zapojenie k mikroprocesoru ATmega328P. Analógový výstup snímača pripojte na vstup ADC0 (pin PC0). Na LCD displeji EA-DOGM163 zobrazte aktuálnu teplotu podľa predpís…“ |
dBez shrnutí editace |
||
| (2 medziľahlé úpravy od rovnakého používateľa nie sú zobrazené.) | |||
| Riadok 1: | Riadok 1: | ||
Praktická časť skúšky z predmetu MIPS / LS2026 - '''Richard Balogh''' | Praktická časť skúšky z predmetu MIPS / LS2026 - '''Richard Balogh''' | ||
| Riadok 27: | Riadok 25: | ||
Zapojenie je jednoduché — napájanie na 5V, zem na GND a výstup Vout priamo na pin PC0 (ADC0). Nie je potrebný žiadny prídavný rezistor ani kondenzátor. | Zapojenie je jednoduché — napájanie na 5V, zem na GND a výstup Vout priamo na pin PC0 (ADC0). Nie je potrebný žiadny prídavný rezistor ani kondenzátor. | ||
[[Súbor:MIPS2026-LM35DZ-schema. | [[Súbor:MIPS2026-LM35DZ-schema.png|600px|center]] | ||
''Schéma zapojenia LM35DZ k ATmega328P.'' | ''Schéma zapojenia LM35DZ k ATmega328P.'' | ||
| Riadok 108: | Riadok 106: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== Analýza problémov a najčastejšie chyby == | |||
Prevažná väčšina dokázala správne identifikovať funkciu súčiastky a väčšinou aj správne identifikovať pinout z datasheetu (ak si odmyslím "pohľad zdola"). | |||
Väčšina študentov tiež ovláda jednotlivé stavebné bloky — napr. ADC inicializácia sa objavuje takmer všade a je väčšinou správna, sériová linka fungovala a často aj displej. | |||
Hlavný problém nebol v žiadnej jednotlivej časti — každú z nich (ADC, LCD, UART) sme robili na cvičeniach samostatne. Problém je však celková integrácia. Na skúške ste mali spojiť všetky tri naraz, navyše | |||
s neznámou súčiastkou a pochopiť datasheet v angličtine. | |||
Vaše programy boli obvykle mozaikou kúskov z rôznych cvičení (PWM, tlačidlá, ADC, UART, LCD), poskladaných vedľa seba bez toho, aby tvorili súvislý celok. To naznačuje, že ste kód z cvičení | |||
skôr kopírovali než pochopili, a keď ho bolo potrebné poskladať inak, nevedeli ste ako. | |||
=== Najčastejšie chyby === | |||
* Príliš ambiciózny prístup | |||
** písanie celého kódu na jeden krát bez priebežnej kompilácie a overovania, alebo | |||
** pokus o čítanie ADC cez prerušenie (na skúšku zbytočne zložité a nedá sa stihnúť) | |||
* Zmätok a neprehľadnosť v kóde | |||
** chýba slučka while(1), takže celý program zbehne len raz, | |||
** funkcia ktorá sa ani neskompiluje, pretože chýba jej deklarácia, | |||
** mŕtvy kód - displej je za nekonečnou slučkou, takže sa nikdy nevykoná | |||
** kompiluje sa celkom iný program z iného cvičenia ako ten čo je otvorený v editore | |||
** Copy-paste bez rozmyslu - často sa v kóde objavovali funkcie na prácu s časovačmi a PWM výstupom. | |||
=== Na čo sa sústrediť pri príprave na opravný termín === | |||
* Pochopiť, nielen kopírovať príkazy | |||
* Snažiť sa natrénovať celý reťazec od nuly, nie jednotlivé bloky. | |||
* Kompletný program: inicializuj ADC → prečítaj → prepočítaj → zobraz na LCD → opakuj. | |||
* Naučiť sa vzor sprintf → lcd_puts. Toto je mechanický vzor, ktorý sa opakuje stále rovnako: | |||
<syntaxhighlight lang="c"> | |||
cchar buf[17]; | |||
sprintf(buf, "T = %2d.%d oC", cele, desatiny); | |||
lcd_setCursor(2, 0); | |||
lcd_puts(buf); | |||
</syntaxhighlight> | |||
Kto si toto zapamätá ako jeden blok, ušetrí na skúške cenné minúty. | |||
* Vedieť rýchlo preskenovať a prečítať datasheet: Stačí nájsť tri veci: čo to je, aký je pinout, aká je charakteristika. | |||
== Rozšírená verzia kódu == | |||
Na záver ukážka programu, ktorý rieši aj niektoré menšie problémy. Je tu zadefinovaný vlastný znak pre stupeň celzia aj | |||
pre priezvisko s diakritikou. Aby hodnota teploty nekolísala, spravíme 16 meraní a vypočítame z nich priemernú hodnotu, | |||
teda spravíme akýsi jednoduchý filter. | |||
Najzložitejšie je pochopiť, že v tomto kóde sme zmenili referenčné napätie z 5,0V na interných 1,1 V. Predpokladáme, že | |||
teplota nikdy neprekročí 100 stupňov a teda aj napätie bude vždy menšie ako 1,0V. Preto zmenou referenčného napätia | |||
rapídne zlepšíme presnosť merania. | |||
<syntaxhighlight lang="c"> | |||
/* | |||
* Vzorové riešenie — rozšírená verzia (bonus) | |||
* ============================================= | |||
* LM35DZ na ADC0 (PC0), displej EA-DOGM163 | |||
* | |||
* Vylepšenia oproti základu: | |||
* 1. Interná referencia 1,1V (rozlíšenie ~0,1 °C) | |||
* 2. Priemerovanie 16 vzoriek (potlačenie šumu) | |||
* 3. Vlastné znaky: °C (stupeň), ž, č → "Jožko Mrkvička" | |||
* | |||
* F_CPU=16000000UL, BAUDRATE=9600 | |||
*/ | |||
#define F_CPU 16000000UL | |||
#include <avr/io.h> | |||
#include <util/delay.h> | |||
#include <stdio.h> | |||
#include "uart.h" | |||
#include "lcd.h" | |||
FILE mystdout = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE); | |||
/* ===================================================================== | |||
* Vlastné znaky v CGRAM (5×8 pixelov) | |||
* | |||
* CGRAM má 8 pozícií (0–7). Znak na pozícii N sa vloží ako '\x0N'. | |||
* ===================================================================== */ | |||
/* Pozícia 1: stupeň ° | |||
* | |||
* .XX.. 0x06 | |||
* X..X. 0x09 | |||
* X..X. 0x09 | |||
* .XX.. 0x06 | |||
* ..... 0x00 | |||
* ..... 0x00 | |||
* ..... 0x00 | |||
* ..... 0x00 | |||
*/ | |||
unsigned char znak_stupen[8] = { | |||
0x06, 0x09, 0x09, 0x06, 0x00, 0x00, 0x00, 0x00 | |||
}; | |||
/* Pozícia 2: ž (z s mäkčeňom) | |||
* | |||
* .X.X. 0x0A | |||
* ..X.. 0x04 | |||
* XXXX. 0x1E | |||
* ...X. 0x02 | |||
* ..X.. 0x04 | |||
* .X... 0x08 | |||
* XXXX. 0x1E | |||
* ..... 0x00 | |||
*/ | |||
unsigned char znak_z_hacik[8] = { | |||
0x0A, 0x04, 0x1E, 0x02, 0x04, 0x08, 0x1E, 0x00 | |||
}; | |||
/* Pozícia 3: č (c s mäkčeňom) | |||
* | |||
* .X.X. 0x0A | |||
* ..X.. 0x04 | |||
* .XXX. 0x0E | |||
* X.... 0x10 | |||
* X.... 0x10 | |||
* X.... 0x10 | |||
* .XXX. 0x0E | |||
* ..... 0x00 | |||
*/ | |||
unsigned char znak_c_hacik[8] = { | |||
0x0A, 0x04, 0x0E, 0x10, 0x10, 0x10, 0x0E, 0x00 | |||
}; | |||
/* ===================================================================== | |||
* ADC — interná referencia 1,1V + priemerovanie | |||
* ===================================================================== */ | |||
void adc_init_1(void) | |||
{ | |||
/* REFS1=1, REFS0=1 → interná referencia 1,1V | |||
* | |||
* Prečo 1,1V a nie 5V? | |||
* 5V: rozlíšenie = 5000/1024 = 4,88 mV/krok → ~0,49 °C/krok | |||
* 1,1V: rozlíšenie = 1100/1024 = 1,07 mV/krok → ~0,11 °C/krok | |||
* | |||
* Maximum s 1,1V referenciou je ~110 °C, čo LM35DZ (0–100 °C) pokryje. | |||
*/ | |||
ADMUX = (1 << REFS1) | (1 << REFS0); | |||
ADCSRA = (1 << ADEN) | |||
| (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); /* /128 → 125 kHz */ | |||
} | |||
/* Priemer z N meraní — potlačenie šumu | |||
* | |||
* Prečo priemerovať? | |||
* Jeden ADC prevod kolíše ±1–2 LSB kvôli šumu. | |||
* Priemer z 16 vzoriek to vyfiltruje. | |||
* 16 je mocnina 2, takže delenie je rýchly bitový posun. | |||
*/ | |||
uint16_t adc_read_avg(uint8_t channel, uint8_t n) | |||
{ | |||
uint32_t sum = 0; | |||
for (uint8_t i = 0; i < n; i++) | |||
{ | |||
sum += adc_read(channel); | |||
_delay_ms(2); | |||
} | |||
return (uint16_t)(sum / n); | |||
} | |||
/* ===================================================================== | |||
* MAIN | |||
* ===================================================================== */ | |||
int main(void) | |||
{ | |||
/* --- Inicializácia --- */ | |||
uart_init(); | |||
stdout = &mystdout; | |||
printf("\r\n=== LM35DZ Teplomer (bonus) ===\r\n"); | |||
printf("Ref: 1.1V interna, priemer 16 vzoriek\r\n\r\n"); | |||
lcd_init(); | |||
lcd_bklt(1); | |||
lcd_command(0x0C); /* display ON, cursor OFF */ | |||
/* Nahraj vlastné znaky do CGRAM */ | |||
def_znak(znak_stupen, 1); /* ° na pozícii 1 → '\x01' */ | |||
def_znak(znak_z_hacik, 2); /* ž na pozícii 2 → '\x02' */ | |||
def_znak(znak_c_hacik, 3); /* č na pozícii 3 → '\x03' */ | |||
/* Inicializuj ADC s internou 1,1V referenciou */ | |||
adc_init_1(); | |||
(void)adc_read(0); /* zahoď prvý prevod po zmene Vref */ | |||
_delay_ms(50); /* nechaj referenciu ustáliť sa */ | |||
char riadok[17]; | |||
/* --- Hlavná slučka --- */ | |||
while (1) | |||
{ | |||
uint16_t adc_val = adc_read_avg(0, 16); | |||
/* Prepočet s 1,1V referenciou: | |||
* | |||
* U [mV] = adc_val × 1100 / 1024 | |||
* T [°C] = U / 10 (LM35: 10 mV/°C) | |||
* t_x10 = adc_val × 1100 / 1024 (teplota × 10) | |||
* | |||
* Príklad: adc_val = 227 | |||
* t_x10 = 227 × 1100 / 1024 = 243 → 24,3 °C | |||
*/ | |||
uint16_t t_x10 = (uint32_t)adc_val * 1100 / 1024; | |||
uint8_t cele = t_x10 / 10; | |||
uint8_t desatiny = t_x10 % 10; | |||
/* Debug na UART */ | |||
printf("ADC=%4u T=%2u.%1u C\r\n", adc_val, cele, desatiny); | |||
/* Riadok 1: nadpis */ | |||
lcd_setCursor(1, 0); | |||
lcd_puts(" Senzor LM35 "); | |||
/* Riadok 2: teplota so znakom ° z CGRAM pozície 1 */ | |||
sprintf(riadok, " T = %2u.%1u \x01""C ", cele, desatiny); | |||
lcd_setCursor(2, 0); | |||
lcd_puts(riadok); | |||
/* Riadok 3: "Jožko Mrkvička" s vlastnými ž a č */ | |||
lcd_setCursor(3, 0); | |||
lcd_puts(" Jo\x02ko Mrkvi\x03ka "); | |||
_delay_ms(500); | |||
} | |||
return 0; | |||
} | |||
</syntaxhighlight> | |||
=== Overenie === | === Overenie === | ||
Program | Program funguje ako vidno na videu - je na ňom vidieť aktuálnu teplotu na displeji, ktorá reaguje na dotyk prsta (zahriatie). | ||
[[Súbor:MIPS2026-LM35DZ-video.gif|center]] | [[Súbor:MIPS2026-LM35DZ-video.gif|center]] | ||
Aktuálna revízia z 08:25, 9. jún 2026
Praktická časť skúšky z predmetu MIPS / LS2026 - Richard Balogh
Zadanie
Dostali ste neznámu elektronickú súčiastku spolu s jej datasheet-om. Vašou úlohou je z datasheetu zistiť, o aký snímač ide, identifikovať jeho vývody a navrhnúť zapojenie k mikroprocesoru ATmega328P. Analógový výstup snímača pripojte na vstup ADC0 (pin PC0). Na LCD displeji EA-DOGM163 zobrazte aktuálnu teplotu podľa predpísaného formátu.
+----------------+ | Snimac teploty | | T = 25.3 °C | | Meno Priezvisk | +----------------+
K dispozícii máte:
- Rozširujúci modul s displejom EA-DOGM163
- Knižnice lcd.h / lcd.c a uart.h / uart.c z cvičení
- Datasheet obvodu LM35
Analýza a opis riešenia
Z datasheetu zistíme, že súčiastka LM35DZ je analógový snímač teploty v puzdre TO-92 s lineárnym výstupom 10 mV/°C. Má tri vývody — pri pohľade spredu (plochá strana k nám, nožičky smerujú dole) sú zľava: +Vs (napájanie), Vout (analógový výstup) a GND (zem). Napájací rozsah je 4–30 V, takže 5 V z dosky Acrob vyhovuje.
Zapojenie je jednoduché — napájanie na 5V, zem na GND a výstup Vout priamo na pin PC0 (ADC0). Nie je potrebný žiadny prídavný rezistor ani kondenzátor.

Schéma zapojenia LM35DZ k ATmega328P.
Ak sa zo schémy zapojenia neviete celkom zorientovať, možno vám pomôže fotografia zapojenia priamo na doštičke.

Zapojenie na doštičke.
Prepočet ADC na teplotu
ATmega328P má 10-bitový ADC prevodník (rozsah 0–1023). S referenčným napätím AVcc = 5 V je rozlíšenie jedného kroku:
5000 mV / 1024 = 4,88 mV/krok
Keďže LM35 dáva 10 mV/°C, rozlíšenie merania je približne 0,5 °C. Prepočet na teplotu v desatinách stupňa (celočíselná aritmetika):
t_x10 = adc_val × 5000 / 1024
Pozor na pretečenie — hodnota 1023 × 5000 = 5 115 000, čo sa nezmestí do 16-bitového typu (max 65 535). Preto je nutné pretypovanie na uint32_t:
uint16_t t_x10 = (uint32_t)adc_val * 5000 / 1024;
uint8_t cele = t_x10 / 10; // celá časť
uint8_t desatiny = t_x10 % 10; // desatinná časť
Algoritmus a program
Program najprv inicializuje UART (pre ladenie cez printf), LCD displej a ADC prevodník.
V hlavnej slučke periodicky číta hodnotu z ADC0, prepočíta ju na teplotu a zobrazí na displej.
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include "uart.h"
#include "adc.h"
#include "lcd.h"
FILE mystdout = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE);
int main(void)
{
uart_init();
stdout = &mystdout;
lcd_init();
lcd_bklt(1);
lcd_command(0x0C);
adc_init();
char riadok[17];
while (1)
{
uint16_t adc_val = adc_read(0);
uint16_t t_x10 = (uint32_t)adc_val * 5000 / 1024;
uint8_t cele = t_x10 / 10;
uint8_t desatiny = t_x10 % 10;
printf("ADC=%4u T=%2u.%1u C\r\n", adc_val, cele, desatiny);
lcd_setCursor(1, 0);
lcd_puts(" Snimac teploty ");
sprintf(riadok, " T = %2u.%1u oC ", cele, desatiny);
lcd_setCursor(2, 0);
lcd_puts(riadok);
lcd_setCursor(3, 0);
lcd_puts(" Meno Priezvisko ");
_delay_ms(100);
}
return 0;
}
Analýza problémov a najčastejšie chyby
Prevažná väčšina dokázala správne identifikovať funkciu súčiastky a väčšinou aj správne identifikovať pinout z datasheetu (ak si odmyslím "pohľad zdola"). Väčšina študentov tiež ovláda jednotlivé stavebné bloky — napr. ADC inicializácia sa objavuje takmer všade a je väčšinou správna, sériová linka fungovala a často aj displej.
Hlavný problém nebol v žiadnej jednotlivej časti — každú z nich (ADC, LCD, UART) sme robili na cvičeniach samostatne. Problém je však celková integrácia. Na skúške ste mali spojiť všetky tri naraz, navyše s neznámou súčiastkou a pochopiť datasheet v angličtine.
Vaše programy boli obvykle mozaikou kúskov z rôznych cvičení (PWM, tlačidlá, ADC, UART, LCD), poskladaných vedľa seba bez toho, aby tvorili súvislý celok. To naznačuje, že ste kód z cvičení skôr kopírovali než pochopili, a keď ho bolo potrebné poskladať inak, nevedeli ste ako.
Najčastejšie chyby
- Príliš ambiciózny prístup
- písanie celého kódu na jeden krát bez priebežnej kompilácie a overovania, alebo
- pokus o čítanie ADC cez prerušenie (na skúšku zbytočne zložité a nedá sa stihnúť)
- Zmätok a neprehľadnosť v kóde
- chýba slučka while(1), takže celý program zbehne len raz,
- funkcia ktorá sa ani neskompiluje, pretože chýba jej deklarácia,
- mŕtvy kód - displej je za nekonečnou slučkou, takže sa nikdy nevykoná
- kompiluje sa celkom iný program z iného cvičenia ako ten čo je otvorený v editore
- Copy-paste bez rozmyslu - často sa v kóde objavovali funkcie na prácu s časovačmi a PWM výstupom.
Na čo sa sústrediť pri príprave na opravný termín
- Pochopiť, nielen kopírovať príkazy
- Snažiť sa natrénovať celý reťazec od nuly, nie jednotlivé bloky.
- Kompletný program: inicializuj ADC → prečítaj → prepočítaj → zobraz na LCD → opakuj.
- Naučiť sa vzor sprintf → lcd_puts. Toto je mechanický vzor, ktorý sa opakuje stále rovnako:
cchar buf[17];
sprintf(buf, "T = %2d.%d oC", cele, desatiny);
lcd_setCursor(2, 0);
lcd_puts(buf);
Kto si toto zapamätá ako jeden blok, ušetrí na skúške cenné minúty.
- Vedieť rýchlo preskenovať a prečítať datasheet: Stačí nájsť tri veci: čo to je, aký je pinout, aká je charakteristika.
Rozšírená verzia kódu
Na záver ukážka programu, ktorý rieši aj niektoré menšie problémy. Je tu zadefinovaný vlastný znak pre stupeň celzia aj pre priezvisko s diakritikou. Aby hodnota teploty nekolísala, spravíme 16 meraní a vypočítame z nich priemernú hodnotu, teda spravíme akýsi jednoduchý filter.
Najzložitejšie je pochopiť, že v tomto kóde sme zmenili referenčné napätie z 5,0V na interných 1,1 V. Predpokladáme, že teplota nikdy neprekročí 100 stupňov a teda aj napätie bude vždy menšie ako 1,0V. Preto zmenou referenčného napätia rapídne zlepšíme presnosť merania.
/*
* Vzorové riešenie — rozšírená verzia (bonus)
* =============================================
* LM35DZ na ADC0 (PC0), displej EA-DOGM163
*
* Vylepšenia oproti základu:
* 1. Interná referencia 1,1V (rozlíšenie ~0,1 °C)
* 2. Priemerovanie 16 vzoriek (potlačenie šumu)
* 3. Vlastné znaky: °C (stupeň), ž, č → "Jožko Mrkvička"
*
* F_CPU=16000000UL, BAUDRATE=9600
*/
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <stdio.h>
#include "uart.h"
#include "lcd.h"
FILE mystdout = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE);
/* =====================================================================
* Vlastné znaky v CGRAM (5×8 pixelov)
*
* CGRAM má 8 pozícií (0–7). Znak na pozícii N sa vloží ako '\x0N'.
* ===================================================================== */
/* Pozícia 1: stupeň °
*
* .XX.. 0x06
* X..X. 0x09
* X..X. 0x09
* .XX.. 0x06
* ..... 0x00
* ..... 0x00
* ..... 0x00
* ..... 0x00
*/
unsigned char znak_stupen[8] = {
0x06, 0x09, 0x09, 0x06, 0x00, 0x00, 0x00, 0x00
};
/* Pozícia 2: ž (z s mäkčeňom)
*
* .X.X. 0x0A
* ..X.. 0x04
* XXXX. 0x1E
* ...X. 0x02
* ..X.. 0x04
* .X... 0x08
* XXXX. 0x1E
* ..... 0x00
*/
unsigned char znak_z_hacik[8] = {
0x0A, 0x04, 0x1E, 0x02, 0x04, 0x08, 0x1E, 0x00
};
/* Pozícia 3: č (c s mäkčeňom)
*
* .X.X. 0x0A
* ..X.. 0x04
* .XXX. 0x0E
* X.... 0x10
* X.... 0x10
* X.... 0x10
* .XXX. 0x0E
* ..... 0x00
*/
unsigned char znak_c_hacik[8] = {
0x0A, 0x04, 0x0E, 0x10, 0x10, 0x10, 0x0E, 0x00
};
/* =====================================================================
* ADC — interná referencia 1,1V + priemerovanie
* ===================================================================== */
void adc_init_1(void)
{
/* REFS1=1, REFS0=1 → interná referencia 1,1V
*
* Prečo 1,1V a nie 5V?
* 5V: rozlíšenie = 5000/1024 = 4,88 mV/krok → ~0,49 °C/krok
* 1,1V: rozlíšenie = 1100/1024 = 1,07 mV/krok → ~0,11 °C/krok
*
* Maximum s 1,1V referenciou je ~110 °C, čo LM35DZ (0–100 °C) pokryje.
*/
ADMUX = (1 << REFS1) | (1 << REFS0);
ADCSRA = (1 << ADEN)
| (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); /* /128 → 125 kHz */
}
/* Priemer z N meraní — potlačenie šumu
*
* Prečo priemerovať?
* Jeden ADC prevod kolíše ±1–2 LSB kvôli šumu.
* Priemer z 16 vzoriek to vyfiltruje.
* 16 je mocnina 2, takže delenie je rýchly bitový posun.
*/
uint16_t adc_read_avg(uint8_t channel, uint8_t n)
{
uint32_t sum = 0;
for (uint8_t i = 0; i < n; i++)
{
sum += adc_read(channel);
_delay_ms(2);
}
return (uint16_t)(sum / n);
}
/* =====================================================================
* MAIN
* ===================================================================== */
int main(void)
{
/* --- Inicializácia --- */
uart_init();
stdout = &mystdout;
printf("\r\n=== LM35DZ Teplomer (bonus) ===\r\n");
printf("Ref: 1.1V interna, priemer 16 vzoriek\r\n\r\n");
lcd_init();
lcd_bklt(1);
lcd_command(0x0C); /* display ON, cursor OFF */
/* Nahraj vlastné znaky do CGRAM */
def_znak(znak_stupen, 1); /* ° na pozícii 1 → '\x01' */
def_znak(znak_z_hacik, 2); /* ž na pozícii 2 → '\x02' */
def_znak(znak_c_hacik, 3); /* č na pozícii 3 → '\x03' */
/* Inicializuj ADC s internou 1,1V referenciou */
adc_init_1();
(void)adc_read(0); /* zahoď prvý prevod po zmene Vref */
_delay_ms(50); /* nechaj referenciu ustáliť sa */
char riadok[17];
/* --- Hlavná slučka --- */
while (1)
{
uint16_t adc_val = adc_read_avg(0, 16);
/* Prepočet s 1,1V referenciou:
*
* U [mV] = adc_val × 1100 / 1024
* T [°C] = U / 10 (LM35: 10 mV/°C)
* t_x10 = adc_val × 1100 / 1024 (teplota × 10)
*
* Príklad: adc_val = 227
* t_x10 = 227 × 1100 / 1024 = 243 → 24,3 °C
*/
uint16_t t_x10 = (uint32_t)adc_val * 1100 / 1024;
uint8_t cele = t_x10 / 10;
uint8_t desatiny = t_x10 % 10;
/* Debug na UART */
printf("ADC=%4u T=%2u.%1u C\r\n", adc_val, cele, desatiny);
/* Riadok 1: nadpis */
lcd_setCursor(1, 0);
lcd_puts(" Senzor LM35 ");
/* Riadok 2: teplota so znakom ° z CGRAM pozície 1 */
sprintf(riadok, " T = %2u.%1u \x01""C ", cele, desatiny);
lcd_setCursor(2, 0);
lcd_puts(riadok);
/* Riadok 3: "Jožko Mrkvička" s vlastnými ž a č */
lcd_setCursor(3, 0);
lcd_puts(" Jo\x02ko Mrkvi\x03ka ");
_delay_ms(500);
}
return 0;
}
Overenie
Program funguje ako vidno na videu - je na ňom vidieť aktuálnu teplotu na displeji, ktorá reaguje na dotyk prsta (zahriatie).
