You are on page 1of 29

1

UNIVERSITY OF NOTTINGHAM SCHOOL OF ELECTRICAL AND ELECTRONIC ENGINEERING INTRODUCTION TO REAL-TIME SYSTEMS(H61RTS) TITLE: REPORT (LABS 5-9)

Students name:Anant Johri Students ID:4042046 PC Number: 18 Name of Partner:Adam Neale Submission date: 30/5/06

INDEX

1. Introduction..3

2. Aims .4

3. Task 15

4. Task 28

5. Task 3...11

6. Task 4...12

7. Conclusion...13

8. Appendix.14

3 Introduction The uses of DSPs in modern technology is increasing day by day so now there are of companies which manufacture DSPs for industrial use, some of these are designed for specific applications. The particular DSP used in this project is the Texas Instruments DSP Starter Kit, a basic DSP suitable for the programs and applications included in this particular project.

Most of the work in the lab sessions was carried out on a DSK board, Vero board and on the software Code Composer Studio. Simple devices were built onto the Vero board and were controlled through the input and output ports of the DSK. The controlling of these devices were carried out through C code written on the software Code Composer Studio, running in real time with functions taking place on the board. The projects covered most of the input and output features of the DSK.

One of the major parts of the project was to write proper C codes for operating the different devices on the vero-board and obtaining the desired results. Considerations particularly of calibration should be kept in mind while writing the code for controlling and interaction with devices on the Veroboard.

In the following lab sessions the students revisited the concepts of the DAC (Digital to Analogue Converter) and timing events. The labs also introduced new interface techniques such as various kinds of Bit Manipulation (Bit masking, bit shifting etc) and also introduced Interrupts. The key feature of the session was familiarization with the hardware ensemble of the DSK which includes the keypad and the LCD (liquid crystal display).

The concept of the ADC (Analogue to Digital Converter) was introduced. ADC converts analogue signals to digital ones. This technique is very helpful in the field of communication since transmission of digital data is faster, secure and also more noise resistant. All the concepts were applied and tested in a series of four tasks which culminated with the building of a Stand Alone Voltmeter.

4 AIMS

The aim of the session was the completion of the following tasks:-

1. To modify the DAC into an ADC and to use it as a voltmeter.

2. To interface with the Liquid Crystal Display Writing a message onto the screen Exploring some of the Character Control Instructions given in lab sheet. Making a timing diagram between the R/W, RS and E during a write operation.

3. To interface with the Keypad By writing a code in the main routine By using an Interrupt

4. To make a Stand Alone Voltmeter

5 Task 1.Modify the DAC to become an ADC

This task was mainly about to build an ADC using the DAC made in the lab sessions 3 and 4 and then testing the ADC using a potentiometer. With use of a comparator, the output of the DAC (VDAC) could be coupled with another DC voltage (Vi) and a digital voltage would be seen at the output. The output from the DAC is connected to the inverting input of the comparator and DC voltage is connected to the non-inverting input of the comparator. The unknown voltage Vi is provided from the potentiometer. Also 5 volt supply is also supplied to the comparator.

The resistor at the output of the comparator is present to give a definite switch between logic low and logic high. When the output of the comparator is at logic high, the potential difference across the resistor will be very close to zero and the output voltage will be pulled up to 5V. While when the comparator output is at logic low, the potential difference across the resistor is high and so the output is kept at zero volts.

Also known from the connections to the comparator are the values of inputs that will govern the logic state of the output, it is known that;

If Vi > VDAC then Vout = 5v If Vi < VDAC then Vout = 0v

and,

By monitoring the output of the comparator with an oscilloscope the changes between logic states can be seen as the DAC value is altered.

The table below shows how the successive approximation was carried out;

MSB Bit 0-7 VDAC LM393 Output Low High Low Low High Low Low Switchin g 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 1 1 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 V0 (128) V1 (64) V2 (32) V3 (16) V4 (8) V5 (4) V6 (2)

LSB V7 (1)

0 0 0 0 0 0 0 1

The table shows how the successive approximation was carried out, setting the Most Significant Bit to one (logic high) first and monitoring the output of the comparator.

By looking at the two statements that were known to be true for values of Vi & VDAC it was possible to see whether the value of VDAC needed to be increased or decreased. The high/low statements to the left of the table represent the output of the comparator, when it was low the value of VDAC had to be decreased and vice versa. At the value of VDAC that matched the value of Vi the scope displayed some switching between the two logic levels, this was because the voltages at the two inputs were very closely matched, any fluctuations in these voltages would result in a change in the output value.

7 To ensure that the ADC was accurate it would have to be calibrated, the correct value of VDAC in the program would have to correspond to the correct value as the result of the successive approximation. In brackets in the top row of the table is the value that each significant bit of the DAC represents at the output, with the maximum value being 255 when all bits are set to high. The conversion between these numbers and the value that they represent can be carried using the following formula;

Sum of values set to logic 1 x 3.3 255

VDAC

Where 255 is the Max. value of DAC mask and 3.3 is the Max. voltage of DAC

So using this formula the value of VDAC can be found at any point, although it was only necessary to find the voltage at the end of the successive approximation and compare it to the measured value.

8 Task 2. Interface with the LCD The LCD is an interface which consists of a series of digital inputs to the display and it displays characters given to it either via code or by the keypad. There are 14 different pins on the LCD which are used for power supply, register selection, data bits etc. Three of these pins are (1). RS: This pin selects the register to be used, that is, it chooses between the data register and the input register and it is connected to bit 6 of *dpr0. (2). R/W: This pin mainly selects the working mode, that is, the reading mode or the writing mode and it is connected to bit 7 of *dpr0. (3). E: This pin enables the signal to read or write and it is connected to bit 5 of *dpr0. The functions performed by the LCD depend on the combinations in which the pins go high. For example putting in the code *dpr1 = 0 x 01 would set the pins DB1-DB7 as low and only DB0 would be high which is a signal to clear the screen and putting *dpr1=0x42 or =B will display B on the screen. The main task involved in this section was to test the working of the display using the display_test.out code and then programming the LCD to display a message, hold it for five seconds, clear and reset the display, followed by another message.After that to test the character control instructions described in the data sheet provided on the webpage and in the last to draw a timing diagram of the E, R/W and RS pin signals. For these tasks first of all the file display_test.out was run to test the display unit of the DSK. The result of running the file was that a message Ea2 is greatwas displayed on the screen on the LCD proving that the display unit is working properly. For the second test a program (included in appendix) was written. The code started with declaring the header files and then declared all the global variables. The two memory mapped latches used were declared and initialized. The display was initialised, modes loaded, and the cursor was initiated. All these functions were carried out using the various display libraries and C routines provided. These functions are predefined in the display_lib.c file and enable the basic LCD functions. The following header files had to be included in the code to access the LCD; Init_display() Load_modes() Displayon_cursorblink() Write_character(xxxx) -Initialises display. -Modes of operation of the LCD. -Turns display on and makes cursor blink. -Writes character to display. A table of reference must be consulted to set the correct hexadecimal value of the character to be displayed. Can be converted to decimal.

9 The function write_character() was used to write the character on the screen. An argument, which is the character to be displayed, is passed to the function. There are two ways of passing an argument which include passing it as a hexadecimal code or within quotes. For example the codes write_character(0x42); write_character(B); Both the above codes will display B on the LCD. The logic behind this is that the hex codes represent the pins DB0 to DB7 of the LCD. The upper bit (4= 0100) represents the pins DB4 to DB7 and the lower bit of the hex code (2=0010) represents the pins DB0 to DB3. But the main problem in displaying the characters using the above statements is that only one character can be displayed at a time so if a long message is to be displayed then this method becomes quite tedious. So for overcoming this problem the array and loop can be used for long messages. One more limitation of the LCD was that it can display a maximum of 16 characters so if a very long message is to be displayed then only the last 16 characters will be displayed. For example if the message hello guys! How are you? then only uys! How are you will be displayed on LCD. The second job involved in this task was to use some of the other character control instructions described in the datasheet. For this the display was shifted to the left after displaying a message for sometime short time and then shifting that message to the left and displaying the message following that. This was done by taking reference from the data sheet, as shown in the datasheet in the instructions section the code for cursor/display movement is 0 0 0 1 S/C R/L 0 0 and for this condition S/C=0 and R/L is also 0. So code for this becomes 0 0 0 1 1 0 0 0 and decimal equivalent for this is 18 so using *dpr1 = 0x18; in the code(given in the appendix) the display will be shifted to the left. This whole process of shifting was done in a subroutine called moveleft() so in the main this function was called after displaying some message and this subroutine shifted the display to the left. Also different characters given in the figure 12 of the datasheet was displayed on the LCD e.g < sign was displayed on the LCD using statement write_character(0xC3). Similarly more characters can be displayed like this.

10

The task also required a timing diagram between the signals at the E, R/W, RS during a write operation. This was to be achieved using the oscilloscope. Three extra pins were also added to the veroboard so as to enable connection with the oscilloscope. The following timing diagram was obtained.

11 Task3-Interfacing the Keypad

The keypad was based on a grid with 4 rows and 4 columns. For this task the keypad need to be properly interfaced with the LCD so that messages could be displayed on the LCD as the keys are pressed. The connections of the keypad were in a grid so the basic operation was dependent on it. The data sheet provided on the webpage was really important as it provides all the knowledge about the connections and operations of the keypad. Also the lecture on keypad was really helpful as all things about keypad were told in that and due to this the students didnt face much problems during the lab sessions.

The process for identifying the pressed key was that the rows of the keypad were activated consecutively and then the logic state of the columns was monitored and in this way the pressed key can be located. The ASCII value of the pressed key is returned to the DSK and then transferred to an alphanumeric value. Using this method a program (included in appendix) was made, which reads the keypad once every second and prints the key pressed on the screen. In the program keypad.c each row was read and if the pressed key is present in it then the program displays it on the screen and after a short delay of 0.25sec it reads for another pressed key in the same procedure.

The above method would require the program to be activating and reading the inputs and outputs of the keypad at all times, essentially waiting for a key to be pressed. This method of operation uses large amounts of CPU power that could be better employed elsewhere. Using interrupts in the program would mean that the program would only run when absolutely necessary, freeing up DSP resources. The interrupt would be used to trigger the scanning of the keypad. So another program keypad2.c which uses interrupts for the above purpose was made.

12 Task4. Stand Alone Voltmeter This was the main task out of the four tasks as it requires all the knowledge which was applied in the last three tasks. The students were supposed to build a voltmeter that should work without getting any information from the computer. The voltage was measured between pin0 and pin14 and then the output was displayed on the LCD screen. It was also to be triggered when a key is pressed on the keypad.

The code started with the declaration of all the header files. All the variables and functions used were also declared and initiated. The input and output ports (input_latch and output_latch respectively) were also declared. In the main routine the display was initiated and loaded. Also all the interrupts were assigned pins and were enabled. The timer function was also declared.

The code for this task was quite similar to the code used for the first task expect keypad_isr() interrupt service routine was used since it was to triggered by the keypad. After making the required code, the voltage that is to be measured was given to the noninverting input of the comparator. The DAC then starts supplying voltage to the comparator till the voltage is equal to the one being fed. When the two voltages are equal the comparator goes high. This voltage was then measured and displayed on the LCD. All this happens only after a key is pressed on the keypad (which triggers the ISR).

To check the working of the voltmeter a potentiometer was connected between the DAC and the input (to provide a range of voltages). The program was built, loaded and run. The Code Composer was closed so as to disconnect the DSP from the computer. When a key was pressed on the keypad, the voltage supplied was displayed on the screen. Every time a button was pressed the current voltage being supplied was displayed.

At this point a few difficulties were faced. For instance the value of the voltage calculated was different than the value displayed (less accurate). To improve upon this the following code was used sprintf(ch,"%3.2f",var); which calculated and displayed the voltage value to an accuracy up to two decimal places.

13 Conclusion

In the lab sessions the waves on the oscilloscope were created and DSK was used to read voltages. Also sources other then computer were used to read information. In the end, the DSK was made to function alone without receiving any information from the computer. The modification of DAC to become an ADC was also very interesting and learning. The different codes written during the lab sessions gave the students a good understanding of how the software and hardware works together so that desired results can be obtained. The routing of inputs and outputs, voltage supplies and ground terminals around the board helped in understanding how all of the components and devices worked together. The module required that the students should establish the relevant knowledge of the software tools such as scanf, printf, delays, timers etc before the writing each code so that the most efficient programs can be created. Many difficulties arose during the labs sessions. One of them was that sometimes the DSKs behaved in a surprising way as the programs that were not working first started working as soon as the DSK was turned off and restarted. The students also came to know the limitations of LCD that it can display a maximum of 16 characters at a time so if a very long message is passed then only the last 16 characters would be displayed. The data sheets proved to be very useful when trying to overcome specific problems or when trying to make the programs for efficient and work faster. So microprocessors are the building blocks of technology. They can be used as voltmeters, waveform generators and comparators at the very basic level, and as external controllers of machinery at the higher and industrial levels. The art of data analysis and transmission depends a lot on the power of the microprocessors used.

NOTE:- This report was supposed to be done by our group i.e. by me and my partner
Adam Neale but he didnt turn-up for 4 lab sessions out of 5. So almost all the lab work was done by me. Also he didnt help me in making this report so I made this whole report by myself only .as he dint turn up and did not help in making this report i expect the mark

distribution to be 100 % mark distribution Anant Johri and 0 % mark distribution Adam Neale.

14 /* C code for task 1 */ /* simple program to output a sine or triangle wave to the DAC */ /* Group x 10/2002 */ /* */ /* */ /********************************************************/ #include <stdio.h> #include <math.h> #include "c6x11dsk.h" void delay_microsec(int msec); /* declare the function which is coded after the main routine */ volatile char *output_latch = (char *) 0xA0000010; /* pointer to external o/p latch */ volatile unsigned int *input_latch = (unsigned int *) 0xA000000C; /* * ======== main ======== */ void main() { int x, volts; float var; while(1) { x=1; volts=-1; while((x>0) && (volts<=255)) { volts++; *output_latch = volts; x = *input_latch; x&=0x00000001; } var = (volts*3.5)/255.0; printf("voltage is %f\n",var); delay_microsec(1000000); }

} /* end of main */

15

/******************************************************************/ * FUNCTION : delay_microsec * * DESCRIPTION : * uses the on board Timer 0 to produce a delay of x us during program execution * *********************************************************************/ void delay_microsec(int msec) { int timer_limit, time_start, time_gone, time_now; /* declare variables */ timer_limit = (msec*75>>1); /*37.5 timer clock periods = 1 us*/ /* set up Timer by writing control values to the timer control registers */ /* Hold the timer */ *(unsigned volatile int *)TIMER0_CTRL &= 0xff3f; /* Use CPU CLK - 37.5 MHz */ *(unsigned volatile int *)TIMER0_CTRL |= 0x200; /* Set the max possible value for the 32 bit counter */ *(unsigned volatile int *)TIMER0_PRD = 2147483648; /* Start the timer */ *(unsigned volatile int *)TIMER0_CTRL |= 0xC0; time_start = *(unsigned volatile int *)TIMER0_COUNT; /* read the present value of timer0 */ time_gone = 0; /* set initial value for time_gone */ /* keep reading Timer 0 until you reach the value reqd for the delay */ while (time_gone < timer_limit) { time_now = *(unsigned volatile int *)TIMER0_COUNT; /* read the present value of timer0 */ time_gone = time_now - time_start; /* calculate how long we have waited */ } /* end while loop */ } /* end delay_microsec() */

16 /***************************************/ /* C code for Task 2 */ /* display . C */ /* */ /* C file to write message to LCD display */ /* */ /* */ /**************************************/ #include <stdio.h> #include <c6x.h> #include "c6711dsk.h" #include "timer_lib.h" #include "display_lib.h" /* * ======== main ======== */ void main() { puts("program starting!\n"); /* set up the display */ init_display(); load_modes(); displayon_cursorblink(); puts("modes loaded\n"); /*write a message*/ /* write_character('H'); write_character('E'); write_character('L'); write_character('L'); write_character('O'); delay_millisec(5000); moveleft(); write_character('H'); write_character('E'); write_character('L'); write_character('L'); write_character('O'); write_character('H'); write_character('E'); write_character('L'); write_character(0xC3); write_character('L');

17 write_character('O'); write_character('H'); write_character('E'); write_character('L'); write_character('L'); write_character('O'); write_character('J'); write_character('K'); write_character('L'); write_character('M'); write_character('O');*/ //delay_millisec(5000); //load_modes(); //displayon_cursorblink(); while(1) { write_character('A'); } }

18

/******************************************/ /* C code for Task 2 */ /* display_lib.C */ /* */ /* C functions to drive the LCD display */ /* */ /* */ /******************************************/ #include "timer_lib.h" void busy(); void init_display(); void load_modes(); void displayon_cursorblink(); void write_character(int my_char); void moveleft(); void moveleft() { volatile unsigned int *dpr0 = (unsigned int *) 0xA0000000; memory address */ volatile unsigned int *dpr1 = (unsigned int *) 0xA0000004; *dpr0 = 0x0F; /* set reg select, r/W and enable low*/ delay_millisec(15); *dpr1 = 0x18; /* set DL to high*/ delay_millisec(1); *dpr0 = 0x20; /* set enable high (ie write an instruction)*/ delay_millisec(1); /* keep high for at least 200 ns !!*/ *dpr0 = 0x0F; /* take enable low again */ } /* busy */ void busy() { int i, bu; volatile unsigned int *dpr0 = (unsigned int *) 0xA0000000; memory address */ volatile unsigned int *dpr1 = (unsigned int *) 0xA0000004; memory address */ volatile unsigned int *dpr2 = (unsigned int *) 0xA0000008; memory ad */ bu = 1; while (bu != 0) // repeat whilst busy flag (bit 7) is 1 { *dpr1 = 0; /* set input to display register = 0 */

/* 1st external

/* 1st external /* 2nd external /* 3rd external

19 delay_millisec(1); *dpr0 = 0x80; // r/w high delay_millisec(1); // simple delay to ensure access timing is OK *dpr0 = 0x20; // enable high delay_millisec(1); i = *dpr2; // read busy delay_millisec(1); *dpr0 = 0xDF; // enable low bu = i & 0x01; /* mask to read only bit 0 */ } delay_millisec(1); } /* end of busy */ /* initialisation */ void init_display() { volatile unsigned int *dpr0 = (unsigned int *) 0xA0000000; memory address */ volatile unsigned int *dpr1 = (unsigned int *) 0xA0000004; memory address */ *dpr0 = 0x0F; /* set reg select, r/W and enable low*/ delay_millisec(15); *dpr1 = 0x30; /* set DL to high*/ delay_millisec(1); *dpr0 = 0x20; /* set enable high (ie write an instruction)*/ delay_millisec(1); /* keep high for at least 200 ns !!*/ *dpr0 = 0x0F; /* take enable low again */ delay_millisec(5); *dpr1 = 0x30; /* set DL to high*/ delay_millisec(1); *dpr0 = 0x20; /* set renable high (ie write an instruction)*/ delay_millisec(1); /* keep high for at least 200 ns !!*/ *dpr0 = 0x0F; /* take enable low again*/ delay_millisec(1); *dpr1 = 0x30; /* set DL to high*/ delay_millisec(1); *dpr0 = 0x20; /* set renable high (ie write an instruction)*/ delay_millisec(1); /* keep high for at least 200 ns !!*/ *dpr0 = 0x0F; /* take enable low again*/ delay_millisec(1); } /* end of dislay_init() */

/* 1st external /* 2nd external

20 /* function set */ void load_modes() { volatile unsigned int *dpr0 = (unsigned int *) 0xA0000000; memory address */ volatile unsigned int *dpr1 = (unsigned int *) 0xA0000004; memory address */ busy(); *dpr0 = 0x0F; /* set reg select, r/W and enable low*/ delay_millisec(1); *dpr1 = 0x38; /* 8 bits, 2 lines 5x7 dots */ delay_millisec(1); *dpr0 = 0x20; /* set renable high (ie write an instruction)*/ delay_millisec(1); /* keep high for at least 200 ns !!*/ *dpr0 = 0x0F; /* take enable low again */ delay_millisec(1); busy(); *dpr0 = 0x0F; /* set reg select, r/W and enable low*/ delay_millisec(1); *dpr1 = 0x08; /* display off */ delay_millisec(1); *dpr0 = 0x20; /* set renable high (ie write an instruction)*/ delay_millisec(1); /* keep high for at least 200 ns !!*/ *dpr0 = 0x0F; /* take enable low again */ delay_millisec(1); busy(); *dpr0 = 0x0F; /* set reg select, r/W and enable low*/ delay_millisec(1); *dpr1 = 0x01; /* clear display, return cursor */ delay_millisec(1); *dpr0 = 0x20; /* set renable high (ie write an instruction)*/ delay_millisec(1); /* keep high for at least 200 ns !!*/ *dpr0 = 0x0F; /* take enable low again */ delay_millisec(1); busy(); *dpr0 = 0x0F; /* set reg select, r/W and enable low*/ delay_millisec(1); *dpr1 = 0x06; /* shift mode - entry mode set */ delay_millisec(1); *dpr0 = 0x20; /* set renable high (ie write an instruction)*/ delay_millisec(1); /* keep high for at least 200 ns !!*/ *dpr0 = 0x0F; /* take enable low again */ } /* end load_modes */

/* 1st external /* 2nd external

/* display on, cursor blink */

21 void displayon_cursorblink() { volatile unsigned int *dpr0 = (unsigned int *) 0xA0000000; memory address */ volatile unsigned int *dpr1 = (unsigned int *) 0xA0000004; memory address */ busy(); *dpr0 = 0x0F; /* set reg select, r/W and enable low*/ delay_millisec(1); *dpr1 = 0x0F; /* display on, cursor blink */ delay_millisec(1); *dpr0 = 0x20; /* set renable high (ie write an instruction)*/ delay_millisec(1); /* keep high for at least 200 ns !!*/ *dpr0 = 0x0F; /* take enable low again */ delay_millisec(1); } /* write character to module */ void write_character(int my_char) { volatile unsigned int *dpr0 = (unsigned int *) 0xA0000000; memory address */ volatile unsigned int *dpr1 = (unsigned int *) 0xA0000004; memory address */ busy(); *dpr0 = 0x40; /* set reg select high, r/W and enable low*/ delay_millisec(1); *dpr1 = my_char; /* display my character */ delay_millisec(1); *dpr0 = 0x60; /* set renable high (ie write an instruction)*/ delay_millisec(1); /* keep high for at least 200 ns !!*/ *dpr0 = 0x0F; /* take enable low again */ delay_millisec(1);

/* 1st external /* 2nd external

/* 1st external /* 2nd external

22 /****************************************/ /* C code for Task 3 */ /* keypad . C */ /* */ /* Basic program to interrogate keypad */ /* */ /* */ /***************************************/ #include <stdio.h> #include <c6x.h> #include "c6711dsk.h" #include "timer_lib.h" #include "keypad_lib.h"

/** ======== main ========*/ void main() { char ch; while (1) { ch = read_keypad_rowj(); /* read the first row only */ printf("%c\n",ch); delay_millisec(250); /* 0.25 second delay before next read */ ch = read_keypad_rowk(); /* read the second row only */ printf("%c\n",ch); delay_millisec(250); /* 0.25 second delay before next read */ ch = read_keypad_rowl(); /* read the third row only */ printf("%c\n",ch); delay_millisec(250); /* 0.25 second delay before next read */ ch = read_keypad_rowm(); /* read the fourth row only */ printf("%c\n",ch); delay_millisec(250); /* 0.25 second delay before next read */ } }

23

/***************************************/ C code for Task 3 */ /* /* keypad2 . C */ /* */ /* Basic program to interrogate keypad */ /* */ /* */ /**************************************/ #include <stdio.h> #include <c6x.h> #include "c6711dsk.h" #include "timer_lib.h" #include "keypad_lib.h" void keypad_isr(); /* ======== main ========*/ void main() { int x; CSR = 0x100; /* global disable maskable interrupts puts("interrupts disabled (global)!\n"); IER = 2; /* disable all interrupts*/ ICR = 0xffff; /* clear all pending interrupts */ puts("program is starting \n"); IER |= 0x0020; /* enable int 5 (external interrupt 5)*/ puts("interrupt enabled (individual)!\n"); CSR |= 0x1; /*global interrupt enable*/ puts("interrupts enabled (global)!\n"); */

x = 0; while (x == 0) /* while loop to keep main alive */ { x=0; } }

24

interrupt void keypad_isr() { char ch; IER = 2; /* disable all interrupts at the start of the ISR */ //puts("e5 activated \n"); /* interrupt task */

ch = read_keypad_rowj(); /* read the first row only */ printf("%c\n",ch); delay_millisec(250); /* 0.25 second delay before next read */ ch = read_keypad_rowk(); /* read the second row only */ printf("%c\n",ch); delay_millisec(250); /* 0.25 second delay before next read */ ch = read_keypad_rowl(); /* read the third row only */ printf("%c\n",ch); delay_millisec(250); /* 0.25 second delay before next read */ ch = read_keypad_rowm(); /* read the fourth row only */ printf("%c\n",ch); delay_millisec(250); /* 0.25 second delay before next read */ /* you may even need a delay function in here to prevent retriggering ! */ ICR = 0xffff; /* clear all pending interrupts */ IER |= 0x0020; /* re enable int 5 */ }

25

/***********************************************************/ C code for Task 3 */ /* /* keypad_lib . C */ /* */ /* C function for the keypad access */ /* */ /* */ /************************************************************/ #include <stdio.h> #include "timer_lib.h" #include "keypad_lib.h" char read_keypad_rowj(); char read_keypad_rowk(); /* note the students will have to create row2-row4 read routines */ char read_keypad_rowl(); char read_keypad_rowm(); char read_keypad_rowj() { int y; /* define local variable */ char temp; unsigned int *dpr0 = (unsigned int *) 0xA0000000; /* 2nd external memory address */ unsigned int *dpr2 = (unsigned int *) 0xA0000008; /* 3rd external memory ad */ temp='x'; /* default value for when the key has not been recognised by this function */ *dpr0 = 0x00; /* clear keypad inputs */ *dpr0 = 0x01; /* energise only row 1 of the keypad matrix */ /* read the output of the keypad matrix */ y=*dpr2; y&=0xF0; /* mask to reset irrelevant bits to 0 */ if (y != 0) /* if one of the lines has been set, check which one it is */ { if (y == 0x10) temp = '1'; /* function return value for the key "1" */ if (y == 0x20) temp = '2'; /* function return value for the key "2"*/ if (y == 0x40) temp = '3'; if (y == 0x80) temp = 'F'; //printf("%c\n",temp); } return(temp);

26 } char read_keypad_rowk() { int y; /* define local variable */ char temp; unsigned int *dpr0 = (unsigned int *) 0xA0000000; /* 2nd external memory address */ unsigned int *dpr2 = (unsigned int *) 0xA0000008; /* 3rd external memory ad */ temp='x'; /* default value for when the key has not been recognised by this function */ *dpr0 = 0x00; /* clear keypad inputs */ *dpr0 = 0x02; /* energise only row 1 of the keypad matrix */ y=*dpr2; /* read the output of the keypad matrix */ y&=0xF0; /* mask to reset irrelevant bits to 0 */ if (y != 0) /* if one of the lines has been set, check which one it is */ { if (y == 0x10) temp = '4'; /* function return value for the key "1" */ if (y == 0x20) temp = '5'; /* function return value for the key "2"*/ if (y == 0x40) temp = '6'; if (y == 0x80) temp = 'E'; //printf("%c\n",temp); } return(temp); } char read_keypad_rowl() { int y; /* define local variable */ char temp; unsigned int *dpr0 = (unsigned int *) 0xA0000000; /* 2nd external memory address */ unsigned int *dpr2 = (unsigned int *) 0xA0000008; /* 3rd external memory ad */ temp='x'; /* default value for when the key has not been recognised by this function */ *dpr0 = 0x00; /* clear keypad inputs */ *dpr0 = 0x04; /* energise only row 1 of the keypad matrix */ y=*dpr2; /* read the output of the keypad matrix */ y&=0xF0; /* mask to reset irrelevant bits to 0 */ if (y != 0) { /* if one of the lines has been set, check which one it is */

27 if (y == 0x10) temp = '7'; /* function return value for the key "1" */ if (y == 0x20) temp = '8'; /* function return value for the key "2"*/ if (y == 0x40) temp = '9'; if (y == 0x80) temp = 'D'; //printf("%c\n",temp); } return(temp); } char read_keypad_rowm() { int y; /* define local variable */ char temp; unsigned int *dpr0 = (unsigned int *) 0xA0000000; /* 2nd external memory address */ unsigned int *dpr2 = (unsigned int *) 0xA0000008; /* 3rd external memory ad */ temp='x'; /* default value for when the key has not been recognised by this function */ *dpr0 = 0x00; /* clear keypad inputs */ *dpr0 = 0x08; /* energise only row 1 of the keypad matrix */ y=*dpr2; /* read the output of the keypad matrix */ y&=0xF0; /* mask to reset irrelevant bits to 0 */ if (y != 0) /* if one of the lines has been set, check which one it is */ { if (y == 0x10) temp = 'A'; /* function return value for the key "1" */ if (y == 0x20) temp = '0'; /* function return value for the key "2"*/ if (y == 0x40) temp = 'B'; if (y == 0x80) temp = 'C'; //printf("%c\n",temp); } return(temp); }

28

/******************************************/ /* C code for Task 4 */ /* keypad . C */ /******************************************/ #include <stdio.h> #include <c6x.h> #include "c6711dsk.h" #include "timer_lib.h" #include "keypad_lib.h" #include "display_lib.h" void keypad_isr(); /* declare the interrupt service routine */ char msg1[]="VOLTMETER"; char msg2[]="PRESS A BUTTON"; char msg3[]="PRESS ANY KEY"; char ch[]; int i; unsigned int *dpr0 = (unsigned int *) 0xA0000000; volatile char *output_latch = (char *) 0xA0000010; volatile char *input_latch = (char *) 0xA000000C; /* * ======== main ======== */ void main() { *dpr0 = 0x00; CSR = 0x100; /* global disable maskable interrupts puts("interrupts disabled (global)!\n"); IER = 2; /* disable all interrupts*/ */

ICR = 0xFFFF; /* clear all pending interrupts */ puts("program is starting \n"); /*Loading the Interrupt*/ init_display(); load_modes(); /*Loading the display*/ displayon_cursorblink(); for(i=0;i<strlen(msg1);i++) write_character(msg1[i]); IER |= 0x0020; /* enable int 6 (external interrupt 6)*/ puts("interrupt enabled (individual)!\n");

29

CSR |= 0x1; *dpr0 = 0x0F; while(1) { } }

/*global interrupt enable*/ /*Energise all inputs for keypad interrupt*/

interrupt void keypad_isr() { int x, volts; float var; IER = 2; /*Disable all interrupts*/ delay_millisec(50); /*Delay to stop retriggering of int5*/ x=1; volts=-1; while((x>0) && (volts<=255)) { volts++; *output_latch = volts; x = *input_latch; } var = (volts*3.5)/255.0; sprintf(ch,"%1.3f",var); load_modes(); /*Loading the display*/ displayon_cursorblink(); for(i=0;i<(strlen(ch));i++) write_character(ch[i]); delay_millisec(3000); load_modes(); displayon_cursorblink(); for(i=0;i<strlen(msg3);i++) write_character(msg3[i]); delay_millisec(1000); *dpr0 = 0x0F; ICR = 0xFFFF; /* clear all pending interrupts */ IER |= 0x0020; /* re enable int 5 */ }

You might also like