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();
		}
	}
}
en/projects/can_ping_pong.txt · Last modified: 2020/07/20 09:00 by 127.0.0.1
CC Attribution-Share Alike 4.0 International
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0