Mikrokontroller- Teszt

Kaptam néhány levelet, főleg középiskolás diákoktól melyben a feladat technikai megvalósításához kértek tanácsot. Mivel már az alapoknál elakadtunk, úgy gondoltam talán érdemes lesz egy egyszerű példán keresztül bemutatni majdnem minden mai elektronikai kütyü lelkét a mikrokontrollert. Hatékonyságát annak köszönheti, hogy egyetlen tokban megtalálhatunk sok-sok különböző fajta perifériát.
A tesztnek kiválasztott leküzdendő feladat: villogtassunk egy LED-et. A villogás frekvenciáját szabályozzuk egy potméterrel, egy nyomógomb segítségével tudjuk ki-be kapcsolni a villogást. A kiválasztott két mikrokontroller a két nagy rivális cég egy-egy terméke. A végére tartogattam a jó hírt, mindezt C nyelven.


ATMEL ATMEGA16
Olcsó és könnyen elkészíthető programozó és szofver a párhuzamos portra: PonyProg+STK200

Szeretném felhívni a figyelmet, ha valaki a gyárilag alapban beállított belső órajelet szeretné átállítani (FUSES bitek) pl. külső kavicsosra a (configuration and security bits menüben) a pipa 0-t, az üres jelölőnégyzet 1-t jelent. Roszzul konfigurált procit csak párhuzamos programozóval lehet feléleszteni (van néhány kivétel).

Atmel fejlesztőrendszer: AVRSTUDIO
C fordító: WinAvr

A program direkt úgy lett megírva, hogy csak megszakítást használ mindhárom periféria kezelésére. (analóg-digitál átalakító a potméterhez, külső megszakítás(int0) a nyomógombhoz, belső időzítő a villogtatáshoz).

#include <avr\io.h>
#include <avr\delay.h>
#include <avr\interrupt.h>

//LED ki-be kapcsolásának definiálása
#define LED_ON PORTB |= _BV(PB0);
#define LED_OFF PORTB &= ~(_BV(PB0));
int unsigned i=0; // általános számláló


ISR (INT0_vect)
{
if (bit_is_set(TIMSK,OCIE0)) //ha timer0 megszakítás engedélyezve
{TIMSK &=~(_BV(OCIE0));
LED_OFF}
else
TIMSK |=_BV(OCIE0);
}

ISR (ADC_vect)
{
OCR0=ADCW/ 4; //csak 8 bit kell
};

ISR (TIMER0_COMP_vect)
{
if (bit_is_set(PINB,0))
LED_OFF
else
LED_ON;
}

static void delay_1s(void)
{
uint8_t ii;
for (ii = 0; ii < 100; ii++)
_delay_ms(10);
}

//innen indul a program
int main(void)
{
DDRB=0B00001001; //a PORTB kimenet ha a bit=1, bemenet ha a bit=0
PORTB=0B00000000; //a PORTB beállítása
PORTD=(1<<PD2); //INT0 felhúzó ellenállásának bekapcsolása

//int0 beállítása
MCUCR=0B00000010; //lefutó él generál int0-nál megszakítást
GICR= (1<<INT0); //int0 megszakítás engedélyezve

//TIMER0 beállítása
TCNT0=0; //timer0 számlálója
OCR0=255; //komparátor regiszter
TCCR0=0B00001101; //CTC mód, 1:32 óra
TIMSK|=(1<<OCIE0); //OCR0=TCNT0 és lészen megszakítás

//AD beállítása
ADMUX=0B01000000; //0-ás bemenet
ADCSRA=0B10101111; //ADC mehet,auto mód,megszakítás engedélyezve, előosztó 1:128

//villogunk úgy hármat
for (i=1;i<4;i++)
{
LED_ON;
delay_1s();
LED_OFF;
delay_1s();
}

ADCSRA = ADCSRA | (1<<ADSC); //AD indul ADSC=1
sei(); //globális megszakítás indul

while(1)
{
//végtelen ciklus
}
}

Kapcsolási rajz:


Microchip PIC18F1320

Hasonlóan jól eltalált mikrokontroller család rengeteg extrával és ingyenes C fordítóval.

Fejlesztőrendszer: MPLAB
C18 fordító 60 napig teljes, de utána is használható: C18
Személy szerint a PicKit2 gyári programozót használom, beszerzése: ChipCad

A kezdésnél ki kell tölteni a MPLAB-ban a Project-Build Options-Project ablakban a megfelelő könyvtár útvonalakat.

A program:

//led villogó
#include <p18f1320.h>

#define SW1 PORTBbits.RB0 //SW1 nyomógomb a RB0-n
#define LED PORTAbits.RA0 //led az RA0-n

//konfigurációs bitek leírás a 'MCC18\doc\PIC18-Config-Settings-Addendum_51537f.pdf'
#pragma config WDT = OFF
#pragma config OSC = INTIO2
#pragma config FSCM = OFF
#pragma config IESO = OFF
#pragma config PWRT = ON
#pragma config BOR = ON
#pragma config BORV = 42
#pragma config MCLRE = OFF
#pragma config STVR = ON
#pragma config LVP = OFF
#pragma config DEBUG = OFF

int unsigned i = 0;
int unsigned j = 0;
int unsigned idozito0 = 0;

void high_isr(void);

//magas szintű megszakítás fogadása
#pragma code high_vector = 0x08
void high_vector (void)
{_asm GOTO high_isr _endasm}
#pragma code

//késleltető rutin
void delay (void)
{
for (j = 0;j < 3000;j++);
}

//magas szintű megszakítás szubrutin
#pragma code
#pragma interrupt high_isr
void high_isr()
{
if (INTCONbits.TMR0IF==1) //timer0 váltotta ki a megszakítást
{
LED=!LED; //led állapotának negálása
TMR0L=idozito0; //'frekvencia' beírása
INTCONbits.TMR0IF=0; //a flag-et törölni kell!
}
if (INTCONbits.INT0IF==1) //int0 váltotta ki a megszakítást
{
LED=0;
T0CONbits.TMR0ON=!T0CONbits.TMR0ON; //timer0 engedélyező bitjének negálása
INTCONbits.INT0IF=0; //szoftveresen kell törölni a megszakítás flag-et
}
if (PIR1bits.ADIF==1) //ad váltotta ki a megszakítást
{
idozito0=(ADRESH); //a 10 bitből a felső nyolc kiolvasása
PIR1bits.ADIF=0; //törölni kell a flaget
}
}

//innen indul a buli
void main (void)
{
OSCCON=0B01000000; //belső órajel=1MHz

// RB1/AN5 (9 pin) kivételével minden láb digitális
ADCON1 = 0B01011111;

// portok irányának és állapotának beállítása
TRISA = 0x11111110; //PORTA minden bitje bemenet, kivéve RA0-t (ott a led)
PORTAbits.RA0 = 0; //led kikapcsolva

TRISB=255; //portb minden bitje bemenet
PORTBbits.RB0 = 1; //int0 magasba

//felvillantjuk a ledet 3x, hogy egy ciklus is legyen
for (i=1;i<4;i++)
{
LED=1;
delay();
LED=0;
delay();
}

//int0,timer0 beállítása
//int0-ra kapcsolt nyomógomb engedélyezi vagy nem a led villogását
RCONbits.IPEN=1; //kétszintű megszakítás engedélyezve
INTCON=0B00110000; //INT0 TMR0 engedélyezve, flag-ek nullázva
INTCON2bits.INTEDG0=0; //int0 lefutó élre indul
INTCON2bits.TMR0IP=1; //TMR0 magas szintű megszakítás

//TIMER0 megszakítása kapcsolja ki-be a ledet
T0CON=0B11000110; //TIMER0 1:128 osztó, belső órajel, 8 bites
TMR0H=0;
TMR0L=0;

//AD konverter beállítása
//AD érték szabályozza a led villogásának frekvenciáját
ADCON0=0B00010101; //AN5 a bemenet,engedélyezve, ide jön a poti
ADCON2bits.ADFM=0; //a 10 bitből a felső nyolc a ADRESH-ban keletkezik = 8bites AD
CCP1CON=0B00001011; //ad konverter hardveres automatikus indítása
T3CONbits.T3CCP1=0; //ad konverter a timer1-et használja folyamatos lekérdezéshez
IPR1bits.ADIP=1; //AD megszakítás magas szintű
PIE1bits.ADIE=1; //AD megszakítás engedélyezése
CCPR1H=0; //TMR1H és TMR1L-el hasonlítja össze
CCPR1L=100; //ezzel a két regiszterrrel is állítható a ad konverzió gyakorisága
T1CON=0B10010001; //timer1 be, 16 bites, 1:2 osztó
INTCONbits.GIE=1; //megszakítások globális engedélyezése

//végtelen ciklus
while (1)
{
//homokóra (várni, hogy történjék valami pl. megszakítás
}
}

Kapcsolási rajz:

Sipos Attila