📄 motors.c
字号:
//*****************************************************************************
//
// motors.c - Motor driver code.
//
// Copyright (c) 2005-2007 Luminary Micro, Inc. All rights reserved.
//
// Software License Agreement
//
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
//
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws. All rights are reserved. Any use in violation
// of the foregoing restrictions may subject the user to criminal sanctions
// under applicable laws, as well as to civil liability for the breach of the
// terms and conditions of this license.
//
// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 199 of an01245.
//
//*****************************************************************************
#include "../../hw_gpio.h"
#include "../../hw_memmap.h"
#include "../../hw_pwm.h"
#include "../../hw_sysctl.h"
#include "../../hw_types.h"
#include "compiler.h"
#include "motors.h"
#include "system.h"
//*****************************************************************************
//
//! \page motors_intro Introduction
//!
//! There are four brushed DC motors on the car; two on the left side of the
//! car and two on the right side. The drive for the two motors on each side
//! is ganged together; a single H bridge provides current to both motors on
//! the left side of the car and another H bridge provides current to both
//! motors on the right side of the car.
//!
//! Though they are full H bridges, each bridge has only two inputs; inverters
//! inside the bridge chip provides the other two control signals. Therefore,
//! providing a high signal on one input and alow signal on the other will
//! cause the connected motors to spin one direction, while swapping the inputs
//! will cause the motors to spin in the other direction.
//!
//! The "top" and "bottom" side of each H bridge are defined such that driving
//! the "top" side with a high signal and the "bottom" side with a low signal
//! will cause the motors to spin in the forward direction.
//!
//! When running, the bridge is supplied with a low signal on one if its inputs
//! and a high signal on the other input. The speed of the motors are
//! controlled by providing a PWM signal in place of the high signal,
//! effectively reducing the drive voltage to the motor.
//!
//! The direction of the motors is switched by simply swapping the input
//! signals to the bridge. Note that to prevent shoot-through current in the
//! bridge, and to reduce wear on the motors, the motor direction should only
//! be changed after the speed of the motors has been brought to zero. The
//! motor speed can be brought to zero either by slewing the speed via periodic
//! calls to MotorLeftSpeed() / MotorRightSpeed() or by simply stopping the
//! motors and waiting for a short period.
//!
//! The left and right motors are operated in a fully independent fashion; the
//! only thing they share is a fixed 15 KHz PWM frequency.
//!
//! The code for controlling the motors is contained in <tt>motors.c</tt>,
//! with <tt>motors.h</tt> containing the API definitions for use by the
//! remainder of the application.
//
//*****************************************************************************
//*****************************************************************************
//
//! \defgroup motors_api Definitions
//! @{
//
//*****************************************************************************
//*****************************************************************************
//
//! Enable this define to provide a workaround for the PWM clocking errata that
//! exists on all silicon revision previous to C0 (errata 4.1). The workaround
//! is harmless for silicon that does not have the clocking errata; the net
//! result of the workaround is to reduce the duty cycle resolution by one bit
//! by pre-dividing the input clock to the PWM generator by two.
//
//*****************************************************************************
#define PWM_ERRATA_WORKAROUND
//*****************************************************************************
//
//! The number of clocks per 15kHz PWM period. This is used to determine the
//! match value for a particular PWM duty cycle.
//
//*****************************************************************************
#ifdef PWM_ERRATA_WORKAROUND
#define PWM_CLOCK (SYSTEM_CLOCK / (2 * 15000))
#else
#define PWM_CLOCK (SYSTEM_CLOCK / 15000)
#endif
//*****************************************************************************
//
//! The GPIO port that contains the pins to which the left motor bridge is
//! connected.
//
//*****************************************************************************
#define LEFT_PORT GPIO_PORTD_BASE
//*****************************************************************************
//
//! The GPIO pin to which the "top side" of the left motor bridge is connected.
//
//*****************************************************************************
#define LEFT_FORWARD (1 << 0)
//*****************************************************************************
//
//! The GPIO pin to which the "bottom side" of the left motor bridge is
//! connected.
//
//*****************************************************************************
#define LEFT_BACKWARD (1 << 1)
//*****************************************************************************
//
//! The GPIO port that contains the pins to which the right motor bridge is
//! connected.
//
//*****************************************************************************
#define RIGHT_PORT GPIO_PORTB_BASE
//*****************************************************************************
//
//! The GPIO pin to which the "top side" of the right motor bridge is
//! connected.
//
//*****************************************************************************
#define RIGHT_FORWARD (1 << 0)
//*****************************************************************************
//
//! The GPIO pin to which the "bottom side" of the right motor bridge is
//! connected.
//
//*****************************************************************************
#define RIGHT_BACKWARD (1 << 1)
//*****************************************************************************
//
//! Configures the motors for operation.
//!
//! This function prepares the motors for normal operation. The PWM and GPIO
//! blocks are configured to properly drive the motors. The motors are stopped
//! by default and no default direction is provided (i.e. MotorLeftDir() must
//! be called before the left motor will run, and MotorRightDir() must be
//! called before the right motor will run).
//!
//! \return None.
//
//*****************************************************************************
void
MotorInit(void)
{
//
// Stop the motors.
//
HWREG(LEFT_PORT + GPIO_O_DIR) |= LEFT_FORWARD | LEFT_BACKWARD;
HWREG(LEFT_PORT + GPIO_O_DATA + ((LEFT_FORWARD | LEFT_BACKWARD) << 2)) = 0;
HWREG(RIGHT_PORT + GPIO_O_DIR) |= RIGHT_FORWARD | RIGHT_BACKWARD;
HWREG(RIGHT_PORT + GPIO_O_DATA + ((RIGHT_FORWARD | RIGHT_BACKWARD) << 2)) =
0;
//
// Configure the PWM generator for the left motor.
//
HWREG(PWM_BASE + PWM_GEN_0_OFFSET + PWM_O_X_LOAD) = PWM_CLOCK - 1;
HWREG(PWM_BASE + PWM_GEN_0_OFFSET + PWM_O_X_CMPA) = PWM_CLOCK - 2;
HWREG(PWM_BASE + PWM_GEN_0_OFFSET + PWM_O_X_CMPB) = PWM_CLOCK;
HWREG(PWM_BASE + PWM_GEN_0_OFFSET + PWM_O_X_GENA) =
((PWM_GEN_ACT_ONE << PWM_GEN_ACT_LOAD_SHIFT) |
(PWM_GEN_ACT_ZERO << PWM_GEN_ACT_A_DN_SHIFT));
HWREG(PWM_BASE + PWM_GEN_0_OFFSET + PWM_O_X_GENB) =
((PWM_GEN_ACT_ONE << PWM_GEN_ACT_LOAD_SHIFT) |
(PWM_GEN_ACT_ZERO << PWM_GEN_ACT_A_DN_SHIFT));
HWREG(PWM_BASE + PWM_GEN_0_OFFSET + PWM_O_X_CTL) = PWM_X_CTL_ENABLE;
//
// Configure the PWM generator for the right motor.
//
HWREG(PWM_BASE + PWM_GEN_1_OFFSET + PWM_O_X_LOAD) = PWM_CLOCK - 1;
HWREG(PWM_BASE + PWM_GEN_1_OFFSET + PWM_O_X_CMPA) = PWM_CLOCK - 2;
HWREG(PWM_BASE + PWM_GEN_1_OFFSET + PWM_O_X_CMPB) = PWM_CLOCK;
HWREG(PWM_BASE + PWM_GEN_1_OFFSET + PWM_O_X_GENA) =
((PWM_GEN_ACT_ONE << PWM_GEN_ACT_LOAD_SHIFT) |
(PWM_GEN_ACT_ZERO << PWM_GEN_ACT_A_DN_SHIFT));
HWREG(PWM_BASE + PWM_GEN_1_OFFSET + PWM_O_X_GENB) =
((PWM_GEN_ACT_ONE << PWM_GEN_ACT_LOAD_SHIFT) |
(PWM_GEN_ACT_ZERO << PWM_GEN_ACT_A_DN_SHIFT));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -