Sunteți pe pagina 1din 4

/****************************************************************************

Module
PWM4Wheel.c
Revision
1.0
Description
This is the PWM4Wheel Module for Initialization of PWM for wheels, set the
direction and duty cycle of PWM.
Notes
History
When
Who
What/Why
----------------------02/10/2015
10:33 Sky
Initial version
****************************************************************************/
#include <stdint.h>
#include
#include
#include
#include
#include
#include
#include

"inc/hw_memmap.h"
"inc/hw_gpio.h"
"inc/hw_pwm.h"
"inc/hw_sysctl.h"
"inc/hw_types.h"
"bitdefs.h"
<stdio.h>

#include "PWM4Wheel.h"
// 40,000 ticks per mS assumes a 40Mhz clock, we will use SysClk/32 for PWM
#define PWMTicksPerMS 8000/32
// set 200 Hz frequency so 5mS period
#define PeriodInMS 1
#define BitsPerNibble 4
#define FORWARD 0
#define BACKWARD 1
#define LEFTWHEEL 1
#define RIGHTWHEEL 2
#ifndef ALL_BITS
#define ALL_BITS (0xff<<2)
#endif
static uint8_t DirectionLeft;
static uint8_t DirectionRight;
// we will use PWM module 0 for this demo and program it for up/down counting
void InitPWMDemo( void ){
volatile uint32_t Dummy; // use volatile to avoid over-optimization
// start by enabling the clock to the PWM Module (PWM0)
HWREG(SYSCTL_RCGCPWM) |= SYSCTL_RCGCPWM_R0;
// enable the clock to Port B
HWREG(SYSCTL_RCGCGPIO) |= SYSCTL_RCGCGPIO_R1;

// Select the PWM clock as System Clock/32


HWREG(SYSCTL_RCC) = (HWREG(SYSCTL_RCC) & ~SYSCTL_RCC_PWMDIV_M) |
(SYSCTL_RCC_USEPWMDIV | SYSCTL_RCC_PWMDIV_32);
// make sure that the PWM module clock has gotten going
while ((HWREG(SYSCTL_PRPWM) & SYSCTL_PRPWM_R0) != SYSCTL_PRPWM_R0)
;
// disable the PWM while initializing
HWREG( PWM0_BASE+PWM_O_0_CTL ) = 0;
// program generator A to go to 0 at rising comare A, 1 on falling compare A
HWREG( PWM0_BASE+PWM_O_0_GENA) =
(PWM_0_GENA_ACTCMPAU_ZERO | PWM_0_GENA_ACTCMPAD_ONE );
// program generator B to go to 0 at rising comare B, 1 on falling compare B
HWREG( PWM0_BASE+PWM_O_0_GENB) =
(PWM_0_GENA_ACTCMPBU_ZERO | PWM_0_GENA_ACTCMPBD_ONE );
// Set the PWM period. Since we are counting both up & down, we initialize
// the load register to 1/2 the desired total period
HWREG( PWM0_BASE+PWM_O_0_LOAD) = ((PeriodInMS * PWMTicksPerMS)-1)>>1;
// Set the initial Duty cycle on A to 50% by programming the compare value
// to 1/2 the period to count up (or down)
HWREG( PWM0_BASE+PWM_O_0_CMPA) = ((PeriodInMS * PWMTicksPerMS)-1)>>2;
// Set the initial Duty cycle on B to 25% by programming the compare value
// to 1/4 the period
HWREG( PWM0_BASE+PWM_O_0_CMPB) = ((PeriodInMS * PWMTicksPerMS)-1)>>3;
// set changes to the PWM output Enables to be locally syncronized to a
// zero count
HWREG(PWM0_BASE+PWM_O_ENUPD) = (HWREG(PWM0_BASE+PWM_O_ENUPD) &
~(PWM_ENUPD_ENUPD0_M | PWM_ENUPD_ENUPD1_M)) |
(PWM_ENUPD_ENUPD0_LSYNC | PWM_ENUPD_ENUPD1_LSYNC);
// enable the PWM outputs
HWREG( PWM0_BASE+PWM_O_ENABLE) |= (PWM_ENABLE_PWM1EN | PWM_ENABLE_PWM0EN);
// now configure the Port B pins to be PWM outputs
// start by selecting the alternate function for PB6 & 7
HWREG(GPIO_PORTB_BASE+GPIO_O_AFSEL) |= (BIT7HI | BIT6HI);
// now choose to map PWM to those pins, this is a mux value of 4 that we
// want to use for specifying the function on bits 6 & 7
HWREG(GPIO_PORTB_BASE+GPIO_O_PCTL) =
(HWREG(GPIO_PORTB_BASE+GPIO_O_PCTL) & 0x00fffff) + (4<<(7*BitsPerNibble)) +
(4<<(6*BitsPerNibble));
// Enable pins 6 & 7 on Port B for digital I/O
HWREG(GPIO_PORTB_BASE+GPIO_O_DEN) |= (BIT7HI | BIT6HI);
// make pins 6 & 7 on Port B into outputs
HWREG(GPIO_PORTB_BASE+GPIO_O_DIR) |= (BIT7HI | BIT6HI);
// set the up/down count mode and enable the PWM generator
HWREG(PWM0_BASE+ PWM_O_0_CTL) |= (PWM_0_CTL_MODE | PWM_0_CTL_ENABLE);

//set initial direction of motor


DirectionLeft = FORWARD;
DirectionRight = FORWARD;
}
/****************************************************************
FUNCTION SetDuty
ARGUMENTS

: channelNum (LEFTWHEEL or RIGHTWHEEL)


newDuty --> the new duty
cycle which will be set to PWM channel
RETURN
DESCRIPTION
)

: No return
: This function will set new dutycycle to PWM channel(channelNum

Always set rotate direct


ion before set duty.
****************************************************************/
void SetDuty(uint16_t newDuty, uint8_t channelNum)
{
if (channelNum == 1) // set dutycycle of channel #1
{
//puts("setDuty1");
uint8_t Duty = newDuty;
//if (DirectionLeft == BACKWARD) Duty = 100-newDuty; //c
alculate the duty that should be set to PWM depends on newDuty and current direc
tion
if ((HWREG( PWM0_BASE+PWM_O_ENABLE) & PWM_ENABLE_PWM0EN)
== 0)
HWREG( PWM0_BASE+PWM_O_ENABLE) |= PWM_ENABLE_PWM0EN;
//if this PWM channel is disabled, enable it
if (Duty == 0) HWREG( PWM0_BASE+PWM_O_ENABLE) &= ~PWM_EN
ABLE_PWM0EN; //set new dutycycle
else HWREG(PWM0_BASE+PWM_O_0_CMPA) = (((PeriodInMS * PWM
TicksPerMS) -1)>>1) * Duty / 100;
} else
if (channelNum == 2) // set dutycycle of channel #2
{
//puts("setDuty2");
uint8_t Duty = newDuty;
//if (DirectionRight == BACKWARD) Duty = 100-newDuty; //
calculate the duty that should be set to PWM depends on newDuty and current dire
ction
if ((HWREG( PWM0_BASE+PWM_O_ENABLE) & PWM_ENABLE_PWM1EN)
== 0)
HWREG( PWM0_BASE+PWM_O_ENABLE) |= PWM_ENABLE_PWM1EN;
//if this PWM channel is disabled, enable it
if (Duty == 0) HWREG( PWM0_BASE+PWM_O_ENABLE) &= ~PWM_EN
ABLE_PWM1EN; //set new dutycycle
else HWREG(PWM0_BASE+PWM_O_0_CMPB) = (((PeriodInMS * PWM
TicksPerMS) -1)>>1) * Duty / 100;
}
}
/****************************************************************
FUNCTION SetDirection

ARGUMENTS

: channelNum (LEFTWHEEL or RIGHTWHEEL)


newDirection (FORWARD or

BACKWARD)
RETURN

: No return

DESCRIPTION
HEEL)

: This function will set direction of motor (LEFTWHEEL or RIGHTW

Always set rotate direct


ion before set duty.
****************************************************************/
void SetDirection(uint8_t newDirection, uint8_t channelNum)
{
if (channelNum == 1)
{
//
if (newDirection != DirectionLeft)
//
{
if (newDirection == FORWARD) HWREG(GPIO_PORTB_BA
SE+(GPIO_O_DATA+ALL_BITS)) |= BIT0HI;
else HWREG(GPIO_PORTB_BASE+(GPIO_O_DATA+ALL_BITS
)) &= BIT0LO;
DirectionLeft = newDirection;
//set ne
w direction
//
}
}
else if (channelNum == 2)
{
//
if (newDirection != DirectionRight)
//
{
if (newDirection == FORWARD) HWREG(GPIO_PORTB_BA
SE+(GPIO_O_DATA+ALL_BITS)) &= BIT3LO;
else HWREG(GPIO_PORTB_BASE+(GPIO_O_DATA+ALL_BITS
)) |= BIT3HI;
DirectionRight = newDirection;
//set ne
w direction
//
}
}
}
void InitMotorControlPin(void)
{
//PB1, PB3: DIR
//PB0, PB4: brake
//PB2, PB5: therm.flag
//PB6, PB7: PWM
HWREG(SYSCTL_RCGCGPIO) |= SYSCTL_RCGCGPIO_R1;
HWREG(GPIO_PORTB_BASE+GPIO_O_DEN) |= (BIT0HI | BIT1HI | BIT3HI | BIT4HI)
;
HWREG(GPIO_PORTB_BASE+GPIO_O_DIR) |= (BIT0HI | BIT1HI | BIT3HI | BIT4HI)
;
HWREG(GPIO_PORTB_BASE+GPIO_O_DIR) &= BIT2LO;
HWREG(GPIO_PORTB_BASE+GPIO_O_DIR) &= BIT5LO;
HWREG(GPIO_PORTB_BASE+(GPIO_O_DATA+ALL_BITS)) &= ~(BIT1HI | BIT4HI);
HWREG(GPIO_PORTB_BASE+(GPIO_O_DATA+ALL_BITS)) |= BIT0HI;
HWREG(GPIO_PORTB_BASE+(GPIO_O_DATA+ALL_BITS)) &= BIT3LO;
}

S-ar putea să vă placă și