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!
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
}