📄 main.c
字号:
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//-----------------------------------------------------------------------------
/// \dir "USB HID Keyboard Project"
///
/// !!!Purpose
///
/// The USB HID Keyboard Project will help you to get familiar with the
/// USB Device Port(UDP) and PIO interface on AT91SAM microcontrollers. Also
/// it can help you to be familiar with the USB Framework that is used for
/// rapid development of USB-compliant class drivers such as USB Humen
/// Interface Device class (HID).
///
/// You can find following information depends on your needs:
/// - Sample usage of USB HID driver and PIO driver.
/// - USB HID driver development based on the AT91 USB Framework.
/// - USB enumerate sequence, the standard and class-specific descriptors and
/// requests handling.
/// - The initialize sequence and usage of UDP interface.
///
/// !See
/// - pio: PIO interface driver
/// - usb: USB Framework, USB HID driver and UDP interface driver
/// - "AT91 USB device framework"
/// - "USBD API"
/// - "hid-keyboard"
/// - "USB HID Keyboard"
///
/// !!!Requirements
///
/// This package can be used with all Atmel evaluation kits that has UDP
/// interface and have push buttons on it.
///
/// The current supported board list:
/// - at91sam7s-ek (exclude at91sam7s32)
/// - at91sam7x-ek
/// - at91sam7xc-ek
/// - at91sam7a3-ek
/// - at91sam7se-ek
/// - at91sam9260-ek
/// - at91sam9263-ek
///
/// !!!Description
///
/// When an EK running this program connected to a host (PC for example), with
/// USB cable, the EK appears as a HID Keyboard for the host. Then you can use
/// the push buttons on the EK to input letter to the host. E.g, to open a
/// editor and input a letter 'a' or '9'.
///
/// !!!Usage
///
/// -# Build the program and download it inside the evaluation board. Please
/// refer to the
/// <a href="http://www.atmel.com/dyn/resources/prod_documents/doc6224.pdf">
/// SAM-BA User Guide</a>, the
/// <a href="http://www.atmel.com/dyn/resources/prod_documents/doc6310.pdf">
/// GNU-Based Software Development</a> application note or to the
/// <a href="ftp://ftp.iar.se/WWWfiles/arm/Guides/EWARM_UserGuide.ENU.pdf">
/// IAR EWARM User Guide</a>, depending on your chosen solution.
/// -# On the computer, open and configure a terminal application
/// (e.g. HyperTerminal on Microsoft Windows) with these settings:
/// - 115200 bauds
/// - 8 bits of data
/// - No parity
/// - 1 stop bit
/// - No flow control
/// -# Start the application.
/// -# In the terminal window, the following text should appear:
/// \code
/// -- USB Device HID Keyboard Project xxx --
/// -- AT91xxxxxx-xx
/// -- Compiled: xxx xx xxxx xx:xx:xx --
/// \endcode
/// -# When connecting USB cable to windows, the LED blinks.
/// Then new "HID Keyboard Device" appears in the
/// hardware %device list.
/// -# Once the device is connected and configured, pressing any of the board buttons
/// should send characters to the host PC. Pressing num. lock should also make the third
/// LED toggle its state (on/off).
///
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// \unit
///
/// !Purpose
///
/// This file contains all the specific code for the
/// usb-device-hid-keyboard-project
///
/// !Contents
///
/// The code can be roughly broken down as follows:
/// - Configuration functions
/// - VBus_Configure
/// - ConfigurePit
/// - ConfigureWakeUp
/// - PIO & Timer configurations in start of main
/// - Interrupt handlers
/// - ISR_Vbus
/// - ISR_Pit
/// - WakeUpHandler
/// - Callback functions
/// - HIDDKeyboardCallbacks_LedsChanged
/// - The main function, which implements the program behavior
///
/// Please refer to the list of functions in the #Overview# tab of this unit
/// for more detailed information.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
#include <pio/pio.h>
#include <pio/pio_it.h>
#include <pit/pit.h>
#include <aic/aic.h>
#include <utility/trace.h>
#include <utility/led.h>
#include <pmc/pmc.h>
#include <usb/common/hid/HIDKeypad.h>
#include <usb/device/core/USBD.h>
#include <usb/common/core/USBConfigurationDescriptor.h>
#include <usb/device/hid-keyboard/HIDDKeyboardDriver.h>
#include <string.h>
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
/// Number of keys used in the example.
#define NUM_KEYS 4
/// Number of non-modifiers keys.
#define NUM_NORMAL_KEYS 3
/// Number of modifier keys.
#define NUM_MODIFIER_KEYS (NUM_KEYS - NUM_NORMAL_KEYS)
/// Num lock LED index.
#define LED_NUMLOCK USBD_LEDOTHER
/// Delay for pushbutton debouncing (ms)
#define DEBOUNCE_TIME 10
/// PIT period value (祍econds)
#define PIT_PERIOD 1000
/// Use for power management
#define STATE_IDLE 0
/// The USB device is in suspend state
#define STATE_SUSPEND 4
/// The USB device is in resume state
#define STATE_RESUME 5
//------------------------------------------------------------------------------
// Internal variables
//------------------------------------------------------------------------------
/// State of USB, for suspend and resume
unsigned char USBState = STATE_IDLE;
/// List of pinsPushButtons to configure for the applicatino.
static Pin pinsPushButtons[] = {PINS_PUSHBUTTONS};
/// Array of key codes produced by each button.
static unsigned char keyCodes[NUM_KEYS] = {
HIDKeypad_A,
HIDKeypad_NUMLOCK,
HIDKeypad_9,
HIDKeypad_RIGHTSHIFT
};
/// Current status (pressed or not) for each key.
static unsigned char keyStatus[NUM_KEYS];
//------------------------------------------------------------------------------
// Remote wake-up support (optional)
//------------------------------------------------------------------------------
#if (BOARD_USB_BMATTRIBUTES == USBConfigurationDescriptor_BUSPOWERED_RWAKEUP) \
|| (BOARD_USB_BMATTRIBUTES == USBConfigurationDescriptor_SELFPOWERED_RWAKEUP)
#define WAKEUP_CONFIGURE() ConfigureWakeUp()
/// Button for Wake-UP the USB device.
static const Pin pinWakeUp = PIN_PUSHBUTTON_1;
//------------------------------------------------------------------------------
/// Interrupt service routine for the PIT. Debounces the wake-up pin input.
//------------------------------------------------------------------------------
static void ISR_Pit(void)
{
static unsigned long debounceCounter = DEBOUNCE_TIME;
unsigned long pisr = 0;
// Read the PISR
pisr = PIT_GetStatus() & AT91C_PITC_PITS;
if (pisr != 0) {
// Read the PIVR. It acknowledges the IT
PIT_GetPIVR();
}
// Button released
if (PIO_Get(&pinWakeUp)) {
debounceCounter = DEBOUNCE_TIME;
}
// Button still pressed
else {
debounceCounter--;
}
// End of debounce time
if (debounceCounter == 0) {
debounceCounter = DEBOUNCE_TIME;
PIT_DisableIT();
AT91C_BASE_PITC->PITC_PIMR &= ~AT91C_PITC_PITEN;
HIDDKeyboardDriver_RemoteWakeUp();
}
}
//------------------------------------------------------------------------------
/// Configures the PIT to generate 1ms ticks.
//------------------------------------------------------------------------------
static void ConfigurePit(void)
{
// Initialize and enable the PIT
PIT_Init(PIT_PERIOD, BOARD_MCK / 1000000);
// Disable the interrupt on the interrupt controller
AIC_DisableIT(AT91C_ID_SYS);
// Configure the AIC for PIT interrupts
AIC_ConfigureIT(AT91C_ID_SYS, 0, ISR_Pit);
// Enable the interrupt on the interrupt controller
AIC_EnableIT(AT91C_ID_SYS);
// Enable the interrupt on the pit
PIT_EnableIT();
// Enable the pit
PIT_Enable();
}
//------------------------------------------------------------------------------
/// Interrupt service routine for the remote wake-up pin. Starts the debouncing
/// sequence.
//------------------------------------------------------------------------------
static void WakeUpHandler(const Pin *pin)
{
TRACE_DEBUG("Wake-up handler\n\r");
// Check current level on the remote wake-up pin
if (!PIO_Get(&pinWakeUp)) {
ConfigurePit();
}
}
//------------------------------------------------------------------------------
/// Configures the wake-up pin to generate interrupts.
//------------------------------------------------------------------------------
static void ConfigureWakeUp(void)
{
TRACE_INFO("Wake-up configuration\n\r");
// Configure PIO
PIO_Configure(&pinWakeUp, 1);
PIO_ConfigureIt(&pinWakeUp, WakeUpHandler);
PIO_EnableIt(&pinWakeUp);
}
#else
#define WAKEUP_CONFIGURE()
#endif
//------------------------------------------------------------------------------
// VBus monitoring (optional)
//------------------------------------------------------------------------------
#if defined(PIN_USB_VBUS)
#define VBUS_CONFIGURE() VBus_Configure()
/// VBus pin instance.
static const Pin pinVbus = PIN_USB_VBUS;
//------------------------------------------------------------------------------
/// Handles interrupts coming from PIO controllers.
//------------------------------------------------------------------------------
static void ISR_Vbus(const Pin *pPin)
{
// Check current level on VBus
if (PIO_Get(&pinVbus)) {
TRACE_INFO("VBUS conn\n\r");
USBD_Connect();
}
else {
TRACE_INFO("VBUS discon\n\r");
USBD_Disconnect();
}
}
//------------------------------------------------------------------------------
/// Configures the VBus pin to trigger an interrupt when the level on that pin
/// changes.
//------------------------------------------------------------------------------
static void VBus_Configure( void )
{
TRACE_INFO("VBus configuration\n\r");
// Configure PIO
PIO_Configure(&pinVbus, 1);
PIO_ConfigureIt(&pinVbus, ISR_Vbus);
PIO_EnableIt(&pinVbus);
// Check current level on VBus
if (PIO_Get(&pinVbus)) {
// if VBUS present, force the connect
TRACE_INFO("conn\n\r");
USBD_Connect();
}
else {
USBD_Disconnect();
}
}
#else
#define VBUS_CONFIGURE() USBD_Connect()
#endif //#if defined(PIN_USB_VBUS)
#if defined (CP15_PRESENT)
//------------------------------------------------------------------------------
/// Put the CPU in 32kHz, disable PLL, main oscillator
/// Put voltage regulator in standby mode
//------------------------------------------------------------------------------
void LowPowerMode(void)
{
PMC_CPUInIdleMode();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -