cau, mohl by mi (jako uplnemu lajkovi, ktery se chce naucit programovat) nekdo pomoci svymi slovy vysvetlit co delaji nasledne programky?
/**
- Modul na komunikaci po I2C
- © 2009 Pavel Rozhon
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include “i2c.h”
#include “protokol.h”
#include “led.h”
uint8_t i2c_address = 1;
void i2c_set_reply(uint8_t data)
{
}
void (*i2c_on_data_received)(uint8_t data);
void i2c_init(void)
{
// Pripravi preruseni pri START stavu
USICR = _BV(USISIE) | _BV(USIWM1) | _BV(USIWM0) | _BV(USICS1);
}
// Start stav na sbernici
ISR(USI_START_vect)
{
// Pripravi prijem adresy a R/W
USISR &= ~USI_CNT_MASK; // Vynuluje citac (16 - prijima 8 bitu)
USISR |= _BV(USISIF); // Vynuluje priznak START preruseni USI a povoli preruseni preteceni citace
USICR &= ~_BV(USISIE);
USICR |= _BV(USIOIE);
}
#define I2C_ADDR 1
#define I2C_DATA_RECV 2
#define I2C_DATA_SEND 3
uint8_t i2c_stav = I2C_ADDR; // Poprve prijimame adresu
// Zmena stavu na USI sbernici
ISR(USI_OVERFLOW_vect)
{
DDRD = 0xFF;
DDRA = 0xFF;
PORTD = USIDR;
PORTA = USIDR >> 7;
for(;;){
switch(i2c_stav){
// Prisla adresa a r/w
case I2C_ADDR:
if((USIDR & ~_BV(7)) == i2c_address){
// Master komunikuje s nami
if(USIDR & _BV(7))
i2c_stav = I2C_DATA_SEND; // My vysilame
else
i2c_stav = I2C_DATA_RECV; // My prijimame
// Pripravi vysunuti ACK
USISR &= ~USI_CNT_MASK;
USISR |= (USI_CNT_MASK - 2); // Pripravi vysunuti jednoho bitu - ACK
USIDR = 0xFF;
status_led_on();
} else {
// Master nekomunikuje s nami, cekame na dalsi START stav
USICR |= _BV(USISIE);
USICR &= ~_BV(USIOIE);
}
break;
}
USISR |= _BV(USIOIF); // Uvolni sbernici
}
}
**
- Stara se o indikacni LED (sdileno mezi moduly na I2C a tlacitka)
- © 2009 Pavel Rozhon
*/
#include <avr/io.h>
#include “zapojeni.h”
#include “led.h”
uint8_t led_counter = 0;
void status_led_init(void)
{
DDR_STATUS_LED &= _BV(STATUS_LED);
}
void status_led_on(void)
{
led_counter = 0;
PORT_STATUS_LED |= _BV(STATUS_LED);
}
void status_led_off(void)
{
PORT_STATUS_LED &= ~_BV(STATUS_LED);
}
// Po poctu volani urcenym STATUS_LED_TICK_COUNT vypne stavovou LED
void status_led_tick(void)
{
if(++led_counter >= STATUS_LED_TICK_COUNT) status_led_off();
}
/**
- Vstupni bod programu pro MASTER zarizeni
- Zarizeni na I2C sbernici postupne poptava stav jednotlivych hlasovacich zarizeni
- a odesila jakykoliv prijaty stisknuty znak kontrolnimu programu pres USB - USART
- prevodnik. Tyto soucasti tvori hlasovaci system.
- © 2009 Pavel Rozhon
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include “protokol.h”
#include “i2c.h”
uint8_t slave = 1;
void prijat_status(uint8_t povedlo, char znak)
{
if(povedlo && znak != P_STATUS_NONE){
// Ve slavovi byl stisknut nejaky znak
if(slave == 1 && znak == ‘1’) PORTA = PORTA & (~PORTA & 1);
if(slave == 2 && znak == ‘1’) PORTA = PORTA & (~PORTA & 2);
PORTA |= 4;
return;
}
if(slave++ == 128) slave = 1;
i2c_init_send(slave, P_STATUS);
}
void odeslan_status(uint8_t povedlo)
{
if(povedlo){
// Zkontaktovali jsme uspesne SLAVE, nechame ho rict stav
on_i2c_received = &prijat_status;
i2c_init_receive(slave);
}
if(slave++ == 128) slave = 1;
}
// Inicializace zarizeni
void init()
{
DDRA = _BV(PA0) | _BV(PA1) | _BV(PA2);
//set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Nastavi vychozi rezim spani
i2c_init();
on_i2c_sent = &odeslan_status;
i2c_init_send(slave, P_STATUS); // Zepta se prvniho SLAVE na stav
sei();
}
int main(void)
{
init();
for(;;);
}
/**
- Definice protokolu pro komunikaci mezi MASTER a SLAVE jednotkami
- © 2009 Pavel Rozhon
*/
// ------ Prikazy ------
// Posli stav
#define P_STATUS 0
// Odpoved: nic nestisknuto
#define P_STATUS_NONE 0
// Enumerace (jsi tu)
#define P_ENUM 128
// Odpoved: ok
#define P_ENUM_OK 0xAA
// Vsechno ostatni: programovat adresu
// Odpoved: adresa naprogramovana
#define P_ADR_OK 1
// Odpoved: programovani selhalo
#define P_ADR_FAIL 0
/**
- Vstupni bod programu pro SLAVE zarizeni (klavesnici)
- Zarizeni odpovida na pozadavky MASTER jednotky a pri stisknuti tlacitka mu
- posle prislusny znak po I2C sbernici.
- © 2009 Pavel Rozhon
*/
#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include “zapojeni.h”
#include “protokol.h”
#include “tlacitka.h”
#include “led.h”
#include “i2c.h”
// Inicializace zarizeni
void init()
{
// --------- TODO: TOHLE PRIJDE DO MODULU NA I2C ------------
ACSR = _BV(ACD); // Vypne komparator (setri energii)
USICR = _BV(USISIE) | _BV(USIWM1) | _BV(USIWM0) | _BV(USICS1); // Zapne preruseni pri START stavu
// ----------------------------------------------------
// Citac/casovac
TCCR1B = _BV(WGM12) | _BV(CS11) | _BV(CS10); // Nastavi casovac 1 do CTC rezimu, zdroj fclk/64
OCR1A = 1439; // Predvolba, preruseni po 100ms
TIMSK |= _BV(OCIE1A); // Zapne preruseni casovace1
tlacitka_init();
status_led_init();
i2c_init();
sei(); // Zapne preruseni
// status_led_on(); // Bliknutim indikuje zapnuti
}
int main(void)
{
init();
for(;;);
}
// Preruseni asi po 100ms
ISR(TIMER1_COMPA_vect)
{
status_led_tick();
tlacitka_tick();
}
/**
- Ovladani tlacitek ve slave jednotce
- © 2009 Pavel Rozhon
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include “zapojeni.h”
#include “tlacitka.h”
#include “led.h”
// Ukazatel na fci volanou pri zmacknuti tlacitka
void (*on_btn_press)(char znak);
// Prazdna funkce - nedela nic (vychozi akce pri zmacknuti tlacitka)
void nop(char znak){};
// Inicializuje tlacitek a casovac pro cteni jejich stavu
void tlacitka_init(void)
{
// Tlacitka
DDR_TL &= ~MASKA_TL; // Nastavi tlacitka jako vstupy
PORT_TL |= MASKA_TL; // Zapne pull-upy
on_btn_press = &nop; // Vychozi akce pri zmacknuti tlacitka
}
// Preruseni pro zpracovani tlacitek
uint8_t predchozi = 0, stabilni = 0;
void tlacitka_tick(void)
{
uint8_t okamzite = ~PIN_TL & MASKA_TL; // Ulozi okamzity stav tlacitek
if(okamzite == predchozi){
// Mame novy stabilni stav. Sem se dostaneme kdyz nedoslo k zakmitu.
if(stabilni && !okamzite){
// Tlacitko bylo zmacknuto a uz neni, testujeme ktere bylo zmacknuto
char znak = 0;
if(okamzite & _BV(TL1)) znak = ZN1;
if(okamzite & _BV(TL2)) znak = ZN2;
if(okamzite & _BV(TL3)) znak = ZN3;
if(okamzite & _BV(TL4)) znak = ZN4;
if(okamzite & _BV(TL5)) znak = ZN5;
if(okamzite & _BV(TL6)) znak = ZN6;
on_btn_press(znak); // Volame udalost pri zmacknuti tlacitka
}
// Ulozime tento stabilni stav pro priste
stabilni = okamzite;
}
// Ulozime tento okamzity stav pro priste
predchozi = okamzite;
}
/**
- Konstanty zapojeni obvodu pro slave
- © 2009 Pavel Rozhon
*/
// Stavova LED dioda
#define STATUS_LED PB0
#define DDR_STATUS_LED DDRB
#define PORT_STATUS_LED PORTB
#define PIN_STATUS_LED PINB
// Tlacitka zapojena na PD0-PD5
#define DDR_TL DDRD
#define PORT_TL PORTD
#define PIN_TL PIND
#define TL1 PD0
#define TL2 PD1
#define TL3 PD2
#define TL4 PD3
#define TL5 PD4
#define TL6 PD5
// Znaky na tlacitkach
#define ZN1 ‘1’
#define ZN2 ‘2’
#define ZN3 ‘3’
#define ZN4 ‘4’
#define ZN5 ‘5’
#define ZN6 ‘6’
#define MASKA_TL ( _BV(TL1) | _BV(TL2) | _BV(TL3) | _BV(TL4) | _BV(TL5) | _BV(TL6) )
vim, ze jsou tam k dyspozici i komentare, ale z uvedenych komentaru jsem funkci zcela uplne nepochopil:-(.
jeste jsem se chtel opitat jestli nahodou nekdo nevi o nejake strance, kde je programovani s AVR (nejlepe v programu WinAVR) prehledne pro lajky popsano?