-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathoveradc.h
213 lines (181 loc) · 8.62 KB
/
overadc.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
//----------------------------------------------------------------------------
//Ðåàëèçàöèÿ øàáëîííîãî êëàññà TOverAdc
//----------------------- Èñïîëüçóåìûå ðåñóðñû: ------------------------------
//Øàáëîííûé êëàññ TOverAdc ðåàëèçóåò Oversampled ADC íà îñíîâå âñòðîåííîãî
//ÀÖÏ, ýôôåêòèâíàÿ ðàçðÿäíîñòü êîòîðîãî ïîâûøàåòñÿ ñ ïîìîùüþ îâåðñýìïëèíãà.
//Âñåãî ìîãóò áûòü ñîçäàíû 2 ýêçåìïëÿðà ýòîãî êëàññà ñ ëîãè÷åñêèìè
//íîìåðàìè 0 è 1. ÀÖÏ èñïîëüçóåòñÿ â ðåæèìå ïðåîáðàçîâàíèÿ èíæåêòèðîâàííîé
//ãðóïïû êàíàëîâ, ñîñòîÿùåé èç 2-õ êàíàëîâ. Çàïóñê ïðåîáðàçîâàíèÿ ãðóïïû
//îñóùåñòâëÿåòñÿ ñîáûòèåì TIM2 TRGO. Ðåçóëüòàòû ïðåîáðàçîâàíèÿ ñîõðàíÿþòñÿ
//â ïàìÿòè â âèäå ìàñèâà ñ ïîìîùüþ DMA. Äëÿ ëîãè÷åñêîãî ÀÖÏ 0 èñïîëüçóåòñÿ
//êàíàë DMA 5, äëÿ ëîãè÷åñêîãî ÀÖÏ 1 - êàíàë DMA 7. DMA ðàáîòàåò â îäíîêðàòíîì
//ðåæèìå, ïîñëå çàïîëíåíèÿ ìàññèâà ïåðåñûëêà îñòàíàâëèâàåòñÿ è óñòàíàâëèâàåòñÿ
//ôëàã ãîòîâíîñòè äàííûõ DMA_ISR_TCIF5 èëè DMA_ISR_TCIF7. Ïîñëå ýòîãî
//ðåçóëüòàò ìîæåò áûòü ñ÷èòàí ñ ïîìîùüþ ôóíêöèè AdcGetCode, êàòîðàÿ
//àâòîìàòè÷åñêè çàïóñêàåò ñëåäóþùèé öèêë íàêîïëåíèÿ.
//Ñ÷èòàííûé êîä ïðåîáðàçîâàí â ôîðìàò ñ ðàçðÿäíîñòüþ ADC_RES.
//----------------------------------------------------------------------------
#ifndef OVERADC_H
#define OVERADC_H
//------------------------------- Êîíñòàíòû: ---------------------------------
#define ADC_NR 12 //Native ADC Resolution, bits
#define ADC_RES 16 //Oversampled ADC Resolution, bits
#define ADC_FS 100000 //Sampling frequency, Hz
#define ADC_MAX_CODE ((1 << ADC_RES) - (1 << (ADC_RES - ADC_NR)))
#define OVER_N 100 //Oversampling ratio
//Êîäû âðåìåíè ñýìïëèðîâàíèÿ:
enum smp_t
{
SMP1T5,
SMP7T5,
SMP13T5,
SMP28T5,
SMP41T5,
SMP55T5,
SMP71T5,
SMP239T5
};
//----------------------------------------------------------------------------
//------------------------ Øàáëîííûé êëàññ TOverAdc: -------------------------
//----------------------------------------------------------------------------
//AdcN = 0, 1 - ëîãè÷åñêèé íîìåð ÀÖÏ
//AdcPin = 0..9 - íîìåð âõîäíîãî ïèíà ÀÖÏ (íîìåð êàíàëà)
template<uint8_t AdcN, uint8_t AdcPin>
class TOverAdc
{
private:
TGpio<PORTA, AdcPin> Pin_ADC;
uint16_t Samples[OVER_N];
public:
TOverAdc(void) {};
void Init(void);
bool Ready(void);
operator uint16_t();
};
//---------------------------- Èíèöèàëèçàöèÿ: --------------------------------
template<uint8_t AdcN, uint8_t AdcPin>
void TOverAdc<AdcN, AdcPin>::Init(void)
{
Pin_ADC.Init(IN_ANALOG); //íàñòðîéêà ïîðòà ADC
RCC->CFGR |= RCC_CFGR_ADCPRE_DIV4; //ïðåñêàëåð ÀÖÏ (APB2 / 4)
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; //âêëþ÷åíèå òàêòèðîâàíèÿ ADC
ADC1->SMPR2 |= ADC_SMPR2_SMP0_0 * SMP13T5 << AdcPin * 3; //sample time
ADC1->JSQR |=
ADC_JSQR_JL_0 * 1 | //2 conversions in inj. group
ADC_JSQR_JSQ3_0 * AdcPin << AdcN * 5; //inj. channel select
ADC1->CR1 =
ADC_CR1_AWDEN * 0 | //reg. analog watchdog disable
ADC_CR1_JAWDEN * 0 | //inj. analog watchdog disable
ADC_CR1_DISCNUM_0 * 0 | //no disc. mode channels
ADC_CR1_JDISCEN * 0 | //inj. disc. mode disable
ADC_CR1_DISCEN * 0 | //reg. disc. mode disable
ADC_CR1_JAUTO * 1 | //auto injected group conversion
ADC_CR1_AWDSGL * 0 | //watchdog single scan channel disable
ADC_CR1_SCAN * 1 | //scan mode
ADC_CR1_JEOCIE * 0 | //inj. channels interrupt disable
ADC_CR1_AWDIE * 0 | //analog watchdog interrupt disable
ADC_CR1_EOCIE * 0 | //EOC interrupt disable
ADC_CR1_AWDCH_0 * 0; //analog watchdog channel
ADC1->CR2 =
ADC_CR2_TSVREFE * 0 | //temp. sensor disable
ADC_CR2_SWSTART * 0 | //reg. start conversion
ADC_CR2_JSWSTART * 0 | //inj. start conversion
ADC_CR2_EXTTRIG * 0 | //reg. ext. start
ADC_CR2_EXTSEL_0 * 0 | //reg. ext. event select
ADC_CR2_JEXTTRIG * 1 | //inj. ext. start
ADC_CR2_JEXTSEL_0 * 2 | //inj. ext. event select - TIM2 TRGO
ADC_CR2_ALIGN * 0 | //right data alignment
ADC_CR2_DMA * 0 | //DMA disable
ADC_CR2_RSTCAL * 0 | //calibration reset
ADC_CR2_CAL * 0 | //calibration
ADC_CR2_CONT * 0 | //continuous conversion
ADC_CR2_ADON * 1; //ADC enable
ADC1->CR2 |= ADC_CR2_RSTCAL; //ADC calibration reset
while(ADC1->CR2 & ADC_CR2_RSTCAL);
ADC1->CR2 |= ADC_CR2_CAL; //ADC calibration
while(ADC1->CR2 & ADC_CR2_CAL);
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; //âêëþ÷åíèå òàêòèðîâàíèÿ TIM2
TIM2->CR1 &= ~TIM_CR1_CEN; //çàïðåùåíèå òàéìåðà
TIM2->PSC = 0; //çàãðóçêà ïðåñêàëåðà
TIM2->ARR = (SYSTEM_CORE_CLOCK / ADC_FS) - 1; //ïåðèîä òàéìåðà
TIM2->CR2 =
TIM_CR2_TI1S * 0 |
TIM_CR2_MMS_0 * 2 | //Update -> TRGO
TIM_CR2_CCDS * 0; //DMA request when CC event
if(AdcN == 0) //ñðàâíåíèå êîíñòàíò, îïòèìèçàòîð óáåðåò íåíóæíîå
{
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
DMA1_Channel5->CPAR = (uint32_t)&ADC1->JDR1; //periph. address
DMA1_Channel5->CMAR = (uint32_t)&Samples; //memory address
DMA1_Channel5->CNDTR = OVER_N; //buffer size
DMA1_Channel5->CCR =
DMA_CCR5_MEM2MEM * 0 | //memory to memory off
DMA_CCR5_PL_0 * 2 | //high priority
DMA_CCR5_MSIZE_0 * 1 | //mem. size 16 bit
DMA_CCR5_PSIZE_0 * 1 | //periph. size 16 bit
DMA_CCR5_MINC * 1 | //memory increment enable
DMA_CCR5_PINC * 0 | //periph. increment disable
DMA_CCR5_CIRC * 0 | //circular mode disable
DMA_CCR5_DIR * 0 | //direction - from periph.
DMA_CCR5_TEIE * 0 | //transfer error interrupt disable
DMA_CCR5_HTIE * 0 | //half transfer interrupt disable
DMA_CCR5_TCIE * 0 | //transfer complete interrupt disable
DMA_CCR5_EN * 1; //DMA enable
TIM2->CCR1 = TIM2->ARR / 2; //CC1 register load
TIM2->DIER |= TIM_DIER_CC1DE; //CC1 DMA request enable
}
if(AdcN == 1) //ñðàâíåíèå êîíñòàíò, îïòèìèçàòîð óáåðåò íåíóæíîå
{
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
DMA1_Channel7->CPAR = (uint32_t)&ADC1->JDR2; //periph. address
DMA1_Channel7->CMAR = (uint32_t)&Samples; //memory address
DMA1_Channel7->CNDTR = OVER_N; //buffer size
DMA1_Channel7->CCR =
DMA_CCR7_MEM2MEM * 0 | //memory to memory off
DMA_CCR7_PL_0 * 2 | //high priority
DMA_CCR7_MSIZE_0 * 1 | //mem. size 16 bit
DMA_CCR7_PSIZE_0 * 1 | //periph. size 16 bit
DMA_CCR7_MINC * 1 | //memory increment enable
DMA_CCR7_PINC * 0 | //periph. increment disable
DMA_CCR7_CIRC * 0 | //circular mode disable
DMA_CCR7_DIR * 0 | //direction - from periph.
DMA_CCR7_TEIE * 0 | //transfer error interrupt disable
DMA_CCR7_HTIE * 0 | //half transfer interrupt disable
DMA_CCR7_TCIE * 0 | //transfer complete interrupt disable
DMA_CCR7_EN * 1; //DMA enable
TIM2->CCR2 = TIM2->ARR; //CC2 register load
TIM2->DIER |= TIM_DIER_CC2DE; //CC2 DMA request enable
}
TIM2->CR1 |= TIM_CR1_CEN; //timer 2 enable
}
//------------------------ ×òåíèå ãîòîâíîñòè ADC: ----------------------------
template<uint8_t AdcN, uint8_t AdcPin>
inline bool TOverAdc<AdcN, AdcPin>::Ready(void)
{
return(DMA1->ISR & (AdcN? DMA_ISR_TCIF7 : DMA_ISR_TCIF5));
}
//------------------------- ×òåíèå äàííûõ ADC: -------------------------------
template<uint8_t AdcN, uint8_t AdcCh>
inline TOverAdc<AdcN, AdcCh>::operator uint16_t()
{
int32_t Avg = 0;
for(int16_t i = 0; i < OVER_N; i++)
Avg += Samples[i];
if(AdcN == 0) //ñðàâíåíèå êîíñòàíò, îïòèìèçàòîð óáåðåò íåíóæíîå
{
DMA1_Channel5->CCR &= ~DMA_CCR5_EN; //DMA disable
DMA1_Channel5->CNDTR = OVER_N; //buffer size
DMA1->IFCR = DMA_IFCR_CTCIF5; //flag clear
DMA1_Channel5->CCR |= DMA_CCR5_EN; //DMA enable
}
if(AdcN == 1) //ñðàâíåíèå êîíñòàíò, îïòèìèçàòîð óáåðåò íåíóæíîå
{
DMA1_Channel7->CCR &= ~DMA_CCR7_EN; //DMA disable
DMA1_Channel7->CNDTR = OVER_N; //buffer size
DMA1->IFCR = DMA_IFCR_CTCIF7; //flag clear
DMA1_Channel7->CCR |= DMA_CCR7_EN; //DMA enable
}
return((Avg * (1 << (ADC_RES - ADC_NR)) + OVER_N / 2) / OVER_N);
}
//----------------------------------------------------------------------------
#endif