Wykorzystanie PWM-a przy pomiarze czasu trwania impulsu - brak wartości w rejestrach CCR1 i CCR2

Odpowiedz Nowy wątek
2018-05-16 21:59
0

Przerabiam kolejne przykłady z poradnika szczywronk-a i niestety utknąłem przy dziale związanym z PWM-em. W jednym z przykładów jest pomiar czasu trwania stanu wysokiego sygnału. Są skonfigurowane dwa kanały, pierwszy kanał jest aktywowany zboczem narastającym, w wyniku, czego wartość licznika jest "zapamiętywana" a sam licznik zerowany natomiast stan drugiego licznika jest "zapamiętywany" i zerowany, gdy wystąpi zbocze opadające. Niestety w podglądzie stanu rejestrów CCR1 i CCR2 dla timera 1 znajduje się cały czas wartość 0. Używam kompilatora Keil uVision v5 i zestawu Nucleo (F103RB) wartości rejestrów w podglądzie debugger-a nie zmieniają się. I teraz kwestia czy problem jest w kodzie programu czy w samym debugger-ze, który może źle ustawiam. Zależy mi na odczytaniu wartości tych rejestrów, ponieważ chciałbym je później przesyłać do wyświetlacza 2x16

#define PRIGROUP_16G_0S ((const uint32_t) 0x03)
#define PRIGROUP_8G_2S ((const uint32_t) 0x04)
#define PRIGROUP_4G_4S ((const uint32_t) 0x05)
#define PRIGROUP_2G_8S ((const uint32_t) 0x06)
#define PRIGROUP_0G_16S ((const uint32_t) 0x07)

enum { SRAM_BB_REGION_START = 0x20000000 };
enum { SRAM_BB_REGION_END = 0x200fffff };
enum { SRAM_BB_ALIAS = 0x22000000 };
enum { PERIPH_BB_REGION_START = 0x40000000 };
enum { PERIPH_BB_REGION_END = 0x400fffff };
enum { PERIPH_BB_ALIAS = 0x42000000 };
#define SRAM_ADR_COND(adres) ( (uint32_t)&adres >= SRAM_BB_REGION_START && (uint32_t)&adres <= SRAM_BB_REGION_END )
#define PERIPH_ADR_COND(adres) ( (uint32_t)&adres >= PERIPH_BB_REGION_START && (uint32_t)&adres <= PERIPH_BB_REGION_END )
#define BB_SRAM2(adres, bit) ( SRAM_BB_ALIAS + ((uint32_t)&adres -SRAM_BB_REGION_START)*32u + (uint32_t)(bit*4u) )
#define BB_PERIPH(adres, bit) ( PERIPH_BB_ALIAS + ((uint32_t)&adres - PERIPH_BB_REGION_START)*32u + (uint32_t)(__builtin_ctz(bit))*4u)
/* bit - bit mask, not bit position! */
#define BB(adres, bit) *(__IO uint32_t *)( SRAM_ADR_COND(adres) ? BB_SRAM2(adres, bit) : \
( PERIPH_ADR_COND(adres) ? BB_PERIPH(adres, bit) : 0 ))
#define BB_SRAM(adres, bit) *(__IO uint32_t *)BB_SRAM2(adres, bit)

typedef enum {
PA0 = 0x00000001,
PA1 = 0x00000002,
PA2 = 0x00000004,
PA3 = 0x00000008,
PA4 = 0x00000010,
PA5 = 0x00000020,
PA6 = 0x00000040,
PA7 = 0x00000080,
PA8 = 0x00000100,
PA9 = 0x00000200,
PA10 = 0x00000400,
PA11 = 0x00000800,
PA12 = 0x00001000,
PA13 = 0x00002000,
PA14 = 0x00004000,
PA15 = 0x00008000,

PB0 = 0x00000001,
PB1 = 0x00000002,
PB2 = 0x00000004,
PB3 = 0x00000008,
PB4 = 0x00000010,
PB5 = 0x00000020,
PB6 = 0x00000040,
PB7 = 0x00000080,
PB8 = 0x00000100,
PB9 = 0x00000200,
PB10 = 0x00000400,
PB11 = 0x00000800,
PB12 = 0x00001000,
PB13 = 0x00002000,
PB14 = 0x00004000,
PB15 = 0x00008000,

PC0 = 0x00000001,
PC1 = 0x00000002,
PC2 = 0x00000004,
PC3 = 0x00000008,
PC4 = 0x00000010,
PC5 = 0x00000020,
PC6 = 0x00000040,
PC7 = 0x00000080,
PC8 = 0x00000100,
PC9 = 0x00000200,
PC10 = 0x00000400,
PC11 = 0x00000800,
PC12 = 0x00001000,
PC13 = 0x00002000,
PC14 = 0x00004000,
PC15 = 0x00008000,

PD0 = 0x00000001,
PD1 = 0x00000002,
PD2 = 0x00000004,
} GpioPin_t;

typedef enum {
/* Push-Pull */
gpio_mode_output_PP_2MHz = 2,
gpio_mode_output_PP_10MHz = 1,
gpio_mode_output_PP_50MHz = 3,
/* Open-Drain */
gpio_mode_output_OD_2MHz = 6,
gpio_mode_output_OD_10MHz = 5,
gpio_mode_output_OD_50MHz = 7,
/* Push-Pull */
gpio_mode_alternate_PP_2MHz = 10,
gpio_mode_alternate_PP_10MHz = 9,
gpio_mode_alternate_PP_50MHz = 11,
/* Open-Drain */
gpio_mode_alternate_OD_2MHz = 14,
gpio_mode_alternate_OD_10MHz = 13,
gpio_mode_alternate_OD_50MHz = 15,
/* Analog input (ADC) */
gpio_mode_input_analog = 0,
/* Floating digital input. */
gpio_mode_input_floating = 4,
/* Digital input with pull-up/down (depending on the ODR reg.). */
gpio_mode_input_pull = 8
} GpioMode_t;

void TIM1_UP_IRQHandler(void){
if (TIM1->SR & TIM_SR_UIF){
TIM1->SR = ~TIM_SR_UIF;
BB(GPIOB->ODR, PB0) ^=1;
}
}
void SysTick_Handler(void){
GPIOA->ODR ^= PA8; 
}

void gpio_pin_cfg(GPIO_TypeDef * const port, GpioPin_t pin, GpioMode_t mode){
pin = __builtin_ctz(pin)*4;
uint32_t volatile * cr_reg;
uint32_t cr_val;
cr_reg = &port->CRL;
if (pin > 28){
pin -= 32;
cr_reg = &port->CRH;
}
cr_val = *cr_reg;
cr_val &= ~((uint32_t)(0x0f << pin));
cr_val |= (uint32_t)(mode << pin);
*cr_reg = cr_val;
}

uint16_t licznik;

int main(void) {
RCC->APB2ENR = RCC_APB2ENR_IOPAEN | RCC_APB2ENR_TIM1EN;
RCC->APB1ENR = RCC_APB1ENR_TIM2EN;
/* Testowy PWM */
gpio_pin_cfg(GPIOA, PA0, gpio_mode_alternate_PP_2MHz);
TIM2->CCMR1 = TIM_CCMR1_OC1PE | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1;
TIM2->CCER = TIM_CCER_CC1E;
TIM2->PSC = 100;
TIM2->ARR = 100;
TIM2->CCR1 = 37;
TIM2->EGR = TIM_EGR_UG;
TIM2->CR1 = TIM_CR1_CEN;
/* PWM Input Mode */
gpio_pin_cfg(GPIOA, PA8, gpio_mode_input_floating);
TIM1->ARR = UINT16_MAX;
TIM1->PSC = 50;
TIM1->CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_1;
TIM1->CCER = TIM_CCER_CC2P | TIM_CCER_CC1E | TIM_CCER_CC2E;
TIM1->SMCR = TIM_SMCR_TS_2 | TIM_SMCR_TS_0 | TIM_SMCR_SMS_2;
TIM1->CR1 = TIM_CR1_CEN;
licznik = TIM1->CCR1;
while(1);
}
edytowany 1x, ostatnio: furious programming, 2018-05-16 22:03

Pozostało 580 znaków

2018-05-17 08:59
0

1. Kim jest ten "Szczywronek", że nauczył Cię pisać tak brzydki kod?? Ten fragment to bezpośrednio z jego poradnikowych przykładów, czy sam go napisałeś?
Ten kod jest tak nieczytelny, że wspomniane rejestry nawet ciężko znaleźć...

2. Sprawdziłeś w dokumentacji, że licznik Timer1 na pewno podpina się pod zegar używając rejestru APB2ENR? Często takie błędy wynikają właśnie z powodu nie ustawienia tego bitu.

3. Co z innymi rejestrami tego licznika? Co z innymi licznikami w ogóle?

4. STM'y słyną niestety ze swoich errat, które warto czasem sprawdzać. Masz aktualny RM do tego procka? Sprawdziłeś, czy zapis do tych rejestrów nie wymaga dodatkowych zabiegów lub workaround'ów, które wprowadził producent?

edytowany 1x, ostatnio: Bartosz36, 2018-05-17 09:00

Pozostało 580 znaków

2018-05-17 14:10
0

No to fakt nad czytelnością kodu będę musiał jeszcze mocno popracować. Poradnik pochodzi z elektrody i pomyślałem, że warto się nauczyć pracować na rejestrach, żeby chociażby wiedzieć później, co siedzi w bibliotekach. Wywaliłem część kodu związaną z obsługą przerwań od układu SysTick i Timera (zostało mi z wcześniejszych „zabaw” z SycTickiem ) i wszytko zaczęło działać.

Pozostało 580 znaków

2018-05-17 14:19
0

1. Piszesz, że:

żeby chociażby wiedzieć później, co siedzi w bibliotekach.

A jednak wrzucasz do swojego kodu wielki enum z definicją poszczególnych pinów. Żeby było gorzej, piny A, B, C wrzucasz do jednego worka. Te definicje także znajdziesz w nagłówkach, poszukaj.

2. Może i wywaliłeś część kodu związaną z Timerem i SysTickiem, ale czy to rozwiązało problem wartości wpisywanych do rejestru Timer'a? Nie, ponieważ wywaliłeś ten kod, a nie naprawiłeś go.
edit: W sumie jest to jakieś rozwiązanie... Jak to mawiał Stalin: Śmierć rozwiązuje wszystkie problemy - nie ma człowieka, nie ma problemu.

3. Co masz na myśli zaczęło działać?? Co wcześniej nie działało? Teraz wpisuje Ci już wartości prawidłowo do tych rejestrów? Przecież usunąłeś kod związany z Timer'em. Co się tutaj dzieje?!

edytowany 1x, ostatnio: Bartosz36, 2018-05-17 14:24

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0