示例#1
0
文件: pwm.c 项目: bechu/hexapod
// Set up PWM on the given pin
boolean pwmInitDeciHertz(const IOPin* pin, uint32_t deciHertz, PERCENTAGE duty, uint32_t* actualDeciHertz){
	boolean rtn = FALSE;
	const TimerCompare* channel = compareFromIOPin(pin);

	if(channel==null){
		setError(PWM_PIN_NOT_AVAILABLE);
	}else{
		// The pin is valid
		// The pin is valid and available
		TIMER_MODE mode;
		uint16_t icr;
		uint16_t prescaler;
		uint32_t actual;

		const Timer* timer = compareGetTimer(channel);

		// Find the best PWM setting
		boolean valid = timerCalcPwm(timer, deciHertz, 100, &mode, &icr, &prescaler, &actual);

		if(!valid){
			// There is no PWM setting that is valid
			setError( (timerIsInUse(timer)) ? PWM_TIMER_IN_USE : TIMER_HAS_NO_PWM );
		}else{
			// Lets set up the PWM
			timerSetMode(timer,mode);
			if(modeIsICR(mode)){
				// Set the ICR
				PORT icrPort = pgm_read_word(&timer->pgm_icr);
				_SFR_MEM16(icrPort)=icr;
			}

			// Mark the channel as in use
//			compareAttach(channel,&nullTimerCompareCallback,0,null);

			// Turn the pin into an output, low
			pin_make_output(pin, FALSE);

			// Turn on the PWM pin output
			compareSetOutputMode(channel, CHANNEL_MODE_NON_INVERTING);

			// Turn on the timer
			timerSetPrescaler(timer,prescaler);

			// Set the initial duty cycle
			pwmSetDutyCycle(pin,duty);

			// Set the return value
			if(actualDeciHertz){
				*actualDeciHertz = actual;
			}

			rtn = TRUE;
		}
	}
	return rtn;
}
示例#2
0
// Author: unknown
// Modified by  : Markus Joos ([email protected])


#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/sleep.h>
#include "global.h"
#include "timer.h"


// Program ROM constants
// the pre-scale division values stored in order of timer control register index
// STOP, CLK, CLK/8, CLK/64, CLK/256, CLK/1024
unsigned short __attribute__ ((progmem)) const TimerPrescaleFactor[] = {0,1,8,64,256,1024};

typedef void (*voidFuncPtr)(void);
volatile static voidFuncPtr TimerIntFunc;

// Delay for a minimum of <us> microseconds
// The time resolution is dependent on the time the loop takes
// e.g. with 4Mhz and 5 cycles per loop, the resolution is 1.25 us 
//***********************/
void delay_us(u16 time_us)     //Called from ipmi_if.c and fru.c
//***********************/
{
	u16 delay_loops;
	register u16 i;     

	// one loop takes 5 cpu cycles 
	delay_loops = (time_us + 3) / 22 * 3 * CYCLES_PER_US; // +3 for rounding up (dirty)  //MJ: "22 * 3" is the result of a manual calibration of the delay

	for (i=0; i < delay_loops; i++)
	    asm volatile("nop");          //MJ: Without the "nop" there is the risk that the loop gets removed by the optimizer
}


//*****************/
void timerInit(void)     //Called from mmc_main.c
//*****************/
{
    TimerIntFunc = 0;                       // detach all user functions from interrupts

    // Initialise timer 0
    outb(TCCR0, (inb(TCCR0) | CTC_MODE));   // set set CTC mode
	timerSetPrescaler(TIMER0PRESCALE);	    // set pre-scaler
	outb(TCNT0, 0);							// reset TCNT0
    outb(OCR0, 0x8C);                       // set value to output compare register
	sbi(TIMSK, OCIE0);						// enable output compare match interrupt
}
示例#3
0
static boolean initPWM(const IOPin* pin, uint32_t deciHertz){
	const TimerCompare* channel = compareFromIOPin(pin);

	if(channel==null){
		setError(PWM_PIN_NOT_AVAILABLE);
		return FALSE;
	}
	if(compareIsInUse(channel)){
		setError(PWM_PIN_IN_USE);
		return FALSE;
	}

	TIMER_MODE mode;
	uint16_t icr;
	uint16_t prescaler;

	const Timer* timer = compareGetTimer(channel);

	// Find the best PWM setting for 10kHz, with 128 steps
	boolean valid = timerCalcPwm(timer, deciHertz, 128, &mode, &icr, &prescaler);

	if(!valid){
		// There is no PWM setting that is valid
		setError( (timerIsInUse(timer)) ? PWM_TIMER_IN_USE : TIMER_HAS_NO_PWM );
	}else{
		// Lets set up the PWM
		if(!timerIsInUse(timer)){
			timerSetMode(timer,mode);
			if(modeIsICR(mode)){
				// Set the ICR
				PORT icrPort = pgm_read_word(&timer->pgm_icr);
				_SFR_MEM16(icrPort)=icr;
			}
		}

		// Make it an output pin and set high for brake
		pin_make_output(pin,TRUE);

		// Use inverting PWM
		compareSetOutputMode(channel,CHANNEL_MODE_INVERTING);

		// Mark the channels as in use
		compareAttach(channel,&nullTimerCompareCallback,0,null);

		// Do this last as it then turns on the timer
		timerSetPrescaler(timer,prescaler);
	}
	return valid;
}
示例#4
0
/*
void delay_ms(unsigned char time_ms)
{
	unsigned short delay_count = F_CPU / 4000;

	unsigned short cnt;
	asm volatile ("\n"
                  "L_dl1%=:\n\t"
                  "mov %A0, %A2\n\t"
                  "mov %B0, %B2\n"
                  "L_dl2%=:\n\t"
                  "sbiw %A0, 1\n\t"
                  "brne L_dl2%=\n\t"
                  "dec %1\n\t" "brne L_dl1%=\n\t":"=&w" (cnt)
                  :"r"(time_ms), "r"((unsigned short) (delay_count))
	);
}
*/
void timerInit(void)
{
	// detach all user functions from interrupts
    TimerIntFunc = 0;
	// initialize  timer 0
    outb(TCCR0, (inb(TCCR0) | CTC_MODE));    // set set CTC mode
	timerSetPrescaler( TIMER0PRESCALE );	// set prescaler
//	timerSetPrescaler( TIMER_CLK_DIV1024 );	// set prescaler
	outb(TCNT0, 0);							// reset TCNT0
    outb(OCR0, 0x8C);                       // set value to output compare register
	sbi(TIMSK, OCIE0);						// enable output compare match interrupt


	// enable interrupts
	//sei();
}