1 | /*********************************************************************
|
2 | * SEGGER Microcontroller GmbH *
|
3 | * The Embedded Experts *
|
4 | **********************************************************************
|
5 | * *
|
6 | * (c) 2014 - 2020 SEGGER Microcontroller GmbH *
|
7 | * *
|
8 | * www.segger.com Support: support@segger.com *
|
9 | * *
|
10 | **********************************************************************
|
11 | * *
|
12 | * All rights reserved. *
|
13 | * *
|
14 | * Redistribution and use in source and binary forms, with or *
|
15 | * without modification, are permitted provided that the following *
|
16 | * conditions are met: *
|
17 | * *
|
18 | * - Redistributions of source code must retain the above copyright *
|
19 | * notice, this list of conditions and the following disclaimer. *
|
20 | * *
|
21 | * - Neither the name of SEGGER Microcontroller GmbH *
|
22 | * nor the names of its contributors may be used to endorse or *
|
23 | * promote products derived from this software without specific *
|
24 | * prior written permission. *
|
25 | * *
|
26 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
|
27 | * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
|
28 | * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
29 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
|
30 | * DISCLAIMED. *
|
31 | * IN NO EVENT SHALL SEGGER Microcontroller GmbH BE LIABLE FOR *
|
32 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR *
|
33 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT *
|
34 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
35 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
|
36 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT *
|
37 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *
|
38 | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
|
39 | * DAMAGE. *
|
40 | * *
|
41 | **********************************************************************
|
42 |
|
43 | -------------------------- END-OF-HEADER -----------------------------
|
44 |
|
45 | File : main.c
|
46 | Purpose : Generic application start
|
47 |
|
48 | */
|
49 |
|
50 | //#include <stdio.h>
|
51 | //#include <stdlib.h>
|
52 |
|
53 | #include <stm32f4xx.h>
|
54 | #include "SEGGER_SYSVIEW.h"
|
55 |
|
56 | void ClockInit(void)
|
57 | {
|
58 | uint32_t timeout = 1000000;
|
59 |
|
60 | // enable flash prefetch
|
61 | FLASH->ACR |= FLASH_ACR_PRFTEN;
|
62 | // set 5 wait states (needed for high PLL frequency)
|
63 | FLASH->ACR &= ~FLASH_ACR_LATENCY_Msk;
|
64 | FLASH->ACR |= FLASH_ACR_LATENCY_5WS;
|
65 | do
|
66 | {
|
67 | timeout--;
|
68 | } while (((FLASH->ACR & FLASH_ACR_LATENCY_Msk) != FLASH_ACR_LATENCY_5WS) && (timeout > 0));
|
69 |
|
70 | // switch on external clock, bypass HSE with it and wait for clock to be ready
|
71 | RCC->CR |= (RCC_CR_HSEON | RCC_CR_HSEBYP);
|
72 | timeout = 1000000;
|
73 | do
|
74 | {
|
75 | timeout--;
|
76 | } while (((RCC->CR & RCC_CR_HSERDY_Msk) != RCC_CR_HSERDY) && (timeout > 0));
|
77 |
|
78 | // configure (HSE as clock source, M = 4, N = 180, P = 2), enable and wait for PLL
|
79 | RCC->PLLCFGR = (RCC_PLLCFGR_PLLSRC_HSE | (4 << RCC_PLLCFGR_PLLM_Pos) | (180 << RCC_PLLCFGR_PLLN_Pos));
|
80 | RCC->CR |= RCC_CR_PLLON;
|
81 | timeout = 1000000;
|
82 | do
|
83 | {
|
84 | timeout--;
|
85 | } while (((RCC->CR & RCC_CR_PLLRDY_Msk) != RCC_CR_PLLRDY) && (timeout > 0));
|
86 |
|
87 | // configure rest of clock tree
|
88 | RCC->CFGR &= ~(RCC_CFGR_PPRE2_Msk | RCC_CFGR_PPRE1_Msk | RCC_CFGR_HPRE_Msk);
|
89 | RCC->CFGR |= (RCC_CFGR_PPRE2_DIV2 | RCC_CFGR_PPRE1_DIV4 | RCC_CFGR_HPRE_DIV1);
|
90 |
|
91 | // set PLL as clock source and wait until clock is ready
|
92 | RCC->CFGR &= ~(RCC_CFGR_SW_Msk);
|
93 | RCC->CFGR |= RCC_CFGR_SW_PLL;
|
94 | timeout = 1000000;
|
95 | do
|
96 | {
|
97 | timeout--;
|
98 | } while (((RCC->CFGR & RCC_CFGR_SWS_Msk) != RCC_CFGR_SWS_PLL) && (timeout > 0));
|
99 |
|
100 | SystemCoreClockUpdate();
|
101 |
|
102 | // enable GPIOA, ADC1, TIM1 and TIM2 clocks
|
103 | RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
|
104 | RCC->APB2ENR |= RCC_APB2ENR_ADC1EN;
|
105 | RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
|
106 | }
|
107 |
|
108 | void TimerInit(void)
|
109 | {
|
110 | // counter direction down, generate update event only on underflow
|
111 | TIM2->CR1 |= (TIM_CR1_DIR | TIM_CR1_URS);
|
112 | // set update event as trigger source
|
113 | TIM2->CR2 &= ~TIM_CR2_MMS_Msk;
|
114 | TIM2->CR2 |= TIM_CR2_MMS_1;
|
115 | // enable update interrupt
|
116 | TIM2->DIER |= TIM_DIER_UIE;
|
117 | // set timer and reload value for update generation every 1000 ms
|
118 | TIM2->ARR = TIM2->CNT = 90000000;
|
119 | }
|
120 |
|
121 | void TimerStart(void)
|
122 | {
|
123 | TIM2->CR1 |= TIM_CR1_CEN;
|
124 | }
|
125 |
|
126 | void AdcInit(void)
|
127 | {
|
128 | // PA3 as analog input
|
129 | GPIOA->MODER |= GPIO_MODER_MODE3;
|
130 | // set clock prescaler to 4 -> 22,5 MHz
|
131 | ADC123_COMMON->CCR |= ADC_CCR_ADCPRE_0;
|
132 | // enable timer 2 trigger event as start trigger on rising edge and generate EOC interrupt after each conversion
|
133 | ADC1->CR2 |= (ADC_CR2_EXTSEL_2 | ADC_CR2_EXTSEL_1 | ADC_CR2_EXTEN_0 | ADC_CR2_EOCS);
|
134 | // set 480 cycles sample time for channel 3
|
135 | ADC1->SMPR2 |= ADC_SMPR2_SMP3;
|
136 | // set channel 3 as first (any only) regular channel
|
137 | ADC1->SQR3 |= (ADC_SQR3_SQ1_2 | ADC_SQR3_SQ1_1);
|
138 | // enable EOC interrupt
|
139 | ADC1->CR1 |= ADC_CR1_EOCIE;
|
140 | // enable ADC
|
141 | ADC1->CR2 |= ADC_CR2_ADON;
|
142 | }
|
143 |
|
144 | void InterruptInit(void)
|
145 | {
|
146 | // Timer 2
|
147 | NVIC_SetPriority(TIM2_IRQn, 3);
|
148 | NVIC_ClearPendingIRQ(TIM2_IRQn);
|
149 | NVIC_EnableIRQ(TIM2_IRQn);
|
150 | // ADC
|
151 | NVIC_SetPriority(ADC_IRQn, 2);
|
152 | NVIC_ClearPendingIRQ(ADC_IRQn);
|
153 | NVIC_EnableIRQ(ADC_IRQn);
|
154 | }
|
155 |
|
156 | void TIM2_IRQHandler(void)
|
157 | {
|
158 | SEGGER_SYSVIEW_RecordEnterISR();
|
159 | NVIC_ClearPendingIRQ(TIM2_IRQn);
|
160 | TIM2->SR &= ~TIM_SR_UIF;
|
161 | }
|
162 |
|
163 | void ADC_IRQHandler(void)
|
164 | {
|
165 | uint16_t Value;
|
166 | SEGGER_SYSVIEW_RecordEnterISR();
|
167 | Value = ADC1->DR;
|
168 | NVIC_ClearPendingIRQ(ADC_IRQn);
|
169 | }
|
170 |
|
171 | int main(void)
|
172 | {
|
173 | ClockInit();
|
174 |
|
175 | SEGGER_SYSVIEW_Conf();
|
176 |
|
177 | TimerInit();
|
178 | AdcInit();
|
179 | InterruptInit();
|
180 |
|
181 | TimerStart();
|
182 | while(1);
|
183 | }
|
184 |
|
185 | /*************************** End of file ****************************/
|