Embedded Control Sample C Code

f l i t e c

ENGR 2350: Laboratory Introduction to Embedded Control

Embedded Control Sample C Code

This page includes the Sample Introl C code that will be discussed in the Embedded Control lectures. Periodically, you will be asked to modify sample C code in order to accomplish an in-class exercise. If you have any problems with the code listed here, ask the professor or one of your TAs for help.

Cut and paste the desired code into a new WinEdit window. Please make sure that you have filled in the blanks correctly and have supplied the necessary indentation when needed!

Be sure to REMOVE all of your code from the computer at the end of class!

Homework #1 Code

#include // include files. This file is available online void main(void) // start main function { // declare variables before first executable code int imax, i; Sys_Init(); // Initialize UART, System clock and crossbar while(1) // begin infinite loop { printf("\n Enter count number\n"); scanf("%d", &imax); // accept keyboard input printf("\n\n Decimal \t hex \n"); for(i = 0; i <= imax; i++) { count=i; // print number both decimal and hex printf("%bu \t %bx \n", count, count); } // end for loop } // end while loop } // end main function

Sample Code for Lab 1.1

/* This program lights LED0 if the pushbutton is activated. You need to modify this code to complete the Lab 1.1 */ #include // include files. This file is available online //-------------------------------------------------------- // Function PROTOTYPES //-------------------------------------------------------- void Port_Init(void); // Initialize ports for input and output int sensor(void); // function which checks Pushbutton sbit LED0 = P2^2; // LED0 associated with Port 2 Pin 2 sbit Push = P3^4; // Push associated with Port 3 Pin 4 //*************** void main(void) { Sys_Init(); // System Initialization Port_Init(); // Initialize port 2 and 3 while (1) // infinite loop { if (sensor()) { // if Pushbutton activated LED0 = 0; // Light LED0 printf("\rPushbutton Activated! \t"); } else { LED0 = 1; // turn off LED0 printf("\rPushbutton Not Activated! "); } } } void Port_Init(void) { // Port 2 P2MDOUT |= 0x04; // set output pin P2.2 in push-pull mode // Port 3 P3MDOUT &= ~0x10; // set input pin P3.4 in open drain mode P3 |= 0x10; // set input pin P3.4 to high impedance state } /* Sensor - Returns a 0 if Pushbutton not activated */ /* or a 1 if Pushbutton is activated */ int sensor(void){ if (!Push) return 1; else return 0; }

Sample Code for Lab 1.2

/* This program demonstrates the use of T0 interrupt. The code will count the number of T0 timer overflows that occur while a slide switch is in Off position */ #include // include files. This file is available online //------------------------------------------------------------- // Function PROTOTYPES //------------------------------------------------------------- void Port_Init(void); // Initialize ports for input and output void Timer_Init(); // Initialize Timer 0 //------------------------------------------------------------- // Global variables //------------------------------------------------------------- // one end of bicolor LED0 is associated with Port 2 Pin 0 sbit BiLED0_1 = P2^0; // other end of bicolor LED0 is associated with Port 2 Pin 1 sbit BiLED0_2 = P2^1; sbit SW = P3^1; // Slide Switch associated with Port 3 Pin 0 int Counts = 0; //*************** void main(void) { Sys_Init(); // System Initialization Port_Init(); // Initialize port 2 and 3 Timer_Init(); // Initialize Timer 0 IE |= 0x02; // enable Timer0 Interrupt request EA = 1; // enable global interrupts BiLED0_1 = 0; // Turn off bicolor LED BiLED0_2 = 0; printf("Start\n"); while (1) { if ( !SW ) { TR0 = 1; BiLED0_1 = 1; // Turn ON bicolor LED BiLED0_2 = 0; while ( !SW ); // Wait while switch is activated TR0 = 0; // Switch is no longer activated, stop counting BiLED0_1 = 0; // Turn off bicolor LED BiLED0_2 = 0; printf("Number of Overflows = %d\n", Counts); Counts = 0; TL0 = 0; TH0 = 0; } } } void Port_Init(void) { // Port 2 P2MDOUT |= 0x03; // set output pins P2.0 and P2.1 in push-pull mode // Port 3 P3MDOUT &= ~0x02; // set input pin P3.1 in open drain mode P3 |= 0x02; // set input pin P3.1 to high impedance state } void Timer_Init(void) { CKCON &= ~0x08; // Make T1 intact and T0 use SYSCLK/12 TMOD &= 0xF0; // Clear the 4 least significant bits TMOD |= 0x01; // Make T1 intact and T0 use mode 1 TR0 = 0; // Stop Timer0 TL0 = 0; // Clear low byte of register T0 TH0 = 0; // Clear high byte of register T0 } void T0_ISR ( void ) interrupt 1 //Interrupt service routine { TF0 = 0; // clear interrupt request Counts++; // increment overflow counter }

A/D Conversion on P1.0

/* Sample Code to perform an A/D conversion on P1.0 */ #include #include //------------------------------------------------------------- // Global CONSTANTS //------------------------------------------------------------- //------------------------------------------------------------- // Function PROTOTYPES //------------------------------------------------------------- void Port_Init(void); void ADC_Init(void); unsigned char read_AD_input(unsigned char n); //------------------------------------------------------------- // Main Routine //------------------------------------------------------------- void main(void) { unsigned char result; Sys_Init(); //initialize 8051 board Port_Init(); //Configure P1.0 analog input ADC_Init(); //initialize AD conversion while(1) { result = read_AD_input(0); // get A/D value on P1.0 } } void Port_Init(void) { //Port 1 P1MDIN &= ~0x01; //set P1.0 as analog input P1MDOUT &= ~0x01; //set input pin P1.0 to open-drain P1 |= 0x01; //initialize input pin P1.0 to high impedance state } void ADC_Init(void) { //set VREF to use internal generator (2.4V range) (manual pg92) REF0CN = 0x03; ADC1CN = 0x80; //enable ADC1 (manual pg80) ADC1CF |= 0x01; //set ADC gain to 1 } unsigned char read_AD_input(unsigned char n) { AMX1SL = n; //set P1.n as ADC1 input ADC1CN = ADC1CN & ~0x20; // clear conversion complete indicator ADC1CN = ADC1CN | 0x10; // initiate conversion while ((ADC1CN & 0x20) == 0x00); // wait for conversion complete return ADC1; // return ADC value }

Type Casting and Control Algorithms Example

#include #include unsigned int motorpw; #define ki 150 #define kp 150 // Var declaration long temp_motorpw; // Function declaration void show_results (unsigned char, unsigned char, int); void main (void) { Sys_Init(); while(1) { printf ("\t\tEqu #1\tEqu #2\tEqu #3\tEqu #4\tEqu #5\tEqu #6 \n"); // first case: motorpw=10000, desired=15, actual=35 // (car is going too fast) motorpw = 10000; printf (" Case #1:\t"); show_results(15,35,-20); // second case: motorpw= 10000, desired=35, actual=15 // (car is going too slow) printf ("Case #2:\t"); show_results(35,15,20); // third case: motorpw=1000, desired=5, actual=25 // (car is going too fast) motorpw = 1000; printf ("Case #3:\t"); show_results(5,25,-20); // fourth case: motorpw=63000, desired=35, actual=15 (car is at full // power, but is running slower than desired speed motorpw = 63000; printf ("Case #4:\t"); show_results(35,15,20); printf ("\n\nEqu #1: temp_motorpw = motorpw + (kp+ki) * (desired - actual) - kp*prev_error;\n"); printf ("Equ #2: temp_motorpw = motorpw + (int)(kp+ki) * (desired - actual) - kp*prev_error;\n"); printf ("Equ #3: temp_motorpw = (long)(motorpw + (kp+ki) * (desired - actual) - kp*prev_error);\n"); printf ("Equ #4: temp_motorpw = motorpw + (kp+ki)*(int)(desired - actual) - kp*prev_error;\n"); printf ("Equ #5: temp_motorpw = (long)motorpw + (long)((kp+ki)*(desired - actual)) - (long)(kp*prev_error);\n"); printf ("Equ #6: temp_motorpw = (long)motorpw + (long)(kp+ki)*((long)desired - (long)actual) - (long)kp*(long)prev_error;\n"); getchar(); }//end of while(1) } // end main function void show_results (unsigned char desired, unsigned char actual, int prev_error) { // 1st control algorithm temp_motorpw = motorpw + (kp+ki) // * (desired - actual) - kp*prev_error; printf ("%ld \t", temp_motorpw); // 2nd control algorithm temp_motorpw = motorpw + (int)(kp+ki) // * (desired - actual) - kp*prev_error; printf ("%ld \t", temp_motorpw); // 3rd control algorithm temp_motorpw = (long)(motorpw + (kp+ki) // * (desired - actual) - kp*prev_error); printf ("%ld \t ", temp_motorpw); // 4th control algorithm temp_motorpw = motorpw // + (kp+ki)*(int)(desired - actual) - kp*(int)prev_error; printf ("%ld \t ", temp_motorpw); // 5th control algorithm temp_motorpw = (long)motorpw + (long)((kp+ki)*(desired // - actual)) - (long int)(kp*prev_error); printf ("%ld \t ", temp_motorpw); // 6th control algorithm temp_motorpw = (long)motorpw + (long)(kp+ki) // * ((long)desired - (long)actual) - (long)kp * (long)prev_error; printf ("%ld \n ", temp_motorpw); } // end function

WorkSheet 5: PWM : Frequency and Pulsewidth

/* Test Code Understand the meaning of frequency, period, on time, duty cycle */ #include #define pw_min 1000 #define pw_max 65000 void PCA_Init (void); void Port_Init (void); unsigned int PW = 5000; // pulsewidth for speed controller unsigned int nOverFlows; unsigned int PCA_start = 10000; // start count for PCA to have 20ms period sbit sw1 = P3^7; sbit sw2 = P3^6; void main() { unsigned char input; Sys_Init(); //initial functions in the blimp_init.h file printf("start /n"); Port_Init(); //initialize XBAR PCA_Init (); // initialize PCA printf("\r start "); printf("\n a - increases PCA start count by 1000"); printf("\n s - decreases PCA srart count by 1000"); printf("\n k - increases pulse width by 1000"); printf("\n l - decreases pulse width by 1000"); PCA0CPL1 = 65535 - PW; // set initial pulse width PCA0CPH1 = (65535 - PW) >> 8; while(1) { input = getchar(); if (input == 'a') if (PCA_start < pw_max) PCA_start += 1000; if (input == 's') if (PCA_start > pw_min) PCA_start -= 1000; if (input == 'k') { if (PW < pw_max) { PW += 1000; PCA0CPL1 = 65525 - PW; // change pulse width PCA0CPH1 = (65525 - PW) >> 8; } } if (input == 'l') { if (PW > pw_min) { PW -= 1000; PCA0CPL1 = 65525 - PW; // change pulse width PCA0CPH1 = (65525 - PW) >> 8; } } printf(" PCA_start = %u PW = %u \n", PCA_start,PW); } } void Port_Init () { P3MDOUT &= ~0xC0; // set port 3, bits 6 and 7 for input P3 |= 0xC0; XBR0 = 0x27; // set up URART0, SPI, SMB, and CEX 0-3 } void PCA_Init () { PCA0MD = 0x81; // SYSCLK/12, enable CF interrupts, suspend when idle PCA0CPM1 = 0xC2; // 16 bit, enable compare, enable PWM EIE1 |= 0x08; // enable PCA interrupts PCA0CN |= 0x40; // enable PCA EA = 1; // enable all interrupts } void PCA_ISR (void) interrupt 9 { if (CF) { nOverFlows++; PCA0L = PCA_start; // low byte of start count PCA0H = PCA_start>>8; // high byte of start count CF = 0; // Very important - clear interrupt flag } else PCA0CN &= 0xC0; // all other type 9 interrupts }

BASIC FUNCTION CODE:

unsigned char i2c_read(void); unsigned char i2c_stop_and_read(void); void i2c_write(unsigned char output_data); void i2c_write_and_stop(unsigned char output_data); void i2c_write_data(unsigned char addr, unsigned char start_reg, unsigned char *buffer, unsigned char num_bytes); void i2c_read_data(unsigned char addr, unsigned char start_reg, unsigned char *buffer, unsigned char num_bytes); void i2c_start(void); void i2c_start(void) { while(BUSY); //Wait until SMBus0 is free STA = 1; //Set Start Bit while(!SI); //Wait until start sent STA = 0; //Clear start bit SI = 0; //Clear SI } void i2c_write(unsigned char output_data) { SMB0DAT = output_data; //Data to be written put into register while(!SI); //Wait until send is complete SI = 0; //Clear SI } void i2c_write_and_stop(unsigned char output_data) { SMB0DAT = output_data; //Data to be written put into register STO = 1; //Set stop bit while(!SI); //Wait until send is complete SI = 0; //clear SI } unsigned char i2c_read(void) { unsigned char input_data; while(!SI); //Wait until we have data to read input_data = SMB0DAT; //Read the data SI = 0; //Clear SI return input_data; //Return the read data } unsigned char i2c_read_and_stop(void) { unsigned char input_data; while(!SI); //Wait until we have data to read input_data = SMB0DAT; //Read the data SI = 0; //Clear SI STO = 1; //Set stop bit while(!SI); //wait for stop SI = 0; return input_data; // Return the read data }

Hello world!

Welcome to www.51lelele.com.  If you want to find the soccer activity info, please go to visit  www.51lelele.ca.

The web site is under construction!

The web site is under construction!