Ten post będzie kontynuacją poprzedniego, który dotyczył obsługi ekspandera portów GPIO. Tym razem przedstawię jak obsługiwać za jego pomocą przyciski.
Wszystkie istotne informacje zostały umieszczone bezpośrednio w programie w formie komentarzy.
Działanie polega na tym, że w momencie przyciśnięcia przycisku następuje zapalenie kolejnej diody. Zostały one podłączone poprzez rezystor 1kOhm do wyprowadzeń od GP0 do GP3. Do portu GP4 został podłączony przycisk.
W celu odczytania stanu panującego na linii należy wystawić stan niski na linię CS, po czym wysłać dane do rejestru, informując układ, że nastąpi odczytywanie danych. Dana z rejestu zostaje odczytana i przesłana i wysłana do mikrokontrolera. Jeżeli przycisk został wciśnięty, czyli linia została zwarta do masy nastąpi wykonywanie zadania w pętli.
Wszystkie istotne informacje zostały umieszczone bezpośrednio w programie w formie komentarzy.
Działanie polega na tym, że w momencie przyciśnięcia przycisku następuje zapalenie kolejnej diody. Zostały one podłączone poprzez rezystor 1kOhm do wyprowadzeń od GP0 do GP3. Do portu GP4 został podłączony przycisk.
W celu odczytania stanu panującego na linii należy wystawić stan niski na linię CS, po czym wysłać dane do rejestru, informując układ, że nastąpi odczytywanie danych. Dana z rejestu zostaje odczytana i przesłana i wysłana do mikrokontrolera. Jeżeli przycisk został wciśnięty, czyli linia została zwarta do masy nastąpi wykonywanie zadania w pętli.
#include "stm32f10x.h" //Deklaracja rejestrów #define MCP_IODIR 0x00 #define MCP_IPOL 0x01 #define MCP_GPINTEN 0x02 #define MCP_DEFVAL 0x03 #define MCP_INTCON 0x04 #define MCP_IOCON 0x05 #define MCP_GPPU 0x06 #define MCP_INTF 0x07 #define MCP_INTCAP 0x08 #define MCP_GPIO 0x09 #define MCP_OLAT 0x0a //Deklaracja pinów #define CS_PIN GPIO_Pin_0 #define CS_LINE GPIOC #define SCK_PIN GPIO_Pin_5 #define SCK_LINE GPIOA #define MISO_PIN GPIO_Pin_6 #define MISO_LINE GPIOA #define MOSI_PIN GPIO_Pin_7 #define MOSI_LINE GPIOA void SPIInit(void); void GPIOInit(void); uint8_t SPI_SEND(uint8_t); void MCP_WRITE(uint8_t, uint8_t); uint8_t MCP_READ(uint8_t); void Delay(int); int main(void) { volatile int wcisniecie = 0; GPIOInit(); SPIInit(); MCP_WRITE(MCP_IODIR, ~0x0F); //Podłączenie rejestu podciągającego do linii GP4 MCP_WRITE(MCP_GPPU, 0x10); while (1) { if ((MCP_READ(MCP_GPIO) & 0x10) == 0) { Delay(200); wcisniecie++; switch(wcisniecie) { case 1: { MCP_WRITE(MCP_OLAT, 0x01); break; } case 2: { MCP_WRITE(MCP_OLAT, 0x03); break; } case 3: { MCP_WRITE(MCP_OLAT, 0x07); break; } case 4: { MCP_WRITE(MCP_OLAT, 0x0f); break; } case 5: { MCP_WRITE(MCP_OLAT, 0x00); Delay(10); wcisniecie = 0; } } } } } void SPIInit(void) { SPI_InitTypeDef SPIInit; RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); SPI_StructInit(&SPIInit); //Transmisja z wykorzystaniem dwóch linii SPIInit.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //Tryb pracy mikrokontrolera SPIInit.SPI_Mode = SPI_Mode_Master; //Stan sygnału taktującego przy braku transmisji SPIInit.SPI_CPOL = SPI_CPOL_Low; //Aktywne zbocze sygnału taktującego SPIInit.SPI_CPHA = SPI_CPHA_1Edge; //Wylaczenie sprzetowej obslugi linii CS SPIInit.SPI_NSS = SPI_NSS_Soft; //Szybkośc transmisji 64MHz/16 = 4MHz SPIInit.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; //Inicjalizacja SPI SPI_Init(SPI1, &SPIInit); //Włączenie SPI SPI_Cmd(SPI1, ENABLE); } //Ustawienie pinów SPI void GPIOInit(void) { GPIO_InitTypeDef GPIOInit; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); GPIO_StructInit(&GPIOInit); //piny SCK, MOSI GPIOInit.GPIO_Pin = SCK_PIN|MOSI_PIN; // SCK, MOSI GPIOInit.GPIO_Mode = GPIO_Mode_AF_PP; GPIOInit.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(SCK_LINE, &GPIOInit); //Pin Miso GPIOInit.GPIO_Pin = MISO_PIN; // MISO GPIOInit.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIOInit.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(MISO_LINE, &GPIOInit); //Pin CS GPIOInit.GPIO_Pin = CS_PIN; GPIOInit.GPIO_Mode = GPIO_Mode_Out_PP; GPIOInit.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(CS_LINE, &GPIOInit); //Ustawienie pinu CS na niski, następuje wybranie urządzenia GPIO_SetBits(GPIOC, GPIO_Pin_0); } //Wyslanie danych uint8_t SPI_SEND(uint8_t byte) { //Sprawdzanie zajętości bufora nadawczego, jak będzie wolny nastąpi wysłanie danych while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); SPI_I2S_SendData(SPI1, byte); //Sprawdzanie, czy dane są w buforze odbiorczym, jeśli tak to zostaną zwrócone while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); return SPI_I2S_ReceiveData(SPI1); } //Wpisanie danych do rejestrów void MCP_WRITE(uint8_t rejestr, uint8_t wartosc) { //Ustawienie pinu CS na stan niski, wybranie urządzenia GPIO_ResetBits(CS_LINE, CS_PIN); //wpisanie danych do CS. SPI_SEND(0x40); //wyslanie informacji do którego rejestru dane zostaną przesłane SPI_SEND(rejestr); //wysłanie ustawienia wartości SPI_SEND(wartosc); //Zakończenie transmisji, zmiana stanu linii CS na wysoki GPIO_SetBits(CS_LINE, CS_PIN); } //Odczytanie danych z rejestru uint8_t MCP_READ(uint8_t addr) { //Inicjalizacja zmiennej uint8_t VAL = 0; //Stan niski na pic CS wybranie urządzenia GPIO_ResetBits(CS_LINE, CS_PIN); //Tym razem wprowadzamy dane, więc bit R/W z 0 na 1 co daje 0x41 całościowo SPI_SEND(0x41); SPI_SEND(addr); //Przypisanie wartości do zmiennej VAL = SPI_SEND(0xff); //Zmiana stanu na linii CS GPIO_SetBits(CS_LINE, CS_PIN); return VAL; } void Delay(int czas) { int i; for (i = 0; i < czas * 5000; i++) {} }