Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.94/50: Рейтинг темы: голосов - 50, средняя оценка - 4.94
LoPuX
2 / 2 / 3
Регистрация: 03.05.2015
Сообщений: 63
1

БПФ для STM32F103

17.07.2015, 09:12. Просмотров 9351. Ответов 40
Метки нет (Все метки)

Здравствуйте, помогите подцепить БПФ на stm32. Есть некая библиотека DSP, не могу с ней разобраться. Можно ли просто функцию на C запихнуть? Я пробую, у меня почему-то не выходит. На компьютере выводит, а МК зависает. Код брал с https://ru.wikibooks.org/wiki/%D0%A0%D0 ... 1%8C%D0%B5. Может подскажете код, на C/С++, который точно заведется на МК? (с ассемблером я не дружу). Ну или скажите как этот DSP включить.
Делаю гитарный тюнер (в виде частотометра). Хотелось бы хотя бы 1024 отсчета. АЦП работает. Выводит результат на 7-сегментный индикатор.
На индикаторе будет частота, до десятой, поэтому точка.
Помогите пожалуйста.
0
Миниатюры
БПФ для STM32F103  
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
17.07.2015, 09:12
Ответы с готовыми решениями:

STM32F103:производительность 32бит БПФ выше, чем 16-битного?
Подбираю какой использовать вариант БПФ. С удивлением обнаружил: ...

Возможно ли преобразование в стиле БПФ для нелинейных чирпов
Пусть имеется источник сигналов с нелинейно меняющейся со временем частотой, например упрощенно...

STM32VLDISCOVERY в качестве программатора для stm32f103
Здравствуйте! Сегодня приехало вот это http://wvshare.com/product/EX-STM32-Q100a.htm И решил...

Самодельная отладочная плата для stm32f103
Запаял stm32f103 на плате - переходнике TQFP24-144. Расспаял питание, ресет, ноги бута. Пытаюсь...

Настройка OSC_OUT как GPIO для STM32f103
Добрый день. Контроллер STM32f103 тактируется от внешнего генератора, неиспользованный пин OSC_OUT...

40
ValeryS
Модератор
7476 / 5661 / 723
Регистрация: 14.02.2011
Сообщений: 19,357
Завершенные тесты: 1
25.07.2015, 14:28 21
Цитата Сообщение от LoPuX Посмотреть сообщение
а если сдвиг фаз 90. то что?
то косинус
sin(90-a)=cos(a)

будет та же фигура со сдвигом фазы
поиграйся в том же экселе, создай таблицу с одинаковой частотой, со сдвигом фазы и без, и с разными

вообще все колебания в Фурье раскладываются в комплексные числа
типа B*cos(a)+A sin(a) где косинус действительная часть синус мнимая
0
LoPuX
2 / 2 / 3
Регистрация: 03.05.2015
Сообщений: 63
25.07.2015, 14:46  [ТС] 22
ValeryS, можешь взглянуть на код
C++ (Qt)
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
#include "stm32f10x.h"
#include "math.h"
#include "indicator.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stdlib.h"
#include "misc.h"
#include "arm_math.h"
#include "stm32f10x_adc.h"
#include "stm32f10x_dma.h"
 
#define ADC1_DR_Address    ((uint32_t)0x4001244C)
 
void ADC_DMA_Init(void);
void RCC_Configuration(void);
void GPIO_Configuration(void);
void DMAChannel1_IRQHandler( void );
 
#define SAMPLE          1024
#define FFT_SIZE    SAMPLE / 2  //maybe: 128, 512, 2048
#define Fs                  1000
#define f                   Fs/SAMPLE
#define pi                  3.14159265359
 
uint16_t i = 0;
uint16_t freq = 0;
q15_t Input[SAMPLE], Output[SAMPLE], max = 0;
 
int main() {
 
    ADC_DMA_Init();
    RCC_Configuration();
    GPIO_Configuration();
    DMAChannel1_IRQHandler();
    ledInit();
        
    while(1) {
        
    arm_rfft_instance_q15 S;
    arm_cfft_radix4_instance_q15 S_CFFT;
        
         for(i = 0; i < SAMPLE; i++) {
                Input[i] = Input[i]*(0.54-0.46*cos((2*pi*i)/(SAMPLE-1)));
         }
         
    arm_rfft_init_q15(&S, &S_CFFT, FFT_SIZE, 0, 1);
    arm_rfft_q15(&S, Input, Output);
     
         for (i=0; i<SAMPLE; i++) {
                Output[i]<<=10;
         }
     
    arm_cmplx_mag_q15(Output, Input, FFT_SIZE); 
 
            for(i = 0; i < FFT_SIZE; i++) {
                if(Input[i] > max) {
                    max = Input[i];
                    freq = i;
                }
            }
    
        show(20*freq*f);
    }
}
 
 
void RCC_Configuration(void) {
  RCC_ADCCLKConfig(RCC_PCLK2_Div2); /* ADCCLK = PCLK2/2 */
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
}
 
void GPIO_Configuration(void) {
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
}
 
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
 
void ADC_DMA_Init(void) {
    
  RCC_Configuration();
  GPIO_Configuration();
 
  DMA_DeInit(DMA1_Channel1);
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&Input;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_BufferSize = sizeof(Input) / sizeof(Input[0]);
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);
 
  DMA_Cmd(DMA1_Channel1, ENABLE);
  
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = 1;
  ADC_Init(ADC1, &ADC_InitStructure);
 
  ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_55Cycles5);
  
  ADC_DMACmd(ADC1, ENABLE); 
  
  ADC_Cmd(ADC1, ENABLE);    
  
  ADC_ResetCalibration(ADC1);        
  
  while(ADC_GetResetCalibrationStatus(ADC1));       
  
  ADC_StartCalibration(ADC1);   
  
  while(ADC_GetCalibrationStatus(ADC1));    
     
  ADC_SoftwareStartConvCmd(ADC1, ENABLE);       
    
    NVIC_EnableIRQ(DMA1_Channel1_IRQn);
    
}
 
void DMAChannel1_IRQHandler ( void ) {
        if (DMA1->ISR & DMA_ISR_TCIF1 ) {
            //Здесь нужно высчитывать БПФ???
            DMA1->IFCR |= DMA_IFCR_CGIF1;
        }
}
 
 
#ifdef  USE_FULL_ASSERT
void assert_failed(uint8_t* file, uint32_t line)
{ 
  while (1)
  {
  }
}
#endif
Как мне зайти в это прерывание?
0
Voland_
1694 / 1038 / 98
Регистрация: 04.01.2010
Сообщений: 3,513
25.07.2015, 15:11 23
Цитата Сообщение от LoPuX Посмотреть сообщение
Как мне зайти в это прерывание?
Вопрос, конечно, к Valerys, но... можно я попробую ответить?
Если вы используете KEIL, то в проекте должен быть файл stm32f10x_it.c, который нужно включить в проект. Вы можете взять его из любого проекта под ваш чип и переделать под свои нужды.
0
LoPuX
2 / 2 / 3
Регистрация: 03.05.2015
Сообщений: 63
25.07.2015, 15:29  [ТС] 24
Voland_ тогда в stm32f10x_it.c нужно добавить
C++ (Qt)
1
2
3
4
5
6
void DMAChannel1_IRQHandler ( void ) {
        if (DMA1->ISR & DMA_ISR_TCIF1 ) {
            //Здесь нужно высчитывать БПФ???
            DMA1->IFCR |= DMA_IFCR_CGIF1;
        }
}
Так?
0
LoPuX
2 / 2 / 3
Регистрация: 03.05.2015
Сообщений: 63
25.07.2015, 16:42  [ТС] 25
Может кто поможет
0
Вложения
Тип файла: rar ENDforRFFT.rar (4.94 Мб, 17 просмотров)
Voland_
1694 / 1038 / 98
Регистрация: 04.01.2010
Сообщений: 3,513
25.07.2015, 17:58 26
Цитата Сообщение от LoPuX Посмотреть сообщение
Может кто поможет
помочь в чем? Конкретизируйте вопрос
0
LoPuX
2 / 2 / 3
Регистрация: 03.05.2015
Сообщений: 63
25.07.2015, 18:07  [ТС] 27
Не получается запустить прерывание.

Добавлено через 5 минут
Написал вот как в stm32f10x_it.c
C++ (Qt)
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
void DMAChannel1_IRQHandler(void) {
        if (DMA1->ISR & DMA_ISR_TCIF1) {
 
        arm_rfft_instance_q15 S;
        arm_cfft_radix4_instance_q15 S_CFFT;
            
            DMA1->IFCR |= DMA_IFCR_CGIF1;               
            
            for(i = 0; i < SAMPLE; i++) {
                Input[i] = ADCConvertedValue[i];
            }       
         for(i = 0; i < SAMPLE; i++) {
                Input[i] = Input[i]*(0.54-0.46*cos((2*pi*i)/(SAMPLE-1)));
         }
         
        arm_rfft_init_q15(&S, &S_CFFT, FFT_SIZE, 0, 1);
        arm_rfft_q15(&S, Input, Output);
     
         for (i=0; i<SAMPLE; i++) {
                Output[i]<<=10;
         }
     
        arm_cmplx_mag_q15(Output, Input, FFT_SIZE); 
 
            for(i = 0; i < FFT_SIZE; i++) {
                if(Input[i] > max) {
                    max = Input[i];
                    freq = i;
                }
            }
    
        show(20*freq*f);
        }
}
Результат не выводится
0
Voland_
1694 / 1038 / 98
Регистрация: 04.01.2010
Сообщений: 3,513
25.07.2015, 18:23 28
для запуска DMA надо:
1) Запустить клоки периферии DMA.
2) Запустить клок АЦП.
3) Настроить АЦП на вызов передачи через DMA по окончанию преобразования.
4) Настроить АЦП на цикличное выполнение преобразования - по таймеру, как правило.
5) Настроить NVIC, включить соотв. прерывания.
6) Настроить и разрешить _соответствующий_ канал DMA. (именно для СТМ32 это работает так).
7) Включить АЦП.

... Прерывание должно вызваться.
8) у вас в обработчике прерывания должно сбрасываться два флага. Один соответствует вашему событию, на что вы его настраиваете. Другой - это глобальный флаг.

ЗЫ: рекомендую посмотреть как это сделано в SDK от ST. Там есть куча примеров.
0
ValeryS
Модератор
7476 / 5661 / 723
Регистрация: 14.02.2011
Сообщений: 19,357
Завершенные тесты: 1
25.07.2015, 21:10 29
Лучший ответ Сообщение было отмечено LoPuX как решение

Решение

Цитата Сообщение от LoPuX Посмотреть сообщение
DMA1->ISR & DMA_ISR_TCIF1
вместо этого проще использовать DMA_GetITStatus
вот мой файл на котором тренировался
воды много, нет коментариев, но может поможет
Кликните здесь для просмотра всего текста
C
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
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
#include <stm32f10x.h>
#include "stm32_dsp.h"
#include "table_fft.h"
#include <math.h>
 
#define PI2  6.28318530717959
 
#define NPT   64  /* NPT = No of FFT point*/
 
 
#if NPT==64
    #define myFFT cr4_fft_64_stm32
    #define displayPowerMag displayPowerMag64
     #warning "64"
#elif NPT==256
    #define myFFT cr4_fft_256_stm32
    #define displayPowerMag displayPowerMag256
    #warning "256"
#elif NPT==1024
   #define myFFT cr4_fft_1024_stm32
   #define displayPowerMag displayPowerMag1024
  #warning "1024"
#else
#error  "uncorrect NTP my by 64 or 256 or 1024"
#endif 
void displayPowerMag(uint32_t DisplayPos, uint32_t scale);
 
 
 
 
 
 
 
 
#define ADC_CH NPT//количество каналов
//#define OVER_SAMPL 32 //количество семплов для усреднения
//uint32_t ADC_SUM[ADC_CH]; //буффер для суммирования 
//uint16_t curr_sample;//считаем количество семлов
//uint16_t AI[ADC_CH],
uint16_t ADC_VAL[ADC_CH];//АI- финальный буфер, ADC_VAL- в нее пишем DMA
 
long lBUFIN[NPT];         /* Complex input vector */
long lBUFOUT[NPT];        /* Complex output vector */
long lBUFMAG[NPT];/* Magnitude vector */
long lBufSpectr[NPT/2];/* Magnitude vector */
int * bf= (int *)lBufSpectr;
int iMax;
int FlagDS=0;
int qCh=NPT/2;
 
long powerMag(long nfill)
{
  int32_t lX,lY;
  uint32_t i;
 float s=0.0;
  for (i=0; i < nfill; i++)
  {
    lX= (lBUFOUT[i]<<16)>>16; /* sine_cosine --> cos */
    lY= (lBUFOUT[i] >> 16);   /* sine_cosine --> sin */    
    {
      float X=  64*((float)lX)/32768;
      float Y = 64*((float)lY)/32768;
     #if 1 
       float Mag = sqrt(X*X+ Y*Y)/nfill;
     #else
       float Mag = (X*X+ Y*Y)/nfill; 
     #endif
       lBUFMAG[i] = (uint32_t)(Mag*32768);
       s+=Mag;
     }    
  }
return (s/nfill)*65536;
 
 
}
 
 
 
 
 
 
void Timer_ConfigurationADC()
{
 #if 1
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  //TIM3- управление ADC 50kHz
  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  TIM_TimeBaseStructure.TIM_Period =703-1;
  TIM_TimeBaseStructure.TIM_Prescaler =2-1;
  TIM_TimeBaseStructure.TIM_ClockDivision =0;//TIM_CKD_DIV2;//0
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
 /* TIM3 TRGO selection */
    TIM_SelectOutputTrigger(TIM3, TIM_TRGOSource_Update);
    /* TIM3 enable counter */
    TIM_Cmd(TIM3, ENABLE);
   //TIM_DMACmd(TIM3, TIM_DMA_Update, ENABLE); 
  // TIM_DMACmd(TIM3,TIM_DMA_Trigger,ENABLE);
    NVIC_EnableIRQ(TIM3_IRQn); 
    TIM_ITConfig(TIM3, TIM_DIER_UIE, ENABLE);
 
 
 
#endif
}
int intTimer=0;
 
void TIM3_IRQHandler()
{
  static int state=0;
  TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
    if(state)
      GPIO_WriteBit(GPIOC, GPIO_Pin_9, Bit_SET);
    else
      GPIO_WriteBit(GPIOC, GPIO_Pin_9, Bit_RESET);
    state = 1 - state;
  intTimer++;
 }
 
 
 
 
 
 
 
 
void GPIO_ConfigurationADC()
{
  //Выход DAC Output 1
  //GPIO_InitTypeDef GPIO_InitStructure;
  //GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_4;
 // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
 // GPIO_Init(GPIOA, &GPIO_InitStructure);
}
 
 
 
 
void ADC_Config(void)
{
 GPIO_InitTypeDef GPIO_InitStructure;
 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
NVIC_InitTypeDef  NVIC_InitStructure;
DMA_InitTypeDef DMA_InitStructure; //Variable used to setup the DMA
 
  ///      ADC_InitTypeDef ADC_InitStructure;
 
        //--Enable DMA1 clock--
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
 
        //==Configure DMA1 - Channel1==
           DMA_DeInit(DMA1_Channel1); //Set DMA registers to default values
           DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; //Address of peripheral the DMA must map to
           DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) & ADC_VAL; //Variable to which ADC values will be stored
           DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
           DMA_InitStructure.DMA_BufferSize = ADC_CH; //Buffer size (8 because we using 8 channels)
           DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
           DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
           DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
           DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
           DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
           DMA_InitStructure.DMA_Priority = DMA_Priority_High;
           DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
 
       
           DMA_Init(DMA1_Channel1, &DMA_InitStructure); //Initialise the DMA 
              DMA_ITConfig(DMA1_Channel1, DMA1_IT_TC1, ENABLE);
 
    //DMA_ITConfig(DMA1_Channel1, (DMA_IT_TC | DMA_IT_HT), ENABLE);
    DMA_ClearITPendingBit(DMA1_IT_HT1);
    DMA_ClearITPendingBit(DMA1_IT_TC1);
    DMA_ITConfig(DMA1_Channel1, DMA1_IT_HT1, ENABLE);
    /* Enable DMA1 channel1 */
    DMA_Cmd(DMA1_Channel1, ENABLE);
    ADC_ExternalTrigConvCmd(ADC1, ENABLE);
 
 
           //Настройка Прерывание -по окончании трансфера
 
         NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn ;
           NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
           NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
           NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
           NVIC_Init(&NVIC_InitStructure);
          NVIC_EnableIRQ(DMA1_Channel1_IRQn);
 
 
 
 
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_1;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
 
  GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8 | GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOC, &GPIO_InitStructure);
 
 
 
 
 // настройки ADC
 ADC_InitTypeDef ADC_InitStructure;
 ADC_StructInit(&ADC_InitStructure);
 
 ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; // режим работы - одиночный, независимый
 ADC_InitStructure.ADC_ScanConvMode = DISABLE; // не сканировать каналы, просто измерить один канал
 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; // однократное измерение
 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO;//ADC_ExternalTrigConv_None; ADC_ExternalTrigConv_T3_CC1// без внешнего триггера
 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //выравнивание битов результат - прижать вправо
 ADC_InitStructure.ADC_NbrOfChannel = 1; //количество каналов - одна штука
 ADC_Init(ADC1, &ADC_InitStructure);
 
 ADC_Cmd(ADC1, ENABLE);
 
 // настройка канала
 ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1,ADC_SampleTime_13Cycles5);// ADC_SampleTime_239Cycles5);//
 ADC_DMACmd(ADC1, ENABLE);
 // калибровка АЦП
 ADC_ResetCalibration(ADC1);
 while (ADC_GetResetCalibrationStatus(ADC1));
 ADC_StartCalibration(ADC1);
 while (ADC_GetCalibrationStatus(ADC1));  
 
}
 
void InitADC()
{
ADC_Config();
Timer_ConfigurationADC();
}
 
int  SetFrec(void)
{
static int  Fr=20;
//Fr++;
//if(Fr>4000)
 Fr=100;
 TIM_Cmd(TIM4,DISABLE);
 
TIM4->CCR1 = Fr/2;
  /* Set the Autoreload value */
  TIM4->ARR = Fr;
 
  /* Set the Prescaler value */
  //TIMx->PSC = TIM_TimeBaseInitStruct->TIM_Prescaler;
 TIM_Cmd(TIM4,ENABLE);
return Fr;
 
}
 
 
 
 
 
 
 
void DMA1_Channel1_IRQHandler(void)
{
static long Mid;
if(DMA_GetITStatus(DMA1_IT_TC1))
{
   TIM_Cmd(TIM3, DISABLE);
   DMA_ClearITPendingBit( DMA1_IT_TC1);
   GPIOC->ODR^=GPIO_Pin_8;
   DMA_ITConfig(DMA1_Channel1, DMA1_IT_TC1, DISABLE);
  
  
for(int i=0;i<NPT;i++)
{
  lBUFIN[i]=ADC_VAL[i]<<4;
//if(((i/(NPT/2))%2)!=0)
// lBUFIN[i]=1<<5;
//else
// lBUFIN[i]=0;
}
  myFFT(lBUFOUT, lBUFIN, NPT);
 Mid=powerMag(NPT);//lBUFMAG
for(int i=0;i<NPT/2;i++)
{
 lBufSpectr[i]+=lBUFMAG[i+1];
 lBufSpectr[i]/=2;
}
 
long GetMax(long* scr,int sz);
 iMax=GetMax(lBufSpectr,NPT/2);
FlagDS=1;
 
TIM3->ARR = SetFrec()/4;
TIM3->CNT=0;
TIM4->CNT=0;
   DMA_ITConfig(DMA1_Channel1, DMA1_IT_TC1, ENABLE);
   TIM_Cmd(TIM3, ENABLE);
}
DMA_ClearITPendingBit(DMA1_IT_GL1);
 
}
1
LoPuX
2 / 2 / 3
Регистрация: 03.05.2015
Сообщений: 63
28.07.2015, 15:29  [ТС] 30
А таймером задается частота дискретизации?
0
LoPuX
2 / 2 / 3
Регистрация: 03.05.2015
Сообщений: 63
29.07.2015, 22:22  [ТС] 31
Настроил я этот таймер + ацп + дма + прерывания + прочая нечисть. Результаты какие-то левые, да еще через раз.
0
LoPuX
2 / 2 / 3
Регистрация: 03.05.2015
Сообщений: 63
31.07.2015, 14:04  [ТС] 32
Работает БПФ от ассемблера. Какой я идиот невнимательный, думал, что выходной массив это сразу амплитудный спектр.

Добавлено через 2 часа 9 минут
ЗАРАБОТАЛО!!!
Точность до целой, но это пока я на чистом синусе с генератора на компе запускал.

Добавлено через 1 минуту
И да, почему-то минуты через две, девайс перестает реагировать на частоту. Что очень странно...

Добавлено через 6 минут
Так, кто теперь что мне скажит насчет моей идеи?
Цитата Сообщение от LoPuX Посмотреть сообщение
1) Примерно подтянуть струну до нужной частоты с помощью БПФ (Сделано!).
2) Второй режим: создаю на ЦАПе идеальную синусоиду с частотой струны, которая должна быть.
3) Сигнал с ЦАПа и звук с гитары подаю на смеситель.
4) На выход смесителя ставлю ФНЧ
5) Считаю частоту биений.
??????
0
ValeryS
Модератор
7476 / 5661 / 723
Регистрация: 14.02.2011
Сообщений: 19,357
Завершенные тесты: 1
31.07.2015, 14:17 33
Цитата Сообщение от LoPuX Посмотреть сообщение
Считаю частоту биений.
подумай о том что биения будет если частота струны или выше или ниже идеала, как различать будешь?
и нафига тебе первый пункт?
меряй сразу на биениях
0
LoPuX
2 / 2 / 3
Регистрация: 03.05.2015
Сообщений: 63
31.07.2015, 14:44  [ТС] 34
Цитата Сообщение от ValeryS Посмотреть сообщение
подумай о том что биения будет если частота струны или выше или ниже идеала, как различать будешь?
Предполагал так: Частота биений увеличилась при натяге струны -> струну нужно наоборот ослабить. И наоборот)
Цитата Сообщение от ValeryS Посмотреть сообщение
и нафига тебе первый пункт?
меряй сразу на биениях
Ну так я хотя бы примерно буду знать подтянута ли струна до уровня. Да и биения будут в определенный промежуток влезать, а не ± 100 Герц.
0
ValeryS
Модератор
7476 / 5661 / 723
Регистрация: 14.02.2011
Сообщений: 19,357
Завершенные тесты: 1
31.07.2015, 15:02 35
Цитата Сообщение от LoPuX Посмотреть сообщение
Предполагал так: Частота биений увеличилась при натяге струны -> струну нужно наоборот ослабить. И наоборот)
Ну как бы да, но получается что решать будет оператор, сиречь музыкант, а не прибор покажет выше/ниже
а китайские "балалайки" кои я видел, показывают, какой у них внутри принцип,я не знаю
0
LoPuX
2 / 2 / 3
Регистрация: 03.05.2015
Сообщений: 63
31.07.2015, 15:43  [ТС] 36
Хм... Верно. Под воздействием элексира, или чего еще, трудно перебрать 4 варианта.
Ну можно пробегать ГКЧ, сейчас в маткаде этот вариант проэмулирую
0
LoPuX
2 / 2 / 3
Регистрация: 03.05.2015
Сообщений: 63
31.07.2015, 20:42  [ТС] 37
ValeryS Рассуждать буду на низких частотах, потому что на высоких графики становятся непонятными.
Смотрите: ГКЧ выдает нечто вроде ЛЧМ радиоимпульса (неправильно - поправь). https://ru.wikipedia.org/wiki/%D0%9B...86%D0%B8%D1%8F . Так вот, представим, что сигнал с ЦАПа есть синус с линейно-меняющейся частотой от 20 до 30 Герца за 1 секунду. Истинная частота струны, которая должна звучать 25 Герц (посередине). А в жизни звучит она на 24 Герцах. Значит чуть раньше чем за пол секунды я увижу пик. Результаты:
0
Миниатюры
БПФ для STM32F103   БПФ для STM32F103   БПФ для STM32F103  

БПФ для STM32F103   БПФ для STM32F103  
LoPuX
2 / 2 / 3
Регистрация: 03.05.2015
Сообщений: 63
01.08.2015, 19:32  [ТС] 38
Полная белиберда, не намека на пик. И суммировал и умножал.

Добавлено через 10 минут
Со вторым уравнением немного ошибся, там 24 должно быть) Но это вообще ничего не меняет.

Добавлено через 3 минуты
Было бы конечно классно, если бы это работало, но по моему это не работает.

Добавлено через 4 часа 16 минут
Даже если диодом поделить, и рассматривать только "верхушку" постоянная составляющая в центре наоборот маленькая

Добавлено через 47 минут
Может считать биения глупо, но чего-то больше вариантов не вижу. можно попробовать подавать с ЦАПа три синуса с различными частотами.
например нужно получить 300 герц, создаю три сигнала: 295, 300, 305 герц поочереди пускаю и трижды вычисляю бпф.
Допустим поступил сигнал 303 герца. Значит получу 8, 3, 2 герца в спектрах. Раз 8>2 значит сигнал справа; Раз 3<5 значит сигнал между 300 и 305

Добавлено через 21 минуту
Хотя можно оставить два сигнала с ЦАПа 299 и 301. Если между ними, значит все ок. И можно сделать индикацию уже в виде уровней выше/ниже.

Добавлено через 3 минуты
Самый главный вопрос: Лучше цифровой фильтр использовать, или аналоговый типа Чебышева посчитать?

Добавлено через 16 часов 50 минут
Блин, сегодня нашел гитару. результат и без никаких биений неплохой. Все настраивается сносно. Даже не знаю, нужны ли теперь эти довороты
0
ValeryS
Модератор
7476 / 5661 / 723
Регистрация: 14.02.2011
Сообщений: 19,357
Завершенные тесты: 1
01.08.2015, 20:14 39
Цитата Сообщение от LoPuX Посмотреть сообщение
Все настраивается сносно.
я тоже так думаю вряд ли ухо услышит плюс минус 1 Гц, а тем более десятые
но лучше пообщаться с музыкантами, а еще паче с настройщиками, я встречал таких которые по слуху весь рояль настраивают, вот они то и могли бы быть экспертами
0
LoPuX
2 / 2 / 3
Регистрация: 03.05.2015
Сообщений: 63
01.08.2015, 20:19  [ТС] 40
ValeryS Спасибо за помощь . Теперь осталось сделать красивую маленькую коробочку и засунуть туда все. Фотки пришлю.
0
01.08.2015, 20:19
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.08.2015, 20:19

БПФ на STM32
Друзья, может быть кто-то может подсказать, где достать библиотеку для прямого и обратного Быстрого...

БПФ STM32F4
Доброго времени суток! Раскуриваю БПФ на STM32F4, люди добрые, если у кого есть собранный проект...

БПФ. Как найти фазы гармоник
-- Добрый день! Мучаю вибрацию на stm32f373 (М4 с FPU) под Кокосом. Есть входной сигнал вибрации...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru