Jens Altenburg
/
Fachbuch_Initialisierungen
Initialisation Nucleo-F446 by Jens Altenburg
main.cpp
- Committer:
- prof_al
- Date:
- 2021-03-17
- Revision:
- 0:9b6fbe273511
File content as of revision 0:9b6fbe273511:
/******************************************************************** * * Name: main.cpp * Beschreibung: HAL für "Embedded Systems Engineering" * Autor: * Erstellung: 29.05.2020 * * Revisionsliste * Datum | Autor | Änderung * ------------+---------------+-------------------------- * 29.05.2020 | Altenburg | Ersterstellung * ------------+---------------+-------------------------- * 04.02.2021 | Altenburg | syntaktische Korrekturen * ------------+---------------+-------------------------- * ********************************************************************/ #include "mbed.h" #include "main.h" #include "oled.h" DigitalOut pinLed4(PC_0); /* SCL - I2C; rote LED2 */ DigitalInOut pinLed2(PC_2); /* SDA - I2C; grüne LED */ DigitalOut pinLed3(PC_7); /* rote LED1 */ /* Interruptprioritäten */ #define nSystickLevel 31 /* niedrigste Priorität */ #define nMillisecLevel 30 /* aufsteigende Priorität */ #define nSbusTimerLevel 29 #define nSbusUartLevel 28 /* Interrupts global freigeben/sperren */ #define mcIntEnable() \ { __asm(" cpsie i\n"); } #define mcIntDisable() \ { __asm(" cpsid i\n"); } void vWaitFast( void ); /* 200 ms Warten */ void vWaitSlow( void ); /* 1 Sekunde warten */ volatile word wTimer;/* * Description : */ Def_fFunc afFuncList[] = { vWaitFast, vWaitSlow };/* * Description : Liste mit Funktionen */ Def_fFunc *pafFuncList;/* * Description : Zeiger auf Funktionspointerliste */ /**************************************************************************** * Init Systemclock * PLLCFGR 0b00100010010000100010110100000100 Reserved: 0 PLLR: 010 = 2 PLLQ: 0010 = 2 Reserved: 0 PLLSRC: 1 = HSE Reserved: 00 00 PLLP: 10 = 6 PLLN: 0010110100 = 180 PLLM: 000100 = 4 CFGR 0b00000000000000001011010000001111 PPRE: 101 = AHB2 clock divided by 4 PPRE: 101 = AHB1 clock divided by 4 Reserved: 00 = HPRE: 0000 = AHB prescaler divided by 1 SWS: 11 = PLL_R used as the system clock SW: 11 = PLL_R selected as system clock * Author : J. Altenburg (based on C. Hilgert) * * Revison : 17.07.17 * * Parameters * * Input : Nothing * * Output : Nothing * ****************************************************************************/ void vSysClockInit(void) { volatile dword dw; RCC->APB1ENR |= RCC_APB1ENR_PWREN; /* __PWR_CLK_ENABLE(); */ PWR->CR |= 0x0000C000; /* VOS[1:0] Scale 1 = 0b11 */ dw = RCC->PLLCFGR; dw = 0x22422d04; /* PLLCFG-Register einstellen */ RCC->PLLCFGR = dw; PWR->CR |= PWR_CR_ODEN; /* overdrive enable */ while ((PWR->CSR & PWR_CSR_ODRDY) == 0);/* wait until overdrive is ready */ PWR->CR |= PWR_CR_ODSWEN; RCC->CR |= RCC_CR_HSEON; /* 1. Clocking the controller from external HSC crystal (8 MHz) */ while ((RCC->CR & RCC_CR_HSERDY) == 0); /* wait until the HSE is ready */ RCC->CR |= RCC_CR_PLLON; /* 2. PLL on */ while ((RCC->CR & RCC_CR_PLLRDY) == 0); /* wait until PLL is locked */ FLASH->ACR = FLASH_ACR_LATENCY_5WS; /* Zugriffsverz?gerung */ dw = RCC->CFGR; dw |= (RCC_CFGR_PPRE2_DIV4 | RCC_CFGR_PPRE1_DIV4 | RCC_CFGR_HPRE_DIV1 | RCC_CFGR_SW_PLLR); RCC->CFGR = dw; /* APB2 = 45 MHz, APB1 = 45 MHz */ } /**************************************************************************** * Init-Port - A * * Author : J. Altenburg (based on C. Hilgert) * * Revison : 17.07.17 * * Parameters * * Input : Nothing * * Output : Nothing * * Hinweis : Beschreibung GPIO_AFR[x] Table 11 im Datasheet * ****************************************************************************/ void vPortAInit(void) { dword dw; RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; /* GPIO-Port A initialisieren */ dw = GPIOA->MODER; dw &= ~(GPIO_MODER_MODE15_Msk /* PA15 maskieren */ | GPIO_MODER_MODE0_Msk /* PA0 - UART4 TX */ | GPIO_MODER_MODE1_Msk /* PA1 - UART4 RX */ | GPIO_MODER_MODE2_Msk /* PA2 - UART2 TX */ | GPIO_MODER_MODE3_Msk /* PA3 - UART2 RX */ | GPIO_MODER_MODE4_Msk /* PA4 - SPI1_CS */ | GPIO_MODER_MODE5_Msk /* PA5 - SPI1 SCK */ | GPIO_MODER_MODE6_Msk /* PA6 - SPI1 MISO */ | GPIO_MODER_MODE7_Msk /* PA7 - SPI1 MOSI */ | GPIO_MODER_MODE9_Msk /* PA9 - UART1 TX */ | GPIO_MODER_MODE10_Msk /* PA10- UART1 RX */ ); dw |= (GPIO_MODER_MODE15_0 /* PA15- output */ | GPIO_MODER_MODE0_1 /* PA0 - alternate output */ | GPIO_MODER_MODE1_1 /* PA1 - alternate output */ | GPIO_MODER_MODE2_1 /* PA2 - alternate output */ | GPIO_MODER_MODE3_1 /* PA3 - alternate output */ | GPIO_MODER_MODE4_0 /* PA4 - output */ | GPIO_MODER_MODE5_1 /* PA5 - alternate output */ | GPIO_MODER_MODE6_1 /* PA6 - alternate output */ | GPIO_MODER_MODE7_1 /* PA7 - alternate output */ | GPIO_MODER_MODE9_1 /* PA9 - alternate output */ | GPIO_MODER_MODE10_1 /* PA10- alternate output */ ); GPIOA->MODER = dw; dw = GPIOA->OTYPER; dw |= GPIO_OTYPER_OT15; /* open drain */ //GPIOA->OTYPER = dw; dw = GPIOA->OSPEEDR; dw |= GPIO_OSPEEDR_OSPEED15_1; GPIOA->AFR[0] = 0x55507788; GPIOA->AFR[1] = 0x00000770; //vCS1High(); /* CS BME280 inaktiv */ } /*************************************************************************** * Init Systemticker * Author : J. Altenburg * Revison : 17.07.17 * Parameters – alle 15 Millisekunden einen Interrupt ***************************************************************************/ void vSystickInit( void ) { NVIC_SetPriority(SysTick_IRQn, nSystickLevel); /* INT freigeben */ /* 15m/180MHz^-1 set reload register = 15 Millisekunden */ SysTick->LOAD = (2700000 - 1); SysTick->VAL = 0; /* Init Counter */ SysTick->CTRL = ( SysTick_CTRL_ENABLE_Msk |SysTick_CTRL_CLKSOURCE_Msk |SysTick_CTRL_TICKINT_Msk ); } /**************************************************************************** * Timer2 * * Author : J. Altenburg * * Revison : 18.07.17 * * Parameters * * Input : Nothing * * Output : Nothing * ****************************************************************************/ void vTimer2Init(void) { RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; /* Power on */ TIM2->PSC = 8; /* 90MHz^-1 * (8+1) = 100 ns */ TIM2->ARR = 60000; /* 100ns * 10000 = 1 ms */ TIM2->CR1 &= ~TIM_CR1_DIR; /* aufw?rts z?hlen */ //TIM2->CCR1 = 20000; NVIC_SetPriority(TIM2_IRQn, nMillisecLevel); NVIC_EnableIRQ(TIM2_IRQn); TIM2->DIER = TIM_DIER_CC1IE; /* compare interrupt enable */ TIM2->CR1 |= TIM_CR1_CEN; } /**************************************************************************** * Timer4 als Interruptquelle Uhrzeiger-Arithmetik * * Author : J. Altenburg * * Revison : 21.05.20 * * Parameters * * Input : Nothing * * Output : Nothing * ****************************************************************************/ void vTimer4Init(void) { RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; /* Power on */ TIM4->PSC = 8; /* 90MHz^-1 * (8+1) = 100 ns */ TIM4->ARR = 0xffff; /* 100ns * 10000 = 1 ms */ TIM4->CR1 &= ~TIM_CR1_DIR; /* aufwärts zählen */ TIM4->CCR1 = 15000; NVIC_SetPriority(TIM4_IRQn, nMillisecLevel); NVIC_EnableIRQ(TIM4_IRQn); TIM4->DIER = TIM_DIER_CC1IE; /* compare interrupt enable */ TIM4->CR1 |= TIM_CR1_CEN; } /**************************************************************************** * UART 2 * Author : J. Altenburg * Revison : 20.07.17 ****************************************************************************/ void vUart2Init(void) { RCC->APB1ENR |= RCC_APB1ENR_USART2EN; /* UART2 freigeben */ USART2->CR3 = 0; /* Reset-Value */ /* 1 Stop Bit; Keine Parität; 8-Databits */ USART2->CR1 |= (USART_CR1_UE + USART_CR1_RXNEIE + USART_CR1_RE + USART_CR1_TCIE + USART_CR1_TE); /* Baudrate UART */ /* Bit 0-3 sind Fraction->Kommazahl; 15-4 sind Mantissa->ganze Zahl */ /* UARTDIV = f/(Baud*16); UART5->BRR = UARTDIV << 4 | UARTDIV_Komma */ /* 146.48 = 45MHz/(19200 * 16) */ USART2->BRR = (word)((146 << 4) | 5); #if 0 NVIC_SetPriority(USART2_IRQn, nMillisecLevel); /* Prioritaet */ NVIC_EnableIRQ(USART2_IRQn); #endif } /**************************************************************************** * ISR - Systemtimer * * - Aufruf der APPs alle x ms * * - Aufruf des "Millisekunden"-Containers * * Author : J. Altenburg * * Revison : 17.07.17 * ****************************************************************************/ extern "C" void SysTick_Handler( void ){ SysTick->CTRL &= ~SysTick_CTRL_COUNTFLAG_Msk; //GPIOA->ODR ^= (1<<15); /* Testsignal auf GPIO legen */ } /**************************************************************************** * ISR - Timer 2 * * Author : J. Altenburg * * Revison : 30.08.17 * * Parameters * * Laufzeit: x.y µs * ****************************************************************************/ extern "C" void TIM2_IRQHandler(void) { //volatile word w; TIM2->SR &= ~TIM_SR_CC1IF; /* clear pending bit (sicherheitshalber) */ //TIM2->CCR1 += 10000; //GPIOA->ODR ^= (1<<15); //pinLed2 = !pinLed2; } /**************************************************************************** * ISR - Timer 4 * * Author : J. Altenburg * * Revison : 30.08.17 * * Parameters * * Laufzeit: x.y µs * ****************************************************************************/ extern "C" void TIM4_IRQHandler(void) { //volatile word w; TIM4->SR &= ~TIM_SR_CC1IF; /* clear pending bit (sicherheitshalber) */ TIM4->CCR1 += wTimer; wTimer += 1500; //GPIOA->ODR ^= (1<<15); /* Testsignal auf GPIO legen */ } /* I2C - Zugriff */ void vSDAOutput( void ){ /* SDA-Datenrichtung -> Output */ pinLed2.output(); /* auf Ausgang setzen */ } void vSDAInput( void ){ /* SDA-Datenrichtung -> Input */ pinLed2.input(); /* auf Ausgang setzen */ } void vSDA_H( void ){ /* SDA setzen */ pinLed2 = On; } void vSDA_L( void ){ /* SDA löschen */ pinLed2 = Off; } void vSCL_H( void ){ /* SCL setzen */ pinLed4 = On; } void vSCL_L( void ){ /* SCL löschen */ pinLed4 = Off; } void vI2CDelay( void ){ /* ca. 5µs Verzögerung */ volatile word wDelay = 6; while(wDelay--); } void vI2CShort( void ){ /* ca. 5µs Verzögerung */ volatile word wDelay = 2; while(wDelay--); } /* schnelles Blinken */ void vWaitFast( void ){ wait(0.2); } /* langsames Blinken */ void vWaitSlow( void ){ wait(1); } Def_stValue stRaw1 = {1,1,1,1,1,1,1,1}; Def_stValue stRaw2 = {2,2,2,2,2,2,2,2}; byte bAverage1(Def_stValue stLocal){ byte i, j = 0; for(i = 0; i < 8; i++){ j = j + stLocal.abData[i]; } return j>>3; } void vAverage2(byte *pAverage, Def_stValue *stLocal){ byte i, j = 0; for(i = 0; i < 8; i++){ j = j + stLocal->abData[i]; } *pAverage = (j>>3); } int main() { byte abText[] = "Hallo OLED!"; dword dwTime = 11; byte bPos = 0; byte i = 'A'; byte y = 0; pinLed2.mode(OpenDrain); /* bidirektionaler Pin */ //pinLed2.output(); /* auf Ausgang setzen */ mcIntDisable(); vSysClockInit(); vPortAInit(); vSystickInit(); vTimer2Init(); vTimer4Init(); vUart2Init(); mcIntEnable(); vOledInit(); ssd1306_fill4(255, 255, 255, 255); ssd1306_fill4(0, 0, 0, 0); pafFuncList = &afFuncList[0]; /* referenzieren auf Liste */ y = bAverage1(stRaw1); ssd1306tx_large(y+'0', 4, 10); vAverage2(&y, &stRaw2); ssd1306tx_large(y+'0', 4, 2); y = 1; while(1) { #if 1 bPos = 0; for(i = 0; i < sizeof(abText)-1; i++){ pinLed3 = 0; ssd1306tx_large(abText[i], bPos, 6); bPos = bPos + 9; pinLed3 = 1; USART2->DR = 'J'; (*(pafFuncList + y))(); /* unterschiedliche Wartezeiten */ dwTime--; if(dwTime == 0){ dwTime = 11; (y == 0) ? y = 1 : y = 0; ssd1306_fill4(0, 0, 0, 0); } GPIOA->ODR ^= (1<<15); } #else dwTime = 10000000; while(dwTime--); pinLed3 = 0; ssd1306_setpos(0,0); //ssd1306_setpos(bPos, y); //ssd1306tx_char(i); ssd1306tx_large(i, bPos, y); pinLed3 = 1; if(i < 'Z') i++; else i = 'A'; bPos = bPos + 9; y = y + 2; #endif } }