/** ****************************************************************************** * @file : main.c * @brief : Dieser Code bewirkt, dass ein 16-Bit-Messwert über SPI2 vom * MCP 3008 empfangen wird. * Für SPI werden die Pins PB13 (CLK), PB14 (MISO), PB15 (MOSI) * und PA8 (CS) verwendet. * * ****************************************************************************** */ // Standardbibliotheken von C #include #include // Bibliotheke des verwendeten Mikrocontrollers #include "stm32f446xx.h" #include "system_stm32f4xx.h" // Funktionsprototypen void initialisiereClock(void); void initialisiereGPIO(void); void initialisiereSPI(void); void initialisiereSystick(void); void sendeBytesUSART(uint8_t ByteFolge[5]); void empfangeBitSPI(uint8_t *gesendeterWert, uint8_t *empfangenerWert); void AuslesenDesADU(uint16_t *WertDesADU); bool timerTrigger = false; uint16_t WertDesADU; uint8_t WertDesAduAlsDezimalzahlEinzeln[5]; int main(void) { initialisiereClock(); initialisiereGPIO(); initialisiereSPI(); initialisiereSystick(); while(1) { if(timerTrigger == true) { WertDesADU = 0; WertDesAduAlsDezimalzahlEinzeln[0] = 0; WertDesAduAlsDezimalzahlEinzeln[1] = 0; WertDesAduAlsDezimalzahlEinzeln[2] = 0; WertDesAduAlsDezimalzahlEinzeln[3] = 0; WertDesAduAlsDezimalzahlEinzeln[4] = 0; AuslesenDesADU(&WertDesADU); timerTrigger = false; } } } void initialisiereSystick(void) { // Konfiguration des SYSTICK Timers SystemCoreClockUpdate(); SysTick_Config(SystemCoreClock / 1); // Interrup bei 1 s } void initialisiereGPIO(void) { // Definition von GPIO B Pin 5, 6, 7 als alternative Funktion für SPI2 GPIOB->MODER &= ~(GPIO_MODER_MODER13); GPIOB->MODER |= GPIO_MODER_MODER13_1; // SPI2 CLK GPIOB->MODER &= ~(GPIO_MODER_MODER14); GPIOB->MODER |= GPIO_MODER_MODER14_1; // SPI2 MISO GPIOB->MODER &= ~(GPIO_MODER_MODER15); GPIOB->MODER |= GPIO_MODER_MODER15_1; // SPI2 MOSI // Definition von GPIO A Pin 8 als Output (Für CS) GPIOA->MODER |= GPIO_MODER_MODER8_0; // GPIO OUTPUT // Definition von GPIO A Pin 13, 14 und 15 als alternative Funktion AF5 GPIOB->AFR[1] &= ~(GPIO_AFRH_AFSEL13); GPIOB->AFR[1] |= GPIO_AFRH_AFSEL13_0 | GPIO_AFRH_AFSEL13_2; GPIOB->AFR[1] &= ~(GPIO_AFRH_AFSEL14); GPIOB->AFR[1] |= GPIO_AFRH_AFSEL14_0 | GPIO_AFRH_AFSEL14_2; GPIOB->AFR[1] &= ~(GPIO_AFRH_AFSEL15); GPIOB->AFR[1] |= GPIO_AFRH_AFSEL15_0 | GPIO_AFRH_AFSEL15_2; //Alternativ: GPIOB->AFR[1] |= (5<<20)|(5<<24)|(5<<28); } void initialisiereSPI(void) { // SPI Clock Polarität (CPOL) und Phasenverschiebung (CPHA) werden eingestellt SPI2->CR1 &= ~SPI_CR1_CPHA_Msk; SPI2->CR1 &= ~SPI_CR1_CPOL_Msk; // Selektieren, ob es sich um einen Master oder Slave handelt SPI2->CR1 |= SPI_CR1_MSTR; // Einstellen der Baudrate = Clock des jeweiligen SPI Bus (fPCLK) / Prescaler (PSC) SPI2->CR1 |= (0x3) << 3; // Format of the data: LSB SPI2->CR1 |= SPI_CR1_LSBFIRST; // Software Slavemanagement: // SSM = SSI = 1 --> Software Slave management (Also Slave wird mit GPIO gewählt) SPI2->CR1 |= SPI_CR1_SSM; SPI2->CR1 |= SPI_CR1_SSI; // Diese Einstellungen sind beim Standard belassen worden. //SPI2->CR1 &= ~(SPI_CR1_BIDIMODE_Msk); //SPI2->CR1 &= ~(SPI_CR1_RXONLY_Msk); //SPI2->CR1 &= ~SPI_CR1_BIDIOE; // DFF: Data frame format: 8-Bit SPI2->CR1 &= ~(SPI_CR1_DFF_Msk); SPI2->CR2 = 0; // SPI2 wird aktiviert SPI2->CR1 |= SPI_CR1_SPE; GPIOA->BSRR |= GPIO_BSRR_BS8; } void initialisiereClock(void) { // Aktivieren der Clock für GPIO Port A und B RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN; // Aktivieren der Clock für USART1- und SPI2-Schnittstelle RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; } void empfangeBitSPI(uint8_t *gesendeterWert, uint8_t *empfangenerWert) { // Warten bis der Sendepuffer des SPI leer ist. while ((SPI2->SR & SPI_SR_TXE) == 0){}; // Byte an das SPI Modul senden SPI2->DR = (uint8_t)(*gesendeterWert); // Warten bis der Empfangspuffer des SPI nicht mehr leer ist. while ((SPI2->SR & SPI_SR_RXNE) == 0){}; // Byte vom SPI erhalten *empfangenerWert = SPI2->DR; // Warten bis das SPI nicht mehr beschäftigt ist. while ((SPI2->SR & SPI_SR_BSY) != 0){}; } void AuslesenDesADU(uint16_t *WertDesADUx) { uint8_t SendeByteNiedrig = 0, SendeByteHoch = 0, DummyByte = 0; uint8_t KonfigByte = 0b10000000; GPIOA->BSRR |= GPIO_BSRR_BR8; // CS aktivieren, damit SPI arbeitet empfangeBitSPI(&KonfigByte, &DummyByte); // Konfigurations-Byte an das SPI senden empfangeBitSPI(&DummyByte, &SendeByteHoch); // Dummy-Byte an das SPI senden und obere 8-Bit des ADU Werts empfangen empfangeBitSPI(&DummyByte, &SendeByteNiedrig); // Dummy-Byte an das SPI senden und untere 8-Bit des ADU Werts empfangen GPIOA->BSRR |= GPIO_BSRR_BS8; // CS inaktiv, damit SPI nicht mehr arbeitet // Der ADU Wert kann jetzt zu einem 16-Bit zusammengesetzt werden mit *WertDesADUx |= ( ((uint16_t)SendeByteHoch) << 8) | ( (uint16_t)SendeByteNiedrig); } void SysTick_Handler(void) { timerTrigger = true; }