Table of Contents

ARM-CAN HomeLab Kit

The ARM-CAN HomeLab kit is a set of interconnected modules and arrangements. Main module is a microcontroller boards which can be used to build up the node network. The kit has in different interfaces for peripheral device connections as a subject of training. All together the HomeLab kit is a mobile ready for use a small test stand, which could be connected to PC and operated in home or working place. HomeLab has a modular structure, meaning that the content can be combined according the needs and given task.

The ARM-CAN HomeLab kit is intended for the high level algorithm and car network teaching. The kit is based on the state-of-art ARM Cortex M3 controller and supports lots of peripheral. The kit included two (or three) controller board, one user interface and programmer. The user interface is equipped with color LCD, two dimensional joystick, push-buttons and polyphonic speaker. The kit is packed into handy case and has all necessary accessories, like power supply and cables included. The CD is included with software and user guides.

Controller

Controller module

Features

MCU

Ports

Every pin has I/O functionality (except PWM) ADC and PWM have 3 pin headers with ground and +5 V

On-board features

Electrical

Physical

Connectors

ARM-CAN connectors

The following chapters describe each of the connectors on ARM-CAN Controller module. To recognize the connectors the Controller has to be held as shown on the picture.

PWM

PWM1 connector
PWM2 connector

PWM1/2 connector has standard RC-servo compatible pinout. In both connectors there are two vertically placed RC-servo pinouts (signal, supply, ground) therefore up to 4 RC-servos can be driven. Controller board supplies up to 2 A total (not counting other consumers) from PWM supply pins. PWM1/2 connector can also be used to drive DC motor which should be connected between leftmost PWM signal pins. Those signals are driven by 5V 600 mA MOSFET half-bridges and can form a full H-bridge. Because of transistors PWM signals can only be used as output.

ADC

ADC1 connector
ADC2 connector

Both ADC1 and ADC2 connectors have two RC-servo like pinouts. There are ground, supply and input-output pins. It is easy to connect simple sensors like potentiometer, thermistor, IR distance sensor and ultrasonic distance sensor to these pins. I/O pins can be used as +5 V compatible inputs or outputs with +3.3 V high level. These connectors can also be used to control RC-servos with software PWM when the servo accepts 3.3 V signal.

COMM

COMM connector

COMM connector is a combination of UART, SPI and I2C interfaces. Beside the +5 V supply it contains +3.3 V supply which supplies up to 700 mA. COMM connector is intended to connect with ARM-CAN User Interface and that is why it also features 2 ADC and 1 PWM pins, which are used by the joystick and speaker.

JTAG

JTAG connector

ARM-CAN Controller board has a standard 20-pin JTAG connector with essential pins for programming and debugging. Although the kit contains ARM-CAN programmer, other standard ARM debuggers can be used.

CAN

CAN connector(s)

ARM-CAN Controller board contains two identical CAN 10-pin header connectors. Both of the connectors are on the same bus, therefore CAN network can be formed by daisy-chaining several Controllers. There is no CAN signal terminator on the Controller board so external terminators should be used.

Microcontroller CAN RX and TX pins which connect to the on-board CAN translator are marked with orange color on the image.

USB

USB pins

The controller board incorporates the USB micro-AB connector on the right side. Although micro-AB is intended for OTG applications the same connector can be used for device-only and host-only applications. USB inteface has ESD protection on bus and 750 mA fuse on supply line. USB power supply is bi-directional. When the controller acts as a USB device, current from the USB bus to controller board flows through a Schottky diode, when the controller is used as a host, external power switch to USB bus can be opened with USB_EPEN high signal.

RGB LED

RGB LED pins

In the middle of the controller board there is a 350 mW RGB LED. Each of the three colors are driven by separate signal. Green LED has a pull-up resistor which lights up green led by default. It can be turned off when microcontroller pin is configured as output with low signal.

Buttons

BTN pin

There are two buttons on board. The left one resets microcontroller when pressed; the right one is used as a custom button for user application. The button has an RC filter which filters button bounces.

Programmer

Programmer module

Features

Programmer

Power supply

Physical

Connectors

Programmer connectors

ARM-CAN Programmer has two connectors: USB to connect the Programmer to PC and JTAG to connect the Programmer to ARM-CAN Controller. To recognize the connectors the programmer has to be held as shown in the picture.

JTAG

JTAG connector

Programmer board has standard 20-pin JTAG connector with essential pins for programming and debugging. When voltage is detected on VREF pin, a red light on the Programmer board lights up.

USB

Programmer board has USB micro-AB connector to connect it with the PC.

User-interface

User-interface module

Features

LCD

Inputs

Speaker

Physical

Connector

User-interface connectors

ARM-CAN User-interface connects only to the controller board with COMM connector. This one and only connector has all the pins necessary to use with on-board LCD, buttons, speaker and joystick. The correct way to look at the user-interface is shown in the illustration on the right.

COMM

COMM connector

Both the controller and user-interface COMM connectors are identical, except the names of the pins are different. Blue colored names represent microcontroller pin names to help use features.

Kit Setup

Connecting Modules

Connecting Programmer to Controller

To use the programmer connect it as shown in the picture. Currently there are two versions of programmers - one which plugs right on top of controller boar, and another one with 20-pin ribbon cable. Both of these versions have a USB receptable on the right side.

Connecting User-interface to Controller

The connection of the user-interface is done through a COMM connector with ribbon cable as shown in the picture.

Installing Software

  1. Install Keil uVision Evaluation version
    It is named Software/mdk410.exe on CD. The same evaluation version is available on the uVision homepage.
  2. Install StellarisWare
    It's path on CD is Software/SW-LM3S-5570.exe. It can also be downloaded from Texas Instruments Stellaris web page. It is necessary to install the software to the “C:\StellarisWare” folder otherwise example project files should be re-configured.
  3. Copy examples to your computer
    Copy Examples folder from CD or from web-page to any place in your harddrive. Please note that after modifing project files, uVision saves file paths as absolute so moving the folder later can cause trouble.
  4. Connect the programmer to your computer
    Stellaris Evalution Board clone should be found. Install the device drivers located in Software/Luminary_FTDI_Driver folder on CD or download them from the same site as StellarisWare.

Run test

RGB LED demo project opened with Keil uVision

Try any of the example projects with Keil uVision. For example, locate “rgb_led_demo” project and open “rgb_led_demo.uvproj” file. You can use uVision to compile and download project code to an ARM device - there are quickbuttons on the left side of the toolbar for this. Please note that uVision does not reset the device after programming so it is required to press the reset button on the Controller board (the left one) after downloading the code.

CAN protocol

From Wikipedia, the free encyclopedia

Controller–area network (CAN or CAN-bus) is a vehicle bus standard designed to allow microcontrollers and devices to communicate with each other within a vehicle without a host computer.

CAN is a message based protocol, designed specifically for automotive applications but now also used in other areas such as industrial automation and medical equipment.

Development of the CAN-bus started originally in 1983 at Robert Bosch GmbH. The protocol was officially released in 1986 at the Society of Automotive Engineers (SAE) congress in Detroit, Michigan. The first CAN controller chips, produced by Intel and Philips, came on the market in 1987. Bosch published the CAN 2.0 specification in 1991.

CAN is one of five protocols used in the OBD-II vehicle diagnostics standard, mandatory for all cars and light trucks sold in the United States since 1996, and the EOBD standard, mandatory for all petrol vehicles sold in the European Union since 2001 and all diesel vehicles since 2004.

CAN messaging

Requirements: [HW] Controller

Theory

From Wikipedia, the free encyclopedia

Controller–area network (CAN or CAN-bus) is a vehicle bus standard designed to allow microcontrollers and devices to communicate with each other within a vehicle without a host computer.

CAN is a message based protocol, designed specifically for automotive applications but now also used in other areas such as industrial automation and medical equipment.

Development of the CAN-bus started originally in 1983 at Robert Bosch GmbH. The protocol was officially released in 1986 at the Society of Automotive Engineers (SAE) congress in Detroit, Michigan. The first CAN controller chips, produced by Intel and Philips, came on the market in 1987. Bosch published the CAN 2.0 specification in 1991.

CAN is one of five protocols used in the OBD-II vehicle diagnostics standard, mandatory for all cars and light trucks sold in the United States since 1996, and the EOBD standard, mandatory for all petrol vehicles sold in the European Union since 2001 and all diesel vehicles since 2004.

Practice

ARM-CAN controller board LM3S5632 MCU is programmed with the help of Texas Instruments (former Luminary Micro) StellarisWare software library. The library includes all the functions to alter microcontroller's registers. LM3S5632 incorporates CAN 2.0 controller with 32 message objects which can be used to automatically transmit and receive messages.

Most common functions to deal with CAN controller are CANMessageSet and CANMessageGet. The first one is used to configure one of the 32 message objects to send or receive a message, another one is used to read the message which was sent or received. They both use tCANMsgObject structure to specify message ID, mask, flags and payload.

The following program demonstrates how to set up CAN controller and wait for a message:

//*****************************************************************************
//
// CAN message receiving.
//
//*****************************************************************************
 
#include <inc/hw_ints.h>
#include <inc/hw_memmap.h>
#include <inc/hw_types.h>
#include <driverlib/sysctl.h>
#include <driverlib/can.h>
 
//*****************************************************************************
//
// Main function.
//
//*****************************************************************************
int main(void)
{	
	tCANMsgObject psMsg;
	unsigned char pucData[8];
 
	//
	// Set the clocking to run from the PLL at 50MHz
	//
	SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
	   SYSCTL_XTAL_8MHZ);
 
	//
	// Enable peripherals.
	//	
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);		
 
	//
	// Configure CAN pins.
	//
	GPIOPinTypeCAN(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1);	
 
	//
	// Enable the CAN controller.
	//    
	CANInit(CAN0_BASE);
	CANBitRateSet(CAN0_BASE, SysCtlClockGet(), CAN_BITRATE);
	CANEnable(CAN0_BASE);	
 
	//
	// Create receive message object.
	//	
	psMsg.ulMsgID     = 0x01;
	psMsg.ulMsgIDMask = 0xFF;
	psMsg.ulFlags     = MSG_OBJ_NO_FLAGS;	
	psMsg.pucMsgData  = pucData;
 
	//
	// Set message object on box 1.
	//
	CANMessageSet(CAN0_BASE, 1, &psEchoMsg, MSG_OBJ_TYPE_RX);
 
	//
	// Loop forever.
	//
	while (1)
	{	
		//
		// CAN message received ?
		//
		if (CANStatusGet(CAN0_BASE, CAN_STS_NEWDAT) & 1)
		{
			//
			// Get the message.
			//
			CANMessageGet(CAN0_BASE, CAN_MSG_OBJ_RX, &psMsg, true);
 
			//
			// Access pucData here.
			// To get the length of the data read psMsg.ulMsgLen
			//
		}
	}
}

CAN ping-pong

Requirements: [HW] 2 x Controller

RGB LEDs flashing on frame arrival

The following program demonstrates the usage of CAN messaging on ARM-CAN controllers. Both controller have the same code. Whenever the button is pressed, a CAN message carrying a ping number is sent. If the message is received by the other node, it lights up it's red LED with intensity relative to the ping number and waits for 200 ms. After that it turns the LED off and sends the similar packet with decreased ping number to the controller which sent it out at first place. Messages are exchanged until the ping count reaches zero.

can_ping_pong.c

//*****************************************************************************
//
// CAN ping-pong demo
//
// This program does not use CAN interrupts.
//
// Copyright (c) 2009 TUT Department of Mechatronics
//
//*****************************************************************************
 
#include <inc/hw_ints.h>
#include <inc/hw_memmap.h>
#include <inc/hw_types.h>
#include <driverlib/sysctl.h>
#include <driverlib/interrupt.h>
#include <driverlib/gpio.h>
#include <driverlib/can.h>
#include <drivers/general.h>
#include <drivers/rgb_led.h>
 
//*****************************************************************************
//
// Configuration.
//
//*****************************************************************************
#define CAN_BITRATE         250000
#define CAN_MSG_ID          0x01
#define CAN_MSG_OBJ_RX      1
#define CAN_MSG_OBJ_TX      2
#define PING_START_COUNT    15
#define PING_PERIOD         200
 
//*****************************************************************************
//
// Ping command. Send CAN TX frame.
//
//*****************************************************************************
void Ping(unsigned long ulCount)
{
	tCANMsgObject psPingMsg;
 
	//
	// Setup ping message object.
	//
	psPingMsg.ulMsgID    = CAN_MSG_ID;	
	psPingMsg.ulFlags    = MSG_OBJ_NO_FLAGS;
	psPingMsg.ulMsgLen   = 4;
	psPingMsg.pucMsgData = (unsigned char *)&ulCount;
 
	//
	// Set message.
	//
	CANMessageSet(CAN0_BASE, CAN_MSG_OBJ_TX, &psPingMsg, MSG_OBJ_TYPE_TX);
}
 
//*****************************************************************************
//
// Main function.
//
//*****************************************************************************
int main(void)
{	
	tCANMsgObject psEchoMsg;
	tBoolean bButtonState, bButtonOldState = false;
	unsigned char pucRxData[8];
	unsigned long ulPingCount = 0;	
 
	//
	// Set the clocking to run from the PLL at 50MHz
	//
	SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
	   SYSCTL_XTAL_8MHZ);
 
	//
	// Enable peripherals.
	//	
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);	
	SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);		
 
	//
	// Configuring.
	//
	DeviceConfigure();	
	RGBLEDConfigure();
 
	//
	// Configure CAN pins.
	//
	GPIOPinTypeCAN(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1);	
 
	//
	// Enable the CAN controller.
	//    
	CANInit(CAN0_BASE);
	CANBitRateSet(CAN0_BASE, SysCtlClockGet(), CAN_BITRATE);
	CANEnable(CAN0_BASE);	
 
	//
	// Create echo message object.
	//	
	psEchoMsg.ulMsgID     = CAN_MSG_ID;
	psEchoMsg.ulMsgIDMask = 0xFF;
	psEchoMsg.ulFlags     = MSG_OBJ_NO_FLAGS;	
	psEchoMsg.pucMsgData  = pucRxData;
 
	//
	// Set message object.
	//
	CANMessageSet(CAN0_BASE, CAN_MSG_OBJ_RX, &psEchoMsg, MSG_OBJ_TYPE_RX);
 
	//
	// Enable processor interrupts.
	//
	IntMasterEnable();	
 
	//
	// Loop forever.
	//
	while (1)
	{	
		//
		// Get button state.
		//
		bButtonState = ButtonIsPressed();
 
		//
		// Button has been pressed down ?
		//
		if (bButtonState && !bButtonOldState)
		{					
			//
			// First ping.
			//
			Ping(PING_START_COUNT);
 
			//
			// Reset countdown.
			//
			CountDownReset();
		}
 
		//
		// Remember last button state.
		//
		bButtonOldState = bButtonState;
 
		//
		// CAN message received ?
		//
		if (CANStatusGet(CAN0_BASE, CAN_STS_NEWDAT) & (1 << (CAN_MSG_OBJ_RX - 1)))
		{
			//
			// Get the message.
			//
			CANMessageGet(CAN0_BASE, CAN_MSG_OBJ_RX, &psEchoMsg, true);
 
			//
			// Check message length.
			//
			if (psEchoMsg.ulMsgLen == 4)
			{
				//
				// Get ping count and decrease it.				
				//
				ulPingCount = *((unsigned long *)psEchoMsg.pucMsgData);
 
				//
				// Light up RGB LED.
				//
				RGBLEDSetRed(ulPingCount * 255 / PING_START_COUNT);
 
				//
				// Start countdown timer.
				//
				CountDownStartMS(PING_PERIOD);
			}			
		}
 
		//
		// Countdown ended ?
		//
		if (CountDownHasEnded())
		{
			//
			// Turn off the LED.
			//			
			RGBLEDSetRed(0);
 
			//
			// Send ping if any bounces left.
			//
			if (ulPingCount > 0)
			{				
				//
				// Ping with decreased count.
				//
				Ping(--ulPingCount);
			}
 
			//
			// Reset countdown.
			//
			CountDownReset();
		}
	}
}

CAN windscreen wiper

Requirements: [HW] 2 x Controller, [HW] Servo-motor

Windscreen wiper in different modes

This project demonstrates how to use CAN interface to transfer commands from one device to other. Two ARM-CAN contollers are need of which one acts as a lever on the steering wheel of a car and another one as a windscreen wiper controller. When buttons is pressed on lever controller, next wiping mode is selected and wiper is notified. Servo-motor is used for simulating the wiper. There are three modes:

windscreen_wiper_control.c

//*****************************************************************************
//
// Windscreen wiper control
//
// Program is entirely interrupts based.
//
// Copyright (c) 2009 TUT Department of Mechatronics
//
//*****************************************************************************
 
#include <inc/hw_ints.h>
#include <inc/hw_memmap.h>
#include <inc/hw_types.h>
#include <driverlib/sysctl.h>
#include <driverlib/interrupt.h>
#include <driverlib/gpio.h>
#include <driverlib/timer.h>
#include <driverlib/can.h>
#include <drivers/general.h>
#include <drivers/rgb_led.h>
 
//*****************************************************************************
//
// Configuration.
//
//*****************************************************************************
#define CAN_BITRATE           250000
#define CAN_ACTUATOR_MSG_ID   0x01
#define CAN_ACTUATOR_MSG_BOX  1
 
//*****************************************************************************
//
// Global variables.
//
//*****************************************************************************
unsigned char g_ucMode = 0;
 
//*****************************************************************************
//
// The interrupt handler for the port B interrupt.
//
//*****************************************************************************
void PortBIntHandler(void)
{
	tCANMsgObject psCommandMsg;
 
	//
	// Clear the port interrupt.
	//
	GPIOPinIntClear(GPIO_PORTB_BASE, GPIO_PIN_7);	
 
	//
	// Next wiper mode of 3 modes.
	//
	g_ucMode = (g_ucMode + 1) % 3;
 
	//
	// Create message.
	//			
	psCommandMsg.ulMsgID    = CAN_ACTUATOR_MSG_ID;	
	psCommandMsg.ulFlags    = MSG_OBJ_NO_FLAGS;
	psCommandMsg.ulMsgLen   = 1;
	psCommandMsg.pucMsgData = &g_ucMode;
 
	//
	// Set message.
	//
	CANMessageSet(CAN0_BASE, CAN_ACTUATOR_MSG_BOX,
	              &psCommandMsg, MSG_OBJ_TYPE_TX);
 
	//
	// Turn on the appropriate LED.
	//			
	RGBLEDSetRGB((g_ucMode == 0 ? 255 : 0),
	             (g_ucMode == 1 ? 255 : 0),
	             (g_ucMode == 2 ? 255 : 0));
}
 
//*****************************************************************************
//
// Main function.
//
//*****************************************************************************
int main(void)
{	
	//
	// Set the clocking to run from the PLL at 50MHz
	//
	SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
	SYSCTL_XTAL_8MHZ);
 
	//
	// Enable peripherals.
	//	
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);		
	SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);		
 
	//
	// Enable the peripherals that should continue to run when the processor
	// is sleeping.
	//		
	SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOB);
	SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOC);    
	SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOD);
	SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOE);	
	SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_CAN0);
 
	//
	// Drivers configuring.
	//
	DeviceConfigure();	
	RGBLEDConfigure();
 
	// 
	// Configure button to generate interrupt on press.
	//		
	GPIOIntTypeSet(GPIO_PORTB_BASE, GPIO_PIN_7, GPIO_FALLING_EDGE);
	GPIOPinIntEnable(GPIO_PORTB_BASE, GPIO_PIN_7);
	IntEnable(INT_GPIOB);
 
	//
	// Configure CAN pins.
	//    
	GPIOPinTypeCAN(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1);	
 
	//
	// Enable the CAN controller.
	//	    
	CANInit(CAN0_BASE);
	CANBitRateSet(CAN0_BASE, SysCtlClockGet(), CAN_BITRATE);
	CANEnable(CAN0_BASE);	
 
	//
	// Enable processor interrupts.
	//
	IntMasterEnable();	
 
	//
	// Loop forever.
	//
	while (1)
	{	
		//
		// Save power - turn off CPU.
		//
		SysCtlSleep();
	}
}

windscreen_wiper_actuator.c

//*****************************************************************************
//
// Windscreen wiper actuator
//
// Program is entirely interrupts based.
//
// Copyright (c) 2009 TUT Department of Mechatronics
//
//*****************************************************************************
 
#include <inc/hw_ints.h>
#include <inc/hw_memmap.h>
#include <inc/hw_types.h>
#include <driverlib/sysctl.h>
#include <driverlib/interrupt.h>
#include <driverlib/gpio.h>
#include <driverlib/timer.h>
#include <driverlib/can.h>
#include <drivers/general.h>
#include <drivers/rgb_led.h>
#include <drivers/servo_motor.h>
 
//*****************************************************************************
//
// Configuration.
//
//*****************************************************************************
#define SERVO_INDEX                0
#define CAN_BITRATE                250000
#define CAN_ACTUATOR_MSG_ID        0x01
#define CAN_ACTUATOR_MSG_BOX       1
#define CAN_ACTUATOR_MSG_BOX_FLAG  (1 << (CAN_ACTUATOR_MSG_BOX - 1))
 
//*****************************************************************************
//
// Global variables.
//
//*****************************************************************************
signed long g_slWiperDirection = 1;
 
//*****************************************************************************
//
// The interrupt handler for the timer2 interrupt.
//
//*****************************************************************************
void Timer2IntHandler(void)
{
	//
	// Clear the timer interrupt.
	//
	TimerIntClear(TIMER2_BASE, TIMER_TIMA_TIMEOUT);	
 
	//
	// Set servo position.
	//
	ServoSetPulseWidth(SERVO_INDEX, 100 * g_slWiperDirection);
 
	//
	// Reverse wiper direction.
	//
	g_slWiperDirection = -g_slWiperDirection;
}
 
//*****************************************************************************
//
// Wiper mode setting.
//
//*****************************************************************************
void WiperModeSet(unsigned char ucMode)
{	
	unsigned long ulPeriod = 0;
 
	//
	// Turn on the appropriate LED.
	//			
	RGBLEDSetRGB((ucMode == 0 ? 255 : 0),
	             (ucMode == 1 ? 255 : 0),
	             (ucMode == 2 ? 255 : 0));	
 
	//
	// Mode 0 ?
	//	
	if (ucMode == 0)
	{	
		//
		// Disable wiper timer.
		//
		TimerDisable(TIMER2_BASE, TIMER_A);
 
		//
		// Stop servo motor.
		//
		ServoSetPulseWidth(SERVO_INDEX, 0);				
	}
	//
	// Mode 1 or 2 ?
	//
	else if (ucMode <= 2)
	{
		//
		// Set period according to the mode.
		//
		switch (ucMode)
		{
			case 1:
				ulPeriod = SysCtlClockGet() * 2; // 2 s
				break;
 
			case 2:
				ulPeriod = SysCtlClockGet() / 2; // 500 ms
				break;
		}
 
		//
		// Configure periodic timer to generate interrupt.		
		//
		TimerLoadSet(TIMER2_BASE, TIMER_A, ulPeriod);
		TimerEnable(TIMER2_BASE, TIMER_A);
	}
}
 
//*****************************************************************************
//
// The interrupt handler for the CAN interrupt.
//
//*****************************************************************************
void CAN0IntHandler(void)
{
	tCANMsgObject psCommandMsg;
	unsigned char pucRxData[8];
	unsigned char ucMode = 0;
 
	//
	// Set pointer to data.
	//
	psCommandMsg.pucMsgData = pucRxData;	
 
	//
	// New CAN message received ?
	//
	if (CANStatusGet(CAN0_BASE, CAN_STS_NEWDAT) & CAN_ACTUATOR_MSG_BOX_FLAG)
	{
		//
		// Get the message.
		//
		CANMessageGet(CAN0_BASE, CAN_ACTUATOR_MSG_BOX_FLAG, &psCommandMsg, true);
 
		//
		// Check message length.
		//
		if (psCommandMsg.ulMsgLen == 1)
		{
			//
			// Get mode from data.
			//
			ucMode = *psCommandMsg.pucMsgData;
 
			//
			// Set wiper mode.
			//				
			WiperModeSet(ucMode);		
		}
	}	
}
 
//*****************************************************************************
//
// Main function.
//
//*****************************************************************************
int main(void)
{		
	tCANMsgObject psCommandMsg;	
 
	//
	// Set the clocking to run from the PLL at 50MHz
	//
	SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
	   SYSCTL_XTAL_8MHZ);
 
	//
	// Enable peripherals.
	//	
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOB);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOC);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);	
	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);
	SysCtlPeripheralEnable(SYSCTL_PERIPH_CAN0);		
 
	//
	// Enable the peripherals that should continue to run when the processor
	// is sleeping.
	//		
	SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOB);
	SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOC);    
	SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOD);
	SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_GPIOE);    
	SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_TIMER0);
	SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_TIMER2);
	SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_CAN0);
 
	//
	// Drivers configuring.
	//
	DeviceConfigure();
	RGBLEDConfigure();
	ServoConfigure(SERVO_INDEX);
 
	//
	// Configure timer 2 as periodic wiper timer.
	//	
	TimerConfigure(TIMER2_BASE, TIMER_CFG_32_BIT_PER);		
 
	//
	// Enable timer 2 interrupt.
	//	
	TimerIntEnable(TIMER2_BASE, TIMER_TIMA_TIMEOUT);
	IntEnable(INT_TIMER2A);	
 
	//
	// Configure CAN pins.
	//    
	GPIOPinTypeCAN(GPIO_PORTD_BASE, GPIO_PIN_0 | GPIO_PIN_1);	
 
	//
	// Enable the CAN controller.
	//	    
	CANInit(CAN0_BASE);
	CANBitRateSet(CAN0_BASE, SysCtlClockGet(), CAN_BITRATE);
	CANEnable(CAN0_BASE);	
 
	//
	// Enable CAN interrupts.
	//
	CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_STATUS);
	IntEnable(INT_CAN0);    
 
	//
	// Create receive command message object.
	//	
	psCommandMsg.ulMsgID     = CAN_ACTUATOR_MSG_ID;
	psCommandMsg.ulMsgIDMask = CAN_ACTUATOR_MSG_ID;
	psCommandMsg.ulFlags     = MSG_OBJ_RX_INT_ENABLE;
 
	//
	// Set message object.
	//
	CANMessageSet(CAN0_BASE, CAN_ACTUATOR_MSG_BOX, &psCommandMsg, MSG_OBJ_TYPE_RX);
 
	//
	// Enable processor interrupts.
	//
	IntMasterEnable();	
 
	//
	// Loop forever.
	//
	while (1)
	{
		//
		// Save power - turn off CPU.
		//
		SysCtlSleep();
	}
}

Crazy USB mouse

Requirements: [HW] Controller

Mouse cursor moving round

ARM-CAN USB mouse demo project. Software is based on TI StellarisWare USB library. When attaching the ARM-CAN controller board to the PC, it acts as a standard USB HID mouse. Fixed-point sine calculation functions are used to move cursor around. Push-button on the controller board acts as a left button.

crazy_mouse.c

//*****************************************************************************
//
// Crazy USB mouse.
//
// Copyright (c) 2009 TUT Department of Mechatronics
//
//*****************************************************************************
 
#include <inc/hw_ints.h>
#include <inc/hw_types.h>
#include <driverlib/sysctl.h>
#include <driverlib/interrupt.h>
#include <driverlib/usb.h>
#include <usblib/usblib.h>
#include <usblib/usbhid.h>
#include <usblib/usb-ids.h>
#include <usblib/device/usbdevice.h>
#include <usblib/device/usbdhid.h>
#include <usblib/device/usbdhidmouse.h>
#include <drivers/general.h>
#include <utils/sine.h>
#include "usb_mouse_structs.h"
 
//*****************************************************************************
//
// Global variables.
//
//*****************************************************************************
volatile tBoolean g_bConnected;
volatile tBoolean g_bCanSend;
 
//*****************************************************************************
//
// Mouse handler.
//
//*****************************************************************************
unsigned long MouseHandler(void *pvCBData, unsigned long ulEvent,
                           unsigned long ulMsgData, void *pvMsgData)
{
    switch (ulEvent)
    {
        //
        // The USB host has connected to and configured the device.
        //
        case USB_EVENT_CONNECTED:
        {            
            g_bConnected = true;
			g_bCanSend = true;
            break;
        }
 
        //
        // The USB host has disconnected from the device.
        //
        case USB_EVENT_DISCONNECTED:
        {         
            g_bConnected = false;         
			g_bCanSend = false;
            break;
        }
 
        //
        // A report was sent to the host.
        //
        case USB_EVENT_TX_COMPLETE:
        {            
			g_bCanSend = true;
            break;
        }
 
    }
    return(0);
}
 
//*****************************************************************************
//
// Main function.
//
//*****************************************************************************
int main(void)
{	
	unsigned long ulAngle = 0;
	char cDeltaX = 0, cDeltaY = 0;		
 
	//
	// Set the clocking to run from the PLL at 50MHz
	//
	SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |
					SYSCTL_XTAL_8MHZ);
 
	//
	// Drivers configuring.
	//
	DeviceConfigure();
 
	//
	// Pass the USB library our device information, initialize the USB
	// controller and connect the device to the bus.
	//
	USBDHIDMouseInit(0, (tUSBDHIDMouseDevice *)&g_sMouseDevice);
 
	//
	// Enable processor interrupts.
	//
	IntMasterEnable();	
 
	//
	// Loop forever.
	//
	while (true)
	{			
		//
		// Device connected and ready ?
		//
		if (g_bConnected && g_bCanSend)
		{			
			//
			// Rotate by 1 / 256 of full circle.
			//
			ulAngle += 0x1000000;
 
			//
			// Calculate X and Y movement.
			// Use sine function with fixed point numbers.
			//
			cDeltaX = sine(ulAngle) >> 14;
			cDeltaY = sine(ulAngle - 0x40000000) >> 14;
 
			//
			// Keep a small break.
			//
			DelayMS(5);
 
			//
			// Update mouse state.
			//			
			USBDHIDMouseStateChange((void *)&g_sMouseDevice,
				cDeltaX, cDeltaY,
				(ButtonIsPressed() ? MOUSE_REPORT_BUTTON_1 : 0));
		}
	}
}

usb_mouse_struct.h

//*****************************************************************************
//
// usb_mouse_structs.h - Data structures defining the mouse USB device.
//
//*****************************************************************************
 
#ifndef _USB_MOUSE_STRUCTS_H_
#define _USB_MOUSE_STRUCTS_H_
//*****************************************************************************
//
// Application event handlers.
//
//*****************************************************************************
extern unsigned long MouseHandler(void *pvCBData,
                                  unsigned long ulEvent,
                                  unsigned long ulMsgData,
                                  void *pvMsgData);
 
extern const tUSBDHIDMouseDevice g_sMouseDevice;
 
#endif

usb_mouse_struct.c

//*****************************************************************************
//
// usb_mouse_structs.c - Data structures defining the USB mouse device.
//
//*****************************************************************************
 
#include "inc/hw_types.h"
#include "driverlib/usb.h"
#include "usblib/usblib.h"
#include "usblib/usbhid.h"
#include "usblib/usb-ids.h"
#include "usblib/device/usbdevice.h"
#include "usblib/device/usbdhid.h"
#include "usblib/device/usbdhidmouse.h"
#include "usb_mouse_structs.h"
 
//*****************************************************************************
//
// The languages supported by this device.
//
//*****************************************************************************
const unsigned char g_pLangDescriptor[] =
{
    4,
    USB_DTYPE_STRING,
    USBShort(USB_LANG_EN_US)
};
 
//*****************************************************************************
//
// The manufacturer string.
//
//*****************************************************************************
const unsigned char g_pManufacturerString[] =
{
    (30 + 1) * 2,
    USB_DTYPE_STRING,
    'T', 0, 'U', 0, 'T', 0, ' ', 0, 'D', 0, 'e', 0, 'p', 0, 'a', 0,
	'r', 0, 't', 0, 'm', 0, 'e', 0, 'n', 0, 't', 0, ' ', 0, 'o', 0,
	'f', 0, ' ', 0, 'm', 0, 'e', 0, 'c', 0, 'h', 0, 'a', 0, 't', 0,
	'r', 0, 'o', 0, 'n', 0, 'i', 0, 'c', 0, 's', 0
};
 
//*****************************************************************************
//
// The product string.
//
//*****************************************************************************
const unsigned char g_pProductString[] =
{
    (11 + 1) * 2,
    USB_DTYPE_STRING,
    'C', 0, 'r', 0, 'a', 0, 'z', 0, 'y', 0, ' ', 0, 'M', 0, 'o', 0, 'u', 0,
    's', 0, 'e', 0
};
 
//*****************************************************************************
//
// The serial number string.
//
//*****************************************************************************
const unsigned char g_pSerialNumberString[] =
{
    (8 + 1) * 2,
    USB_DTYPE_STRING,
    'F', 0, 'F', 0, 'F', 0, 'F', 0, 'F', 0, 'F', 0, 'F', 0, 'F', 0
};
 
//*****************************************************************************
//
// The interface description string.
//
//*****************************************************************************
const unsigned char g_pHIDInterfaceString[] =
{
    (19 + 1) * 2,
    USB_DTYPE_STRING,
    'H', 0, 'I', 0, 'D', 0, ' ', 0, 'M', 0, 'o', 0, 'u', 0, 's', 0,
    'e', 0, ' ', 0, 'I', 0, 'n', 0, 't', 0, 'e', 0, 'r', 0, 'f', 0,
    'a', 0, 'c', 0, 'e', 0
};
 
//*****************************************************************************
//
// The configuration description string.
//
//*****************************************************************************
const unsigned char g_pConfigString[] =
{
    (23 + 1) * 2,
    USB_DTYPE_STRING,
    'H', 0, 'I', 0, 'D', 0, ' ', 0, 'M', 0, 'o', 0, 'u', 0, 's', 0,
    'e', 0, ' ', 0, 'C', 0, 'o', 0, 'n', 0, 'f', 0, 'i', 0, 'g', 0,
    'u', 0, 'r', 0, 'a', 0, 't', 0, 'i', 0, 'o', 0, 'n', 0
};
 
//*****************************************************************************
//
// The descriptor string table.
//
//*****************************************************************************
const unsigned char * const g_pStringDescriptors[] =
{
    g_pLangDescriptor,
    g_pManufacturerString,
    g_pProductString,
    g_pSerialNumberString,
    g_pHIDInterfaceString,
    g_pConfigString
};
 
#define NUM_STRING_DESCRIPTORS (sizeof(g_pStringDescriptors) /                \
                                sizeof(unsigned char *))
 
//*****************************************************************************
//
// The HID mouse device initialization and customization structures.
//
//*****************************************************************************
tHIDMouseInstance g_sMouseInstance;
 
const tUSBDHIDMouseDevice g_sMouseDevice =
{
    USB_VID_LUMINARY,
    USB_PID_MOUSE,
    500,
    USB_CONF_ATTR_SELF_PWR,
    MouseHandler,
    (void *)&g_sMouseDevice,
    g_pStringDescriptors,
    NUM_STRING_DESCRIPTORS,
    &g_sMouseInstance
};