The Data Acquisition System Engineering Essay

Published: November 21, 2015 Words: 2368

The purpose of this project is to design and implement a 3-channel data acquisition (DAQ) system using a HCS12 target board. The main emphasis in this project is to present a student's understanding of the various features of the MC9S12E128 microcontroller and demonstrate skills in using C programming Language to program the microprocessor.

The PK-HCS12E128 uses both the Metrowerks CodeWarrior IDE and the SofTec Microsystems software. The microcontroller is programmed to display the user interface and select the appropriate ATD channel and is sampled at a rate of 1kS/s with 8-bit resolution. Only one ATD channel can be actively sampled at a time. The system flashes an 'operating' status led once every 0.5 secs to indicate that acquisition is taking place.

The DAQ system design is a simple one with two active blocks the Hardware and the Software. The hardware section consists of the PK-HCS12E128 starter kit, the PC display and the keyboard. The software kit includes the HCS12 controller and the Hyperterminal.

Block Diagram:

Software

Output

Controller

HC12

VT100

Hardware

Logic Circuit

PK-HCS12E128

Case Diagram of Simple DAQ system:

Background

The MC9S12E128 microcontroller is basically a self-contained computer on a single integrated circuit containing a processor core, memory, and programmable input/output peripherals. Microcontrollers are mainly used in the embedded systems industry.

The main features of the MC9S12E128 microcontroller are:

High-performance 16-bit HCS12 core;

128 KB of FLASH memory;

8 KB of RAM;

Three asynchronous serial communications interface (SCI);

A serial peripheral interface (SPI);

An Inter-IC Bus (IIC);

Three 4-channel, 16-bit timer module (TIM);

6-channel, 8-bit Pulse Width Modulator (PWM);

6-channel Pulse Width Modulator with Fault Protection (PMF);

16-channel, 10-bit Analog-to-Digital converter (ADC);

Two 1-channel, 8-bit Digital-to-Analog converter (DAC);

Clock and Reset Generator (CRG);

25 MHz bus speed;

Input voltage range from 3.135 V to 5.5 V;

Single-wire background debug mode (BDM);

Enhanced Debug 12 Module, including breakpoints and change-of-flow trace buffer (DBG12).

Interrupts:

The purpose of interrupts on a microcontroller such as the HCS12 is to allow your software to run a main routine of the program and when the interrupt occurs it switches to another routine that is designed to run. An interrupt is run by interrupt handlers or interrupt routines which are specific software routines that are called when the interrupt occurs. Each interrupt source has associated with it something called an interrupt vector. There is a vector table kept in memory of interrupt vectors. A vector is merely the address of the Interrupt Handler. When an interrupt occurs, the chip automatically jumps to the address stored for that interrupt. In context of this project the software linker file is modified to point to the vector table 7 which run the RTIHan.

Programming Language:

C programming language is used and the set of compilers and assemblers are used to convert high-level language to machine code and its is compact enough to fit in the chips 128 KB of FLASH program memory.

Other microcontroller features:

The microcontroller also has an analog-to-digital converter (ADC) to convert and condition the incoming analog signal into digital signals that the processor can handle and digital-to-analog converter (DAC) that allows the processor to output analog signals or voltage levels.

FLOW CHART

Start

Peripheral Initialization Routine

Interrupts Peripheral Initialization routine

DISPLAY tx_msg1

DISPLAY tx_msg2

IS

rx_msg1 = h

READ rx_msg1

DISPLAY tx_msg3

DISPLAY tx_msg4

DISPLAY tx_msg5

DISPLAY tx_msg6

NO

YES

IS

rx_msg1 = s

DISPLAY tx_msg7

IS

rx_msg1 = 1

Switch to Channel 1

IS

rx_msg1 = 2

IS

rx_msg1 = 3

Switch to Channel 2

Switch to Channel 3

DISPLAY tx_msg11

READ rx_msg1

NO

YES

YES

YES

YES

NO

NO

D2A Routine

Enable Interrupts

DISPLAY tx_msg6

HALT

STOP

sOURCE CODE FOR SofTec_linker.PRM

NAMES

END

SEGMENTS

RAM = READ_WRITE 0x0400 TO 0x1FFF;

/* unbanked FLASH ROM */

ROM_4000 = READ_ONLY 0x4000 TO 0x7FFF;

ROM_C000 = READ_ONLY 0xC000 TO 0xFEFF;

/* banked FLASH ROM */

PAGE_38 = READ_ONLY 0x388000 TO 0x38BFFF;

PAGE_39 = READ_ONLY 0x398000 TO 0x39BFFF;

PAGE_3A = READ_ONLY 0x3A8000 TO 0x3ABFFF;

PAGE_3B = READ_ONLY 0x3B8000 TO 0x3BBFFF;

PAGE_3C = READ_ONLY 0x3C8000 TO 0x3CBFFF;

PAGE_3D = READ_ONLY 0x3D8000 TO 0x3DBFFF;

/* PAGE_3E = READ_ONLY 0x3E8000 TO 0x3EBFFF; not used: equivalent to ROM_4000 */

/* PAGE_3F = READ_ONLY 0x3F8000 TO 0x3FBFFF; not used: equivalent to ROM_C000 */

END

PLACEMENT

_PRESTART, /* Used in HIWARE format: jump to _Startup at the code

start */

STARTUP, /* startup data structures */

ROM_VAR, /* constant variables */

STRINGS, /* string literals */

VIRTUAL_TABLE_SEGMENT, /* C++ virtual table segment */

NON_BANKED, /* runtime routines which must not be banked */

COPY /* copy down information: how to initialize variables */

/* in case you want to use ROM_4000 here as well, make sure

that all files (incl. library files) are compiled with the

option: -OnB=b */

INTO ROM_C000/*, ROM_4000*/;

DEFAULT_ROM INTO PAGE_38,PAGE_39,PAGE_3A,PAGE_3B,PAGE_3C,PAGE_3D;

DEFAULT_RAM INTO RAM;

END

STACKSIZE 0x100

VECTOR 0 _Startup /* reset vector: this is the default entry point for a C/C++ application. */

//VECTOR 0 Entry /* reset vector: this is the default entry point for a Assembly

application. */

//INIT Entry /* for assembly applications: that this is as well the initialisation

entry point */

VECTOR 7 RTIHan

MAIN sOURCE CODE

// Program to use SERIAL section of SOFTEC HCS12E128

// Set up for 9600 baud, No parity, 8 bits, 1 stop bit,

// Then use TXRDY and RXRDY status bits to poll for TX and RX

//

//

// Philip S. April 2010

#include <hidef.h> /* common defines and macros */

#include <mc9s12e128.h> /* derivative information */

#pragma LINK_INFO DERIVATIVE "SampleS12"

// ---------------------------------------------------------------------------

// Real Time interrupt routine

// ---------------------------------------------------------------------------

static int setpoint = 0;

// ---------------------------------------------------------------------------

// Puts the following code into NOT BANKED FLASH MEMORY

// ---------------------------------------------------------------------------

#pragma TRAP_PROC

#pragma CODE_SEG __NEAR_SEG NON_BANKED

void RTIHan(void){ /* periodic interrupt */

setpoint++; // Increment setpoint each time there is an interrupt

PTT ^= 0x01; // Toggle Bit 0 of Port T

CRGFLG = 0x80; // Acknowledge by clearing RTIF (by writing a '1'

// to the bit position)

if(ATDSTAT1_CCF0) // If ATD conversion complete flag 0

DAC0_DACDRight = ATDDR0H;

}

#pragma CODE_SEG DEFAULT

// ---------------------------------------------------------------------------

// Peripheral Initialization Routine

// ---------------------------------------------------------------------------

void PeriphInit(void)

{

// Serial IO setup

SCI0BDL = 0x34; // set 9600

SCI0CR1 = 0x00; // set N, 8, 1

SCI0CR2 = 0x0C; // set TX and RX enable

//A to D input setup

ATDCTL3 = 0x08 ; // One conversion per sequence

ATDCTL4_SRES8 = 0 ; // Sets A/D conversion to 8 bit resolution

ATDCTL5_SCAN = 1 ; // Continuous conversion (scan mode)

ATDCTL5_MULT = 0; // One input only

ATDCTL5_CA = 0 ; // now set selection bits to channel 0

ATDCTL5_CB = 0 ;

ATDCTL5_CC = 0 ;

ATDCTL5_CD = 0 ;

ATDCTL5_DJM = 1; // Set the correct justification.

ATDCTL2 = 0x08 ; // Turn on normal ATD functionality

DAC0_DACDRight = 0x00; // Sets DAC data to 0

DAC0_DACC0 |= 0x89; // Enables DAC: DACE = 1, DSGN = 1, DACOE = 1

}

//////////////////////////////////////////////////////////////////

// Interrupts Peripheral Initialization routine

//////////////////////////////////////////////////////////////////

void RTIinit(void){

COPCTL = 0x00; // disable COP

PTT &= 0xBE; // Clear relevant bits of Port T

DDRT |= 0x41; // Port T bit 6,0 are outputs to LEDs

RTICTL = 0x7F; // Arm and set RTI

CRGINT = 0x80; // enable RTI interrupts by setting RTIE bit

}

void sendmessage(char* tx_string) /* transmits whole string using transmit function */

{

int i=0;

char tx_data;

i=0;

while (tx_string[i] != '\0') // stop when you see <END OF STRING>

{

tx_data=tx_string[i++];

while ( ! (SCI0SR1 & 0x80) ) /* is Tx ready for data? */

{;}; /* repeat until ready for data. */

SCI0DRL = tx_data; /* transmit data. */

}

}

void getmessage(char* rx_string) /* receives whole string using receive function */

{

int i=0;

char rx_data;

i=0;

do

{

while( !( SCI0SR1 &0x20 )) /* does Rx have data for reading? */

{;} ; /* repeat until data received. */

rx_data = SCI0DRL; /* read data. */

rx_string[i]=rx_data;

while ( ! (SCI0SR1 & 0x80) ) /* is Tx ready for data? */

{;}; /* repeat until ready for data. */

SCI0DRL = rx_data; /* transmit data. */

} while (rx_string[i++]!='\r'); /* until you see <ENTER> */

}

void selectchannel(rec) {

static char tx_msg8[80]="Channel 1 is now being acquired\r\n";

static char tx_msg9[80]="Channel 2 is now being acquired\r\n";

static char tx_msg10[80]="Channel 3 is now being acquired\r\n";

RTIinit();

if (rec == '1') {

sendmessage (tx_msg8);

ATDCTL5_CA = 1 ; // now set selection bits to channel 1

ATDCTL5_CB = 0 ;

ATDCTL5_CC = 0 ;

ATDCTL5_CD = 0 ;

}

if (rec == '2') {

sendmessage (tx_msg9);

ATDCTL5_CA = 0 ; // now set selection bits to channel 2

ATDCTL5_CB = 1 ;

ATDCTL5_CC = 0 ;

ATDCTL5_CD = 0 ;

}

if (rec == '3') {

sendmessage (tx_msg10);

ATDCTL5_CA = 1 ; // now set selection bits to channel 3

ATDCTL5_CB = 1 ;

ATDCTL5_CC = 0 ;

ATDCTL5_CD = 0 ;

}

}

// ---------------------------------------------------------------------------

// Analogue Display:

// ---------------------------------------------------------------------------

adis (void){

DAC0_DACDRight = ATDDR0L;

}

// ---------------------------------------------------------------------------

// Digital Display

// ---------------------------------------------------------------------------

ddis (void){

PTT=ATDDR0L;

}

// ---------------------------------------------------------------------------

// Main Routine

// ---------------------------------------------------------------------------

void main(void)

{

int i=0;

char rx_msg1[80]="";

static char tx_msg1[80]="Welcome to the MCS2 DAQ system\r\n" ;

static char tx_msg2[80]="Press a key to begin('h' for help, 's' for DAQ system)\r\n";

static char tx_msg3[80]=" User Commands:\r\n";

static char tx_msg4[80]="Press 's' to start system\r\n";

static char tx_msg5[80]="Press 'h' to help dialog\r\n";

static char tx_msg6[80]="Press 'c' to change sampled channel\r\n";

static char tx_msg7[80]="Which channel would you like to acquire (1, 2, or 3)?\r\n";

static char tx_msg11[80]=" Error, character not recognised\r\n";

EnableInterrupts; // Enables interrupts

PeriphInit(); // Microcontroller initialization

sendmessage (tx_msg1);

sendmessage (tx_msg2);

getmessage(rx_msg1);

if (rx_msg1[0] == 'h'){

sendmessage (tx_msg3);

sendmessage (tx_msg4);

sendmessage (tx_msg5);

sendmessage (tx_msg6);

getmessage(rx_msg1);

}

else {

sendmessage (tx_msg11);

getmessage(rx_msg1);

}

if (rx_msg1[0] == 's') {

sendmessage (tx_msg7);

getmessage(rx_msg1);

}

else {

sendmessage (tx_msg11);

getmessage(rx_msg1);

}

selectchannel(rx_msg1[0]);

// ---------------------------------------------------------------------------

// D2A Routine

// ---------------------------------------------------------------------------

do

{

if(ATDSTAT1_CCF0) // If ATD conversion complete flag 0

if (!(PORTAD1 & 0X10)); // If Button 4 Pressed

ddis (); // Call Digital Display Function

if (!(PORTAD1 & 0X20)); // If Button 5 Pressed

adis (); // Call Analogue Display Function

} while ((PORTAD1 & 0X10) || (PORTAD1 & 0X20)); // Loop unit buttons 4 and 5 are pressed.

//////////////////////////////////////////////////////////////////

//Interrupts

//////////////////////////////////////////////////////////////////

sendmessage (tx_msg6);

while(1)

{

getmessage(rx_msg1);

if (rx_msg1[0] == 'c'){

sendmessage (tx_msg7);

getmessage(rx_msg1);

selectchannel(rx_msg1[0]);

}

}

} // end main

Testing

Equipments:

The list of equipments used for this project is outlined below:

A 133-MHz (or higher) PC compatible system running Windows 98, Windows 2000 or Windows XP;

128 MB of available system RAM plus 500 MB of available hard disk space;

PC Motherboard with a spare serial port or one having PCI Express card with one serial port installed;

A USB port;

CD-ROM drive for installation;

The PK-HCS12E128 evaluation board;

A USB cable (A Standard-B plug);

A Serial cable;

The Metrowerks CodeWarrior HC(S)12 CD-ROM;

The SofTec Microsystems PK-HCS12E128 "System Software" CD-ROM;

PC Monitor;

PC Keyboard;

Oscilloscope and probes.

Hardware Test Set-Up.

The PK-HCS12E128 board is connected through a USB port to a host PC. Connection steps are listed below in the recommended flow order:

Install all the required system software as described in the product manual.

Insert one (A) end of the USB cable into a free USB port.

Insert the other (B) end of the USB cable into the "USB" connector on the PK-HCS12E128 board. The green "POWER" LED on the instrument should turn on.

Software Test Set-Up.

Ensure that the PK-HCS12E128 board is connected to the PC (via the USB cable).

Start the MS Hyperterminal program and configure the VT100 terminal with Com port settings at 8-N-1 @ 9600 baud with no hardware control.

Start the CodeWarrior HC(S)12 IDE by selecting Start>Programs>Metrowerks CodeWarrior>CW12 3.1> CodeWarrior IDE. The CodeWarrior HC(S)12 IDE will open.

From the Menu bar, select File > New.

Create a new project using the project wizard and select the correct HC12 derivative (MC9S12E128) and create a new CodeWarrior Project with all appropriate parameters and save it in your personal workspace.

Edit SofTec_linker.prm linker command file to include the code VECTOR 7 RTIHan

Enter the C code of this project in the "main.c" file. Click to save the file.

From the main menu, choose Project > Debug. This will compile the source code, generate an executable file and download it to the PK-HCS12E128 board.

A new debugger environment will open.

From the main menu, choose Run > Start/Continue. The program will be executed in real-time.

From the main menu, choose Run > Halt. The program execution will stop.

In the Source window, insert a breakpoint to debug your code.

Results:

When the program is downloaded on to the microprocessor and run in real time the VT100 terminal show the following messages on the PC monitor:

"Welcome to the MCS2 DAQ system"

"Press a key to begin('h' for help, 's' for DAQ system)"

>

If 'h' is pressed the screen message and dialog displays:

" User Commands"

"Press 's' to start system"

"Press 'h' to help dialog"

"Press 'c' to change sampled channel"

>

If 's' pressed screen message and dialog becomes:

"Which channel would you like to acquire (1, 2, or 3)?"

>

Depending on the input '1, 2 or 3' the screen message and dialog displays the system will respond with:

"Channel 1 is now being acquired"

or

"Channel 2 is now being acquired"

or

"Channel 3 is now being acquired"

>

If any other character input is given during any stage the system responds with an error message:

"Error, character not recognised"

When the user selects the required channel to be sampled the output LED on the target board starts blinking with the required frequency.

conclusion

The DAQ System designed was partially successful. It successfully completed the User Command Interface and selects the ATD channel to be active and sampled. There is a scope for a massive improvement.

Appendix I

Electrical and Physical Specifications for PK-HCS12E128:

Operating Voltage 4.75 to 5.0 V DC (provided by the USB connection)

Power Consumption 200 mA (max)

Dimensions 137 x 86 x 15 mm

Weight 55 g

Operating Temperature 0 °C to 50 °C

Storage Temperature -20 °C to 70 °C

Humidity 90% (without condensation