i'm trying to control my led in 256 (0-255) different levels of brightness. my controller is set to 80mhz and running on rtos. i'm setting the clock module to interrupt every 5 microseconds and the brightness e.g. to 150. the led is dimming, but i'm not sure if it is done right to really have 256 different levels
int counter = 1;
int brightness = 0;
void SetUp(void)
{
SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);
GPIOPinTypeGPIOOutput(PORT_4, PIN_1);
Clock_Params clockParams;
Clock_Handle myClock;
Error_Block eb;
Error_init(&eb);
Clock_Params_init(&clockParams);
clockParams.period = 400; // every 5 microseconds
clockParams.startFlag = TRUE;
myClock = Clock_create(myHandler1, 400, &clockParams, &eb);
if (myClock == NULL) {
System_abort("Clock create failed");
}
}
void myHandler1 (){
brightness = 150;
while(1){
counter = (++counter) % 256;
if (counter < brightness){
GPIOPinWrite(PORT_4, PIN_1, PIN_1);
}else{
GPIOPinWrite(PORT_4, PIN_1, 0);
}
}
}
A 5 microsecond interrupt is a tall ask for an 80 MHz processor, and will leave little time for other work, and if you are not doing other work, you need not use interrupts at all - you could simply poll the clock counter; then it would still be a lot of processor to throw at a rather trivial task - and the RTOS is overkill too.
A better way to perform your task is to use the timer's PWM (Pulse Width Modulation) feature. You will then be able to accurately control the brightness with zero software overhead; leaving your processor to do more interesting things.
Using a PWM you could manage with a far lower performance processor if LED control is all it will do.
If you must use an interrupt/GPIO (for example your timer does not support PWM generation or the LED is not connected to a PWM capable pin), then it would be more efficient to set the timer incrementally. So for example for a mark:space of 150:105, you would set the timer for 150*5us (9.6ms), on the interrupt toggle the GPIO, then set the timer to 105*5us (6.72ms).
A major problem with your solution is the interrupt handler does not return - interrupts must run to completion and be as short as possible and preferably deterministic in execution time.
Without using hardware PWM, the following based on your code fragment is probably closer to what you need:
#define PWM_QUANTA = 400 ; // 5us
static volatile uint8_t brightness = 150 ;
static Clock_Handle myClock ;
void setBrightness( uint8_t br )
{
brightness = br ;
}
void SetUp(void)
{
SysCtlClockSet(SYSCTL_SYSDIV_2_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);
GPIOPinTypeGPIOOutput(PORT_4, PIN_1);
Clock_Params clockParams;
Error_Block eb;
Error_init(&eb);
Clock_Params_init(&clockParams);
clockParams.period = brightness * PWM_QUANTA ;
clockParams.startFlag = TRUE;
myClock = Clock_create(myHandler1, 400, &clockParams, &eb);
if (myClock == NULL)
{
System_abort("Clock create failed");
}
}
void myHandler1(void)
{
static int pin_state = 1 ;
// Toggle pin state and timer period
if( pin_state == 0 )
{
pin_sate = 1 ;
Clock_setPeriod( myClock, brightness * PWM_QUANTA ) ;
}
else
{
pin_sate = 0 ;
Clock_setPeriod( myClock, (255 - brightness) * PWM_QUANTA ) ;
}
// Set pin state
GPIOPinWrite(PORT_4, PIN_1, pin_state) ;
}