CAN Ping-Pong

Requirements: [HW] 2 x Controller

RGB LEDs flashing on frame arrival

Das folgende Programm zeigt wie man CAN-Nachrichten an ARM-CAN Controllern nutzt. Beide Controller haben den gleichen Code. Wenn der Knopf gedrückt wird, wird eine CAN-Message mit einer Pingnummer gesendet. Wenn die Nachricht empfangen wird, leuchtet die Rote LED mit der Intensität relativ zur Pingnummer und wartet 200ms. Danach wird die LED ausgeschaltet und ein ähnliches Paket mit einer kleineren Pingnummer wird zum Controller gesendet von dem der ursprüngliche Ping kam. Nachrichten werden solange ausgetauscht bis die Pingnummer 0 erreicht.

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();
		}
	}
}