You are on page 1of 4

D:\Projects\Voltech\Modbus\USBModbus\main.

c
/*!---------------------------------------------------------------------------
** @file main.c
**
** @brief Firmware main file for USB Modbus I/O Interface
**
**---------------------------------------------------------------------------
**
** Copyright 2010 Roy Hopkins (roy_web@fieldofcows.com)
**
** This file is part of the firmware for the Field of Cows USB Modbus I/O
** project (USBModbus)
**
** USBModbus is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** USBModbus is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with USBModbus. If not, see <http://www.gnu.org/licenses/>.
**
*/
/*---------------------------------------------------------------------------
** Includes
*/
#include <p18f4550.h>
#include <portb.h>
#include "usb_config.h"
#include "USB/usb.h"
#include "USB/usb_function_cdc.h"
#include "USB/usb_device.h"
#include "modbus.h"
/*---------------------------------------------------------------------------
** Defines and Macros
*/
#pragma config PLLDIV = 5 // (20 MHz crystal)
#pragma config CPUDIV = OSC1_PLL2
#pragma config USBDIV = 2 // Clock source from 96MHz PLL/2
#pragma config FOSC = HSPLL_HS
#pragma config FCMEN = OFF
#pragma config IESO = OFF
#pragma config PWRT = OFF
#pragma config BOR = ON
#pragma config BORV = 3
#pragma config VREGEN = ON // USB Voltage Regulator
#pragma config WDT = OFF
#pragma config WDTPS = 32768
#pragma config MCLRE = ON
#pragma config LPT1OSC = OFF
#pragma config PBADEN = OFF
#pragma config STVREN = ON
#pragma config LVP = OFF
#pragma config XINST = OFF // Extended Instruction Set
#pragma config CP0 = OFF
#pragma config CP1 = OFF
#pragma config CPB = OFF
#pragma config WRT0 = OFF
#pragma config WRT1 = OFF
#pragma config WRTB = OFF // Boot Block Write Protection
#pragma config WRTC = OFF
#pragma config EBTR0 = OFF
#pragma config EBTR1 = OFF
#pragma config EBTRB = OFF
1
D:\Projects\Voltech\Modbus\USBModbus\main.c
#define CLOCK_FREQ 48000000
#define GetSystemClock() (CLOCK_FREQ)
/*---------------------------------------------------------------------------
** Typedefs
*/
/*---------------------------------------------------------------------------
** Local function prototypes
*/
void handle_high_isr(void);
void handle_low_isr(void);
/*---------------------------------------------------------------------------
** Data
*/
/*---------------------------------------------------------------------------
** Interrupt vectors and handlers
*/
//
// Define the high priority interrupt vector jump at address 0x08
//
#pragma code HIGH_INTERRUPT_VECTOR = 0x08
void
high_isr(
void
) {
// The code here is in a vector table so we have only got a few
// bytes to play with. Therefore just jump to the isr
_asm goto handle_high_isr _endasm
}
//
// Define the low priority interrupt vector jump at address 0x18
//
#pragma code LOW_INTERRUPT_VECTOR = 0x18
void
low_isr(
void
) {
_asm goto handle_low_isr _endasm
}
#pragma code
//
// The vector jump for the high priority interrupt jumps
// to this function. The #pragma interrupt ensures that
// the correct return is generated from the function
//
#pragma interrupt handle_high_isr
void
handle_high_isr(
void
) {
// Handle any pending USB tasks
USBDeviceTasks();
}
//
// The vector jump for the low priority interrupt jumps
// to this function. The #pragma interruptlow ensures that
// the correct return is generated from the function
//
#pragma interruptlow handle_low_isr
void
handle_low_isr(
void
) {
2
D:\Projects\Voltech\Modbus\USBModbus\main.c
}
//--------------------------------------------------------------------------
/*!
** @brief Main firmware process entry point
**
*/
void main(void) {
unsigned char count = 0;
// Initialise the USB library
USBDeviceInit();
USBDeviceAttach();
// Initialise the Modbus routines
#ifdef MODECONTROL_SW
setMode(MODE_RTU);
#endif
initialiseModbus();
// Enter the main processing loop
while (1) {
if ((USBDeviceState >= CONFIGURED_STATE) &&
(USBSuspendControl != 1)) {
processModbus();
CDCTxService();
}
}
}
//--------------------------------------------------------------------------
/*!
** @brief Handler that is called when the host sets the baud rate for
** the CDC connection
**
** This function gets called when a SetLineCoding command
** is sent on the bus. This function will evaluate the request
** and determine if the application should update the baudrate
** or not.
**
*/
void
set_line_coding_handler(
void
) {
//If the request is not in a valid range
if (cdc_notice.GetLineCoding.dwDTERate.Val > 115200) {
// Stalling the endpoint is the correct thing to do in this
// case but it can cause the host application to crash if it
// doesn't handle this properly. If that is the case then
// the line below can be commented-out
USBStallEndpoint(0, 1);
}
else {
DWORD_VAL baud;
// Update the baudrate info in the CDC driver
CDCSetBaudRate(cdc_notice.GetLineCoding.dwDTERate.Val);
// Update the baudrate of the UART
baud.Val = (GetSystemClock() / 4) / line_coding.dwDTERate.Val - 1;
SPBRG = baud.v[0];
SPBRGH = baud.v[1];
}
}
//--------------------------------------------------------------------------
/*!
** @brief USB event callback
**
** @return TRUE
3
D:\Projects\Voltech\Modbus\USBModbus\main.c
**
** This function is called from the USB stack to
** notify a user application that a USB event
** occured. This callback is in interrupt context
**
** @param[in] event Type of event
** @param[in] pdata Pointer to event data
** @param[in] size Size of event data
*/
BOOL
USER_USB_CALLBACK_EVENT_HANDLER(
USB_EVENT event,
void *pdata,
WORD size
) {
// We just forward these events to the relevant CDC handler
switch (event) {
case EVENT_CONFIGURED:
CDCInitEP();
break;
case EVENT_EP0_REQUEST:
USBCheckCDCRequest();
break;
case EVENT_TRANSFER:
Nop();
break;
default:
break;
}
return TRUE;
}
4

You might also like