Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp
00001 /******************************************************************** 00002 * 00003 * Name: main.cpp 00004 * Beschreibung: HAL für "Embedded Systems Engineering" 00005 * Autor: 00006 * Erstellung: 29.05.2020 00007 * 00008 * Revisionsliste 00009 * Datum | Autor | Änderung 00010 * ------------+---------------+-------------------------- 00011 * 29.05.2020 | Altenburg | Ersterstellung 00012 * ------------+---------------+-------------------------- 00013 * 04.02.2021 | Altenburg | syntaktische Korrekturen 00014 * ------------+---------------+-------------------------- 00015 * 00016 ********************************************************************/ 00017 #include "mbed.h" 00018 #include "main.h" 00019 #include "oled.h" 00020 00021 DigitalOut pinLed4(PC_0); /* SCL - I2C; rote LED2 */ 00022 DigitalInOut pinLed2(PC_2); /* SDA - I2C; grüne LED */ 00023 00024 DigitalOut pinLed3(PC_7); /* rote LED1 */ 00025 00026 /* Interruptprioritäten */ 00027 #define nSystickLevel 31 /* niedrigste Priorität */ 00028 #define nMillisecLevel 30 /* aufsteigende Priorität */ 00029 #define nSbusTimerLevel 29 00030 #define nSbusUartLevel 28 00031 00032 /* Interrupts global freigeben/sperren */ 00033 #define mcIntEnable() \ 00034 { __asm(" cpsie i\n"); } 00035 #define mcIntDisable() \ 00036 { __asm(" cpsid i\n"); } 00037 00038 void vWaitFast( void ); /* 200 ms Warten */ 00039 void vWaitSlow( void ); /* 1 Sekunde warten */ 00040 00041 volatile word wTimer;/* 00042 * Description : 00043 */ 00044 Def_fFunc afFuncList[] = { vWaitFast, vWaitSlow };/* 00045 * Description : Liste mit Funktionen 00046 */ 00047 Def_fFunc *pafFuncList;/* 00048 * Description : Zeiger auf Funktionspointerliste 00049 */ 00050 00051 /**************************************************************************** 00052 * Init Systemclock * 00053 PLLCFGR 0b00100010010000100010110100000100 00054 Reserved: 0 00055 PLLR: 010 = 2 00056 PLLQ: 0010 = 2 00057 Reserved: 0 00058 PLLSRC: 1 = HSE 00059 Reserved: 00 00 00060 PLLP: 10 = 6 00061 PLLN: 0010110100 = 180 00062 PLLM: 000100 = 4 00063 00064 CFGR 0b00000000000000001011010000001111 00065 PPRE: 101 = AHB2 clock divided by 4 00066 PPRE: 101 = AHB1 clock divided by 4 00067 Reserved: 00 = 00068 HPRE: 0000 = AHB prescaler divided by 1 00069 SWS: 11 = PLL_R used as the system clock 00070 SW: 11 = PLL_R selected as system clock 00071 00072 * Author : J. Altenburg (based on C. Hilgert) * 00073 * Revison : 17.07.17 * 00074 * Parameters * 00075 * Input : Nothing * 00076 * Output : Nothing * 00077 ****************************************************************************/ 00078 void vSysClockInit(void) { 00079 volatile dword dw; 00080 RCC->APB1ENR |= RCC_APB1ENR_PWREN; /* __PWR_CLK_ENABLE(); */ 00081 PWR->CR |= 0x0000C000; /* VOS[1:0] Scale 1 = 0b11 */ 00082 dw = RCC->PLLCFGR; 00083 dw = 0x22422d04; /* PLLCFG-Register einstellen */ 00084 RCC->PLLCFGR = dw; 00085 PWR->CR |= PWR_CR_ODEN; /* overdrive enable */ 00086 while ((PWR->CSR & PWR_CSR_ODRDY) == 0);/* wait until overdrive is ready */ 00087 PWR->CR |= PWR_CR_ODSWEN; 00088 RCC->CR |= RCC_CR_HSEON; /* 1. Clocking the controller from external HSC crystal (8 MHz) */ 00089 while ((RCC->CR & RCC_CR_HSERDY) == 0); /* wait until the HSE is ready */ 00090 RCC->CR |= RCC_CR_PLLON; /* 2. PLL on */ 00091 while ((RCC->CR & RCC_CR_PLLRDY) == 0); /* wait until PLL is locked */ 00092 FLASH->ACR = FLASH_ACR_LATENCY_5WS; /* Zugriffsverz?gerung */ 00093 dw = RCC->CFGR; 00094 dw |= (RCC_CFGR_PPRE2_DIV4 | RCC_CFGR_PPRE1_DIV4 | RCC_CFGR_HPRE_DIV1 | RCC_CFGR_SW_PLLR); 00095 RCC->CFGR = dw; /* APB2 = 45 MHz, APB1 = 45 MHz */ 00096 } 00097 00098 /**************************************************************************** 00099 * Init-Port - A * 00100 * Author : J. Altenburg (based on C. Hilgert) * 00101 * Revison : 17.07.17 * 00102 * Parameters * 00103 * Input : Nothing * 00104 * Output : Nothing * 00105 * Hinweis : Beschreibung GPIO_AFR[x] Table 11 im Datasheet * 00106 ****************************************************************************/ 00107 void vPortAInit(void) { 00108 dword dw; 00109 RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; /* GPIO-Port A initialisieren */ 00110 dw = GPIOA->MODER; 00111 dw &= ~(GPIO_MODER_MODE15_Msk /* PA15 maskieren */ 00112 | GPIO_MODER_MODE0_Msk /* PA0 - UART4 TX */ 00113 | GPIO_MODER_MODE1_Msk /* PA1 - UART4 RX */ 00114 | GPIO_MODER_MODE2_Msk /* PA2 - UART2 TX */ 00115 | GPIO_MODER_MODE3_Msk /* PA3 - UART2 RX */ 00116 | GPIO_MODER_MODE4_Msk /* PA4 - SPI1_CS */ 00117 | GPIO_MODER_MODE5_Msk /* PA5 - SPI1 SCK */ 00118 | GPIO_MODER_MODE6_Msk /* PA6 - SPI1 MISO */ 00119 | GPIO_MODER_MODE7_Msk /* PA7 - SPI1 MOSI */ 00120 | GPIO_MODER_MODE9_Msk /* PA9 - UART1 TX */ 00121 | GPIO_MODER_MODE10_Msk /* PA10- UART1 RX */ 00122 ); 00123 dw |= (GPIO_MODER_MODE15_0 /* PA15- output */ 00124 | GPIO_MODER_MODE0_1 /* PA0 - alternate output */ 00125 | GPIO_MODER_MODE1_1 /* PA1 - alternate output */ 00126 | GPIO_MODER_MODE2_1 /* PA2 - alternate output */ 00127 | GPIO_MODER_MODE3_1 /* PA3 - alternate output */ 00128 | GPIO_MODER_MODE4_0 /* PA4 - output */ 00129 | GPIO_MODER_MODE5_1 /* PA5 - alternate output */ 00130 | GPIO_MODER_MODE6_1 /* PA6 - alternate output */ 00131 | GPIO_MODER_MODE7_1 /* PA7 - alternate output */ 00132 | GPIO_MODER_MODE9_1 /* PA9 - alternate output */ 00133 | GPIO_MODER_MODE10_1 /* PA10- alternate output */ 00134 ); 00135 GPIOA->MODER = dw; 00136 dw = GPIOA->OTYPER; 00137 dw |= GPIO_OTYPER_OT15; /* open drain */ 00138 //GPIOA->OTYPER = dw; 00139 dw = GPIOA->OSPEEDR; 00140 dw |= GPIO_OSPEEDR_OSPEED15_1; 00141 00142 GPIOA->AFR[0] = 0x55507788; 00143 GPIOA->AFR[1] = 0x00000770; 00144 //vCS1High(); /* CS BME280 inaktiv */ 00145 } 00146 00147 /*************************************************************************** 00148 * Init Systemticker 00149 * Author : J. Altenburg 00150 * Revison : 17.07.17 00151 * Parameters – alle 15 Millisekunden einen Interrupt 00152 ***************************************************************************/ 00153 void vSystickInit( void ) { 00154 NVIC_SetPriority(SysTick_IRQn, nSystickLevel); /* INT freigeben */ 00155 /* 15m/180MHz^-1 set reload register = 15 Millisekunden */ 00156 SysTick->LOAD = (2700000 - 1); 00157 SysTick->VAL = 0; /* Init Counter */ 00158 SysTick->CTRL = ( SysTick_CTRL_ENABLE_Msk 00159 |SysTick_CTRL_CLKSOURCE_Msk 00160 |SysTick_CTRL_TICKINT_Msk 00161 ); 00162 } 00163 00164 00165 /**************************************************************************** 00166 * Timer2 * 00167 * Author : J. Altenburg * 00168 * Revison : 18.07.17 * 00169 * Parameters * 00170 * Input : Nothing * 00171 * Output : Nothing * 00172 ****************************************************************************/ 00173 void vTimer2Init(void) { 00174 RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; /* Power on */ 00175 TIM2->PSC = 8; /* 90MHz^-1 * (8+1) = 100 ns */ 00176 TIM2->ARR = 60000; /* 100ns * 10000 = 1 ms */ 00177 TIM2->CR1 &= ~TIM_CR1_DIR; /* aufw?rts z?hlen */ 00178 //TIM2->CCR1 = 20000; 00179 NVIC_SetPriority(TIM2_IRQn, nMillisecLevel); 00180 NVIC_EnableIRQ(TIM2_IRQn); 00181 TIM2->DIER = TIM_DIER_CC1IE; /* compare interrupt enable */ 00182 TIM2->CR1 |= TIM_CR1_CEN; 00183 } 00184 00185 /**************************************************************************** 00186 * Timer4 als Interruptquelle Uhrzeiger-Arithmetik * 00187 * Author : J. Altenburg * 00188 * Revison : 21.05.20 * 00189 * Parameters * 00190 * Input : Nothing * 00191 * Output : Nothing * 00192 ****************************************************************************/ 00193 void vTimer4Init(void) { 00194 RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; /* Power on */ 00195 TIM4->PSC = 8; /* 90MHz^-1 * (8+1) = 100 ns */ 00196 TIM4->ARR = 0xffff; /* 100ns * 10000 = 1 ms */ 00197 TIM4->CR1 &= ~TIM_CR1_DIR; /* aufwärts zählen */ 00198 TIM4->CCR1 = 15000; 00199 NVIC_SetPriority(TIM4_IRQn, nMillisecLevel); 00200 NVIC_EnableIRQ(TIM4_IRQn); 00201 TIM4->DIER = TIM_DIER_CC1IE; /* compare interrupt enable */ 00202 TIM4->CR1 |= TIM_CR1_CEN; 00203 } 00204 00205 /**************************************************************************** 00206 * UART 2 00207 * Author : J. Altenburg 00208 * Revison : 20.07.17 00209 ****************************************************************************/ 00210 void vUart2Init(void) { 00211 RCC->APB1ENR |= RCC_APB1ENR_USART2EN; /* UART2 freigeben */ 00212 USART2->CR3 = 0; /* Reset-Value */ 00213 /* 1 Stop Bit; Keine Parität; 8-Databits */ 00214 USART2->CR1 |= (USART_CR1_UE + USART_CR1_RXNEIE + USART_CR1_RE + USART_CR1_TCIE + USART_CR1_TE); 00215 /* Baudrate UART */ 00216 /* Bit 0-3 sind Fraction->Kommazahl; 15-4 sind Mantissa->ganze Zahl */ 00217 /* UARTDIV = f/(Baud*16); UART5->BRR = UARTDIV << 4 | UARTDIV_Komma */ 00218 /* 146.48 = 45MHz/(19200 * 16) */ 00219 USART2->BRR = (word)((146 << 4) | 5); 00220 #if 0 00221 NVIC_SetPriority(USART2_IRQn, nMillisecLevel); /* Prioritaet */ 00222 NVIC_EnableIRQ(USART2_IRQn); 00223 #endif 00224 } 00225 00226 00227 00228 /**************************************************************************** 00229 * ISR - Systemtimer * 00230 * - Aufruf der APPs alle x ms * 00231 * - Aufruf des "Millisekunden"-Containers * 00232 * Author : J. Altenburg * 00233 * Revison : 17.07.17 * 00234 ****************************************************************************/ 00235 extern "C" void SysTick_Handler( void ){ 00236 SysTick->CTRL &= ~SysTick_CTRL_COUNTFLAG_Msk; 00237 //GPIOA->ODR ^= (1<<15); /* Testsignal auf GPIO legen */ 00238 } 00239 00240 00241 /**************************************************************************** 00242 * ISR - Timer 2 * 00243 * Author : J. Altenburg * 00244 * Revison : 30.08.17 * 00245 * Parameters * 00246 * Laufzeit: x.y µs * 00247 ****************************************************************************/ 00248 extern "C" void TIM2_IRQHandler(void) { 00249 //volatile word w; 00250 TIM2->SR &= ~TIM_SR_CC1IF; /* clear pending bit (sicherheitshalber) */ 00251 //TIM2->CCR1 += 10000; 00252 //GPIOA->ODR ^= (1<<15); 00253 //pinLed2 = !pinLed2; 00254 } 00255 00256 /**************************************************************************** 00257 * ISR - Timer 4 * 00258 * Author : J. Altenburg * 00259 * Revison : 30.08.17 * 00260 * Parameters * 00261 * Laufzeit: x.y µs * 00262 ****************************************************************************/ 00263 extern "C" void TIM4_IRQHandler(void) { 00264 //volatile word w; 00265 TIM4->SR &= ~TIM_SR_CC1IF; /* clear pending bit (sicherheitshalber) */ 00266 TIM4->CCR1 += wTimer; 00267 wTimer += 1500; 00268 //GPIOA->ODR ^= (1<<15); /* Testsignal auf GPIO legen */ 00269 } 00270 00271 /* I2C - Zugriff */ 00272 void vSDAOutput( void ){ /* SDA-Datenrichtung -> Output */ 00273 pinLed2.output(); /* auf Ausgang setzen */ 00274 } 00275 00276 void vSDAInput( void ){ /* SDA-Datenrichtung -> Input */ 00277 pinLed2.input(); /* auf Ausgang setzen */ 00278 } 00279 00280 void vSDA_H( void ){ /* SDA setzen */ 00281 pinLed2 = On; 00282 } 00283 00284 void vSDA_L( void ){ /* SDA löschen */ 00285 pinLed2 = Off; 00286 } 00287 00288 void vSCL_H( void ){ /* SCL setzen */ 00289 pinLed4 = On; 00290 } 00291 00292 void vSCL_L( void ){ /* SCL löschen */ 00293 pinLed4 = Off; 00294 } 00295 00296 00297 void vI2CDelay( void ){ /* ca. 5µs Verzögerung */ 00298 volatile word wDelay = 6; 00299 while(wDelay--); 00300 } 00301 00302 void vI2CShort( void ){ /* ca. 5µs Verzögerung */ 00303 volatile word wDelay = 2; 00304 while(wDelay--); 00305 } 00306 /* schnelles Blinken */ 00307 void vWaitFast( void ){ 00308 wait(0.2); 00309 } 00310 00311 /* langsames Blinken */ 00312 void vWaitSlow( void ){ 00313 wait(1); 00314 } 00315 00316 Def_stValue stRaw1 = {1,1,1,1,1,1,1,1}; 00317 Def_stValue stRaw2 = {2,2,2,2,2,2,2,2}; 00318 00319 byte bAverage1(Def_stValue stLocal){ 00320 byte i, j = 0; 00321 for(i = 0; i < 8; i++){ 00322 j = j + stLocal.abData[i]; 00323 } 00324 return j>>3; 00325 } 00326 00327 void vAverage2(byte *pAverage, Def_stValue *stLocal){ 00328 byte i, j = 0; 00329 for(i = 0; i < 8; i++){ 00330 j = j + stLocal->abData[i]; 00331 } 00332 *pAverage = (j>>3); 00333 } 00334 00335 00336 int main() { 00337 byte abText[] = "Hallo OLED!"; 00338 dword dwTime = 11; 00339 byte bPos = 0; 00340 byte i = 'A'; 00341 byte y = 0; 00342 pinLed2.mode(OpenDrain); /* bidirektionaler Pin */ 00343 //pinLed2.output(); /* auf Ausgang setzen */ 00344 mcIntDisable(); 00345 vSysClockInit(); 00346 vPortAInit(); 00347 vSystickInit(); 00348 vTimer2Init(); 00349 vTimer4Init(); 00350 vUart2Init(); 00351 mcIntEnable(); 00352 vOledInit(); 00353 ssd1306_fill4(255, 255, 255, 255); 00354 ssd1306_fill4(0, 0, 0, 0); 00355 pafFuncList = &afFuncList[0]; /* referenzieren auf Liste */ 00356 y = bAverage1(stRaw1); 00357 ssd1306tx_large(y+'0', 4, 10); 00358 vAverage2(&y, &stRaw2); 00359 ssd1306tx_large(y+'0', 4, 2); 00360 y = 1; 00361 while(1) { 00362 #if 1 00363 bPos = 0; 00364 for(i = 0; i < sizeof(abText)-1; i++){ 00365 pinLed3 = 0; 00366 ssd1306tx_large(abText[i], bPos, 6); 00367 bPos = bPos + 9; 00368 pinLed3 = 1; 00369 USART2->DR = 'J'; 00370 (*(pafFuncList + y))(); /* unterschiedliche Wartezeiten */ 00371 dwTime--; 00372 if(dwTime == 0){ 00373 dwTime = 11; 00374 (y == 0) ? y = 1 : y = 0; 00375 ssd1306_fill4(0, 0, 0, 0); 00376 } 00377 GPIOA->ODR ^= (1<<15); 00378 } 00379 #else 00380 dwTime = 10000000; 00381 while(dwTime--); 00382 pinLed3 = 0; 00383 ssd1306_setpos(0,0); 00384 //ssd1306_setpos(bPos, y); 00385 //ssd1306tx_char(i); 00386 ssd1306tx_large(i, bPos, y); 00387 pinLed3 = 1; 00388 if(i < 'Z') i++; 00389 else i = 'A'; 00390 bPos = bPos + 9; 00391 y = y + 2; 00392 #endif 00393 } 00394 }
Generated on Wed Aug 3 2022 18:44:12 by
1.7.2