230 likes | 363 Views
Chapter 3 More Loops. Checklist. The following tools will be used in this lesson: MPLAB X, Integrated Development Environment (v1.8 or later, free) MPLAB XC16, C compiler (v1.11 or later, free) The following pieces of documentation will be used during this lesson:
E N D
Checklist The following tools will be used in this lesson: • MPLAB X, Integrated Development Environment (v1.8 or later, free) • MPLAB XC16, C compiler (v1.11 or later, free) The following pieces of documentation will be used during this lesson: • PIC24FJ128GA010 Datasheet –DS39747 (latest rev.) • PIC24 Family Reference Manual - Section 14. Timers Make sure they are available and/or installed and ready to use on your computer. You can download them from Microchip web site at: http://www.microchip.com/mplabx And http://www.microchip.com/xc16
do Loops do { // your code here ... } while ( x); • Notice that we are also re-using the while keyword, don’t let it confuse you! • Quiz: How many times is the loop below going to be executed? do { // your code here ... } while ( 0);
Variables Declarations • Signed integer types: • char c; // from -128 to +127 • intc; // from -32768 to +32767 • long c; // from -2,147,483,648 to + 2,147,483,647 • Unsigned integer types: • unsigned char c; // from 0..255 • unsigned inti; // from 0..65,535 • unsigned long x; // from 0..4,294,967,295 • Floating point types: • float f; // 32-bit single precision • long double d; // 64-bit double precision
for Loops A loop counting from 0 to 4: i = 0; // init the index/counter while ( i<5) { // insert your code here… // it will be executed for i= 0, 1, 2, 3, 4 i = i+1; // increment } Can be expressed more concisely as: for ( i=0; i<5; i=i+1) { // insert your code here … // it will be executed for i=0, 1, 2, 3, 4 }
Increment and Decrement • Introducing two new operators: Use ++ to increment a variable, i++; is equivalent to: i= i+1; Use -- to decrement a variable, i--;is equivalent to: i= i-1; • More on this later...
More Loop Examples • Use the increment operator: for ( i=0; i<5; i++) { // insert your code here … // it will be executed for i= 0, 1, 2, 3, 4 } • Then, a count down from 4 to 0: for ( i=4; i>=0; i--) { // insert your code here … // it will be executed for i= 4, 3, 2, 1, 0 } • Use the for loop to code an (infinite) main program loop(!?): main() { // 0. initialization code … // 1. the main application loop for ( ; 1; ) { … } } // main
Arrays • Declare an array of integers with the following notation: char c[10]; // declares c as an array of 10 x 8-bit integers int i[10]; // declares i as an array of 10 x 16-bit integers long x[10]; // declares x as an array of 10 x 32-bit integers • Use the square bracket notation to access elements of an array: a = c[0]; // copy the 1st element of c[] into a c[1] = 123; // assign 123 to the second element of c[] i[2] = 12345; // assign 12,345 to the third element of i[] x[3] = 123* i[4]; // compute 123 x the 5th element of i[] and // assign result to the 4th element of x[] • Use a for loop to access sequentially array elements: int a[10]; // declare array of 10 integers: a[0], a[1] … a[9] int i; // the loop index for ( i=0; i<10; i++) { a[ i] = 1; }
Sending a Message // 2. declare and initialize an // array with the message bitmap char bitmap[30] = { 0b11111111, // H 0b00001000, 0b00001000, 0b11111111, 0b00000000, 0b00000000, 0b11111111, // E 0b10001001, 0b10001001, 0b10000001, 0b00000000, 0b00000000, 0b11111111, // L 0b10000000, 0b10000000, 0b10000000, 0b00000000, 0b00000000, 0b11111111, // L 0b10000000, 0b10000000, 0b10000000, 0b00000000, 0b00000000, 0b01111110, // O 0b10000001, 0b10000001, 0b01111110, 0b00000000, 0b00000000 }; // 3. the main program main() { // 3.1 variable declarations inti; // i will serve as the index // 3.2 initialization TRISA = 0; // all PORTA as output T1CON = 0x8030; // TMR1 on, prescale 1:256 Tclk/2 // 3.3 the main loop while( 1) { // 3.3.1 display loop, hand moving to the right for( i=0; i<30; i++) { // 3.3.1.1 update the LEDs PORTA = bitmap[i]; // 3.3.1.2 short pause TMR1 = 0; while ( TMR1 < SHORT_DELAY) { } } // for i // 3.3.2 long pause, hand moving back to the left PORTA = 0; // turn LEDs off TMR1 = 0; while ( TMR1 < LONG_DELAY) { } } // main loop } // main #include <config.h> // 1. define timing constant #define SHORT_DELAY 100 #define LONG_DELAY 800
See the Message Now? // 2. declare and initialize an // array with the message bitmap char bitmap[30] = { 0b11111111, // H 0b00001000, 0b00001000, 0b11111111, 0b00000000, 0b00000000, 0b11111111, // E 0b10001001, 0b10001001, 0b10000001, 0b00000000, 0b00000000, 0b11111111, // L 0b10000000, 0b10000000, 0b10000000, 0b00000000, 0b00000000, 0b11111111, // L 0b10000000, 0b10000000, 0b10000000, 0b00000000, 0b00000000, 0b01111110, // O 0b10000001, 0b10000001, 0b01111110, 0b00000000, 0b00000000 }; // 3. the main program main() { // 3.1 variable declarations inti; // i will serve as the index // 3.2 initialization TRISA = 0; // all PORTA as output T1CON = 0x8030; // TMR1 on, prescale 1:256 Tclk/2 // 3.3 the main loop while( 1) { // 3.3.1 display loop, hand moving to the right for( i=0; i<30; i++) { // 3.3.1.1 update the LEDs PORTA = bitmap[i]; // 3.3.1.2 short pause TMR1 = 0; while ( TMR1 < SHORT_DELAY) { } } // for i // 3.3.2 long pause, hand moving back to the left PORTA = 0; // turn LEDs off TMR1 = 0; while ( TMR1 < LONG_DELAY) { } } // main loop } // main #include <config.h> // 1. define timing constant #define SHORT_DELAY 100 #define LONG_DELAY 800
Notes for the Assembly Experts • Most of times the MPLAB XC16 compiler tries to translate ++ and – with inc and dec assembly instructions. • This is not always possible though because the two operators are actually much smarter than that: • If they are applied to a pointer (which is a variable type that contains a memory address) they actually increase the address by the exact number of bytes required to represent the quantity pointed to. • For example: • a pointer to 16-bit integers will increment its address by 2, • a pointer to a 32-bit long integer will increment its address by 4, and so on. • To satisfy your curiosity, switch to the Disassembly Window and see how the MPLAB XC16 compiler chooses the best assembly code depending on the situation. • Loops in C can be confusing at first. In some situations the algorithm you are coding will dictate which one to use, but in many situations you will have a degree of freedom and more than one type might do. In case of doubt, choose the one that makes your code more readable!
Notes for the PIC MCU Experts • Depending on the target microcontroller architecture, and ultimately the Arithmetic Logic Unit (ALU) size, operating on bytes versus operating on word quantities can make a big difference in terms of code compactness and efficiency. • While in 8-bit architectures, there is a strong incentive to use byte-sized integers wherever possible, in the PIC24 16-bit architecture word-sized integers can be manipulated just with the same efficiency.
Notes for C Experts • Even if some 16-bit microcontrollers have a relatively large RAM memory array, embedded control applications will always have to contend with the reality of cost and size limitations. • If you learned to program in C on a PC or a workstation, you probably never considered using anything smaller than an int as a loop index. • In Embedded Control, shaving one byte at a time off the requirements of your application might, in some cases, mean the ability to select a smaller model of microcontroller, saving fractions of a dollar that when multiplied by the thousands or millions of units (depending on production run rates), can mean real money saved from the bottom line.
Tips and Tricks • In this last exercise we declared an array called bitmap[] and we asked for it to be pre-filled with a specific series of values. • The array, being a data structure, resides in RAM during execution. But since RAM is volatile, the XC16 compiler has to copy the assigned values (in the curly brackets {} notation) from a non volatile memory (FLASH memory) before the main program execution is started. • This is the kind of task performed in the crt0 code segment.
Configuring the PPS (for GA1 and GB1 users) #include <pps.h> void InitPPS( void) { // SPI1 PPSOutput( PPS_RP15, PPS_SDO1); // SDO1 =RP15 F8/pin 53 // SPI2 PPSInput( PPS_SDI2, PPS_RP26); // SDI2 =RP26 G7/pin 11 PPSOutput( PPS_RP22, PPS_SCK2OUT); // SCK2 =RP21 G6/pin 10 PPSOutput( PPS_RP21, PPS_SDO2); // SDO2 =RP19 G8/pin 12 // UART PPSInput( PPS_U2RX, PPS_RP10); // U2RX =RP10 F4/pin 49 PPSInput( PPS_U2CTS, PPS_RPI32); // U2CTS=RP32 F12/pin40 PPSOutput( PPS_RP17, PPS_U2TX); // U2TX =RP17 F5/pin 50 PPSOutput( PPS_RP31, PPS_U2RTS); // U2RTS=RP31 F13pin 39 // IC PPSInput( PPS_IC1, PPS_RP2); // IC1 =RP2 D8/pin 68 // OC PPSOutput( PPS_RP19, PPS_OC1); // OC1 =RP11 D0/pin 72 PPSOutput( PPS_RP11, PPS_OC2); // OC2 =RP24 D1/pin 76 PPSOutput( PPS_RP24, PPS_OC4); // OC4 =RP22 D3/pin 78 }
Special Mapping for GB1 PIM Users // GB110 PIM pin-remapping to accomodate additional USB pins // GB110 shares usage of D2/pin 77 between SDI1 and OC3 // pin 54 SDI1 is remapped to Explorer pin 77/D2 // NOTE: we will use it only as OC3 // pin 55 SCK1 is remapped to Explorer pin 25/B0 // NOTE: pin 55 is input only, connecting it to SCK1 // restricts usage to "slave mode" only // pin 56 RG3 is remapped to Explorer pin 89/G1 // pin 57 RG2 is remapped to Explorer pin 90/G0 #ifdef __PIC24FJ256GB110__ PPSOutput( PPS_RP23, PPS_OC3OUT); // OC3=RP23 D2/pin 77 #endif
Intoducing the EX16.c Module /* ** EX16.c */ #include <EX16.h> void InitEX16( void) { // if using a GA1 or GB1 PIM, initialize the PPS module #if defined(__PIC24FJ256GB110__) || defined(__PIC24FJ256GA110__) #include <pps.h> InitPPS(); #endif // prepare Port A for use with LED bar LATA = 0; // all LED off TRISA = 0xFF00; // all output } // InitEX16
EX16.h Header File /* ** EX16.h ** ** Standard definitions for use with the Explorer16 board */ #ifndef _EX16 #define _EX16 #include <p24fxxxx.h> #if defined(__PIC24FJ256GB110__) || defined(__PIC24FJ256GA110__) #include <pps.h> #endif #define FCY 16000000UL // instruction clock 16MHz // prototypes void InitEX16( void); // initialize the Explorer 16 board #endif
Additional Configs for GA1/GB1 • Add the following lines to the config.h file created in lesson 1: #if defined ( __PIC24FJ128GA010__ ) || defined (__PIC24FJ256GA110__) _CONFIG2( IESO_OFF // two speed start up disabled & FCKSM_CSDCMD // disable clock-swithcing/monitor & FNOSC_PRIPLL // primary oscillator: enable PLL & POSCMOD_XT) // primary oscillator: XT mode #else // GB1 configuration requires additional detail _CONFIG2( PLL_96MHZ_ON // enable USB PLL module & PLLDIV_DIV2 // 8MHz/2 = 4Mhz input to USB PLL & IESO_OFF // two speed start up disabled & FCKSM_CSDCMD // disable clock-swithcing/monitor & FNOSC_PRIPLL // primary oscillator: enable PLL & POSCMOD_XT) // primary oscillator: XT mode #endif
Suggested Excercises • Improve the display / hand synchronization by waiting for a button to be pressed before the hand sweep is started • Add a switch to sense the sweep movement reversal and play the LED sequence backward on the back sweep
Recommended Readings • Rony, P., Larsen D. & Titus J., 1976, THE 8080A BUGBOOK, MICROCOMPUTER INTERFACING AND PROGRAMMING, Howard W. Sams & Co., Inc., Indianapolis, IN • No high level language programming here, just the basics of assembly programming and hardware interfacing. • (Too bad this book is already considered museum material, see link below). • Shulman, S. (2003), Unlocking the Sky, Glenn Hammond Curtis and the race to invent the Airplane, Harper Collins, New York, NY • A beautiful recount of the “struggle to innovate” in the early days of aviation.
Online Resources • http://www.bugbookcomputermuseum.com/BugBook-Titles.html • A link to the “Bugbooks museum”. It is 40 years since the introduction of the INTEL 8080 microprocessor and it is like centuries have already passed.