PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : GPIO-Register Ansprechen



kmrish
11.07.2011, 22:47
Jedes Port verfügt über Register.
wenn man den Register von beispielweise Port A ansprechen will (nämlich Lesen oder schreiben), dann muss man zunächst diesen Register identifizieren(Name und Ort).

Wie findet man solche "Identifikation"-Info zu jedem Register raus?
In Memory Map finde ich neben jedem Komponent Ziffern, sind diese Ziffern einfach den Ort für diese Komponente?
Zum Beispiel steht Neben PORTA sowas: PORTA 0x4001 0800.
was bedeutet genau das 0x4001 0800?
soweit ich weiß 0x4001 ist ein Hexadezimal und das entsprechend 16385 Dezimal. wenn das 0800 auch Hex. ist dann entspricht 2048. bedeutet das, dass der Port A über 14337 Einheiten von Speicherzellen verfügt?
Ist der PORTA der Name der Register?

Vielleicht klingen meine Frage doof aber ich muss sie stellen, um weiter damit kommen kann.
Ich danke jedem für Hilfe.

PicNick
12.07.2011, 07:51
Port-Register adressen findest du immer im Datenblatt (Datasheet)

Lies dich doch mal da rein:
http://www.rn-wissen.de/index.php/Atmel_Controller_Mega16_und_Mega32#General_Purpose _Register_.28GPR.29 (http://www.rn-wissen.de/index.php/Atmel_Controller_Mega16_und_Mega32#General_Purpose _Register_.28GPR.29)
http://www.rn-wissen.de/index.php/Atmel_Controller_Mega16_und_Mega32#Adressen_Mappin g

Damit du siehst, wie der Hase läuft, auch wenn du einen anderen Controller hast.

kmrish
12.07.2011, 08:05
Vielen Dank PicNick
ich werde deinen Tipp befolgen. aber ich melde mich wieder wenn ich was nicht verstanden.
ich will die sachen von Kern her verstehen.
Danke nochmals

kmrish
12.07.2011, 20:49
Hallo,

Ich habe die Links und andere auch gelesen, und habe ich das Thema bis 80 % verstanden.

Bei praktischer Umsetzung ergibt sich paar sachen, die ich nicht Verstehe und die mich durcheinander bringen.

Ich habe folgendes Code geschrieben:


#include "stm32f10x.h"
/*--------------------------------------------------------------------------*/

void delayLoop()
{
volatile uint32_t delayCount = 1000000;
while (delayCount > 0)
{
delayCount--;
}
}

void GPIO_Setup ()
{
GPIO_InitTypeDef GPIO_Inity; // Struktur um PortPins zu initialisieren, die Variable heisst: GPIO_Inity

// PortPin als Ausgang configurieren
GPIO_Inity.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; // mit Oder_Verknupfung (|) wählt man mehrere Pins
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); //Damit wird das Port C mit Takt versorgt ansonst ist dieser Port ausgechaltet
GPIO_Inity.GPIO_Mode = GPIO_Mode_Out_PP; // Betriebsmodus
GPIO_Inity.GPIO_Speed = GPIO_Speed_50MHz; // Schaltgeschwindigkeit der Pins
GPIO_Init(GPIOC, &GPIO_Inity); // Tatsächliche der Pins

// PortPin als Eingang configurieren
GPIO_Inity.GPIO_Pin = GPIO_Pin_0;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
GPIO_Inity.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Inity.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_Inity);

}



int main (void)
{
uint8_t read_A0 = 0; Das ist die Variable, in der ich den Wert von PA0 speicher

SystemInit(); // Die Std. Peripherie nun Clocks, PLLs usw. einrichten
GPIO_Setup();


read_A0 = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0); somit kopiere ich den Wert
read_A0 |= 0xE1; und heir maskiere mit Oder ??????



if (read_A0 == 0xE1)
{
GPIOC->BSRR = GPIO_Pin_8; // LED On
delayLoop();

GPIOC->BRR = GPIO_Pin_8; // LED Off
delayLoop();

GPIOC->BSRR = GPIO_Pin_9; // LED On
delayLoop();

GPIOC->BRR = GPIO_Pin_9; // LED Off
delayLoop();
}
return 0;
}
Code-Tags verwenden (PicNIck, Mod)

Ich wollte mit diesem Code den Pin 0 von Poart A Auslesen.
Wenn der Bush-Button (der an PORT A, pin0 angeschlossen ) gedruckt, dann ist der Wert des Pins 0 logisch 1.
Im umgekehrten Fall wäre 0.
Eines der Werte (je nach dem Zustand des Buttons) wird in der Variable read_A0 kopiert.

Durch if-Schleife frage ich nach den Wert der Variable, ist die Bedingung erfüllt dann leuchtet die Leds ansonst nicht.

Nun das Ergebnis ist anders, und zwar die LEDS Leuchten, wenn anderen Button (RESET-Button) gedruckt wird.
Am Anfang dachte ich mir, ich habe die GPIO falsch kunfiguriert, aber nach zwei mal Überprüfung bin ich sicher, es wurde richtig eingestellt.
dann bin iach aud diese Idee gekommen, dass ich den Wert maskiere, hilft auch nicht.

Kann jemand mir sagen, so liegt der Fehler???? ich hae das Code mehr mals durchgeprüft, ich verstehe nicht was habe ich faslch eingestellt.

Danke

PicNick
13.07.2011, 08:16
Naja,
1) bei dir wird der gesamte code nur einmal durchlaufen, dann erst wieder nach µC-reset.

Das übliche Muster für µC-Programme ist sowas wie:


int main()
{

init, setup etc.

//-----------------------------------------------------------------------
// (der folgende Code wird dauernd durchlaufen, bis dass der Tod eintritt)
//-----------------------------------------------------------------------
while (1)
{
// check GPIO
// mach dieses oder jenes
}


return 0; // reiner formalismus, denn da kommt er eh nie hin
}


2)

da ich deine C-Library nicht kenne, muss ich vermuten, dass diese funktion



read_A0 = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0);


ausschliesslich Pin_0 aus dem register liest, also steht danach drin (vermutlich)
1= nicht gedrückt
0=gedrückt

und das kannst du abfragen entweder mit


if (read_A0 == 0x01) // Pin0=Bit0=1 --> nicht gedrückt
if (read_A0 == 0x00) // Pin0=Bit0=0 --> gedrückt
bei nur einem Bit ist das gleichbedeutend mit
if (read_A0) // nicht gedrückt ( read_A0 <> 0 )
if (!read_A0) // gedrückt ( read_A0 == 0 )



würde bei deinem Code dann insgesamt heissen:



int main (void)
{
uint8_t read_A0 = 0;
SystemInit();
GPIO_Setup();

while (1)
{
read_A0 = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0);
if (!read_A0) // = 0 => gedrückt
{
GPIOC->BSRR = GPIO_Pin_8; // LED On
delayLoop();
GPIOC->BRR = GPIO_Pin_8; // LED Off
delayLoop();
GPIOC->BSRR = GPIO_Pin_9; // LED On
delayLoop();
GPIOC->BRR = GPIO_Pin_9; // LED Off
delayLoop();
}
} // while() schleife wiederholen

return 0;
}



verwirrt ? :-)

kmrish
13.07.2011, 10:30
vielen Dank!! endlich funktioniert.
mal andere Frage.

Möchte jetzt gerne so probieren, dass die LEDS nach 3-mal Drucken leuchten.
Dafür habe ich ein Register erstellt der immer beim Betätigung des Buttos einmal nach Links verschoben wird.
Erst wenn der Register den Wert 0x04 erreicht, sollen die LEDS Leuchten.

Bei Debugg läuft es wie geplannt, super!.
Nun Drucke ich zum ersten mal den Button leuchten die LEDS sofort.
was ist jetzt? simuliert der Debugg das Code falsch oder widerspricht das Code dem Debugg?

Könntest du mir bitte sagen wo liegt ds Problem.!!!

Allerdings kann ich Timer/Interrupt dafür einsetzen, aber möchte ich schritt für schritt steigen.

Beste Grüße.


int main (void)
{
uint8_t read_A0 = 0;
uint8_t counter =0;
SystemInit();
GPIO_Setup();


while (1)
{

read_A0 =GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);



if(read_A0 == 0x01)

{

counter= (1 << counter);
//counter= (1 >> counter);
}

if (counter== 0x4)
{
GPIOC->BSRR = GPIO_Pin_8; // LED On
delayLoop();

GPIOC->BRR = GPIO_Pin_8; // LED Off
delayLoop();

GPIOC->BSRR = GPIO_Pin_9; // LED On
delayLoop();

GPIOC->BRR = GPIO_Pin_9; // LED Off
delayLoop();

counter = 0;
}

}
return 0;
}

PicNick
13.07.2011, 10:45
1) Du darfst nur dann das TastenBit auswerten, wenn es sich geändert hat (sonst shiftest du ja bei jeder schleife).
dazu brauchst du (z.B) eine Variable
read_A0_old

2) der anfangswert beim shiften muss "counter=1" sein (nuller shiften ist sinnlos) und abfragen musst du auf "8"

und dann der relevante Code-Teil:



counter = 1;

while (1)
{
read_A0 =GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);
if(read_A0 != readA0_old)
{
if(read_A0 == 0x01)
{
counter <<= 1; // einmal nach links
}
read_A0_old = read_A0; // merken (so oder so)
if (counter== 0x8)
{
//........lichtspiele...........
counter = 1; // ! anfangswert
}
}
}

kmrish
14.07.2011, 09:45
vielen Dank.
ich bin jetzt bei Capture Compare Unit.