12.26.2013

Timer w trybie PWM i preskaler EK-TM4C123GXL

Procesor TM4C123H6PM nie posiada połączenia sprzętowego PWM z diodą RGB na płytce testowej, pozostaje tylko opcja generowania PWM przez sprzętowy timer i włączenia odpowiednich pinów jako wyjścia generatora.

Aby sterować czerwoną diodą na płytce należy przypisać do pinu PF1 -> T0CCP1 aby na pin był wysyłany sygnał z "16-Bit Timer 0 PWM 1".

Biblioteka zawiera mapę pinów  "driverlib/pin_map.h" dzięki której w prosty sposób można włączyć PWM na pinie procesora. Należy wcześniej w opcjach projektu  dodać "predefined symbols" "PART_LM4F230H5QR", gdyż bez tego biblioteka nie zwróci odpowiednich map dla naszego procesora. W zależności od płytki może być potrzebny inny zapis, więcej na forum TI link.

SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

GPIOPinConfigure(GPIO_PF1_T0CCP1 );

GPIOPinTypeTimer(GPIO_PORTF_BASE, GPIO_PIN_1); 

Następnie należy włączyć sprzętowy Timer0 w funkcji PWM kanał B.

SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);

TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_B_PWM);

//TIMER_CFG_SPLIT_PAIR dzieli 32-bitowy timer na dwa 16 bitowe kanały A i B.

Teraz należy ustawić częstotliwość PWM oraz wypełnienie, wpiszę maksymalną liczbę cykli zegara jaką przyjmie 16-bitowy rejestr PWM - 65 535 oraz wypełnienie 10% czyli 58 982 cykli po których zmieni się stan wyjścia na przeciwny na pinie PF1 (z 0 na 1). Przy częstotliwości CPU 80 MHz uzyskamy częstotliwość PWM 1220 Hz.Aby uzyskać niższą należy zastosować preskaler.

TimerLoadSet(TIMER0_BASE, TIMER_B, 65535);

TimerMatchSet(TIMER0_BASE, TIMER_B, 58982);// 10%

TimerEnable(TIMER0_BASE,TIMER_B);


Dioda powinna się świecić słabym światłem.

Aby uzyskać niższą częstotliwość PWM można zastosować preskaler, w trybie PWM działa on jako przedłużenie licznika o 65 536 cykli zegara.
Preskaler  jest  8-bitowy i może maksymalnie wynosić 255 (czyli 255 x 65 536 cykli zegara plus to co zostało wpisane w TimerLoadSet(max 65535))
minimalna częstotliwość przy FCPU 80 MHz to 4,76 Hz (czas 256x65536x13ns=0,209s)

TimerPrescaleSet(TIMER0_BASE, TIMER_B, 255);

TimerPrescaleMatchSet(TIMER0_BASE, TIMER_B, 127); // 50% 127x65536 Tc




Kod z użyciem preskalera, dioda powinna migać z wypełnieniem 50% około 5 razy na sekundę:

#include "inc/hw_types.h"

#include "inc/hw_memmap.h"

#include "driverlib/sysctl.h"

#include "driverlib/gpio.h"

#include "driverlib/timer.h"

#include "driverlib/pin_map.h"





int main(void) {



    //clock:

    SysCtlClockSet(SYSCTL_USE_PLL|SYSCTL_SYSDIV_2_5|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN); // OSC MAIN and PLL DIV 2,5 = 80-MHz frequency



    //Configure PF1 as T0CCP1

    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);

    GPIOPinConfigure(GPIO_PF1_T0CCP1 );

    GPIOPinTypeTimer(GPIO_PORTF_BASE, GPIO_PIN_1);



    // Enable Peripheral Timer0

    SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);



    // Configure Timer0 as PWM

    TimerConfigure(TIMER0_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_B_PWM);





    TimerLoadSet(TIMER0_BASE, TIMER_B, 65535); //  frequency in 1x prescaler = 1 to 65536 Tc

    TimerPrescaleSet(TIMER0_BASE, TIMER_B, 255); // max prescaler 255x65536 Tc

    TimerMatchSet(TIMER0_BASE, TIMER_B,65535);

    TimerPrescaleMatchSet(TIMER0_BASE, TIMER_B, 127); // 50% 127x65536 Tc



    TimerEnable(TIMER0_BASE,TIMER_B);



    while(1) {

    }

}