Toon posts:

ATmega32 beginners probleem

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik ben begonnen met het programmeren van een microcontroller. Ik heb nog niet eerder in c geprogrammeerd, wel in andere (hogere) programmeertalen.

De chip die ik dus gebruik is een ATmega32
als programmer de AVR Dragon

Testen doe ik door te simuleren met AVR studio in combinatie met hapsim

Ik heb het volgende (heel simpele) programma geschreven
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <avr/io.h>
#include <util/delay.h>


int main()
{

while (1)
  {   
    PORTA |= (1 << PA0);
    PORTA &= ~(1 <<PA1);
    
    _delay_ms(50);

    PORTA &= ~(1 <<PA0);
    PORTA |= (1 << PA1);

    _delay_ms(50);

  }
  return 0;
}


Met testen laat hapsim mooi zien dat poort 1 en 2 om de beurt hoog worden.
Maar als ik dit run op de ATmega32 gebeurt er niks.

Ik heb een ander programma (waarvan ik de code zelf nog niet echt begrijp) geprobeerd en dan komt er wel spanning op poort 1 en 2 te staan. Dus het compilen en runnen op de ATmega32 lukt wel.

Wat zie ik over het hoofd?

Acties:
  • 0 Henk 'm!

  • TheGrandWazoo
  • Registratie: Januari 2009
  • Laatst online: 09:33
Hoe meet je de spanning op poort 1 en poort 2? Met een scope? Multimeter? Of ga je er vanuit dat de waardes die in het programma te zien zijn, dat die realtime bijgewerkt worden?
Het laatste geval: dat gaat niet werken. AVR Studio werkt alle registers pas bij als je de executie van het programma op pauze zet. Dan kun je de register pas analyseren. Dit itt simuleren.

Acties:
  • 0 Henk 'm!

  • Carstijn
  • Registratie: Januari 2002
  • Laatst online: 03:27
In het DDRA (data direction) register moet je nog even deze pinnentjes als output zetten (op een 1 dus)
DDRA |= (1 << PA0)|(1 << PA1);

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Hapsim is een programma om te laten zien wat de code in AVR studio doet als die runt en laat het real time zien.

En ik heb via mijn stage bedrijf een printje gekregen waarop de ATmega32 zit. Op dit printje zitten alle poorten duidelijk aangegeven.

Ik heb op bit 1 en 2 van poort a 2 optocouplers aangesloten die schakelen bij 5 volt.

Acties:
  • 0 Henk 'm!

  • TheGrandWazoo
  • Registratie: Januari 2009
  • Laatst online: 09:33
Carstijn schreef op maandag 16 maart 2009 @ 09:41:
In het DDRA (data direction) register moet je nog even deze pinnentjes als output zetten (op een 1 dus)
DDRA |= (1 << PA0)|(1 << PA1);
Het verbaasd mij dat de simulatie wel werkt trouwens. Maar goed, helemaal overheen gelezen. Dat helpt inderdaad ook :P.

Acties:
  • 0 Henk 'm!

  • TheGrandWazoo
  • Registratie: Januari 2009
  • Laatst online: 09:33
Verwijderd schreef op maandag 16 maart 2009 @ 09:44:
Hapsim is een programma om te laten zien wat de code in AVR studio doet als die runt en laat het real time zien.

En ik heb via mijn stage bedrijf een printje gekregen waarop de ATmega32 zit. Op dit printje zitten alle poorten duidelijk aangegeven.

Ik heb op bit 1 en 2 van poort a 2 optocouplers aangesloten die schakelen bij 5 volt.
Hapsim is een simulator. Die heeft niets te zoeken als jij bezig bent op hardware :).

Acties:
  • 0 Henk 'm!

  • Cassettebandje
  • Registratie: Juli 2002
  • Laatst online: 08:38

Cassettebandje

SA-C90 TDK

Wat Carstijn zegt + dat 50ms wel wat kort is. Verder zegt de gcc-avr manual (ik neem maar even aan dat je gcc gebruikt): "The maximal possible delay is 262.14 ms / F_CPU in MHz".

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Carstijn schreef op maandag 16 maart 2009 @ 09:41:
In het DDRA (data direction) register moet je nog even deze pinnentjes als output zetten (op een 1 dus)
DDRA |= (1 << PA0)|(1 << PA1);
Nu werkt het inderdaad
TheGrandWazoo schreef op maandag 16 maart 2009 @ 09:49:
[...]

Het verbaasd mij dat de simulatie wel werkt trouwens. Maar goed, helemaal overheen gelezen. Dat helpt inderdaad ook :P.
Ik vind het ook wel vervelend dat de simulatie wel werkt want nu had ik geen idee waarom de simulatie wel werkt en het op de microcontroller niet werkt.
Cassettebandje schreef op maandag 16 maart 2009 @ 09:50:
Wat Carstijn zegt + dat 50ms wel wat kort is. Verder zegt de gcc-avr manual (ik neem maar even aan dat je gcc gebruikt): "The maximal possible delay is 262.14 ms / F_CPU in MHz".
Dat is inderdaad wat kort, want met die optocouplers worden relais geschakeld en het klonk hier net ineens alsof er 10 man op een typemachine liepen te rammen 8)7

Maar als ik iets voor langere tijd moet schakelen kan ik dus beter op zoek naar een andere functie?

[ Voor 29% gewijzigd door Verwijderd op 16-03-2009 09:58 ]


Acties:
  • 0 Henk 'm!

  • Sphere-
  • Registratie: November 2003
  • Laatst online: 28-08 19:53
Ik vind het ook wel vervelend dat de simulatie wel werkt want nu had ik geen idee waarom de simulatie wel werkt en het op de microcontroller niet werkt.
PORTX kan in de simulatie wel een bepaalde waarde hebben maar de IO pinnen zouden allemaal laag moeten zijn. Geeft de simulatie software echt de status van de pinnen aan of het PORTX register?
Maar als ik iets voor langere tijd moet schakelen kan ik dus beter op zoek naar een andere functie?
Je kan meerdere delays achter elkaar uitvoeren (in een loopje bijvoorbeeld). Of gebruik maken van een hardware timer.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Sphere- schreef op maandag 16 maart 2009 @ 10:36:
[...]
PORTX kan in de simulatie wel een bepaalde waarde hebben maar de IO pinnen zouden allemaal laag moeten zijn. Geeft de simulatie software echt de status van de pinnen aan of het PORTX register?
in hapsim kun je een aantal controls invoeren (zo heet dat in hapsim) waaronder ook 7 ledjes die dan via de instellingen aan een bepaalde pin op een poort verbonden worden. Dus als dan een led op port a 1 zit aangesloten gaat die branden als in mijn programma poort a 1 op hoog wordt gezet
[...]
Je kan meerdere delays achter elkaar uitvoeren (in een loopje bijvoorbeeld). Of gebruik maken van een hardware timer.
ik heb nu voor te testen gewoon een aantal delays achter elkaar gezet, verder zal ik over timers meer op moeten gaan zoeken.

Maar het werkt nu in ieder geval allemaal bedankt 8)

Acties:
  • 0 Henk 'm!

Verwijderd

Cassettebandje schreef op maandag 16 maart 2009 @ 09:50:
Verder zegt de gcc-avr manual (ik neem maar even aan dat je gcc gebruikt): "The maximal possible delay is 262.14 ms / F_CPU in MHz".
Maar ook:
When the user request delay which exceed the maximum possible one, _delay_ms() provides a decreased resolution functionality. In this mode _delay_ms() will work with a resolution of 1/10 ms, providing delays up to 6.5535 seconds (independent from CPU frequency). The user will not be informed about decreased resolution.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik ben ondertussen weer iets verder maar wat ik me ook afvraag is of je de waarde van een variabele ook kan gebruiken als nummer van een pin

bijvoorbeeld:
code:
1
2
3
4
5
for(i=0;0<4;i++);
    {
      PORTA |= (1 << PA *hier moet de waarde van i komen te staan* );
      _delay_ms(5000);
}

(ik weet niet of de code helemaal klopt ik ben nog niet zo lang bezig met c en heb dit nu ff als voorbeeld getypt maar daar gaat het mij niet om)

Ik heb wel iets gevonden voor tekst te laten zien:
code:
1
printf( "hallo, %s", variabele naam);


Kan ik op die manier ook iets neerzetten om te gebruiken bij onderstaand voorbeeldje in plaats van de 0?
code:
1
PORTA |= (1 << PA0);

Acties:
  • 0 Henk 'm!

  • Thralas
  • Registratie: December 2002
  • Laatst online: 10:06
Verwijderd schreef op maandag 16 maart 2009 @ 16:20:
Ik ben ondertussen weer iets verder maar wat ik me ook afvraag is of je de waarde van een variabele ook kan gebruiken als nummer van een pin

bijvoorbeeld:
code:
1
2
3
4
5
for(i=0;0<4;i++);
    {
      PORTA |= (1 << PA *hier moet de waarde van i komen te staan* );
      _delay_ms(5000);
}

(ik weet niet of de code helemaal klopt ik ben nog niet zo lang bezig met c en heb dit nu ff als voorbeeld getypt maar daar gaat het mij niet om)
Ja dat kan, vziw is bijvoorbeeld PAn gewoon defined als n. PA0 is 0, PA4 is 4, enz. (geen idee hoeveel pins de mega32 heeft op port A). Wat je eventueel nog kunt doen is

code:
1
PORTA |= (1 << (PA0 + i));


Dan specifceer je eigenlijk een offset tov. PA0, iets netter imo.
Ik heb wel iets gevonden voor tekst te laten zien:
code:
1
printf( "hallo, %s", variabele naam);


Kan ik op die manier ook iets neerzetten om te gebruiken bij onderstaand voorbeeldje in plaats van de 0?
code:
1
PORTA |= (1 << PA0);
Nee.

Acties:
  • 0 Henk 'm!

  • Cassettebandje
  • Registratie: Juli 2002
  • Laatst online: 08:38

Cassettebandje

SA-C90 TDK

Hee, dat wist ik nog niet!

Verder:
code:
1
2
3
4
5
for(i=0;0<4;i++);
    {
      PORTA |= (1 << i);
      _delay_ms(5000);
}

Werkt ook. << is een bitshift operatie. Je shift het getal i posities naar links. Vervolgens doe je een bitwise OR met de huidge waarde van PORTA. Als je ledjes zou aansluiten zou je elke 5 seconden er een ledje bijkrijgen wat aan staat.
Let op dat je als dit wilt herhalen je even een PORTA=0; doet voor je opnieuw begint, ander zie je geen verschil omdat de bitjes al op 1 staan.

Acties:
  • 0 Henk 'm!

  • Juicy
  • Registratie: December 2000
  • Laatst online: 06:48
Kijk ook eens naar sbi, bijvoorbeeld sbi(PORTA, i). De tegenhanger van sbi (set bit) is cbi (clear bit).

-


Acties:
  • 0 Henk 'm!

  • Wirf
  • Registratie: April 2000
  • Laatst online: 11:19
Of je kunt gewoon een hele nibble (=4 bits) in 1 keer versturen naar portA

Iets van:
i = de_te_versturen_byte;
a = i & (0b11110000);
a = a >> 4;

PORTA &= 0b11110000; //bitjes eerst op 0 zetten
PORTA |= a; //eerste 4 bits op porta zetten

a = i & (0b00001111);
//Hier geen bitshift nodig

PORTA &= 0b11110000; //bitjes eerst op 0 zetten
PORTA |= a; //laatste 4 bits op porta zetten

Waarschijnlijk is dit iets sneller dan elk bitje individueel versturen.

Heeft sinds kort zijn wachtwoord weer terug gevonden!


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Wirf schreef op dinsdag 17 maart 2009 @ 16:41:
Of je kunt gewoon een hele nibble (=4 bits) in 1 keer versturen naar portA

Iets van:
i = de_te_versturen_byte;
a = i & (0b11110000);
a = a >> 4;

PORTA &= 0b11110000; //bitjes eerst op 0 zetten
PORTA |= a; //eerste 4 bits op porta zetten

a = i & (0b00001111);
//Hier geen bitshift nodig

PORTA &= 0b11110000; //bitjes eerst op 0 zetten
PORTA |= a; //laatste 4 bits op porta zetten

Waarschijnlijk is dit iets sneller dan elk bitje individueel versturen.
Ik kan hiervan vrij weinig volgen. :X
Als je er 4 tegelijk aanstuurt dan is het idee van ze om de beurt schakelen toch helemaal weg?

Acties:
  • 0 Henk 'm!

  • Wirf
  • Registratie: April 2000
  • Laatst online: 11:19
Verwijderd schreef op dinsdag 17 maart 2009 @ 16:47:
[...]


Ik kan hiervan vrij weinig volgen. :X
Als je er 4 tegelijk aanstuurt dan is het idee van ze om de beurt schakelen toch helemaal weg?
Het zijn 4 verschillende pinnen die je wil aansturen toch?
Waarom zou je ze dan allemaal om de beurt aan willen sturen?

Als ze je echt daadwerkelijk een voor een van waarde wil veranderen, dan werkt mijn methode niet.. Maar als je bijvoorbeeld een LCDtje aan wil sturen door er 4 bits per keer naar toe te sturen, dan kun je met mijn methode iets sneller data versturen.

Heeft sinds kort zijn wachtwoord weer terug gevonden!


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Wirf schreef op woensdag 18 maart 2009 @ 15:46:
[...]

Het zijn 4 verschillende pinnen die je wil aansturen toch?
Waarom zou je ze dan allemaal om de beurt aan willen sturen?

Als ze je echt daadwerkelijk een voor een van waarde wil veranderen, dan werkt mijn methode niet.. Maar als je bijvoorbeeld een LCDtje aan wil sturen door er 4 bits per keer naar toe te sturen, dan kun je met mijn methode iets sneller data versturen.
Omdat per pin telkens iets anders geschakeld moet worden, en dat moet niet (allemaal) tegelijk gebeuren.


Nu ben ik al een heel stuk verder, maar blijf een beetje hangen met interrupts

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// A simple program to learn how to use interrupts


// CPU snelheid instellen
#define F_CPU 1000000UL // 1 MHz Internal Oscillator

#include <avr/interrupt.h>
#include <util/delay.h>

#define IsPinHigh(PORT, PIN) (((PORT>>PIN) & 0x01) == 0x01)

int i=0;

int main(void)
{
    PORTA=0;
  // A0 t/m A3 worden output
  DDRA |= (1<<PA0 | 1<<PA1 | 1<<PA2 | 1<<PA3);
  // D2 wordt input
  DDRD &= ~(1<<DDD2);


  // Instellen interrupt
  GICR  |= (1<<INT0);
  MCUCR |= (1<<ISC00);

  GIFR  |= (1<<INTF0);


  // Luisteren naar interrupts en timers
  sei();

    while (1)
    {
        if (!IsPinHigh(PINA,PA4) )      //aanknop wordt ingedrukt
            {
                PORTA |= (1<<PA0);      //vulventiel openen voor water inlaat
                for (i=0;i<=5;i++)
                    {
                    _delay_ms(5000);
                    }
                PORTA &= ~(1 << PA0);   //vulventiel sluiten
                PORTA |= (1 << PA1);    //verwarmingselement aanzetten
                PORTA |= (1 << PA2);    //circulatiepomp aanzetten
                for (i=0;i<=10;i++)
                    {
                    _delay_ms(5000);
                    }
                PORTA &= ~(1 << PA1);   //verwarmingselement uitzetten
                PORTA &= ~(1 << PA2);   //circulatiepomp uitzetten
                PORTA |= (1 << PA3);    //afvoerpomp aanzetten
                for (i=0;i<=5;i++)
                    {
                    _delay_ms(5000);
                    }
                PORTA &= ~(1 << PA3);   //afvoerpomp uitzetten
            }
    }
}


ISR(INT0_vect){
  PORTA=0;
}


De interrupt werkt in principe wel maar hoe zorg ik nu dat alles wacht zolang er het signaal op poort D2 hoog is.

Nu triggert de interrupt als het signaal van laag naar hoog gaat. als dan de delay klaar is gaat het programma gewoon weer verder.

Acties:
  • 0 Henk 'm!

  • Wirf
  • Registratie: April 2000
  • Laatst online: 11:19
edit:
Wacht... volgens mij heb ik niet helemaal begrepen wat je bedoelt... ik schrijf hieronder nog een nieuwe reply.

Deze laat ik even staan omdat het misschien wel handig is voor andere mensen..

------------------------

Dit is hoe ik zelf een pin-change interrupt heb gedaan op een tiny13:

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#define F_CPU 18750UL                       // Define software reference clock for delay duration (18.75Khz)
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>

volatile char sleep = 1;
volatile char belgedrukt = 0;
volatile unsigned char seconds = 0;

//ISR for Pin Change on Interrupt 0 (PCINT0)
ISR(PCINT0_vect) {
    if (belgedrukt == 0) {
        PORTB |= (1 << BEL); //BEL on
        PORTB |= (1 << LAMP); //LAMP on
        sleep = 0; //Enable clock (for the timer)
        seconds = 0;
        belgedrukt = 1;
    }
} 

main() {
    //Enable Global Pin Change Interrupt:
    GIMSK = 0b00100000;

    //Enable Pin Change for PB2:
    PCMSK = 0b00000100;

    sei(); //Enable global interrupts

}


Voor de precieze namen en waarden van de registers moet je even in de datasheet van je microcontroller kijken.

[ Voor 11% gewijzigd door Wirf op 20-03-2009 15:54 ]

Heeft sinds kort zijn wachtwoord weer terug gevonden!


Acties:
  • 0 Henk 'm!

  • Wirf
  • Registratie: April 2000
  • Laatst online: 11:19
Verwijderd schreef op vrijdag 20 maart 2009 @ 12:36:

De interrupt werkt in principe wel maar hoe zorg ik nu dat alles wacht zolang er het signaal op poort D2 hoog is.

Nu triggert de interrupt als het signaal van laag naar hoog gaat. als dan de delay klaar is gaat het programma gewoon weer verder.
Hieronder staat 1 oplossing.
Deze maakt gebruik van busy-waiting, en is dus niet helemaal optimaal. In dit geval zal het nog niet zoveel uitmaken.

Wat je ook kunt doen is in de interrupt handler zelf de code zetten die je wil laten uitvoeren op het moment dat de interrupt gebeurd.

C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// A simple program to learn how to use interrupts


// CPU snelheid instellen
#define F_CPU 1000000UL // 1 MHz Internal Oscillator

#include <avr/interrupt.h>
#include <util/delay.h>

#define IsPinHigh(PORT, PIN) (((PORT>>PIN) & 0x01) == 0x01)

int i=0;
viotile uint_8 is_D2_hoog;

int main(void)
{

is_D2_hoog = 0;
    PORTA=0;
  // A0 t/m A3 worden output
  DDRA |= (1<<PA0 | 1<<PA1 | 1<<PA2 | 1<<PA3);
  // D2 wordt input
  DDRD &= ~(1<<DDD2);


  // Instellen interrupt
  GICR  |= (1<<INT0);
  MCUCR |= (1<<ISC00);

  GIFR  |= (1<<INTF0);


  // Luisteren naar interrupts en timers
  sei();

    while (1)
    {
        if (!IsPinHigh(PINA,PA4) )      //aanknop wordt ingedrukt
            {
                PORTA |= (1<<PA0);      //vulventiel openen voor water inlaat
while (is_D2_hoog == 0) {
//Wacht totdat D2 hoog wordt
                    _delay_ms(100);
                    }
is_D2_hoog = 0; //Reset variabele
                PORTA &= ~(1 << PA0);   //vulventiel sluiten
                PORTA |= (1 << PA1);    //verwarmingselement aanzetten
                PORTA |= (1 << PA2);    //circulatiepomp aanzetten
/* Verder zelf invullen */
            }
    }
}


ISR(INT0_vect){
is_D2_hoog = 1;

} 

[ Voor 13% gewijzigd door Wirf op 20-03-2009 16:01 ]

Heeft sinds kort zijn wachtwoord weer terug gevonden!


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik snap de werking niet van:
code:
1
viotile uint_8 is_D2_hoog;


Is dit niet gewoon een variabele waarin je aangeeft of de poort hoog is of niet, want bij deze schrijfwijze krijg ik errors bij het compilen. En als ik het verander naar een andere variabele werkt het programma niet goed

Acties:
  • 0 Henk 'm!

  • mux
  • Registratie: Januari 2007
  • Laatst online: 16-10 12:57

mux

99% efficient!

een volatile (wtf, wat een gigantische tikfout daar?) variable is niets anders dan een normale variabele die je expliciet niet door de compiler wil laten optimaliseren. uint_8 is een tikfout en zou uint8 moeten zijn, dat is een unsigned 8-bit integer, oftewel een getal van 0 tot 255 inclusief.

uint8 is in de wereld van GCC trouwens exact een char.

[ Voor 8% gewijzigd door mux op 20-03-2009 16:37 ]


Acties:
  • 0 Henk 'm!

  • Wirf
  • Registratie: April 2000
  • Laatst online: 11:19
uuhh.. ja, ik heb zo te zien even wat te snel gereageerd en inderdaad een paar tikfoutjes gemaakt :$

het moet dus:
C:
1
volatile uint8_t is_D2_hoog;

zijn.

En ja, een uint8_t is net zo lang als een char. Namelijk allebei 8 bits. Alleen kan de lengte van char verschillen per platform terwijl een uint8_t altijd, op elk platform, 8 bits is.

volatile heb je nodig voor variabelen die je en in een interrupts handler gebruikt en op andere plaatsen. Inderdaad om de compiler te vertellen dat die geen optimalisatie doet die de werking kan beïnvloeden.

Heeft sinds kort zijn wachtwoord weer terug gevonden!


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Oke stuk duidelijk alweer allemaal!

Maar volgens mij doet jou code niet helemaal wat ik bedoel.

Als ik die code test dan word eerst poort 0 hoog, totdat er een signaal op de interrupt komt dan wordt poort 0 laag en 1 en 2 hoog.

Wat ook best logisch is, want hij gaat de delay uitvoeren zolang de interrupt niet getriggerd is. Op het moment dat de interrupt getriggerd wordt gaat het pas door.

Wat ik eigenlijk bedoelde was dat zolang de interrupt getriggerd is dat het programma "wacht" met uitvoeren van dingen.

Heel simpel voorbeeld: als je de deur van een afwasmachine opent stopt alles tot je hem weer dicht doet.

[ Voor 15% gewijzigd door Verwijderd op 23-03-2009 10:33 ]


Acties:
  • 0 Henk 'm!

  • Wirf
  • Registratie: April 2000
  • Laatst online: 11:19
Verwijderd schreef op maandag 23 maart 2009 @ 10:26:
Oke stuk duidelijk alweer allemaal!

Maar volgens mij doet jou code niet helemaal wat ik bedoel.
Wat wil je dan eigenlijk precies?
Kun je vertellen wat er op elke poort is aangesloten, wat er moet gebeuren op welk moment?

Verder kan je ook het stuk:
C:
1
2
3
4
while (is_D2_hoog == 0) {
      //Wacht totdat D2 hoog wordt
      _delay_ms(100);
} 

Verplaatsen of kopiëren naar alle plaatsen waar je wil dat je programma wacht.

Heeft sinds kort zijn wachtwoord weer terug gevonden!


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Zoals jij het uitlegt wacht het programma TOT de interrupt uitgevoerd wordt.

Wat ik wil is dat het programma wacht ALS de interrupt uitgevoerd wordt.

Poort PA0, PA1, PA2 en PA3 zijn outputs.
Poort PA4 en PD2 zijn inputs, PD2 is voor de interrupt.

Als op poort PA4 een hoog signaal komt worden om de beurt, alle outputs voor een bepaalde tijd hoog.

Wat ik aan het proberen ben is om met de interrupt dat om de beurt hoog houden te laten wachten. Op poort PD2 zit gewoon een schakelaar. En telkens als die schakelaar ingedrukt wordt moet het programma wachten. Totdat de schakelaar weer losgelaten wordt.

Net zoals de deur van een afwasmachine die opengaat, alles wordt gestopt tot de deur weer dichtgaat. Dan gaat het programma precies verder waar het gebleven is.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Niemand?

Ondertussen ben ik ADC aan het uitzoeken, maar is toch allemaal wel best ingewikkeld als je het nog nooit gedaan hebt :/

Heeft er iemand misschien voorbeeldjes in c voor het gebruiken van de ACD maar dan de mogelijkheid die er is om tot een bepaalde waarde zo uit lezen? ( ik geloof tot 2.65 v hoeft er op een bepaalde manier niet vergeleken te worden met AREF? )

Acties:
  • 0 Henk 'm!

  • jerbro
  • Registratie: September 2001
  • Niet online
Verwijderd schreef op dinsdag 24 maart 2009 @ 09:16:
Wat ik aan het proberen ben is om met de interrupt dat om de beurt hoog houden te laten wachten. Op poort PD2 zit gewoon een schakelaar. En telkens als die schakelaar ingedrukt wordt moet het programma wachten. Totdat de schakelaar weer losgelaten wordt.
Wat je zou kunnen doen is gewoon in de interrupt handler een while lus zetten die wacht tot je de knop loslaat. Er gebeurt dan niets tot je de knop loslaat.
( ik geloof tot 2.65 v hoeft er op een bepaalde manier niet vergeleken te worden met AREF? )
In tabel 83(pagina 214) van de datasheet staat hoe je kan kiezen welke referentiewaarde je gebruikt.

REFS1 REFS0 Voltage Reference Selection
0 0AREF, Internal Vref turned off
0 1 AVCC with external capacitor at AREF pin
1 0 Reserved
1 1 Internal 2.56V Voltage Reference with external capacitor at AREF pin

Met behulp van REFS1, en REFS0 kan je dus inderdaad kiezen om de interne 2.56V als referentie te gebruiken.
Ook kun je AVCC gebruiken als referentie, of de Aref.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
jerbro schreef op woensdag 25 maart 2009 @ 14:38:
[...]
Wat je zou kunnen doen is gewoon in de interrupt handler een while lus zetten die wacht tot je de knop loslaat. Er gebeurt dan niets tot je de knop loslaat.
Maar dan moet er toch eigenlijk ook een interrupt komen die aangeeft wanneer de knop weer losgelaten wordt, want anders krijg je gewoon een while loop waar het programma in blijft draaien omdat het niet weet wanneer de knop weer losgelaten wordt?
[...]
In tabel 83(pagina 214) van de datasheet staat hoe je kan kiezen welke referentiewaarde je gebruikt.

REFS1 REFS0 Voltage Reference Selection
0 0AREF, Internal Vref turned off
0 1 AVCC with external capacitor at AREF pin
1 0 Reserved
1 1 Internal 2.56V Voltage Reference with external capacitor at AREF pin

Met behulp van REFS1, en REFS0 kan je dus inderdaad kiezen om de interne 2.56V als referentie te gebruiken.
Ook kun je AVCC gebruiken als referentie, of de Aref.
Danke hier ga ik meteen naar kijken

Acties:
  • 0 Henk 'm!

  • jerbro
  • Registratie: September 2001
  • Niet online
Verwijderd schreef op woensdag 25 maart 2009 @ 14:46:
Maar dan moet er toch eigenlijk ook een interrupt komen die aangeeft wanneer de knop weer losgelaten wordt, want anders krijg je gewoon een while loop waar het programma in blijft draaien omdat het niet weet wanneer de knop weer losgelaten wordt?
Als je in de interruptroutine zit te wachten, en het programma verder toch niets te doen heeft kun je ook gewoon elke keer kijken naar de huidige toestand van de pin. Gewoon elke keer PIND2 inlezen, en indien de knop niet meer ingedrukt is de while lus beeindigen.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ja ik had dat zojuist zelf ook bedacht :P . Ik heb veel te lang naar bepaalde dingen zitten kijken dat ik hier nog niet meer aan dacht!


Nu heb ik het met de intterupts zo gedaan:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// CPU snelheid instellen
#define F_CPU 1000000UL // 1 MHz Internal Oscillator

#include <avr/interrupt.h>
#include <util/delay.h>

#define IsPinHigh(PORT, PIN) (((PORT>>PIN) & 0x01) == 0x01)

int i=0;
volatile uint8_t is_D2_hoog=0;

int main(void)
{
  PORTA=0;
  // A0 t/m A3 worden output
  DDRA |= (1<<PA0 | 1<<PA1 | 1<<PA2 | 1<<PA3);
  // D2 wordt input
  DDRD &= ~(1<<DDD2);


  // Instellen interrupt
  GICR  |= (1<<INT0);

  MCUCR |= ~(1<<ISC01);
  MCUCR |= (1<<ISC00);

  GIFR  |= (1<<INTF0);


  // Luisteren naar interrupts en timers
    sei();

      while (1)
    {
        if (!IsPinHigh(PINA,PA4) )          //aanknop wordt ingedrukt
            {
                for (i=0; i<2000; i++)
                {
                    PORTA |= (1<<PA0);          //vulventiel openen voor water inlaat
                    _delay_ms(50);
                }
                
                PORTA &= ~(1 << PA0);       //vulventiel sluiten
                for (i=0; i<4000; i++)
                {
                    PORTA |= (1 << PA1);        //verwarmingselement aanzetten
                    PORTA |= (1 << PA2);        //circulatiepomp aanzetten
                    _delay_ms(50);
                }

                PORTA &= ~(1 << PA1);
                PORTA &= ~(1 << PA2);
                for (i=0; i<2000; i++)
                {
                    PORTA |= (1 << PA3);        //afvoerpomp aanzetten
                    _delay_ms(50);
                }
                PORTA &= ~(1 << PA3);
            }
    }
} 

ISR(INT0_vect){
PORTA =0;
while (IsPinHigh(PIND,PD2))                 //zolang de deur open is wacht het programma
    {
        _delay_ms(50);
    }
}


Ik geloof best dat er veel mooiere betere manieren voor zijn maar ik ben een weekje bezig met programmeren van microcontrollers (en het programmeren van C eigenlijk ook) dus ben best tevreden.

Als iemand nog voorbeeldjes heeft voor ADC gebruik in C graag!

[ Voor 109% gewijzigd door Verwijderd op 25-03-2009 16:52 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
jerbro schreef op woensdag 25 maart 2009 @ 14:38:

REFS1 REFS0 Voltage Reference Selection
0 0AREF, Internal Vref turned off
0 1 AVCC with external capacitor at AREF pin
1 0 Reserved
1 1 Internal 2.56V Voltage Reference with external capacitor at AREF pin

Met behulp van REFS1, en REFS0 kan je dus inderdaad kiezen om de interne 2.56V als referentie te gebruiken.
Ook kun je AVCC gebruiken als referentie, of de Aref.
Ik snap het Internal 2.56V Voltage Reference with external capacitor at AREF pin niet helemaal?
Kan je het niet gewoon vergelijken met de interne 2.56 V zonder de AREF aan te sluiten?

Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op donderdag 26 maart 2009 @ 10:56:
[...]


Ik snap het Internal 2.56V Voltage Reference with external capacitor at AREF pin niet helemaal?
Kan je het niet gewoon vergelijken met de interne 2.56 V zonder de AREF aan te sluiten?
Het kan wel, maar is niet aan te raden. Die condensator is om de referentiespanning strak te houden. Waarom zou je die dan niet aansluiten?

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Omdat de ATmega al op een printje zit en ze bij het bedrijf waar die print van is de AREF aansluiten nooit gebruiken, dus daar is op de print niks mee gedaan.

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Even een kickje

Ik ben ondertussen weer met een ander projectje bezig, ik wil een dimmer maken met een triac. Ik gebruik nog steeds de ATmega32 en AVR studio 4 met de AVR Dragon.

Met nuldetectie van de wisselspanning van het lichtnet kan ik de triac als het goed is pas op de helft van een golfbeweging aanzetten waardoor de lamp op de helft van het vermogen zou moeten werken.
Ik hoop dat iedereen snap wat ik bedoel (en dat het klopt wat ik zeg).

Nou wilde ik om te testen gewoon een blokgolf maken met een frequentie van 50 hz. Dit zou betekenen 10 ms hoog 10 ms laag.

Als ik verder ga rekenen met wat springuin hier zegt:
Cassettebandje schreef op maandag 16 maart 2009 @ 09:50:
Wat Carstijn zegt + dat 50ms wel wat kort is. Verder zegt de gcc-avr manual (ik neem maar even aan dat je gcc gebruikt): "The maximal possible delay is 262.14 ms / F_CPU in MHz".
Dan zou een _delay_ms(10), bij een kloksnelheid van 1 Mhz gewoon 10ms moeten zijn toch?
Ik heb in AVR studio bij de connect dialog de kloksnelheid ingesteld op 1 Mhz en bij Project > Configuration Options de snelheid op 1000000 hz.

Mijn code:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <avr/io.h>
#include <util/delay.h>


int main()
{
DDRA |= (1<<PA0);

    while (1)
    {
        PORTA |= (1<<PA0);
        _delay_ms(200);
        PORTA &= ~(1<<PA0);
        _delay_ms(200);
    }
}


Als ik ga kijken met een oscilloscoop dan kom ik uit op 138,9 Hz? De tijd dat het signaal hoog is is maar +/- 3 ms?

Moet ik nog ergens de snelheid van de klok invullen of heb ik verkeerd begrepen van springuin zei?

Acties:
  • 0 Henk 'm!

  • Sphere-
  • Registratie: November 2003
  • Laatst online: 28-08 19:53
Dat zou inderdaad moeten werken, echter heb ik zelf ook problemen met de nauwkeurigheid van die busy loop delay routines. Je kan beter een hardware timer gebruiken.

Acties:
  • 0 Henk 'm!

  • Wirf
  • Registratie: April 2000
  • Laatst online: 11:19
Verwijderd schreef op vrijdag 05 juni 2009 @ 11:42:
Moet ik nog ergens de snelheid van de klok invullen of heb ik verkeerd begrepen van springuin zei?
ik weet niet helemaal wat in AVRstudio de instellingen precies doen, maar wat ik altijd doe is:
code:
1
#define F_CPU 1000000UL                   // Define software reference clock for delay duration (1.0Mhz)

boven de #include's zetten. Dit zorgt er bij mij altijd voor dat de sleep()'s wel goed gaan.

Heeft sinds kort zijn wachtwoord weer terug gevonden!

Pagina: 1