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

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);
}
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?

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ć.

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?!

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