Skocz do zawartości

Obsługa klawiatury przez stm32f4


jawa000011

Pomocna odpowiedź

Witam odnośnie programu który mam do zrealizowania, komunikacja klawiatury PS/2 z komputerem przez stm32f4 Disco. Jest ktoś w stanie powiedziec jak musza byc skonfigurowane piny aby były przygotowane na odbiór danych? W jakich trybach musza pracowac, obłsuga na zwykłych pinach PA1, PA2.

Link do komentarza
Share on other sites

W czym konkretnie masz problem? Jeśli zajrzałeś do specyfikacji interfejsu PS/2 to wszystko powinno być jasne. Muszą być wejściami - gdy czytasz dane, lub wyjściami - gdy wstrzymujesz zegar lub wysyłasz dane do klawiatury. Czego tu można nie wiedzieć?

Link do komentarza
Share on other sites

Ojej, kiepsko to widzę. Czyli tak: nie znasz protokołu klawiatur IBM-PCAT/PS2 i nie wiesz jak ustawiać konfigurację portów swojego procesora. To może swoją edukację zacznij od tego:

http://www.computer-engineering.org/ps2protocol/

Tam dowiesz się jak wygląda warstwa fizyczna tego interfejsu czyli jak mają działać nadajniki i odbiorniki sygnałów, jakie są standardy elektryczne i jak przesyłać bity i bajty w obie strony. Potem możesz zajrzeć tu:

http://www.computer-engineering.org/ps2keyboard/

gdzie zrozumiesz jak interpretować kody które będziesz dostawał z klawiatury i jakie komendy Ty możesz wysłać do jej kontrolera.

No i gdzieś w międzyczasie proponuję lekturę dokumentacji rodziny STM32F4 ze szczególnym uwzględnieniem rozdziałów dot. portów I/O:

http://www.st.com/stonline/stappl/resourceSelector/app?page=fullResourceSelector&doctype=reference_manual&SeriesID=1577

i oczywiście datasheet konkretnego procesora posadzonego na Twojej płytce.

A Ty w zamian za to napisz po co robisz ten interfejs na tak wielkim procesorze i dlaczego chcesz Disco podłączyć do klawiatury PS2.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

stm jest narzucony z góry, klawiatura ma zostać połączona z stm gdzie w terminalu bedą wyswietlały mi się poszczególne wciśnięte klawisze, tylko albo, aż tyle. Tak dokładnie jestem na etapie zbierania informacji dla tego programu.

Link do komentarza
Share on other sites

Interfejs PS2 jest 5-woltowy więc na początek musisz sprawdzić czy wskazane piny procesora są na 5V odporne. Po drugie sygnały mają jakieś etykiety czyli są jeszcze do czegoś podpięte. Nie widzimy całego schematu więc nie wiadomo, czy 5V podane z zewnątrz będzie temu czemuś przeszkadzało. Poza tym te dodatkowe rzeczy na płytce mogą po prostu uniemożliwić pracę interfejsu bo np. są wyjściami jakichś sygnałów. Jeśli masz cały schemat - sprawdź to. Skąd mamy wiedzieć co tam jeszcze siedzi?

Jeżeli ten pierwszy test zostanie zaliczony, możesz podpinać sygnały i konfigurować linie portów jako wyjścia typu otwarty dren. Najlepiej dolutuj na kabelkach gniazdo miniDIN i doprowadź do niego masę, dwie linie z procesora i zasilanie 5V. Po dołączeniu klawiatury (obowiązkowo przy wyłączonym zasilaniu - PS2 nie jest hot-plugin) będziesz mógł odpalać pierwsze testy odbioru kodów. Wiesz już jak odbierać bajty? Gdzie będziesz je wysyłał? Przez USB do PC?

Link do komentarza
Share on other sites

Odbieranie bajtów zależy od lini clock z tego co wyczytałem. Nie wiem dokładnie jak to zainicjowac w c, czy bedą potrzebne biblioteki ext, obsługujące zewnetrzne przerwania czy da się to zrobić prościej? Dane mają być wysyłane po usarcie do terminala (przez kontroler usb). Jeszcze pytanie odnośnie no hot plugin, to znaczy ze nie moge bezposrdnio podłaczyc zasilania 5V do zlacza kalwiatury zasilania? Oto moj dotychczasowy kod odnośnie odbioru poszczególnych bitów:

static uint8_t bitpos=0;
 static uint8_t scancode=0;
 uint8_t wert;


 wert=GPIO_ReadInputDataBit(DATA_GPIO_PORT, DATA_PIN);
 if((bitpos>0) && (bitpos<9)) {
   // bity danych
   scancode>>=1;
   if(wert==Bit_SET) {
     scancode|=0x80;
   }
 }

 bitpos++;
 //sprawdzanie dlugosci danych
 if(bitpos>=PS2_KEY_FRAME_LEN) {
   // dekodowanie danych za pomoca funkcji
   bitpos=0;
   P_PS2_Key_CheckScancode(scancode);
   scancode=0;
 } 

[ Dodano: 06-02-2016, 18:33 ]

Tutaj własnie zamieszczam obsługę tego zewnętrznego przerwania dla pinu linii clock:

EXT_INT5TO9_t EXT_INT5TO9[] = {

 {7 ,GPIOB,GPIO_Pin_7,RCC_AHB1Periph_GPIOB,EXTI_PortSourceGPIOB,GPIO_PuPd_UP,EXTI_Trigger_Falling},   
};

void UB_Ext_INT5TO9_Init(void)
{
 GPIO_InitTypeDef   GPIO_InitStructure;
 EXTI_InitTypeDef   EXTI_InitStructure;
 NVIC_InitTypeDef   NVIC_InitStructure;
 uint8_t nr;

 for(nr=0;nr<EXT_INT5TO9_ANZ;nr++) {

   RCC_AHB1PeriphClockCmd(EXT_INT5TO9[nr].INT_CLK, ENABLE);


   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
   GPIO_InitStructure.GPIO_PuPd = EXT_INT5TO9[nr].INT_R;
   GPIO_InitStructure.GPIO_Pin = EXT_INT5TO9[nr].INT_PIN;
   GPIO_Init(EXT_INT5TO9[nr].INT_PORT, &GPIO_InitStructure);


   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

   if(EXT_INT5TO9[nr].INT_NR==5) {

     SYSCFG_EXTILineConfig(EXT_INT5TO9[nr].INT_SOURCE, EXTI_PinSource5);


     EXTI_InitStructure.EXTI_Line = EXTI_Line5;
     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
     EXTI_InitStructure.EXTI_Trigger = EXT_INT5TO9[nr].INT_TRG;
     EXTI_InitStructure.EXTI_LineCmd = ENABLE;
     EXTI_Init(&EXTI_InitStructure);
   }
   else if(EXT_INT5TO9[nr].INT_NR==6) {

     SYSCFG_EXTILineConfig(EXT_INT5TO9[nr].INT_SOURCE, EXTI_PinSource6);


     EXTI_InitStructure.EXTI_Line = EXTI_Line6;
     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
     EXTI_InitStructure.EXTI_Trigger = EXT_INT5TO9[nr].INT_TRG;
     EXTI_InitStructure.EXTI_LineCmd = ENABLE;
     EXTI_Init(&EXTI_InitStructure);
   }
   else if(EXT_INT5TO9[nr].INT_NR==7) {

     SYSCFG_EXTILineConfig(EXT_INT5TO9[nr].INT_SOURCE, EXTI_PinSource7);


     EXTI_InitStructure.EXTI_Line = EXTI_Line7;
     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
     EXTI_InitStructure.EXTI_Trigger = EXT_INT5TO9[nr].INT_TRG;
     EXTI_InitStructure.EXTI_LineCmd = ENABLE;
     EXTI_Init(&EXTI_InitStructure);
   }
   else if(EXT_INT5TO9[nr].INT_NR==8) {

     SYSCFG_EXTILineConfig(EXT_INT5TO9[nr].INT_SOURCE, EXTI_PinSource8);


     EXTI_InitStructure.EXTI_Line = EXTI_Line8;
     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
     EXTI_InitStructure.EXTI_Trigger = EXT_INT5TO9[nr].INT_TRG;
     EXTI_InitStructure.EXTI_LineCmd = ENABLE;
     EXTI_Init(&EXTI_InitStructure);
   }
   else if(EXT_INT5TO9[nr].INT_NR==9) {

     SYSCFG_EXTILineConfig(EXT_INT5TO9[nr].INT_SOURCE, EXTI_PinSource9);


     EXTI_InitStructure.EXTI_Line = EXTI_Line9;
     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
     EXTI_InitStructure.EXTI_Trigger = EXT_INT5TO9[nr].INT_TRG;
     EXTI_InitStructure.EXTI_LineCmd = ENABLE;
     EXTI_Init(&EXTI_InitStructure);
   }
 }

 // NVIC config
 NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
 NVIC_Init(&NVIC_InitStructure);
}

void EXTI9_5_IRQHandler(void)
{
 uint32_t wert;
 uint8_t nr;

 if(EXTI_GetITStatus(EXTI_Line5) != RESET)
 {

// jesli nastapilo przerwanie
   EXTI_ClearITPendingBit(EXTI_Line5);

   for(nr=0;nr<EXT_INT5TO9_ANZ;nr++) {
     if(EXT_INT5TO9[nr].INT_NR==5) {
       wert=GPIO_ReadInputDataBit(EXT_INT5TO9[nr].INT_PORT, EXT_INT5TO9[nr].INT_PIN);
       if(wert==Bit_RESET) {
         P_EXT_INT5_LoFlanke();
       }
       else {
         P_EXT_INT5_HiFlanke();
       }
       break;        
     }
   }
 }
 if(EXTI_GetITStatus(EXTI_Line6) != RESET)
 {

   EXTI_ClearITPendingBit(EXTI_Line6);

   for(nr=0;nr<EXT_INT5TO9_ANZ;nr++) {
     if(EXT_INT5TO9[nr].INT_NR==6) {
       wert=GPIO_ReadInputDataBit(EXT_INT5TO9[nr].INT_PORT, EXT_INT5TO9[nr].INT_PIN);
       if(wert==Bit_RESET) {
         P_EXT_INT6_LoFlanke();
       }
       else {
         P_EXT_INT6_HiFlanke();
       }
       break;        
     }
   }
 }
 if(EXTI_GetITStatus(EXTI_Line7) != RESET)
 {

   EXTI_ClearITPendingBit(EXTI_Line7);

   for(nr=0;nr<EXT_INT5TO9_ANZ;nr++) {
     if(EXT_INT5TO9[nr].INT_NR==7) {
       wert=GPIO_ReadInputDataBit(EXT_INT5TO9[nr].INT_PORT, EXT_INT5TO9[nr].INT_PIN);
       if(wert==Bit_RESET) {
         P_EXT_INT7_LoFlanke();
       }
       else {
         P_EXT_INT7_HiFlanke();
       }
       break;        
     }
   }
 }
 if(EXTI_GetITStatus(EXTI_Line8) != RESET)
 {

   EXTI_ClearITPendingBit(EXTI_Line8);

   for(nr=0;nr<EXT_INT5TO9_ANZ;nr++) {
     if(EXT_INT5TO9[nr].INT_NR==8) {
       wert=GPIO_ReadInputDataBit(EXT_INT5TO9[nr].INT_PORT, EXT_INT5TO9[nr].INT_PIN);
       if(wert==Bit_RESET) {
         P_EXT_INT8_LoFlanke();
       }
       else {
         P_EXT_INT8_HiFlanke();
       }
       break;        
     }
   }
 }
 if(EXTI_GetITStatus(EXTI_Line9) != RESET)
 {

   EXTI_ClearITPendingBit(EXTI_Line9);

   for(nr=0;nr<EXT_INT5TO9_ANZ;nr++) {
     if(EXT_INT5TO9[nr].INT_NR==9) {
       wert=GPIO_ReadInputDataBit(EXT_INT5TO9[nr].INT_PORT, EXT_INT5TO9[nr].INT_PIN);
       if(wert==Bit_RESET) {
         P_EXT_INT9_LoFlanke();
       }
       else {
         P_EXT_INT9_HiFlanke();
       }
       break;        
     }
   }
 }
}

Link do komentarza
Share on other sites

Witam, również dołączę do tematu, gdyż mam identyczny projekt do wykonania.

Przejrzałem i przeczytałem wszystkie strony w temacie oraz sugerując się jakimiś projektami, chciałem napisać fragment kodu, który chociaż sprawdzi czy jest jakiekolwiek połączenie z klawiatura... (czy przesyła jakikolwiek znak). Niestety podczas debugowania w CooCoxie obserwując zmienną 'znak' cały czas pozostaje ona pusta. Jestem początkującym w dziedzinie STM32 dlatego proszę o pomoc i odrobinę wyrozumiałości.

Oto kod:

#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "misc.h"
#include "stm32f4xx_exti.h"


#define PS2_CLOCK GPIO_Pin_5
#define PS2_DATA GPIO_Pin_4
#define PS2_PORT GPIOC

static uint8_t znak;
static uint8_t liczba_bitow;

void GPIO_config();
void InterruptConfig();

void GPIO_config(){
GPIO_InitTypeDef gpio_sett; //struktura do ustawien

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); //wlaczenie taktowania zegara dla wszystkich pinow PA

GPIO_StructInit(&gpio_sett);
gpio_sett.GPIO_Pin = PS2_DATA | PS2_CLOCK;
gpio_sett.GPIO_Mode = GPIO_Mode_IN; //jako wejscie
gpio_sett.GPIO_Mode = GPIO_PuPd_NOPULL; //bez rezystorow
gpio_sett.GPIO_Mode = GPIO_Speed_100MHz; //speed na 100
GPIO_Init(PS2_PORT,&gpio_sett);

}

void InterruptConfig(){
EXTI_InitTypeDef exti_sett;
NVIC_InitTypeDef nvic_sett;

EXTI_StructInit(&exti_sett);
exti_sett.EXTI_Mode = EXTI_Mode_Interrupt; //jako przerwanie
exti_sett.EXTI_Trigger = EXTI_Trigger_Falling; //na zbocze opadajace
exti_sett.EXTI_Line = EXTI_Line5; //linia 5 bo pin PC5
exti_sett.EXTI_LineCmd = ENABLE;
EXTI_Init(&exti_sett);

EXTI_ClearITPendingBit(EXTI9_5_IRQn);
NVIC_ClearPendingIRQ(EXTI9_5_IRQn);

nvic_sett.NVIC_IRQChannel = EXTI9_5_IRQn; //wywolywane przez EXTI
nvic_sett.NVIC_IRQChannelPreemptionPriority = 0;
nvic_sett.NVIC_IRQChannelSubPriority = 0;
nvic_sett.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_sett);
}

void EXTI9_5_IRQHandler(){
   uint8_t pomiar;
   if(EXTI_GetITStatus(EXTI_Line5) != RESET)
    {
	pomiar = GPIO_ReadInputDataBit(PS2_PORT, PS2_DATA);
	if (liczba_bitow==11)
	{
		znak = 0x00;
		if (0 == pomiar)
		{
			--liczba_bitow;
		}
	} else
	if (liczba_bitow<11 && liczba_bitow>2)
	{
		znak = (znak >> 1);
		if (0 != pomiar)
			znak = znak + 0x80;
		--liczba_bitow;
	} else
	{
		if (--liczba_bitow == 0)
		{

			liczba_bitow = 11;
		}
	}
	EXTI_ClearITPendingBit(EXTI_Line5);
}
}

int main(void)
{
GPIO_config();
InterruptConfig();
   while(1);

}

Pozdrawiam!

Link do komentarza
Share on other sites

Dobra, wychodzi na to że przerwanie nie występuje... czyli klawiatura jest chyba źle podpięta albo popełniam błąd w innym momencie. To teraz pytanie brzmi czy wystarczy po prostu podpiąć przewody z PS/2 - vcc pod 5V i mase pod GND? Czy trzeba oprocz tego cos jeszcze zrobic? Bo clk i data mam podpiete pod piny, które tolerują 5v(ft).

Link do komentarza
Share on other sites

To co napisał deshipu, czyli volatile dla zmiennej znak, a poza tym musisz inicjalizować zmienną liczba_bitów na jakąś rozsądną wartość (jako ćwiczenie sprawdź na kartce co robi Twój program - podpowiem, początkowa wartość tej zmiennej to zero)

[ Dodano: 15-02-2016, 21:11 ]

Brakuje też w kodzie:

RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

oraz

GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource5);

Może zacznij od przerobienia przykładu z kursu: https://forbot.pl/blog/artykuly/programowanie/kurs-stm32-4-sterowanie-portami-gpio-w-praktyce-id5538

tylko przycisk podłącz pod pin 5?

Link do komentarza
Share on other sites

A no zapomniałem dodać 🙂 volatille dodalem i liczba_bitow ustawilem na 11, to był mój błąd. Jednakże jestem już pewien co jest nie tak. To nie kod, tylko mam źle podłączone to zasilanie w klawie... Wyczytałem, że podobno po dojściu zasilania do klawiatury powinny zaświecić sie chociaż na chwile LED-y, a nic takiego nie występuje. Czy ktoś mógłby doradzić z tym? Podłączone mam tak jak opisałem wyżej.

@edit obecny kod:

#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "misc.h"
#include "stm32f4xx_exti.h"
#include "stm32f4xx_syscfg.h"

#define PS2_CLOCK GPIO_Pin_5
#define PS2_DATA GPIO_Pin_4
#define PS2_PORT GPIOC

static uint8_t znak = 0x00;
volatile static uint8_t liczba_bitow = 0;

void GPIO_config();
void InterruptConfig();

void GPIO_config(){
GPIO_InitTypeDef gpio_sett; //struktura do ustawien

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); //wlaczenie taktowania zegara dla wszystkich pinow PA
GPIO_StructInit(&gpio_sett);
gpio_sett.GPIO_Pin = PS2_DATA | PS2_CLOCK;
gpio_sett.GPIO_Mode = GPIO_Mode_IN; //jako wejscie
gpio_sett.GPIO_OType = GPIO_OType_PP;
gpio_sett.GPIO_PuPd = GPIO_PuPd_UP;
gpio_sett.GPIO_Mode = GPIO_Speed_100MHz; //speed na 100
GPIO_Init(PS2_PORT,&gpio_sett);

}

void InterruptConfig(){
EXTI_InitTypeDef exti_sett;
NVIC_InitTypeDef nvic_sett;

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource5);

EXTI_StructInit(&exti_sett);
exti_sett.EXTI_Mode = EXTI_Mode_Interrupt; //jako przerwanie
exti_sett.EXTI_Trigger = EXTI_Trigger_Falling; //na zbocze opadajace
exti_sett.EXTI_Line = EXTI_Line5; //linia 5 bo pin PC5
exti_sett.EXTI_LineCmd = ENABLE;
EXTI_Init(&exti_sett);

EXTI_ClearITPendingBit(EXTI9_5_IRQn);

nvic_sett.NVIC_IRQChannel = EXTI9_5_IRQn; //wywolywane przez EXTI
nvic_sett.NVIC_IRQChannelPreemptionPriority = 0;
nvic_sett.NVIC_IRQChannelSubPriority = 0;
nvic_sett.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvic_sett);

NVIC_ClearPendingIRQ(EXTI9_5_IRQn);
}

void EXTI9_5_IRQHandler(){
   uint8_t pomiar;
   if(EXTI_GetITStatus(EXTI_Line5) != RESET)
    {
	pomiar = GPIO_ReadInputDataBit(PS2_PORT, PS2_DATA);
	if (liczba_bitow==11)
	{
		znak = 0x00;
		if (0 == pomiar)
		{
			--liczba_bitow;
		}
	} else
	if (liczba_bitow<11 && liczba_bitow>2)
	{
		znak = (znak >> 1);
		if (0 != pomiar)
			znak = znak + 0x80;
		--liczba_bitow;
	} else
	{
		if (--liczba_bitow == 0)
		{

			liczba_bitow = 11;
		}
	}
	EXTI_ClearITPendingBit(EXTI_Line5);
}
}

int main(void)
{
GPIO_config();
InterruptConfig();
   while(1){}

}

@edit I niestety moj nie mam takiej funkcji na f407vg : RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.