Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры ARM, Cortex, STM32
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
845 / 518 / 169
Регистрация: 30.07.2015
Сообщений: 1,682
1

Измерение низких частот на STM32F100RB

21.08.2015, 10:57. Просмотров 1135. Ответов 2
Метки нет (Все метки)

Добрый день. Пытаюсь реализовать частотомер для двигателя ПТ с помощью функции захвата TIM3 2 канал. Вот код:
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
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_tim.h"
 
#define D0 GPIO_Pin_7
#define D1 GPIO_Pin_10
#define D2 GPIO_Pin_11
#define D3 GPIO_Pin_12
 
#define SEG_A GPIO_Pin_0
#define SEG_B GPIO_Pin_1
#define SEG_C GPIO_Pin_2
#define SEG_D GPIO_Pin_3
#define SEG_E GPIO_Pin_4
#define SEG_F GPIO_Pin_5
#define SEG_G GPIO_Pin_6
 
#define DIG0 (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F)
#define DIG1 (SEG_B | SEG_C)
#define DIG2 (SEG_A | SEG_B | SEG_G | SEG_E | SEG_D)
#define DIG3 (SEG_A | SEG_B | SEG_G | SEG_C | SEG_D)
#define DIG4 (SEG_F | SEG_G | SEG_B | SEG_C)
#define DIG5 (SEG_A | SEG_F | SEG_G | SEG_C | SEG_D)
#define DIG6 (SEG_A | SEG_F | SEG_G | SEG_C | SEG_D | SEG_E)
#define DIG7 (SEG_A | SEG_B | SEG_C)
#define DIG8 (SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G)
#define DIG9 (SEG_A | SEG_B | SEG_C | SEG_D | SEG_G | SEG_F)
#define ALL_PINS (DIG8 | D0 | D1 | D2 | D3)
 
void digit_to_port (uint8_t digit)
{
    uint8_t digitsp[] = {DIG0,DIG1,DIG2,DIG3,DIG4,DIG5,DIG6,DIG7,DIG8,DIG9};
    GPIOC-> ODR &= ~DIG8;
    GPIOC-> ODR |= digitsp[digit];
}
uint8_t digit;
uint32_t tmp;
uint32_t i = 500;
GPIO_InitTypeDef port;
TIM_TimeBaseInitTypeDef timer;
TIM_OCInitTypeDef PWM;
uint32_t SwitchPosition = 0;
uint32_t period, capture_1, capture_2;
uint8_t n = 0x00;
 
 
//Функция задержки
void delay()
{
    volatile uint32_t i;
        for (i=0; i !=0x1000; i++);
}
 
// Инициализация ШИМ.
void initPWM()
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
 
    GPIO_StructInit(&port);
    port.GPIO_Mode = GPIO_Mode_AF_PP;
    port.GPIO_Pin = GPIO_Pin_6;
    port.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOB, &port);
 
    TIM_TimeBaseStructInit(&timer);
    TIM_TimeBaseInit(TIM4, &timer);
 
    TIM_OCStructInit(&PWM);
    PWM.TIM_OCMode = TIM_OCMode_PWM1;
    PWM.TIM_OCPolarity = TIM_OCPolarity_High;
    PWM.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OC1Init(TIM4, &PWM);
}
//инициализация тактовой кнопки и светодиода.
void initall()
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
 
    RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;//Включаем тактирование TIM3
    TIM3->CCMR1 |= TIM_CCMR1_CC2S_0;//Выбор активного входа. Записываем "01" в биты CC1S - связываем регистр TIM3_CCR1 со входом TI1
    TIM3->CCMR1 |= (TIM_CCMR1_IC2F_0 | TIM_CCMR1_IC2F_1);//Выбор длительнотси действия фильтра - 8 тактов. IC1F = 0011.
    TIM3->CCER &= ~TIM_CCER_CC2P;//По переднему фронту - положительный перепад импульса
    TIM3->CCMR1 &= ~TIM_CCMR1_IC2PSC;//Предделитель отключен
    TIM3->CCER |= TIM_CCER_CC2E;//Разрешен захват значения счетчика в регистр TIM3_CCR1
    TIM3->DIER |= TIM_DIER_CC2IE;//Разрешена генерация прерывания при захвате
    TIM3->CR1 |= TIM_CR1_CEN;//Запускаем счет таймера
 
    GPIO_StructInit(&port);
    port.GPIO_Mode = GPIO_Mode_Out_PP;
    port.GPIO_Pin = (GPIO_Pin_8 | GPIO_Pin_9 | SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G | D0 | D1 | D2 | D3);
    port.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOC, &port);
 
    port.GPIO_Mode = GPIO_Mode_IPD;
    port.GPIO_Pin = (GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4);
    port.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Init(GPIOA, &port);
//Разрешение внешних прерываний на вход PA0, PA1, PA4
    EXTI->IMR = (EXTI_IMR_MR0 | EXTI_IMR_MR1 | EXTI_IMR_MR4);
    EXTI->RTSR = (EXTI_RTSR_TR0 | EXTI_RTSR_TR1 | EXTI_RTSR_TR4);
    AFIO->EXTICR[0] = (AFIO_EXTICR1_EXTI0_PA | AFIO_EXTICR1_EXTI1_PA);
    AFIO->EXTICR[1] |= AFIO_EXTICR2_EXTI4_PA;
    RCC->APB2ENR |= RCC_APB2ENR_AFIOEN;
}
int main(void)
{
    initall();
    initPWM();
    __enable_irq();
    NVIC_EnableIRQ(EXTI0_IRQn);
    NVIC_EnableIRQ(EXTI1_IRQn);
    NVIC_EnableIRQ(EXTI4_IRQn);
    NVIC_EnableIRQ(TIM3_IRQn);
    NVIC_SetPriority(TIM3_IRQn, 1);
    while(1)
    {
        //при SwitchPosition =1 вкл Таймер+LED
    if (SwitchPosition == 1)
        {
            GPIOC->BSRR = GPIO_BSRR_BS8;
            TIM_Cmd(TIM4, ENABLE);
            TIM4->CCR1 = 10*i; // изменение скважности
        }
    else
        // выкл Таймер+LED
        {
            TIM4->CCR1 = 0;
            GPIOC->BSRR = GPIO_BSRR_BR8;
            TIM4->CNT = 0xFFFF;
            TIM_Cmd(TIM4, DISABLE);
        }
    //вывод регистра сравнения на семисегментный индикатор
    tmp=i;
    digit = tmp%10;
    tmp = tmp/10;
    GPIOC->ODR &= ~(D0|D1|D2|D3);
    GPIOC->ODR |= D0;
    digit_to_port(digit);
    delay();
    digit = tmp% 10;
    tmp = tmp/10;
    GPIOC->ODR &= ~(D0|D1|D2|D3);
    GPIOC->ODR |= D1;
    digit_to_port(digit);
    delay();
    digit = tmp% 10;
    tmp = tmp/10;
    GPIOC->ODR &= ~(D0|D1|D2|D3);
    GPIOC->ODR |= D2;
    digit_to_port(digit);
    delay();
    GPIOC->ODR &= ~(D0|D1|D2|D3);
    GPIOC->ODR |= D3;
    digit_to_port(tmp);
    delay();
    }
 
}
//Изменяем переменную, для определения вкл/выкл состояния.
void EXTI0_IRQHandler()
{
    delay();
    if (SwitchPosition == 0)
    {
        SwitchPosition++;
    }
    else
    {
        SwitchPosition--;
    }
    EXTI->PR =EXTI_PR_PR0;
}
// скважность ++
void EXTI1_IRQHandler()
{
    if (i < 6500)
    {
        i = i+10;
    }
    EXTI->PR =EXTI_PR_PR1;
}
// скважность --
void EXTI4_IRQHandler()
{
    if (i > 500)
    {
        i = i-10;
    }
    EXTI->PR =EXTI_PR_PR4;
}
// измерение периода
void TIM3_IRQHandler()
 {
    if(!n)
    {
      capture_1 = TIM3->CCR2;
      n = ~n;
    }
    else
    {
      capture_2 = TIM3->CCR2;
      period = capture_2 - capture_1;
 
      n = ~n;
    }
}
Пробую для проверки ШИМ который так же генерирую TIM4. частота ШИМ 24МГц/65535= 366 Гц. Возникает проблема: при отладке первый цикл считает частоту импульсов как положено 366 Гц, но при последующих импульсах период становится равен 0. Я так понимаю, что между двумя импульсами помещается как раз полный счетчик и поэтому разность между двумя фронтами равна 0? Можно ли измерять таким способом в диапазоне 5-150 Гц (подскажите как преобразовать код)? Или лучше использовать два счетчика и измерять в прерываниях
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.08.2015, 10:57
Ответы с готовыми решениями:

Измерение средних частот 2 независимых импульсных сигналов
Ребята просьба о помощи, в универе курсовая по микроконтроллерам MSP430, работаем на IAR Workbench....

Фильтр низких частот
формулой: On = On-1 + α(In – On-1), где O – выходное значение сигнала (отфильтрованное), In...

Фильтры высоких и низких частот C#
Всем доброго дня! Мне нужно создать фильтры высоких и низких частот для просто сигнала и для...

Реализация фильтра низких частот
Добрый день! Подскажите пожалуйста, как реализовать программно ФНЧ. Из входных данных имею...

2
845 / 518 / 169
Регистрация: 30.07.2015
Сообщений: 1,682
24.08.2015, 20:00  [ТС] 2
Решено, понижением частоты тактирования измеряющего таймера

Добавлено через 7 часов 11 минут
Возник новый вопрос. Двигатель будет работать в диапазоне 5-110 Гц, но реальную частоту нужно выводить на экран в об/мин. Период одного такта опорного генератора 100 мкс он подобран так, чтобы во всем диапазоне не было переполнения счетчика захвата. Таким образом имея квант измерения меньше Гц, я теоретически могу измерять в частоту в долях Гц. Как можно оперировать с дробными числами? Ведь если брать только целые части Гц, при переходе в об /мин идет ошибка в районе 60 об/мин.
0
1854 / 1179 / 114
Регистрация: 04.01.2010
Сообщений: 4,197
28.08.2015, 10:27 3
Лучший ответ Сообщение было отмечено ValeryS как решение

Решение

Цитата Сообщение от _SayHelli Посмотреть сообщение
Как можно оперировать с дробными числами?
Умножайте "исходник" числа на 10, 100, 100 - сколько надо для вывода. Потом просто ставьте запятую в нужном месте и все ).
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
28.08.2015, 10:27

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

USB микрофон и преобладание низких частот
Добрый день, столкнулся с проблемой, приобрел замечательный микрофон AT 2020 USB, надеялся услышать...

Фильтр низких частот. Передаточная функция
Здравствуйте. Столкнулся с проблемой в расчете фильтра низких частот. Сам фильтр прилагаю ниже....

Сглаживание ШИМ, Фильтр низких частот
Добрый вечер, ставлю своей целью с помощью atmega 32 выдавать стабильное напряжение 0-5 Вольт путем...

Низкоомная реактивная нагрузка на усилителе низких частот
Здравствуйте. Есть 3х фазный маломощный (до 300 Вт электрической мощности) асинхронный двигатель....


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

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

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