Danke für den Codeschnipsel...werd ich mir genauer ansehen wenn die SPI läuft.
Der Code, wie er momentan ist. Momentan versuche ich mich mal an der USART in der Hoffnung, den Fehler eingrenzen zu können. Wenn ich die UART zum Laufen bringe ist die SPI-Init Mist. Wenn die USART auch nicht will hab ich wohl ein grundsätzlicheres Konfiproblem.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <stm32f446xx.h>
//Takteinstellungen konfigurieren
void TaktInit(){
//APB1: Tim6, SPI2, USART3
//AHB1: PortE, PortB, PortC, PortD
//APB2: Tim1
//SysClk 16MHz (interner Oszillator) - Takt für APB1 auf 2MHz setzen
RCC->CFGR |= RCC_CFGR_HPRE_DIV1; //AHB-Prescaler /1 => 16NHz
RCC->CFGR |= RCC_CFGR_PPRE1_DIV1; //Takt für APB1 = AHB/1
}
//Nested Vector Interrupt Controller konfigurieren
void NVICInit(){
//NVIC_EnableIRQ(SPI2_IRQn);
}
//Pins, die als einfache Standard-EAs (Taster/LEDs) verwendet werden,konfigurieren
void EAInit(){
//Pins für LEDs initialisieren
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN; //Takt für PortE aktivieren
//PE0
GPIOE->MODER |= GPIO_MODER_MODER0_0;
GPIOE->MODER &= ~GPIO_MODER_MODER0_1; //PE0 -> Ausgang MODER ->01
GPIOE->OTYPER &= ~GPIO_OTYPER_OT_0; //PE0 als Push-Pull-Stufe
GPIOE->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR0; //PE0 High-Speed
GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR0_0;
GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR0_1; //Pull-up/-down-Widerstände abschalten
GPIOE->BSRR|= GPIO_BSRR_BS_0; //LED abschalten
//PE1
GPIOE->MODER |= GPIO_MODER_MODER1_0;
GPIOE->MODER &= ~GPIO_MODER_MODER1_1; //PE1 -> Ausgang MODER ->01
GPIOE->OTYPER &= ~GPIO_OTYPER_OT_1; //PE1 als Push-Pull-Stufe
GPIOE->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR1; //PE1 High-Speed
GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR1_0;
GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR1_1; //Pull-up/-down-Widerstände abschalten
GPIOE->BSRR|= GPIO_BSRR_BS_1; //LED abschalten
//PE2
GPIOE->MODER |= GPIO_MODER_MODER2_0;
GPIOE->MODER &= ~GPIO_MODER_MODER2_1; //PE2 -> Ausgang MODER ->01
GPIOE->OTYPER &= ~GPIO_OTYPER_OT_2; //PE2 als Push-Pull-Stufe
GPIOE->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR2; //PE2 High-Speed
GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR2_0;
GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR2_1; //Pull-up/-down-Widerstände abschalten
GPIOE->BSRR|= GPIO_BSRR_BS_2; //LED abschalten
//PE3
GPIOE->MODER |= GPIO_MODER_MODER3_0;
GPIOE->MODER &= ~GPIO_MODER_MODER3_1; //PE3 -> Ausgang MODER ->01
GPIOE->OTYPER &= ~GPIO_OTYPER_OT_3; //PE3 als Push-Pull-Stufe
GPIOE->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR3; //PE3 High-Speed
GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR3_0;
GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR3_1; //Pull-up/-down-Widerstände abschalten
GPIOE->BSRR|= GPIO_BSRR_BS_3; //LED abschalten
//PE4
GPIOE->MODER |= GPIO_MODER_MODER4_0;
GPIOE->MODER &= ~GPIO_MODER_MODER4_1; //PE4 -> Ausgang MODER ->01
GPIOE->OTYPER &= ~GPIO_OTYPER_OT_4; //PE4 als Push-Pull-Stufe
GPIOE->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR4; //PE4 High-Speed
GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR4_0;
GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR4_1; //Pull-up/-down-Widerstände abschalten
GPIOE->BSRR|= GPIO_BSRR_BS_4; //LED abschalten
//PE5
GPIOE->MODER |= GPIO_MODER_MODER5_0;
GPIOE->MODER &= ~GPIO_MODER_MODER5_1; //PE5 -> Ausgang MODER ->01
GPIOE->OTYPER &= ~GPIO_OTYPER_OT_5; //PE5 als Push-Pull-Stufe
GPIOE->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR5; //PE5 High-Speed
GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR5_0;
GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR5_1; //Pull-up/-down-Widerstände abschalten
GPIOE->BSRR|= GPIO_BSRR_BS_5; //LED abschalten
//PE6
GPIOE->MODER |= GPIO_MODER_MODER6_0;
GPIOE->MODER &= ~GPIO_MODER_MODER6_1; //PE6 -> Ausgang MODER ->01
GPIOE->OTYPER &= ~GPIO_OTYPER_OT_6; //PE6 als Push-Pull-Stufe
GPIOE->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6; //PE6 High-Speed
GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR6_0;
GPIOE->PUPDR &= ~GPIO_PUPDR_PUPDR6_1; //Pull-up/-down-Widerstände abschalten
GPIOE->BSRR|= GPIO_BSRR_BS_6; //LED abschalten
//Pins für Taster initialisieren
//PB5
GPIOB->MODER &= ~GPIO_MODER_MODER5_0;
GPIOB->MODER &= ~GPIO_MODER_MODER5_1; //PB5 -> Eingang MODER ->00
GPIOB->OTYPER &= ~GPIO_OTYPER_OT_5;
GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR5_0;
GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR5_1;
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR5_0;
GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR5_1; //Pull-up-Widerstände einschalten PUPDR ->0
//PB6
GPIOB->MODER &= ~GPIO_MODER_MODER6_0;
GPIOB->MODER &= ~GPIO_MODER_MODER6_1; //PB6 -> Eingang MODER ->00
GPIOB->OTYPER &= ~GPIO_OTYPER_OT_6;
GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR6_0;
GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR6_1;
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR6_0;
GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR6_1; //Pull-up-Widerstände einschalten PUPDR ->01
//PB7
GPIOB->MODER &= ~GPIO_MODER_MODER7_0;
GPIOB->MODER &= ~GPIO_MODER_MODER7_1; //PB7 -> Eingang MODER ->00
GPIOB->OTYPER &= ~GPIO_OTYPER_OT_7;
GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR7_0;
GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR7_1;
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR7_0;
GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR7_1; //Pull-up-Widerstände einschalten PUPDR ->01
//PB12
GPIOB->MODER &= ~GPIO_MODER_MODER12_0;
GPIOB->MODER &= ~GPIO_MODER_MODER12_1; //PB12 -> Eingang MODER ->00
GPIOB->OTYPER &= ~GPIO_OTYPER_OT_12;
GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR12_0;
GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR12_1;
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR12_0;
GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR12_1; //Pull-up-Widerstände einschalten PUPDR ->01
//PB13
GPIOB->MODER &= ~GPIO_MODER_MODER13_0;
GPIOB->MODER &= ~GPIO_MODER_MODER13_1; //PB13 -> Eingang MODER ->00
GPIOB->OTYPER &= ~GPIO_OTYPER_OT_13;
GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR13_0;
GPIOB->OSPEEDR &= ~GPIO_OSPEEDER_OSPEEDR13_1;
GPIOB->PUPDR |= GPIO_PUPDR_PUPDR13_0;
GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR13_1; //Pull-up-Widerstände einschalten PUPDR ->01
}
//SPI2 konfigurieren, es wird nur ein LCD damit bedient.
void SPIInit(){
//Taktversorgung aktivieren
RCC->APB1ENR |= RCC_APB1ENR_SPI2EN; //Takt für SPI2 aktivieren
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; //Takt für PortB aktivieren
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; //Takt für PortC aktivieren
RCC->APB1ENR |= RCC_APB1ENR_PWREN;
//Pins konfigurieren
//PB10 -> SPI2-Clock
GPIOB->MODER &= ~GPIO_MODER_MODER10_0;
GPIOB->MODER |= GPIO_MODER_MODER10_1; //PB10 -> Alternate Function MODER ->10
GPIOB->OTYPER &= ~GPIO_OTYPER_OT_10; //PB10 als Push-Pull-Stufe
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR10_0;
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR10_1; //PB10 High-Speed
GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR10_0;
GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR10_1; //Pull-up/-down-Widerstände abschalten
GPIOB->AFR[1] |= (0b0110<<8); //SPI2 AF6
//PB15 -> SPI2-MoSi
GPIOB->MODER &= ~GPIO_MODER_MODER15_0;
GPIOB->MODER |= GPIO_MODER_MODER15_1; //PB15 -> Alternate Function MODER ->10
GPIOB->OTYPER &= ~GPIO_OTYPER_OT_15; //PB15 als Push-Pull-Stufe
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR15_0;
GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR15_1; //PB15 High-Speed
GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR15_0;
GPIOB->PUPDR &= ~GPIO_PUPDR_PUPDR15_1; //Pull-up/-down-Widerstände abschalten
GPIOB->AFR[1] |= (0b0110<<28); //SPI2 AF6
//PC3 -> SPI2-Select LCD
GPIOC->MODER |= GPIO_MODER_MODER3_0;
GPIOC->MODER &= ~GPIO_MODER_MODER3_1; //PC3 als Ausgang MODER ->01
GPIOC->OTYPER &= ~GPIO_OTYPER_OT_3; //PC3 als Push-Pull-Stufe
GPIOC->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR3_0;
GPIOC->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR3_1; //PC3 High-Speed
GPIOC->PUPDR &= ~GPIO_PUPDR_PUPDR3_0;
GPIOC->PUPDR &= ~GPIO_PUPDR_PUPDR3_1; //Pull-up/-down-Widerstände abschalten
//PC2 -> SPI2-R/S
GPIOC->MODER |= GPIO_MODER_MODER2_0;
GPIOC->MODER |= GPIO_MODER_MODER2_1; //PC2 als Ausgang MODER ->01
GPIOC->OTYPER &= ~GPIO_OTYPER_OT_3; //PC2 als Push-Pull-Stufe
GPIOC->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR2_0;
GPIOC->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR2_1; //PC2 als High-Speed
GPIOC->PUPDR &= ~GPIO_PUPDR_PUPDR2_0;
GPIOC->PUPDR &= ~GPIO_PUPDR_PUPDR2_1; //Pull-up/-down-Widerstände abschalten
//SPI konfigurieren
SPI2->CR1 |= SPI_CR1_BIDIMODE; //Bidirektionaler Modus
SPI2->CR1 |= SPI_CR1_BIDIOE; //Nur senden
SPI2->CR1 &= ~SPI_CR1_CRCEN; //CRC-Berechnung abschalten
SPI2->CR1 &= ~SPI_CR1_CRCNEXT; //Keine CRC-Phase
SPI2->CR1 &= ~SPI_CR1_DFF; //8-Bit Frameformat
SPI2->CR1 &= ~SPI_CR1_RXONLY; //Receive-Only-Modus abschalten
SPI2->CR1 &= ~SPI_CR1_SSM; //Software Slave Management abschalten
SPI2->CR1 &= ~SPI_CR1_SSI; //NSS-Pin
SPI2->CR1 &= ~SPI_CR1_LSBFIRST; //MSB zuerst übertragen
SPI2->CR1 &= ~SPI_CR1_BR_2 & ~SPI_CR1_BR_1 | SPI_CR1_BR_0; //Taktteiler 4 -> 16MHz/4 -> 4MHz
SPI2->CR1 |= SPI_CR1_MSTR; //Master configuration
SPI2->CR1 |= SPI_CR1_CPOL; //Takt=1 im Leerlauf
SPI2->CR1 &= ~SPI_CR1_CPHA; //Clockphase, first clock transistion is first data capture edge
SPI2->CR1 |= SPI_CR1_SPE; //SPI aktivieren
/*
SPI2->CR2 |= SPI_CR2_TXEIE; //Tx-buffer empty interupt aktivieren
SPI2->CR2 &= ~SPI_CR2_RXNEIE; //Rx-buffer not empty interrupt deaktivieren
SPI2->CR2 &= ~SPI_CR2_ERRIE; //Error Interrupt deaktivieren
SPI2->CR2 &= ~SPI_CR2_FRF; //Motorola-Modus (Sandard)
SPI2->CR2 &= ~SPI_CR2_SSOE; //SS Output deaktivieren
SPI2->CR2 &= ~SPI_CR2_TXDMAEN; //TXE DMA-Request deaktivieren
SPI2->CR2 &= ~SPI_CR2_RXDMAEN; //RXNE DMA Request deaktivieren*/
}
//UART initialisieren
void UARTInit(){
//Taktversorgung aktiviern
RCC->APB1ENR |= RCC_APB1ENR_USART3EN; //UART3 mit Takt versorgen
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN; //PortD mit Takt versorgen
//Pins konfigurieren
//PD9 -> RX
GPIOD->MODER &= ~GPIO_MODER_MODER9_0;
GPIOD->MODER |= GPIO_MODER_MODER9_1; //PD9 -> Alternate Function MODER ->10
GPIOD->OTYPER &= ~GPIO_OTYPER_OT_9; //PD9 als Push-Pull-Stufe
GPIOD->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR9_0;
GPIOD->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR9_1; //PD9 High-Speed
GPIOD->PUPDR &= ~GPIO_PUPDR_PUPDR9_0;
GPIOD->PUPDR &= ~GPIO_PUPDR_PUPDR9_1; //Pull-up/-down-Widerstände abschalten
GPIOD->AFR[1] |= (0b0111<<4); //UART
//PD8 -> TX
GPIOD->MODER &= ~GPIO_MODER_MODER8_0;
GPIOD->MODER |= GPIO_MODER_MODER8_1; //PD8 -> Alternate Function MODER ->10
GPIOD->OTYPER &= ~GPIO_OTYPER_OT_8; //PD8 als Push-Pull-Stufe
GPIOD->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR8_0;
GPIOD->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR8_1; //PD8 High-Speed
GPIOD->PUPDR &= ~GPIO_PUPDR_PUPDR8_0;
GPIOD->PUPDR &= ~GPIO_PUPDR_PUPDR8_1; //Pull-up/-down-Widerstände abschalten
GPIOD->AFR[1] |= (0b0111<<0); //UART
//PD11 -> CTS
GPIOD->MODER &= ~GPIO_MODER_MODER11_0;
GPIOD->MODER |= GPIO_MODER_MODER11_1; //PD11 -> Alternate Function MODER ->10
GPIOD->OTYPER &= ~GPIO_OTYPER_OT_11; //PD11 als Push-Pull-Stufe
GPIOD->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR11_0;
GPIOD->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR11_1; //PD11 High-Speed
GPIOD->PUPDR &= ~GPIO_PUPDR_PUPDR11_0;
GPIOD->PUPDR &= ~GPIO_PUPDR_PUPDR11_1; //Pull-up/-down-Widerstände abschalten
GPIOD->AFR[1] |= (0b0111<<16); //UART
//PD12 -> RTS
GPIOD->MODER &= ~GPIO_MODER_MODER12_0;
GPIOD->MODER |= GPIO_MODER_MODER12_1; //PD12 -> Alternate Function MODER ->10
GPIOD->OTYPER &= ~GPIO_OTYPER_OT_12; //PD12 als Push-Pull-Stufe
GPIOD->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR12_0;
GPIOD->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR12_1; //PD12 High-Speed
GPIOD->PUPDR &= ~GPIO_PUPDR_PUPDR12_0;
GPIOD->PUPDR &= ~GPIO_PUPDR_PUPDR12_1; //Pull-up/-down-Widerstände abschalten
GPIOD->AFR[1] |= (0b0111<<20); //UART
//UART konfigurieren
USART3->CR3 |= USART_CR3_CTSE; //CTS hardware flow control
USART3->CR3 |= USART_CR3_RTSE; //RTS hardware flow control
USART3->BRR |= 0b111110100000001; //Baudrate 16MHz/2000 => 8kHz
USART3->CR1 &= ~ USART_CR1_M; //8-Bit-Modus
USART3->CR1 &= ~USART_CR1_PCE; //Paritätskontrolle deaktivieren
//USART3->CR1 &= ~USART_CR1_PS; //Paritätsmodus
USART3->CR1 &= ~USART_CR1_PEIE; //PE-Interrupt
USART3->CR1 |= USART_CR1_RE; //Receiver Enable
USART3->CR1 |= USART_CR1_TE; //Transmitter Enable
}
void LCDInit(){
SndBfhlLCD(0b00111001);
SndBfhlLCD(0b00010101);
SndBfhlLCD(0b01010101);
SndBfhlLCD(0b01101110);
SndBfhlLCD(0b01110010);
SndBfhlLCD(0b00111000);
SndBfhlLCD(0b00001111);
SndBfhlLCD(0b00000001);
SndBfhlLCD(0b00000110);
printf("Init-Befehle an LCD gesendet\n");
}
//Sendet ein Befehlbyte ans LCD
void SndBfhlLCD(char byte){
SPI2->CR1 |= SPI_CR1_SPE; //SPI aktivieren
GPIOC->BSRR |= GPIO_BSRR_BR_2; //RS-Pin zurücksetzen
GPIOC->BSRR |= GPIO_BSRR_BR_3; //CS runterziehen
while (!(SPI2->SR & SPI_SR_TXE)){ //Warten bis Transmit-Register frei ist
}
SPI2->DR = byte; //Byte senden
while (!(SPI2->SR & SPI_SR_TXE)){ //Warten bis Transmit-Register frei ist
}
while (SPI2->SR & SPI_SR_BSY){ //Warten bis laufende Übertragung abgeschlossen ist
}
GPIOC->BSRR |= GPIO_BSRR_BS_3; //CS high
GPIOC->BSRR |= GPIO_BSRR_BS_2; //RS-Pin high
SPI2->CR1 &= ~SPI_CR1_SPE; //SPI deaktivieren
//RS NICHT toggeln
}
//Sendet ein Datenbyte ans LCD
void SndDtnlLCD(char byte){
SPI2->CR1 |= SPI_CR1_SPE; //SPI aktivieren
GPIOC->BSRR |= GPIO_BSRR_BS_2; //RS-Pin setzen
GPIOC->BSRR |= GPIO_BSRR_BR_3; //CS runterziehen
while (!(SPI2->SR & SPI_SR_TXE)){ //Warten bis Transmit-Register frei ist
}
SPI2->DR = byte; //Byte senden
while (!(SPI2->SR & SPI_SR_TXE)){ //Warten bis Transmit-Register frei ist
}
while (SPI2->SR & SPI_SR_BSY){ //Warten bis laufende Übertragung abgeschlossen ist
}
GPIOC->BSRR |= GPIO_BSRR_BS_3; //CS high
SPI2->CR1 &= ~SPI_CR1_SPE; //SPI deaktivieren
GPIOC->BSRR |= GPIO_BSRR_BS_2; //RS toggeln
GPIOC->BSRR |= GPIO_BSRR_BR_2;
}
//SPI2 Interrupt
void SPI2_IRQHandler (void){
GPIOE->BSRR |= GPIO_BSRR_BR_4; //LED an E4 einschalten
printf("SPI2 Interrupt Event\n");
}
void main(void){
SystemInit();
TaktInit();
NVICInit();
EAInit();
GPIOE->BSRR |= GPIO_BSRR_BR_5; //LED an E5 einschalten
UARTInit();
SPIInit();
LCDInit();
while(1){
SndDtnlLCD('T');
SndDtnlLCD('e');
SndDtnlLCD('s');
SndDtnlLCD('t');
SndDtnlLCD(' ');
SndDtnlLCD('O');
SndDtnlLCD('K');
GPIOE->BSRR |= GPIO_BSRR_BR_1; //LED an E1 einschalten
GPIOE->BSRR |= GPIO_BSRR_BS_1; //LED an E1 ausschalten
}
}
Lesezeichen