Irgendetwas verstehe ich offensichtlich nicht an der STM32F103
Beschaltung.
Ich habe am PA0 und PA1 den Encoder aktiviert, TIM2_CH1 & 2.
Funktioniert, zählt schön hoch und runter.
Am Pin PA2 möchte ich ein PWM Signal zählen, TIM2_CH3. Das funktioniert
auch, aber nur wenn ich den obigen Encoder abschalte. Nur warum geht
nicht beides?
Im main.c rufe ich diese Init Prozeduren auf, zuerst die vom Tim2_Ch3
counter und dann die vom Encoder.
Ich kann doch CH1&2 für eine Sache verwenden und CH3&4 für eine Andere,
oder?
Danke im Voraus!
PWM Zähler 1 void P_ICPWM_InitIO ( void )
2 {
3 GPIO_InitTypeDef GPIO_InitStructure ;
4
5 RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOA , ENABLE );
6 GPIO_InitStructure . GPIO_Mode = GPIO_Mode_IPD ;
7 GPIO_InitStructure . GPIO_Speed = GPIO_Speed_50MHz ;
8 GPIO_InitStructure . GPIO_Pin = GPIO_Pin_2 ;
9 GPIO_Init ( GPIOA , & GPIO_InitStructure );
10 }
11
12 void P_ICPWM_InitTIM ( void )
13 {
14 TIM_ICInitTypeDef TIM_ICInitStructure ;
15 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure ;
16 RCC_APB2PeriphClockCmd ( RCC_APB2Periph_AFIO , ENABLE );
17 TIM_TimeBaseStructure . TIM_Period = 0xFFFF ; /* overflow after ~65 ms */
18 TIM_TimeBaseStructure . TIM_Prescaler = 72 - 1 ; /* counter increments every 1 µs */
19 RCC_APB1PeriphClockCmd ( RCC_APB1Periph_TIM2 , ENABLE );
20 TIM_TimeBaseInit ( TIM2 , & TIM_TimeBaseStructure ); /* initialize timer */
21 TIM_ICInitStructure . TIM_ICPolarity = TIM_ICPolarity_Rising ; /* trigger capture event on rising edge */
22 TIM_ICInitStructure . TIM_ICSelection = TIM_ICSelection_DirectTI ; /* input pins directly connected */
23 TIM_ICInitStructure . TIM_ICFilter = 0x3 ; /* input must be stable for 8 ticks */
24 TIM_ICInitStructure . TIM_Channel = TIM_Channel_3 ; /* configure channel3 (PA2) */
25 TIM_ICInit ( TIM2 , & TIM_ICInitStructure ); /* configure input capture */
26 TIM_Cmd ( TIM2 , ENABLE ); /* start timer */
27 }
28
29 void P_ICPWM_InitNVIC ( void )
30 {
31 NVIC_InitTypeDef NVIC_InitStructure ;
32
33 // NVIC init
34 NVIC_PriorityGroupConfig ( NVIC_PriorityGroup_1 ); /* 1 bit for pre-emption priority, 3 bits for subpriority */
35 NVIC_InitStructure . NVIC_IRQChannelPreemptionPriority = 1 ;
36 NVIC_InitStructure . NVIC_IRQChannelSubPriority = 0 ;
37 NVIC_InitStructure . NVIC_IRQChannelCmd = ENABLE ;
38 NVIC_Init ( & NVIC_InitStructure );
39 NVIC_InitStructure . NVIC_IRQChannel = TIM2_IRQn ;
40 NVIC_Init ( & NVIC_InitStructure );
41
42 TIM_ITConfig ( TIM2 , TIM_IT_CC3 , ENABLE ); /* enable CC-interrupts */
43 }
44
45 //--------------------------------------------------------------
46 // ISR of Timer2
47 //--------------------------------------------------------------
48 void TIM2_IRQHandler ( void )
49 {
50 static uint16_t CCR3_rise ;
51 static uint16_t CCR3_falling ;
52
53 if ( TIM_GetITStatus ( TIM2 , TIM_IT_CC3 ) == SET ) {
54 if ( timing [ 6 ][ 0 ] < 1 || timing [ 6 ][ 0 ] >= MAX_TIMING_SAMPLES ) {
55 timing [ 6 ][ 0 ] = 1 ;
56 }
57 timing [ 6 ][ timing [ 6 ][ 0 ]] = TIM2 -> CCR3 ;
58 timing [ 6 ][ 0 ] ++ ;
59 if ( TIM2 -> CCER & TIM_CCER_CC3P ) { /* captured falling edge? */
60 CCR3_falling = TIM2 -> CCR3 ;
61 ICPWM_Var [ 6 ]. duty = CCR3_falling - CCR3_rise ; /* Get the Input Capture value, calculate high pulse length */
62 ICPWM_Var [ 6 ]. last_update = getCounter ();
63 TIM2 -> CCER &= ~ TIM_CCER_CC3P ; /* select rising edge as capture event */
64 } else { /* captured rising edge? */
65 CCR3_rise = TIM2 -> CCR3 ; /* Get the Input Capture value */
66 TIM2 -> CCER |= TIM_CCER_CC3P ; /* select falling edge as capture event */
67 ICPWM_Var [ 6 ]. pause = CCR3_rise - CCR3_falling ;
68 }
69 TIM_ClearITPendingBit ( TIM2 , TIM_IT_CC3 );
70 }
71 }
Encoder Init 1 void P_ENCODER_InitIO ( void )
2 {
3 GPIO_InitTypeDef GPIO_InitStructure ;
4
5 // Clock Enable
6 RCC_APB2PeriphClockCmd ( RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO , ENABLE );
7
8 GPIO_InitStructure . GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 ;
9 GPIO_InitStructure . GPIO_Mode = GPIO_Mode_IPU ;
10 GPIO_InitStructure . GPIO_Speed = GPIO_Speed_50MHz ;
11 GPIO_Init ( GPIOA , & GPIO_InitStructure );
12 }
13
14
15 void P_ENCODER_InitTIM ()
16 {
17 TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure ;
18 TIM_ICInitTypeDef TIM_ICInitStructure ;
19
20 TIM_DeInit ( TIM2 );
21 TIM_TimeBaseStructInit ( & TIM_TimeBaseStructure );
22
23 // Clock enable
24 RCC_APB1PeriphClockCmd ( RCC_APB1Periph_TIM2 , ENABLE );
25
26 TIM_TimeBaseStructure . TIM_Period = 0xFFFF ;
27 TIM_TimeBaseStructure . TIM_Prescaler = 0 ;
28 TIM_TimeBaseStructure . TIM_ClockDivision = TIM_CKD_DIV1 ;
29 TIM_TimeBaseStructure . TIM_CounterMode = TIM_CounterMode_Up ;
30 TIM_TimeBaseInit ( TIM2 , & TIM_TimeBaseStructure );
31
32 TIM_ICStructInit ( & TIM_ICInitStructure );
33 TIM_ICInitStructure . TIM_ICFilter = 0x00 ;
34 TIM_ICInit ( TIM2 , & TIM_ICInitStructure );
35
36 TIM_EncoderInterfaceConfig ( TIM2 , TIM_EncoderMode_TI12 , TIM_ICPolarity_Rising , TIM_ICPolarity_Rising );
37
38 TIM2 -> CNT = 0 ;
39
40 // Timer enable
41 TIM_Cmd ( TIM2 , ENABLE );
42 }
von
chris (Gast)
02.03.2015 19:20
Werner D. schrieb:
> Ich kann doch CH1&2 für eine Sache verwenden und CH3&4 für eine Andere,
> oder?
Nein, wie soll das auch gehen, wenn du beides mal Timer2 verwendest?
Im Encoder Modus wird das Timerregister von den Encodersignalen rauf-
oder runtergezähzl.
Im "normalen" Modus wird es über den mittels Prescaler vom Systemtakt
abgeleiteten Takt hochgezählt.
Da es nur ein Timer-Register gibt, kann natürlich nicht beides
gleichzeitig gehen.
Du musst für dein Input Capture einen zweiten Timer benutzen.
Ich Esel. Natürlich, alle 4 Kanäle haben ja nur einen Timer-Wert. Also
entweder den vom PWM oder den vom Encoder, wie Du sagst.
Mist, es müssen genau die Pins PA0, PA1 und PA2 sein. Da ist kein
Remapping möglich. Mein Problem.
Danke!
TIM9_CH1 sollte sich auf PA2 remappen lassen. Ich bin allerdings im
Moment überfragt, ob deine MC Version diesen Timer überhaupt hat.
von
Roland (Gast)
04.05.2015 08:36
Hallo Werner,
ich verwende den gleichen Controller und habe einen Encoder auf die
Ports PA6 und PA7 angeschlossen. Als Timer verwende ich dann TIM3. Beim
Auslesen bekomme ich aber nur 0 und 1 ! Habe ich was vergessen ?
Habe auch mal Deine EncoderInitIO und Encoder_InitTim kopiert (und die
Ports sowie TIM auf TIM3 geändert), doch bei mir zählt er nur 0 und 1.
Grüße
Roland
Ich nehme an die verwendest TIM3 nicht für Anderes und Du hast auch
keine Remapping Funktion auf PB4,5? Denn dort kann man TIM3 CH1/2 auch
verwenden...
von
Roland (Gast)
04.05.2015 09:35
Ne, TIM3 ist nur für den Encoder gedacht und ein Remapping mache ich
auch nicht.
Zählen tut er ja, aber nur 0 und 1.
Fällt mir nichts ein. Magst Du mal den kompletten Source Code posten?
von
Roland (Gast)
06.05.2015 08:02
Hier die main.c
/**************************************************************
** MINI STM32
** V: 0.1
** 2015.04.07
***************************************************************/
// Pinbelegung:
// KEY 1: PA0
// KEY 2: PA1
// LED 1: PA2
// LED 2: PA3
//
// ** USART **
// USART1 Tx PA9
// USART1 Rx PA10
//
// ** LCD **
// LCD_CS PC 8
// LCD_RS PC 9
// LCD_WR PC 10
// LCD_RD PC 11
/* Includes
------------------------------------------------------------------*/
#include "stm32f10x.h"
#include "hardware_conf.h"
#include "USART.h"
#include "ili932x_conf.h"
#include <stdio.h>
/* Private define
------------------------------------------------------------*/
/* LED */
#define LED1 PAout(2)
#define LED2 PAout(3)
/* KEY */
#define KEY1 PAin(0)
#define KEY2 PAin(1)
uint8_t AsciiBuff[5];
static __IO uint32_t TimingDelay;
void GPIO_Configuration(void);
void NVIC_Configuration(void);
void TIM2_Configuration(void);
void TIM3_Configuration(void);
uint8_t KEY_Scan(void);
void Delay(__IO uint32_t nTime);
void Delay_Ms(uint16_t time);
void DelayNS(u16 time);
void HexToASCII(uint16_t data);
volatile char Temp=0;
volatile char Frame_Write_Status=0;
volatile char Frame_Writed=0;
/***********************************************************************
******
** main
************************************************************************
*****/
int main(void)
{
uint8_t key;
uint32_t encoder=0;
SystemInit();
while(SysTick_Config(SystemFrequency / 1000));
GPIO_Configuration();
TIM3_Configuration();
USART_Configuration();
LCD_Init();
LCD_Clear(BLACK);
USART_Send_Str(" *** STM32 Test *** \n");
LCD_Clear(BLACK);
WriteString(40,0,"STM32 Demo ! (40,0)",WHITE);
WriteString(0,160, "Encoder: ",WHITE);
LED2=1;
while(1)
{
key=KEY_Scan();
encoder = TIM_GetCounter(TIM3);
HexToASCII(encoder);
WriteString(70,160, (uint8_t*)AsciiBuff,WHITE);
if(key==1) //KEY1 pressed
{
WriteString(150,220,"1 LED -1 ON ",GREEN);
USART_Send_Str(" *** LED -1 ON *** \n");
LED1 = 1;
// Timer enable
TIM_Cmd(TIM3, ENABLE);
}
if(key==2) //KEY2 pressed
{
WriteString(150,220,"2 LED -1 OFF",RED);
USART_Send_Str(" *** LED -1 OFF *** \n");
LED1 = 0;
// Timer disable
TIM_Cmd(TIM3, DISABLE);
}
}
}
/***********************************************************************
******
** GPIO_Configuration
************************************************************************
*****/
void GPIO_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA
| RCC_APB2Periph_GPIOB
| RCC_APB2Periph_GPIOC
| RCC_APB2Periph_GPIOD
| RCC_APB2Periph_AFIO,
ENABLE);
//RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // TIM3
für Encoder
/* Configure Encoder (PA6, PA7)
**************************************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
//GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure IO connected to LED1, LED2 *********************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Configure IO connected to KEY1, KEY2 *********************/
GPIO_InitStructure.GPIO_Pin = KEY1 | KEY2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*Configure USART1 Tx (PA9) as alternate function push-pull*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/*Configure USART1 Rx (PA10) as input floating*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
}
/***********************************************************************
******
** Name: TIM3_Configuration
************************************************************************
*****/
void TIM3_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_DeInit(TIM3);
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
// Clock enable
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 0x000f;
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_ICStructInit(&TIM_ICInitStructure);
TIM_ICInitStructure.TIM_ICFilter = 0x00;
TIM_ICInit(TIM3, &TIM_ICInitStructure);
TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12,
TIM_ICPolarity_Rising, TIM_ICPolarity_Falling);
TIM3->CNT = 0;
}
/***********************************************************************
******
** Delay
************************************************************************
*****/
void Delay(__IO uint32_t nTime)
{
TimingDelay = nTime;
while(TimingDelay != 0);
}
/***********************************************************************
******
** TimingDelay
************************************************************************
*****/
void TimingDelay_Decrement(void)
{
if (TimingDelay != 0x00)
{
TimingDelay--;
}
}
/***********************************************************************
******
** Delay_Ms
************************************************************************
*****/
void Delay_Ms(uint16_t time)
{
uint16_t i,j;
for(i=0;i<time;i++)
for(j=0;j<10260;j++);
}
/***********************************************************************
******
** KEY_Scan
************************************************************************
*****/
u8 KEY_Scan(void)
{
static u8 KEY_UP=1;
if(KEY_UP&&(KEY1==0||KEY2==0))
{
Delay(10);
KEY_UP=0;
if(KEY1==0)return 1;
else if(KEY2==0)return 2;
}
else
if(KEY1==1&&KEY2==1)KEY_UP=1;
return 0;
}
/***********************************************************************
******
** HexToASCII
************************************************************************
*****/
void HexToASCII(uint16_t data)
{
AsciiBuff[0] = data/1000%10 + 0x30;
AsciiBuff[1] = data/100%10 + 0x30;
AsciiBuff[2] = data/10%10 + 0x30;
AsciiBuff[3] = data%10 + 0x30;
AsciiBuff[4] = 0;
}
von
Michael W. (Gast)
06.05.2015 10:09
Looooiiiiiteee!!! Was ist eigentlich an diesem Satz so schwer zu
verstehen?
> Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
von
Roland (Gast)
11.05.2015 11:44
Hallo zusammen,
habe nun in der TIM3-Config folgendes geändert:
TIM_TimeBaseStructure.TIM_Period = 14;
TIM_TimeBaseStructure.TIM_Prescaler = 3;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
Nun zählt der Counter auf 14 nach jedem 3. Schritt, aber nur immer
aufwärts.
Wie muss ich den TIM3 konfigurieren, dass er auf und ab zählt ?
Grüße
Roland
Ich nehme an das bis 14 gezählt wird und alle 3 Schritte, ist klar
warum? Schließlich hast Du das mit Period=14 und PreScalter=3 so
eingestellt.
Zu Deiner Frage:
TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12,
TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
macht das. Der zweite Parameter mit dem Wert TIM_EncoderMode_TI12 sagt
dass zwei Eingänge verwendet werden sollen, somit wird hoch/runter
gezählt.
von
Roland (Gast)
11.05.2015 12:10
Hallo Werner,
danke für die Erläuterung.
Mein Problem ist, dass nur in eine Richtung gezählt wird.
Für meine Steuerung brauche ich aber von 0 - 14, es soll also rauf und
runter gezählt werden.
Habe ich da was vergessen ?
Wie gesagt, dieser TIM_EncoderMode_TI12 Wert macht das. Wenn es nicht
funktioniert, dann scheint kein Signal von einem der beiden Anschlüsse
an den Counter zu kommen. Kann alles sein, von Lötstelle über den GPIOs
nicht richtig konfiguriert bis zu dem Fall dass eine Spannungspitze den
Pin im MCU verschmort hat.
Ich würde als nächstes beide Pins als normalen Input konfigurieren und
deren Werte ausgeben. Bekommst Du von beiden ein High/Low? Wenn ja, dann
ist die Hardware in Ordnung und es muss etwas in Code sein.
Übrigens, mir hat das hier geholfen:
http://www.diller-technologies.de/stm32.html#timer_encoder
von
Roland (Gast)
19.05.2015 10:22
Hallo Werner,
hab nun den TIM4 am Encoder angeschlossen (PB6 und PB7) und nun zählt er
rauf und runter, so wie er soll.
Danke für die Hilfe und den Tipp mit Diller, ein sehr gutes Tutorial !!!
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.