ra68gi 0 Posted December 14, 2006 Report Share Posted December 14, 2006 (edited) " Please don't reply to this thread" Hello friends, This thread is started with the intension of providing quick start to beginners in programming PIC microcontrollers using BoostC compiler. All code examples have been tested by me either using the simulator or by hard wiring the device. Who will benefit from this thread? 1. Absolute beginners. 2. Those wanting to migrate from other compilers/languages like PicBasic,PicPascal, etc. If you have suggestions or questions please post it on a new thread. Raghunathan Edited December 16, 2006 by ra68gi Quote Link to post Share on other sites
ra68gi 0 Posted December 14, 2006 Author Report Share Posted December 14, 2006 (edited) /* WINK LED Our first c program.Blinking two LEDs on portb pin0 & pin1. Chip-16F84,8 i/o pins on portb & 5 i/o pins on porta. TO DO THIS PROJECT YOU REQUIRE.. 1. Source Boost(SB)IDE - FREE Down load is available from www.sourceboost.com 2. BoostC compiler - Comes along with the SB IDE 3. Take a print of the IDE user's manual and follow instructions. 4. Take a print of BoostC compiler reference manual. 5. PIC16F84 microcontroller & components listed below. 6. PIC16F84 data sheet available from microchip website. 7. Any PIC programmer. How to Build/compile your C Program? 1. Select tool suit, target chip and clock rate from settings in the toolbar & view the same on the source boost IDE status bar at the bottom of the screen. At this point your screen is blank. 2. First click the New button on the tool bar. 3. You can Copy & paste this code from this thread or type in the code as written below. 4. Now choose, save as & save your file. 5. Go to the project button on the toolbar. 6. Select the project you want to build by clicking on the appropriate file. In our case it is WINK LED. The sreen will go blank at this point. 7. Now your poject is selected and ready to build. 8. Now open the file again by clicking the file button or open button from the tool bar. 9. To cross check again if its the program you are going to compile, press the project button & see if the name of your file is right at the top of list of projects. 10.Now press Build button. If every thing works out well you can see success on your build/output window at the bottom of the IDE. How to check if your code is working? Before you load the hex file onto your chip, you can use the built in simulator on the SourceBoost IDE to check if your code is working just as intended.Read the IDE user's manual to get help to configure your plugins. Connections: pin4- MCLR pin to +5v via 4.7K resistor pin15-16 4mhz crystal(across pin 15 & 16) connect 22pf capacitors( between pin15 & gnd, pin16 & gnd) pin6-RB0-connect LED to pin6 via 470 ohms. Cathode of LED to gnd. pin7-RB1-connect LED to pin7 via 470 ohms. Cathode of LED to gnd. */ #include <system.h> #pragma CLOCK_FREQ 4000000 // config clock to 4mhz. // Set configuration fuse. #pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _CP_OFF & _PWRTE_OFF void main() { trisb = 0; //configure port B pins as output while( 1 ) //endless loop { portb.0=1; // set portb pin0 to high. portb.1=0; // set portb pin1 to low. delay_ms( 250 ); // pause 0.5 seconds delay_ms( 250 ); // (note we have to call delay_ms twice because it's // argument has unsigned char type) portb=0x02; // shows hex notation for entering data. delay_ms( 250 ); // you can also write portb=2 in decimal delay)ms( 250 ); } } /* The PIC 16F84 contains two I/O ports, portA & PortB. Each port has two registers associated with it, TRIS (Tri state) register and port register itself. The tris register controls whether a particular pin on a port is configured as input pin or output pin.Once the pins have been configured using tris register you may read or write data to the port using the port register. Writing a zero to a bit in tris register will make the corresponding bit or pin in port as output, capable of sourcing and sinking current. writing a one to a bit in tris register will make the corresponding pin in port as input. The microcontroller is capable of reading data placed on this pin. The same pin can be changed from input to output within a program by setting the tris register bit associated with it. In the above example we have entered zero into the trisb register there by making all the eight pins in portb as output. portb=255; will make all pins as input. You can also use binary notation to select individual bits for input or output. example: trisb = 0B10101011; . BoostC also allows us to choose individual bits in a register. example: trisb.0=0; makes portb pin0 as output. Once the pins have been configured as output, placing a one in the port register will make it high(+5v) & placing a zero in the port register will make it low(0v, capable of sinking 25ma current). I am really amazed by the compact code size generated by this compiler. It takes just 34 words of program memory space comp- ared to 54 words by PicBasicPro and 70 words by mikroC. */ pic_project.bmp Edited May 2, 2014 by Pavel Quote Link to post Share on other sites
ra68gi 0 Posted December 15, 2006 Author Report Share Posted December 15, 2006 (edited) /* BINARY COUNTThis is a simple binary counting program that will light eightLEDs connected to portb pins of PIC16f84. The binary count programwill light the LEDs in sequence from "0" to"255" incrementing byone. Each binary 1 in a number will be represented with a lit LED.Every 0.5 seconds the count is incremented. After reaching thebinary number 255 ( the maximum byte value ), the sequence repeats,from zero.Before you load the hex file onto your chip, you can use the builtin simulator on the SourceBoost IDE to check if your code is workingjust as intended.Read the IDE user's manual to get help to configureyour plugins.Connections:pin4- MCLR pin to +5v via 4.7K resistorpin15-16 4mhz crystal(across pin 15 & 16)connect 22pf capacitors( between pin15 & gnd, pin16 & gnd)pin6-RB0-connect LED to pin6 via 470 ohms. Cathode of LED to gnd.pin7-RB1-connect LED to pin7 via 470 ohms. Cathode of LED to gnd.pin8-RB2-connect LED to pin8 via 470 ohms. Cathode of LED to gnd.pin9-RB3-connect LED to pin9 via 470 ohms. Cathode of LED to gnd.pin10-RB4-connect LED to pin10 via 470 ohms. Cathode of LED to gnd.pin11-RB5-connect LED to pin11 via 470 ohms. Cathode of LED to gnd.pin12-RB6-connect LED to pin12 via 470 ohms. Cathode of LED to gnd.pin13-RB7-connect LED to pin13 via 470 ohms. Cathode of LED to gnd.*/ #include <system.h> #pragma CLOCK_FREQ 4000000 // config clock to 4mhz. // Set configuration fuse #pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _CP_OFF & _PWRTE_OFF void main() // Program entry point,mandatory for every C program. { trisb=0; // configure port B pins as output char b0; // Define b0 as character while(1) // Infinite loop { for(b0=0;b0<256;b0++) // For loop in C. See description below. { portb=b0; // Place b0 value at Portb to light LEDs. delay_ms(250); // Pause for 0.5 seconds & then go to display delay_ms(250); } // the next incremented b0 value. } // Because b0 has char data type it never reaches 256 // so this loop never exits. } /* In our second program BINARY COUNT, we see two new statements.The first is char b0;. b0 is a variable declared by us as character.In BoostC variables or data can be declared as bit, char, unsigned char,signed char, short, unsigned short, signed short, int ( integer ),unsigned int, signed int, long ( 32 bit data ), unsigned long, signed long.Please see BoostC user's manual for more info.The second statement is for(b0=0;b0<256;b0++). for is a loop controlconstruct. It controls the number of times a block of statements isexecuted. The construct has an initial value, and a loop-count value thatis incremented each time after the block is executed.This is similar to the Basic command "for x = 0 to 255".Program memory space used in this program is 31 words.*/ PIC4.bmp Edited May 2, 2014 by Pavel Quote Link to post Share on other sites
ra68gi 0 Posted December 18, 2006 Author Report Share Posted December 18, 2006 (edited) /* BINARY PROGRESSIONThe binary progression program lights each LED in sequence,starting from the first LED connected to RB0, then the secondled(RB1) while the first is switched off and then the third ledconnected to RB2 is switched on while the second led is switchedoff and so on. So the LEDs will scroll from left to right.Before you load the hex file onto your chip, you can use the builtin simulator on the SourceBoost IDE to check if your code is workingjust as intended. Read the IDE user's manual to get help to configureyour plugins.Connections:pin4- MCLR pin to +5v via 4.7K resistorpin15-16 4mhz crystal(across pin 15 & 16)connect 22pf capacitors( between pin15 & gnd, pin16 & gnd)pin6-RB0-connect LED to pin6 via 470 ohms. Cathode of LED to gnd.pin7-RB1-connect LED to pin7 via 470 ohms. Cathode of LED to gnd.pin8-RB2-connect LED to pin8 via 470 ohms. Cathode of LED to gnd.pin9-RB3-connect LED to pin9 via 470 ohms. Cathode of LED to gnd.pin10-RB4-connect LED to pin10 via 470 ohms. Cathode of LED to gnd.pin11-RB5-connect LED to pin11 via 470 ohms. Cathode of LED to gnd.pin12-RB6-connect LED to pin12 via 470 ohms. Cathode of LED to gnd.pin13-RB7-connect LED to pin13 via 470 ohms. Cathode of LED to gnd.*/ #include <system.h> #pragma CLOCK_FREQ 4000000 // config clock to 4mhz. // Set configuration fuse #pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _CP_OFF & _PWRTE_OFF void main() { trisb=0; // make portb pins as output char b0; // declare b0 as character char b1; // declare b1 as character while(1) // endless loop { b0=1; // initialize b0 variable to 1. portb=b0; // display b0 value on portb delay_ms(250); // pause 0.5s for us to see the lit LED delay_ms(250); for(b1=0;b1<7;b1++) // for loop for seven times { b0*=2; // C syntax for multiply and assign. portb=b0; // similar to basic syntax of b0=b0*2 delay_ms(250); // pause 0.5 sec to see the LED on. delay_ms(250); } } } /* The only statement new in this C program is " b0*=2;". Here theC compiler multiplies b0 value with 2 and assigns this new valueto b0. It is similar to b0=b0*2. Multiplying b0 with 2, causesthe bits in b0 to shift left by one place.Take a print of BoostC compiler reference manual and you willfind the list of arithmatic operators, assignment operator,comparison operator, logical operators.This program compiles to 43 words.In the above code change b0=1; as b0=128; in the while loopand also change b0 *= 2; as b0 /= 2; in the for loop. Build thecode and check it on the simulator. What do you see?You can see the LED patern has reversed, ie. the LEDs wouldscroll from left to right. You could call it regression. If you wishto store it, use the save as option first and then build it using thequick buid option in the project menu of the tool bar.*/ Edited May 2, 2014 by Pavel Quote Link to post Share on other sites
ra68gi 0 Posted December 19, 2006 Author Report Share Posted December 19, 2006 (edited) /* BUTTON TEST In this program we make our microcontroller(PIC16F84) to read switches connected to porta which will dynamically modify the program as it runs. We have connected three switches to the porta. We have named them button1, button2, button3. The main program is the scrolling LED program we had seen earlier. Pressing button1 will change the direction in which the LEDs scroll. Pressing butt- on2 will increment the delay time for which the LEDs are lit. pres- sing button3 will reduce the delay time for which the LEDs are lit. Before you load the hex file onto your chip, you can use the built in simulator on the SourceBoost IDE to check if your code is working just as intended.Read the IDE user's manual to get help to configure your plugins. Connections: pin4- MCLR pin to +5v via 4.7K resistor pin15-16 4mhz crystal(across pin 15 & 16) connect 22pf capacitors( between pin15 & gnd, pin16 & gnd) pin6-RB0-connect LED to pin6 via 470 ohms. Cathode of LED to gnd. pin7-RB1-connect LED to pin7 via 470 ohms. Cathode of LED to gnd. pin8-RB2-connect LED to pin8 via 470 ohms. Cathode of LED to gnd. pin9-RB3-connect LED to pin9 via 470 ohms. Cathode of LED to gnd. pin10-RB4-connect LED to pin10 via 470 ohms. Cathode of LED to gnd. pin11-RB5-connect LED to pin11 via 470 ohms. Cathode of LED to gnd. pin12-RB6-connect LED to pin12 via 470 ohms. Cathode of LED to gnd. pin13-RB7-connect LED to pin13 via 470 ohms. Cathode of LED to gnd. pin17-RA0-connect switch, button1. pin18-RA1-connect switch, button2. pin1-RA2-connect switch, button3. There are two different ways in which you can configure your switch. .ie. the switch can output a high when pressed or a low when pressed. Based on this information you need to modify the code in your if statement.But this code works as it is on the simulator. In the future i will provide the schematic for all the projects done here. If you hard wire this project, make sure your micro sees the right switch state. */ #include <system.h> #pragma CLOCK_FREQ 4000000 // Set configuration fuse #pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _CP_OFF & _PWRTE_OFF void check1(void); // declare that you are using a routine // called check1. void check2(void); // declare that you are using a routine // called check2. int duration; // duration is declared as global variable. #define button1 porta.0 // button1 is alais for porta.0 #define button2 porta.1 // button2 is alais for porta.1 #define button3 porta.2 // button3 is alais for porta.2 void main(void) { // Program entry point. trisa=7; // set porta pin0-pin2 as inputs. trisb=0; // set portb pins as output. portb=0; // set portb pins to low. duration=250; // set initial value of delay at 250ms while(1) // infinite loop. { if(button2) // if button2 is pressed, execute { // the following statements. duration+=10; // increment duration by 10ms. if(duration==1000) // if duration equals 1000ms, { duration=990; // make it 990ms. } // this will limit the max delay. } if(button3) // if button3 is pressed, execute { // the following statements. duration-=10; // reduce delay by 10ms. if(duration==10) // if delay equals 10ms, { duration=20; // make it 20ms. } // this will limit the min delay. } if(button1==0) // if button1 pin is not pressed, { // execute the statements below check1(); // call routine check1. portb <<= 1; // shift bits in portb to its left, ones. delay_ms(duration); // pause for the value of duration. } else // else if porta.0 pin is high { // execute the statements below. check2(); // call routine check2. portb>>=1; // shift bits in portb to its right by one place. delay_ms(duration); // pause for the value of duration. } } } void check1(void) // check1 routine. { if(portb==0) // if portb equals zero, { // then execute the statements below. portb=1; // make portb to display 1. delay_ms(duration); // pause for the value of duration. } } void check2(void) // check2 routine. { if(portb==0) // if portb equals zero, { // then execute the following statements. portb=128; // make portb to display 128. delay_ms(duration); // pause for the value of duration. } } /* Lets try to understand the C program line by line. In the beginning of the program you can see two routines check1 & check2. These routines get called from the main routine void main(void). In Basic programming we call it sub-routines. Unlike the Basic sub-routine it does not have a return statement.It is important that you declare all the routines used at the beginning of the code for the compiler to recognize it latter in the program. The routine check1 checks if portb value is zero and if found true makes it equal to one, so that the binay progression can repeatedly continue. Similarly check2 checks if portb valve is zero and if true makes it equal to 128, so that the binary regression can continue. See that check2 rou- tine is called only if button1 is pressed or true. Next in line is int duration; statement. See that duration is declared as an integer because we require more than one byte to store a duration of 1000. Also you can see that it is declared outside the all the routines, meaning that all routines can access the variable and modify it. Thats why we call it global variable. The next statement is #define button1 porta.0. What the compiler does is, it simply replaces button1 with porta.0 while compiling. For us its more convenient and easy to understand the code.So the name button1 is an alais for porta.0. The rest of the program is self explanatory.In the main routine trisa=7; sets porta pins 0-2 as input. trisb=0 makes all pins in portb as output. The delay variable is given an initial value of 250ms. Then the program enters the endless loop, while(1);. In this loop we check if the buttons are pressed. The if statement if(button2) is same as if(button2==1). It means if button2 is true or 1 execute the statements that follows. One other new operator we have used is portb>>=0; and portb<<=0;. They are shift right & assign and shift left and assign operators. They create the same effect as b0*=2; and b0/=2; used in our earlier program. This program compiles to 98 words. */ PIC8modified.bmp Edited July 26, 2013 by Pavel Quote Link to post Share on other sites
ra68gi 0 Posted December 26, 2006 Author Report Share Posted December 26, 2006 (edited) /* BINARY CODED DECIMAL DISPLAY In this project we will display the binary data outputted by the port on two seven segment LED modules. We will make the seven segment display decimal 0 to 99. We can use the 4511 BCD to 7-segment converter IC for our purpose. The lower nibble of portb is connected to one of the 7-seg- ment via 4511 to display the units value & the higher nibble of portb is connected to the second 7-segment via another 4511 to display the tens value. Source Boost IDE has got this plugin on its simulator. So its very easy to verify your code. Connections: pin4- MCLR pin to +5v via 4.7K resistor. pin15-16 4mhz crystal(across pin 15 & 16). connect 22pf capacitors( between pin15 & gnd, pin16 & gnd). lower nibble or units display. pin6-RB0-connect to pin7 of 4511(1). pin7-RB1-connect to pin1 of 4511(2). pin8-RB2-connect to pin2 of 4511(4). pin9-RB3-connect to pin6 of 4511(8). upper nibble or tens display. pin10-RB4-connect to pin7 of 4511. pin11-RB5-connect to pin1 of 4511. pin12-RB6-connect to pin2 of 4511. pin13-RB7-connect to pin6 of 4511. Remaining pin connections of 4511. pin13-to "A" segment of 7-segment via 470 ohms. pin12-to "B" segment of 7-segment via 470 ohms. pin11-to "C" segment of 7-segment via 470 ohms. pin10-to "D" segment of 7-segment via 470 ohms. pin9- to "E" segment of 7-segment via 470 ohms. pin15-to "F" segment of 7-segment via 470 ohms. pin14-to "G" segment of 7-segment via 470 ohms. pin16-to +5v. pin3-to +5v. pin4-to +5v. pin5-to ground. pin8-to ground. 7-segment display-common cathode-to ground. */ #include <system.h> #pragma CLOCK_FREQ 4000000 // config clock to 4mhz. // Set configuration fuse. #pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _CP_OFF & _PWRTE_OFF void main() { trisb=0; //make portb as output. portb=0; //set portb pins to low. char b0; //declare b0 as character type variable. char units; //declare units as character type variable. char tens; //declare tens as character type variable. char bcd; //declare bcd as character type variable. while(1) //endless loop { for(b0=0;b0<100;b0++) //for loop, which outputs 0-99 as BCD. { tens=b0/10; //tens value is first calculated. units=b0%10; //next units value is derived. tens *= 16; //we shift the tens value to the upper nibble. bcd=units+tens; //we add the upper & lower nibble to get BCD value. portb=bcd; //out the BCD value on portb. delay_ms(250); //wait half a second for us to see display. delay_ms(250); } } } /* This program compiles to 91 words. In the above program change all char variables to unsigned char variables and see the program words saved. */ Edited May 2, 2014 by Pavel Quote Link to post Share on other sites
ra68gi 0 Posted December 31, 2006 Author Report Share Posted December 31, 2006 (edited) /* 3-digit-7-segment_display(Using PIC16F84)In this project we will connect three common cathode 7-segment modulesin parallel & then connect them to the 7 pins of portb(RB1thro'RB7) via470 ohms resistors. In all our future projects we will use RB1 TO RB7pins for our 7 LEDs of the segment module. We will demultiplex the datato the 7-segment modules by using three transistors connected to thecommon cathode pin of each of the module. The base of the transistors aredriven from porta pins. This project will form the base for our futureprojects like A/D converter or a digital thermometer, digital clock etc.The C program will display decimal 0 to 999 on the three segments. Theprogram is in a loop and so will continue to display from 0 once againafter it reaches the value off 999.We can't use the simulator for this project. So we have to hard wire to seeour code work. I have checked it on my board. You can probably use a breadboard to test it.Connections:PIC16F84pin4- MCLR pin to +5v via 4.7K resistor.pin15-16 4mhz crystal(across pin 15 & 16).connect 22pf capacitors( between pin15 & gnd, pin16 & gnd).pin6-RB0-no connection.pin7-RB1-connect to segment "e" of the 7-segment display via 470 ohms.pin8-RB2-connect to segment "a" of the 7-segment display via 470 ohms.pin9-RB3-connect to segment "f" of the 7-segment display via 470 ohms.pin10-RB4-connect to segment "c" of the 7-segment display via 470 ohms.pin11-RB5-connect to segment "g" of the 7-segment display via 470 ohms.pin12-RB6-connect to segment "b" of the 7-segment display via 470 ohms.pin13-RB7-connect to segment "d" of the 7-segment display via 470 ohms.pin14-connect to +5v supply.pin5- connect to ground.Base of transistor(U) is connected to RA2(pin1 of micro) via 2.2k resistor.Base of transistor(T) is connected to RA1(pin18 of micro) via 2.2k resistor.Base of transistor(H) is connected to RA0(pin17 of micro) via 2.2k resistor.Seven segment modules.The segment pins of the three 7-segment module must be paralled,ie. all"a" segments are connected together & all "b" segments are connected &so on.Let's call them the units digit,tens digit & hundreds digit.Common cathode of units digit is connected to transistor(U)'s collector.Emitter of transistor(U) is connected to ground.Base of transistor(U) is connected to RA2(pin1 of micro) via 2.2k resistor.Common cathode of tens digit is connected to transistor(T)'s collector.Emitter of transistor(T) is connected to ground.Base of transistor(T) is connected to RA1(pin18 of micro) via 2.2k resistor.Common cathode of hundreds digit is connected to transistor(H)'s collector.Emitter of transistor(H) is connected to ground.Base of transistor(H) is connected to RA0(pin17 of micro) via 2.2k resistor.Transistor type-BC 547 NPN.*/ #include <system.h> #pragma CLOCK_FREQ 4000000 // Set configuration word #pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _CP_OFF & _PWRTE_OFF //declare function get_value. unsigned char get_value(unsigned char y); unsigned char y; unsigned char units; //declare units as unsigned char variable. unsigned char tens; //declare tens as unsigned char variable. unsigned char hundreds; //hundreds as unsigned char variable. void main(void) { trisa=0; //make porta as output. porta=0; //make porta pins low. trisb=0; //make portb as output. portb=0; //make portb pins low. while(1) //endless loop. { unsigned int b0; //declare b0 as unsigned integer variable. unsigned char b1; //declare b1 as unsigned character. for (b0=0;b0<1000;b0++) //for loop to display 0-999. { hundreds=b0/100; //get the hundred's value. tens=(b0%100)/10; //get the ten's value. units=b0%10; //get the unit's value. for (b1=0;b1<100;b1++) //display data hundred times. { portb = get_value(hundreds); //get segment value. porta.0=1; //switch on tranisistor(H). delay_ms(1); //pause 1ms to see data. porta.0=0; //switch off transistor(H). portb=get_value(tens); //get segment value. porta.1=1; //switch on tranisistor(T). delay_ms(1); //pause 1ms to see data. porta.1=0; //switch off transistor(T). portb=get_value(units); //get segment value. porta.2=1; //switch on tranisistor(U). delay_ms(1); //pause 1ms to see. porta.2=0; //switch off transistor(U). } } } } //lookup table for the segment values. unsigned char get_value(unsigned char y) { unsigned char segments[10]={0xDE,0x50,0xE6,0xF4,0x78,0xBC,0xBE,0x54,0xFE,0xFC}; return segments[y]; } /* The C program first intializes the ports as output. Next weenter the while loop where we have created a for loop which willmake b0 to take values from 0-999. Next we proceed to determinethe hundred's, ten's and unit's value of b0. These values are thenpassed on to the lookup table which is an array of values. The arraycontains the segment value that has to be outputted on portb. Thevalues are for "0" to "9" decimal.When this value is outputted onportb, the appropriate leds light up to from the digits. First weoutput the hundred's value on portb & switch on the transistor(H)connected to the hundreds digit for a brief period of 1ms and thenswitch it off. Next we place the ten's value on portb and switchon & off the transistor(T) & then we do the same thing for the unitsvalue. This is repeated for 100 times so that we can see all the threedigits on all the time. Changing the loop value b1 will change the rateat which numbers will appear on the display. You can vary the delaytime as well as the loop value b1 to see the effect.See how an arrayis declare in the function get_value & how the return statement returnsthe appropriate segment value.All variables are declared as unsignedcharacter in order to save program words.This program compiles to208 words.*/ pic13.bmp pic11modified.bmp Edited July 26, 2013 by Pavel Quote Link to post Share on other sites
ra68gi 0 Posted January 8, 2007 Author Report Share Posted January 8, 2007 (edited) /* Thermometer1.cIn our previous program we learnt how to display values on 7-segment display.In this program we make PIC16F84A display temperature read from LM35 tempera-ture sensor.PIC16F84A doesn't have built in analog to digital converter.So weshall use an external analog to digital converter(adc) TLC549.This adc is anserial adc & outputs the adc value serially on its (SDA OUT) pin6.A little information about analog and digital signals.An analog signal is infinitely variable between any two of its measuringpoints, no matter how close the two measuring points may be.For example,the number of possible readings between 1volt and 2 volts are infinite.similarly between 1volt and 1.0001volt we can have infinite values of vol-tages like 1.000001 or 1.000000001volts & so on.So we can have infinitesi-mally varying values of voltages.A digital signal equivalent of an analog signal is not infinitely variable.The digital equivalent of an analog signal varies in step proportion deter-mined by the resolution of the a/d converter.Lets take a typical example.suppose we have an anolog signal which varies from 0 to 5volts. and supposewe use an 8 bit adc, then the resolution of our converter is 256(8 bit values)or the adc will typically return values from 0 to 255.The adc will return 0if it finds a analog voltage value of 0 and return 255 if it finds an analogvoltage of 5volts (provided the reference to the adc is +5volts).step resolution of the converter is the step increment in the analog valuefor a step change in digital signal.In our above case its 5volts divided by255(not 256) which is 0.0196volts.Which means that when ever the analog vol-tage changes by 0.0196volts the adc will increment its digital output valueby 1.some adc values for the analog inputs for the above example areanalog value--------------adc value0volts-------------------------00.0196v-----------------------10.0392v-----------------------20.0588v-----------------------3..................................................................................5.0v---------------------------255Some information about LM35 temperature sensor.NATIONAL SEMICONDUCTORS LM35 DATA SHEETLM35Precision Centigrade Temperature SensorsGeneral DescriptionThe LM35 series are precision integrated-circuit temperaturesensors, whose output voltage is linearly proportional to theCelsius (Centigrade) temperature. The LM35 thus has anadvantage over linear temperature sensors calibrated in° Kelvin, as the user is not required to subtract a largeconstant voltage from its output to obtain convenient Centigradescaling. The LM35 does not require any externalcalibration or trimming to provide typical accuracies of ±1/4°Cat room temperature and ±3/4°C over a full -55 to +150°Ctemperature range. Low cost is assured by trimming andcalibration at the wafer level. The LM35’s low output impedance,linear output, and precise inherent calibration makeinterfacing to readout or control circuitry especially easy. Itcan be used with single power supplies, or with plus andminus supplies. As it draws only 60 µA from its supply, it hasvery low self-heating, less than 0.1°C in still air. The LM35 israted to operate over a -55° to +150°C temperature range,while the LM35C is rated for a -40° to +110°C range (-10°with improved accuracy). The LM35 series is available packagedin hermetic TO-46 transistor packages, while theLM35C, LM35CA, and LM35D are also available in theplastic TO-92 transistor package. The LM35D is also availablein an 8-lead surface mount small outline package and aplastic TO-220 package.Features1 Calibrated directly in ° Celsius (Centigrade)2 Linear + 10.0 mV/°C scale factor3 0.5°C accuracy guaranteeable (at +25°C)4 Rated for full -55° to +150°C range5 Suitable for remote applications6 Low cost due to wafer-level trimming7 Operates from 4 to 30 volts8 Less than 60 µA current drain9 Low self-heating, 0.08°C in still air10 Nonlinearity only ±1/4°C typical11 Low impedance output, 0.1 W for 1 mA loadIn our project we will use the sensor in the range of0°C-150°C.Some information about Texas Instruments TLC549 serial adc .TLC549 data sheet.Microprocessor Peripheral or Standalone Operation8-Bit Resolution A/D ConverterDifferential Reference Input VoltagesConversion Time . . . 17 ms MaxTotal Access and Conversion Cycles Per SecondTLC548 . . . up to 45 500TLC549 . . . up to 40 000On-Chip Software-ControllableSample-and-Hold FunctionTotal Unadjusted Error . . . ±0.5 LSB Max4-MHz Typical Internal System ClockWide Supply Range . . . 3 V to 6 VLow Power Consumption . . . 15 mW MaxIdeal for Cost-Effective, High-PerformanceApplications including Battery-OperatedPortable InstrumentationPinout and Control Signals CompatibleWith the TLC540 and TLC545 8-Bit A/DConverters and with the TLC1540 10-BitA/D ConverterCMOS TechnologydescriptionThe TLC548 and TLC549 are CMOS analog-to-digital converter (ADC) integratedcircuits built around an 8-bit switched-capacitor successive-approximationADC. These devices are designed for serial interface with a microprocessoror peripheral through a 3-state data output and an analog input. The TLC548and TLC549 use only the input/output clock (I/O CLOCK) input along with thechip select (CS) input for data control.The maximum I/O CLOCK input frequencyof the TLC548 is 2.048 MHz, and the I/O CLOCK input frequency of the TLC549is specified up to 1.1 MHz.For certain applications, such as strobing applications, it is necessary tostart conversion at a specific point in time.This device accommodates theseapplications. Although the on-chip sample-and-hold function begins samplingupon the high-to-low transition of the fourth I/O CLOCK cycle, the hold fun-ction does not begin until the high-to-low transition of the eighth I/O CLO-CK cycle, which should occur at the moment when the analog signal must beconverted. The TLC548 and TLC549 continue sampling the analog input untilthe high-to-low transition of the eighth I/O CLOCK pulse. The control circu-itry or software then immediately lowers I/O CLOCK and starts the holding f-unction to hold the analog signal at the desired point in time and startsthe conversion.Circuit Connections:PIC16F84pin4- MCLR pin to +5v via 4.7K resistor.pin15-16 4mhz crystal(across pin 15 & 16).connect 22pf capacitors( between pin15 & gnd, pin16 & gnd).pin6-RB0-no connection.pin7-RB1-connect to segment "e" of the 7-segment display via 470 ohms.pin8-RB2-connect to segment "a" of the 7-segment display via 470 ohms.pin9-RB3-connect to segment "f" of the 7-segment display via 470 ohms.pin10-RB4-connect to segment "c" of the 7-segment display via 470 ohms.pin11-RB5-connect to segment "g" of the 7-segment display via 470 ohms.pin12-RB6-connect to segment "b" of the 7-segment display via 470 ohms.pin13-RB7-connect to segment "d" of the 7-segment display via 470 ohms.pin14-connect to +5v supply.pin5- connect to ground.Base of transistor(U) is connected to RA2(pin1 of micro) via 2.2k resistor.Base of transistor(T) is connected to RA1(pin18 of micro) via 2.2k resistor.Base of transistor(H) is connected to RA0(pin17 of micro) via 2.2k resistor.TLC549 connections:pin1(Ref+)- connect this pin to the center or variable terminal or pin of a5k potentiometer. Connect one end of the pot to +5v and other to the ground.pin2(Analog input)- connect this pin to LM35 signal out pin.If LM35 is TO92package,its the center lead.other two pins of LM35 is given to +5v and ground.Again if LM35 is in TO92 pack then its pin1 is +5 & pin3 is ground.Please seedata sheet.pin3(Ref-)- connect this pin to ground.pin4(Gnd)- connect to ground.pin5(CS)- chip select pin is active low.connect this pin to RA3(pin2 of 16f84).pin6(Data out)- connect this pin to RB0(pin6 of 16f84).pin7(i/o clock)- connect this pin to RA4(pin3 of 16f84).Note- Pin RA4 is open drain & so use a 1k pullup resistor to +5v.pin8(Vcc)- connect to +5volts.FIXING THE REFERENCE VOLTAGE.Using a precision multimeter,adjust the 5k pot connected to the Ref+ pin ofTLC549 to around 2.55volts.This will make calculations much easy for us.Now when the analog signal input is 2.55volts the adc will out decimal 255.Our step resolution becomes 2.55 divided by 255, which is 0.01volts.ie.forevery increment of 0.01volt in the analog signal the adc value will incrementby one.Our temperature sensor can be used in the region of 0 to 150°C. At 0°C theanalog output is roughly zero and at 150°C its 150mv.The output varies line-arly by 10mv for an increment of 1°C.Seven segment modules.The segment pins of the three 7-segment module must be paralled,ie. all"a" segments are connected together & all "b" segments are connected &so on.Let's call them the units digit,tens digit & hundreds digit.Common cathode of units digit is connected to transistor(U)'s collector.Emitter of transistor(U) is connected to ground.Base of transistor(U) is connected to RA2(pin1 of micro) via 2.2k resistor.Common cathode of tens digit is connected to transistor(T)'s collector.Emitter of transistor(T) is connected to ground.Base of transistor(T) is connected to RA1(pin18 of micro) via 2.2k resistor.Common cathode of hundreds digit is connected to transistor(H)'s collector.Emitter of transistor(H) is connected to ground.Base of transistor(H) is connected to RA0(pin17 of micro) via 2.2k resistor.Transistor type-BC 547 NPN.One main difference between this project's display schematic & the previousis that in this project we invert the units display module.Please note weonly physically rotate the module through 180° but the electrical connectionsremain the same. We do this so that the decimal point in the segment appears tothe top left position, so that we can create the character "°C".Until the temperature of 99 the units digits will display "°C",beyond 99 it willdisplay all three decimal digits.Since the last digit is inverted i have useda seperate set of segment values or lookup table for it.When i finished programming i realized that i had no pin left to connect thedecimal point in the units segment.So i decided to directly connect this pin to +5volts via 470 ohms. The only oddthing is that it will be lit even while displaying temperatures beyond 99°C.*/ #include <system.h> #pragma CLOCK_FREQ 4000000 // config clock to 4mhz. // Set configuration fuse. #pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _CP_OFF & _PWRTE_OFF #include <system.h> //A function to create clock pulse for TLC549 void clk(void); //A function to get adc value serially from TLC549 void serial_adc(void); //A function for 7-segment display to display "0°C-99°C". void seven_segment1(void); //A function for 7-segment display to dispaly "0-150". void seven_segment2(void); //A function to get segment values for hundreds & tens. unsigned char get_value1(unsigned char x); //A function to get segments value for units. //units display module is inverted so as to display degree celsius, //with decimal point at top of the display. unsigned char get_value2(unsigned char y); /*Variable adc is made global for easy bit access in serial_adc() function which is used in main().*/ unsigned char adc; //Variable temperature is made global for easy access. unsigned char temperature; void main() { trisa=0; //set porta as output. trisb=1; //set porb.0 as input & rest of the pins as output. portb=0; //zero all portb pins. porta=8; // make chip select pin of TLC549 high. unsigned int sample; //sample var holds the adc sample value. unsigned char b0; //for loop var. while( 1 ) //Infinite loop. { sample=0; //initialize the sample to zero. for(b0=0;b0<20;b0++) { serial_adc(); sample += adc; } temperature=sample/20; if(temperature<99) //call seven_segment1 if temperature is less seven_segment1(); //than 99 else call seven_segment2. else seven_segment2(); } } void serial_adc(void) //serial_adc routine. { adc=0; porta.3=0; // bring chip select low to start adc. adc.7=portb.0; //load the most significant bit of adc. clk(); //send clock pulse to get the next adc bit. adc.6=portb.0; //load it onto the next significant bit. clk(); // & so on until the last adc bit. adc.5=portb.0; clk(); adc.4=portb.0; clk(); adc.3=portb.0; clk(); adc.2=portb.0; clk(); adc.1=portb.0; clk(); adc.0=portb.0; clk(); porta.3=1; } void clk(void) //The clock routine. { porta.4=1; //Make porta.4 high. porta.4=0; //Make porta.4 low. } void seven_segment1(void) //seven_segment1 routine. { unsigned char b0; //b0 as for loop counter. unsigned char tens; //holds the tens value to be displayed unsigned char units; //holds the units value. tens=temperature/10; //find the tens value. units=temperature%10; //find the units value. for(b0=0;b0<250;b0++) //loop it 250 times to see. { portb=get_value1(tens); //place the segment value of tens on portb porta.0=1; //turn on transistor(H). delay_ms(1); //keep it on for 1ms. porta.0=0; //turn off transistor(H). portb=get_value1(units); //place the segment value of units. porta.1=1; //turn on transistor(T). delay_ms(1); //keep it on for 1ms. porta.1=0; //turn it off. portb=0xD4; //place character "C" to represent degree celsius. porta.2=1; //turn on transistor(U). delay_ms(1); //keep it on for 1ms. porta.2=0; //turn it off. } } void seven_segment2(void) //seven_segment2 routine. { unsigned char b0; //same as above with the only difference unsigned char hundreds; //in the units segment which in this case unsigned char tens; // will display the units value instead of unsigned char units; // character "C". i wish to remind you that hundreds=temperature/100; //the this display is inverted & so tens=(temperature%100)/10; //requires a diffrent set of segment units=temperature%10; //values.This we do by calling get_value2 for(b0=0;b0<250;b0++) { portb=get_value1(hundreds); porta.0=1; delay_ms(1); porta.0=0; portb=get_value1(tens); porta.1=1; delay_ms(1); porta.1=0; portb=get_value2(units); porta.2=1; delay_ms(1); porta.2=0; } } unsigned char get_value1(unsigned char x) { unsigned char segments[10]={0xDE,0x50,0xE6,0xF4,0x78,0xBC,0xBE,0x54,0xFE,0xFC}; return segments[x]; } unsigned char get_value2(unsigned char y) { unsigned char segments[10]={0xDE,0x0A,0xE6,0xAE,0x3A,0xBC,0xFC,0x8A,0xFE,0xBE}; return segments[y]; } /*Whats new in this program?See how the function serial_adc() milks out the adc value bit by bitand stores it.Twenty samples of adc values are taken and is averaged out to get amore stable read out. Try for yourself with different number of samples.You can see two different display routines. One for displaying upto 99°C& another for beyond 99°C.Since the last segment module is inverted in-order to display °C, i had to use a different look table (get_value2())to put the units value of temperature readings beyond 99.This program compiles to 338 words.You have also got 10bit serial adc chips. Try using them in your projects.Our next project will use the built in adc of the PIC microcontroller.I wish to use PIC16F72. This chip is available for less than a Dollar inmy place & so i purchased them.Try downloading its data sheet and go thro-ugh its adc specs & how to configure them.*/ PIC33.bmp pic13modified_tlc549_thermometer.bmp Edited July 26, 2013 by Pavel Quote Link to post Share on other sites
ra68gi 0 Posted January 21, 2007 Author Report Share Posted January 21, 2007 (edited) /* thermometer2.cThis project is similar to the previous thermometer project, the onlydifference is that we will be using the internal analog to digitalconverter of the PIC16F72 microcontroller.The PIC16F72 has 5 channel8 bit adc and 2k program memory.We will learn how to set the variousregisters that controls the analog to digital conversion.ANALOG-TO DIGITAL CONVERTER(A/D) MODULE OF PIC16F72.The a/d converter module has five inputs for PIC16F72. The adc allowsconversion of an analog input signal to a corresponding 8-bit digitalnumber ie. it outputs values 0-255.The analog reference voltage is soft-ware selectable to either the device's positive supply voltage(vdd)orthe voltage on the RA3/vref pin.The adc module has three registers associated with it. They are,1) a/d result register------------adres2) a/d control register0----------adcon03) a/d control register1----------adcon1Now let's see the individual registers and how to configure them.adcon0(address 0x1F)-----This information is built into your compilerand gets selected as soon as you slect the chip in the tool bar of yourIDE.adcon0 is an 8-bit control register as you all know.Let's see the functionof each of its bits & how we should set them.bit7-6........ADCS<1:0>:a/d conversion clock select bits.00=Fosc/201=Fosc/810=Fosc/3211=Frc(clock derived from the internal a/d module RC oscillator)*IN THIS PROJECT WE USE 4MHZ CRYSTAL SO WE CHOOSE Fosc/8*bit5-3........CHS<2:0>:analog channel select bits.000=channel 0,(RA0/AN0)001=channel 1,(RA1/AN1)010=channel 2,(RA2/AN2)011=channel 3,(RA3/AN3)100=Channel 4,(RA4/AN4)*IN THIS PROJECT WE CHOOSE ONLY CHANNEL 0(RA0)*bit2..........GO/DONE:a/d conversion status.First to check the status of this bit,you must set ADON bit(coming next)to 1.If ADON=1:1=a/d conversion in progress(setting this bit starts a/d conversion).0=a/d conversion completed or conversion not in progress.(this bitis automatically cleared by the hardware when the a/d conversion iscomplete).bit1...........unimplemented,read as 0.bit0...........ADON:a/d on bit.1=a/d converter is working.0=a/d converter is shut off.So in our c program we configure adcon0 asadcon0=0b01000001;adcon1:a/d control register1(address 0x9F)-----This information is builtinto your compiler and gets selected as soon as you slect the chip in thetool bar of your IDE.bits7-3........unimplented,read as 0.bits2-0........PCFG<2:0>:a/d port configuration control bits.PCFG2:PCFG0.....RA0....RA1....RA2....RA5....RA3....VREF.........000.............A........A.......A........A........A........VDD.........001.............A........A.......A........A........VREF...RA3.........010.............A........A.......A........A........A........VDD.........011.............A........A.......A........A........VREF...RA3.........100.............A........A.......D........D........A........VDD.........101.............A........A.......D........D........VREF...RA3.........11x.............D........D......D........D........D........VDDA=Analog inputD=Digital i/o.*IN THIS PROJECT WE CHOOSE RA0,RA1,RA2 PINS AS ANALOG INPUTS& RA3 AS +VREF.*So in our c program we writeadcon1=1;The adres register contains the result of the a/d conversion.When a/dconversion is complete,the result is loaded into the adres register,and the GO/DONE bit(adcon0.2)is cleared.PIC16F72 is a 28 pin chip with porta,portb,portc.In this project ihave used portc pins to drive the transistor(base) connectedto each of the units,tens & hundreds segment ie. to demultiplex data.The segments are connected to portb, similar to our previous project.The units segment like in the previous project is inverted to display"°C".Porta is set for analog mode.The LM35's signal out pin is connected topin RA0.Pin RA3 is connected to the center arm of a 5k pot. The othertwo ends of the pot are connected to vdd and ground respectively.Circuit Connections:PIC16F72pin1- MCLR pin to +5v via 4.7K resistor.pin9-10 4mhz crystal(across pin 9 & 10).connect 22pf capacitors( between pin9 & gnd, pin10 & gnd).pin21-RB0-connect to segment decimal point via 470 ohms.pin22-RB1-connect to segment "e" of the 7-segment display via 470 ohms.pin23-RB2-connect to segment "a" of the 7-segment display via 470 ohms.pin24-RB3-connect to segment "f" of the 7-segment display via 470 ohms.pin25-RB4-connect to segment "c" of the 7-segment display via 470 ohms.pin26-RB5-connect to segment "g" of the 7-segment display via 470 ohms.pin27-RB6-connect to segment "b" of the 7-segment display via 470 ohms.pin28-RB7-connect to segment "d" of the 7-segment display via 470 ohms.pin20-connect to +5v supply.pin8- connect to ground.Base of transistor(U) is connected to RC2(pin13 of micro) via 2.2k resistor.Base of transistor(T) is connected to RC1(pin12 of micro) via 2.2k resistor.Base of transistor(H) is connected to RC0(pin11 of micro) via 2.2k resistor.CONNECTING TEMPERATURE SENSOR LM35 TO PIC16F72.If LM35 is in TO92 pack,then its pin1 is +5 & pin3 is ground.Please seedata sheet.Pin 2 of LM35 is connected to RA0(pin2)of 16F72.FIXING THE REFERENCE VOLTAGE.We have programmed RA3 to be the +vref pin.So connect the centre arm of a 5k pot to the RA3 pin(pin5). The othertwo ends of the pot are connected to vdd and ground respectively.Using a precision multimeter,adjust the 5k pot connected to the +vref pinso that the voltage between RA3 to around is 2.55volts.This will make cal-culations much easy for us.Now when the analog signal input is 2.55volts the adc will out decimal 255.Our step resolution becomes 2.55 divided by 255, which is 0.01volts.ie.forevery increment of 0.01volt in the analog signal the adc value will incrementby one.Our temperature sensor can be used in the region of 0 to 150°C. At 0°C theanalog output is roughly zero and at 150°C its 150mv.The output varies line-arly by 10mv for an increment of 1°C.Seven segment modules.The segment pins of the three 7-segment module must be paralled,ie. all"a" segments are connected together & all "b" segments are connected &so on.Let's call them the units digit,tens digit & hundreds digit.Common cathode of units digit is connected to transistor(U)'s collector.Emitter of transistor(U) is connected to ground.Base of transistor(U) is connected to RC2(pin13 of micro) via 2.2k resistor.Common cathode of tens digit is connected to transistor(T)'s collector.Emitter of transistor(T) is connected to ground.Base of transistor(T) is connected to RC1(pin12 of micro) via 2.2k resistor.Common cathode of hundreds digit is connected to transistor(H)'s collector.Emitter of transistor(H) is connected to ground.Base of transistor(H) is connected to RC0(pin11 of micro) via 2.2k resistor.Transistor type-BC 547 NPN.*/ #include <system.h> #pragma CLOCK_FREQ 4000000 // config clock to 4mhz. // Set configuration fuse. #pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _CP_OFF & _PWRTE_OFF //A function to get adc value from pic's built-in adc. void a_d(void); //A function for 7-segment display to display "0°C-99°C". void seven_segment1(void); //A function for 7-segment display to dispaly "0-150". void seven_segment2(void); //A function to get segment values for hundreds & tens. unsigned char get_value1(unsigned char x); //A function to get segments value for units. //unit's display module is inverted so as to display degree celsius, //with decimal point at top of the display. unsigned char get_value2(unsigned char y); /*Variable adc is made global for easy access, which is used in main().*/ unsigned char adc; //Variable temperature is made global for easy access. unsigned char temperature; void main() { trisa=255; //set porta as input. trisb=0; //set all portb pins as output. trisc=0; //set all portc pins as output pins. portc=0; //make all portc pins low. portb=0; //zero all portb pins. /* make RA0,RA1,RA2 pins as analog inputs & RA3 as +ref.*/ adcon1=1; /*choose Fosc/8,RA0/AN0 as channel(0),go/done=0,adon=1.*/ adcon0=0b01000001; unsigned int sample; //sample var holds the adc sample value. unsigned char b0; //for loop var. while( 1 ) //Infinite loop. { sample=0; //initialize the sample to zero. for(b0=0;b0<20;b0++) //take 20 adc samples. { a_d(); //call function a_d(). sample += adc; } temperature=sample/20; //take average of 20 samples. if(temperature<99) //call seven_segment1 if temperature is less seven_segment1(); //than 99 else call seven_segment2. else seven_segment2(); } } void a_d(void) //adc routine. { adc=0; adcon0.2=1; //start ad conversion. while(adcon0.2==1) //check if conversion is complete. { } adc=adres; //if conversion is over, load adc value. } void seven_segment1(void) //seven_segment1 routine. { unsigned char b0; //b0 as for loop counter. unsigned char tens; //holds the tens value to be displayed unsigned char units; //holds the units value. tens=temperature/10; //find the tens value. units=temperature%10; //find the units value. for(b0=0;b0<250;b0++) //loop it 250 times to see. { portb=get_value1(tens); //place the segment value of tens on portb portc.0=1; //turn on transistor(H). delay_ms(1); //keep it on for 1ms. portc.0=0; //turn off transistor(H). portb=get_value1(units); //place the segment value of units. portc.1=1; //turn on transistor(T). delay_ms(1); //keep it on for 1ms. portc.1=0; //turn it off. portb=0xD5; //place character "°C" to represent degree celsius. portc.2=1; //turn on transistor(U). delay_ms(1); //keep it on for 1ms. portc.2=0; //turn it off. } } void seven_segment2(void) //seven_segment2 routine. { unsigned char b0; //same as above with the only difference unsigned char hundreds; //in the units segment which in this case unsigned char tens; // will display the units value instead of unsigned char units; // character "C". i wish to remind you that hundreds=temperature/100; //the this display is inverted & so tens=(temperature%100)/10; //requires a diffrent set of segment units=temperature%10; //values.This we do by calling get_value2 for(b0=0;b0<250;b0++) { portb=get_value1(hundreds); portc.0=1; delay_ms(1); portc.0=0; portb=get_value1(tens); portc.1=1; delay_ms(1); portc.1=0; portb=get_value2(units); portc.2=1; delay_ms(1); portc.2=0; } } unsigned char get_value1(unsigned char x) { unsigned char segments[10]={0xDE,0x50,0xE6,0xF4,0x78,0xBC,0xBE,0x54,0xFE,0xFC}; return segments[x]; } unsigned char get_value2(unsigned char y) { unsigned char segments[10]={0xDE,0x0A,0xE6,0xAE,0x3A,0xBC,0xFC,0x8A,0xFE,0xBE}; return segments[y]; } /* In this project we configured the hardware registers of the A to Dconverter.See how we do a software polling of pin adcon0.2 to see ifa/d conversion is complete.If we want we can even configure the adc interrupt bits.So thatonce the a/d conversion is complete an interrupt is generated.The bits associated with this interrupt areclear ADIF bitset ADIE bitset GIE bit.Try doing this & have lots of fun.*/ Edited July 26, 2013 by Pavel Quote Link to post Share on other sites
ra68gi 0 Posted March 9, 2007 Author Report Share Posted March 9, 2007 (edited) /* timer0_interrupt.c In this project we make the timer0 of the PIC microcontroller to measure a time interval of 250 micro seconds.The timer0(tmr0) is made to generate an interrupt every 250us.We then count 4000 of such interrupts to get a precise 1 second interval. We change the state of an LED once we finish counting 4000. So the LED will be lit for a duration of 1sec & off for the next 1sec & it keeps switching on & off. The idea behind this project is to help you understand as to how the tmr0 can be set to generate an accurate 1sec interval.This code will turn out to be the building block of our next project a digital clock, which will display hours,minutes & seconds. What's an interrupt? Anything that interrupts our normal course of activity (or program) can be considered an interrupt.Suppose we are doing our normal house hold activity of cleaning our house & all of a sudden we hear the calling bell ringing, you can then consider the ringing of the bell as an interrupt. What do we do? We immediately stop the current activity of cleaning & attend to the person who rang the calling bell. In a similar fashion the main program in the microcontroller gets interrupted by what we call hardware interrupts. Note,here the word main in the main program is not suggestive of the importance of the program. Hardware interrupts will cause the microcontroller to halt the execution of the current code & jump to a location in the program memory where the more important task or program also called interrupt service routine (ISR) is stored.After executing the ISR it gets back to the main program from where it had abruptly left. When an interrupt occurs the first thing the microcontroller does before it jumps to the ISR is to save the contents of the files.ie. the status register, w register,port setting etc so that when it returns back from the ISR it can restore these settings & carry on with its actvity from the setting in which it had left. Interrupt sources on PIC16F84 1.External interrupt RB0/INT pin. 2.TMR0 overflow interrupt. 3.PORTB change interrupts(pins RB7:RB4) 4.Data EEPROM write complete interrupt See the microcontroller data sheet for more information on interrupts. In our project we will be using the tmr0 interrupt. Now i will show you how to set the tmr0 interrupt. The timer0 module. The timer0 module timer/counter has the following fearutes: 1.8-bit timer/counter 2.Readable & writable 3.Internal or external clock select 4.Edge select for external clock 5.8-bit software programmable prescaler 6.Interrupt-on-overflow from 255 to 0 First we need to know the various registers associated with tmr0. They are.. 1.tmr0 module register This register is a counter that can display values 0 to 255 so its a 8bit counter.If the prescaler assignment bit(in the option register) is set to 1 & t0cs( tmr0 clock source select bit) bit in the option register is set to 0 then tmr0 counter value increments itself every instruction cycle. 2.option register(option_reg)(address 0x81) note:In the older chips, data sheet call them option_reg, but in the new ones they call it just option.The SB compiler recognizes only option_reg. The names of these register can be seen from the .h files in the include folder,which in itself are in the SB folder. In this project we are only concerned with the t0cs(tmr0 clock source select bit) & the psa(prescaler assignment bit) of the option_reg. bit5....t0cs: tmr0 clock source select bit 1 = transition on RA4/TOCKI pin 0 = internal instruction cycle clock.(we will use this mode for our proj- ect, so make option_reg.5=0) bit3....psa: prescaler assignment bit 1 = prescaler assigned to WDT. ( we use this mode for our project) 0 = prescaler assigned to tmr0 module so we make option_reg.3=1 bit2-0....ps2:ps0: prescaler rate select bits I have made all three bits as 0 & have chosen 1:1 for the WDT. This setting is not going to be important to us since we have disabled the WDT through our pragma directive(configuration word). To learn more about prescaler see data sheet. Now our option_reg is configured to the value.. option_reg = 0b00001000; //or option_reg=8; 3.intcon register(interrupt controller register)(address 0x0b)(its also mirrored onto all other banks of the chip). Here we are only concerned with three control bits they are.. bit7....gie: global interrupt enable bit 1 = enable all unmasked interrupts.(we choose this bit to enable interrupt) 0 = disable all interrupts. bit5....toie: tmr0 overflow interrupt enable bit. bit2....t0if: tmr0 overflow interrupt flag bit. 1 = tmr0 register has overflowed.(we clear this flag in the ISR so that we can enable the next interrupt) 0 = tmr0 has not overflowed. Circuit connection: Device PIC16F84 pin4- MCLR pin to +5v via 4.7K resistor pin15-16 4mhz crystal(across pin 15 & 16) connect 22pf capacitors( between pin15 & gnd, pin16 & gnd) pin6-RB0-connect LED to pin6 via 470 ohms. Cathode of LED to gnd. Buid this program & step thro' the code using the source boost simulator. See how the micro spends most of its time in while loop and jumps to the ISR every time the tmr0 rolls over from 255 to 0.Since we have connected a 4MHz crystal the internal clock frequency is Fosc/4 = 1MHz & so the tmr0 increments its self every instuction cycle which in our case is 1us.We have set the tmr0 in such a way as to count 250us for an interrupt to occur.This we do by writing tmr0+=9; in the ISR.We count 4000 of such interrupts which will result in 4000*250us = 1000000us or 1second and we change the state of the led to indicate this. */ #include <system.h> // Set clock frequency to 4MHz. #pragma CLOCK_FREQ 4000000 //set configuration fuse. #pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _CP_OFF & _PWRTE_OFF /*Interrupt service routine (ISR).On timer0 interrupt, program will jump to this code location. */ void interrupt( void ) { unsigned char tick; unsigned char tick1; // writing 9 onto tmr0 will generate interrupts at 250us interval. tmr0 +=9; tick++; //increment variable tick. if(tick>19) //if tick equals 20, increment tick1 & reset tick. { tick=0; tick1++; //if tick1 equals 200,we have counted 4000 ticks if(tick1>199) //in total, which equals 1 second(4000*250us). { tick1=0; //reset tick1. portb.0=~portb.0; //toggle the led to show that 1sec has elapsed. } } intcon.2=0; //clear TMR0 overflow flag } // The main code configures the option & intcon registers. void main() { trisb = 0; //configure port B portb = 0; //clear port B option_reg = 8; //no prescaler & start tmr0 // enable interrupts intcon.5=1; //enable tmr0 overflow interrupt intcon.7=1; //enable global interrupt /*simply write 6 to tmr0 counter value.This line will not alter the accuracy of the clock, so it can be removed if you wish. */ tmr0=6; while( 1 ); //do nothing & wait for tmr0 interrupt. } /* To check the accuracy of the timer interrupt code we have written you can use the stop watch in the mplab simulator. For this you need to integrate the boostC compiler with mplab ide. Look into the BoostC com- iler reference manual for information on integrating with mplab. */ Edited July 26, 2013 by Pavel Quote Link to post Share on other sites
ra68gi 0 Posted April 3, 2007 Author Report Share Posted April 3, 2007 (edited) /* digital_clock.cNow that you know how to configure the timer0 to generate accuratetime interval, let's construct a digital clock that will displayhours, minutes and seconds on six led segment display. We will usethe same common cathode segment used in our earlier projects. We willuse PIC16F72 for this project because it has 22 i/o pins. The mainfeatures of this project at a glance.a)Uses tmr0 for time keeping.b)We use PIC16F72c)4MHZ crystal frequencyd)six no. of 7-segment display, to display hours, minutes & seconds.e)two button switch to set hours and minutes.f)six BC547(NPN)transistors to demultiplex the data bus(portb).In the previous project i had explained about interrupts by comparingthe similarity in real world like the example of calling bell ringing& that of microcontrollers hardware interrupts. Let's apply the callingbell example to our digital clock. If you look at the program below,you will see that the microcontroller spends most of its time firingthe transistors to display the hours, minutes & seconds segments, thisis similar to us doing our household activity. But in the backgroundthe tmr0 counter keeps ticking without any of our intervention. In factwe are not even aware that the tmr0 is ticking until an interrupt occurswhen it rolls over from 255 to 0.And when the interrupt occurs we quicklyupdate the tick, tick1, seconds, minutes, hours in the ISR and then getback to doing our usual work of lighting the segments. The interruptgenerated by tmr0 can be considered similar to the ringing of the callingbell.This code may initially look more convoluted with the functionsec(), min(),hrs(),but you will soon see how advantageous it wouldbe to call them only when the data gets updated & rest of the timewe simply display the old value of data. By doing this we get aflicker free display.I had made this circuit on a bread board. Since the segments are dirctlyconnected to the PIC via 150 ohms without any driver and since multiplexingsix segments will reduce the mean led current, you will see that the segmentsare not very bright, but i found it excellent when seen with a red filter.Circuit connection:pin20- VDD pin to +5v.pin8- VSS pin to 0v.pin1- MCLR pin to +5v via 4.7K resistorpin9-10 4mhz crystal(across pin 9 & 10)connect 22pf capacitors( between pin9 & gnd, pin10 & gnd)pin21-RB0-no connection.Seven segment modules.The segment pins of the six 7-segment module must be paralled,ie. all"a" segments are connected together & all "b" segments are connected &so on.pin22-RB1-connect to segment "e" of the 7-segment display via 150 ohms.pin23-RB2-connect to segment "a" of the 7-segment display via 150 ohms.pin24-RB3-connect to segment "f" of the 7-segment display via 150 ohms.pin25-RB4-connect to segment "c" of the 7-segment display via 150 ohms.pin26-RB5-connect to segment "g" of the 7-segment display via 150 ohms.pin27-RB6-connect to segment "b" of the 7-segment display via 150 ohms.pin28-RB7-connect to segment "d" of the 7-segment display via 150 ohms.pin11-RC0-to base of Q1 driving the units segment of seconds via 10k.pin12-RC1-to base of Q2 driving the tens segment of seconds via 10k.pin13-RC2-to base of Q3 driving the units segment of minutes via 10k.pin14-RC3-to base of Q4 driving the tens segment of seconds via 10k.pin15-RC4-to base of Q5 driving the units segment of hours via 10k.pin16-RC5-to base of Q6 driving the tens segment of hours via 10k.collector of Q1 is connected to cc(common cathode)of units segment ofseconds digit & its Emitter to ground.collector of Q2 is connected to cc of tens segment of seconds digit & itsEmitter to ground.collector of Q3 is connected to cc of units segment of minutes digit & itsEmitter to ground.collector of Q4 is connected to cc of tens segment of minutes digit & itsEmitter to ground.collector of Q5 is connected to cc of units segment of hours digit & itsEmitter to ground.collector of Q6 is connected to cc of tens segment of hours digit & itsEmitter to ground.Q1,Q2,Q3,Q4,Q5,Q6- BC547 NPN transistors.button switch connection:button switches will generally have two pins which are normally open andon pressing the button gets closed.Connect a 10k resistor to +5v. on the other end of the resitor is connctedboth to PIC micros input pin & one of the pins of the button switch. Theother pin of the button switch is grounded.When the button switch is NOT pressed the PIC micro will read a high & whenpressed it will read a low.pin17-RC6 to button switch1 and a pullup resistor of 10k connected to +5v.pin18-RC7 to button switch2 and a pullup resistor of 10k connected to +5v.pressing button switch1 will increment minutes.pressing button switch2 will increment hours.How to set the clock?You have two button switches connected to portc.6 & postc.7. As soonas you power on the circuit you will see the hours and minutes segementsflash 00 alternately. Now pressing the hours button(portc.7)will incrementthe hours. As soon as it reaches the right hours, stop pressing or releasethe button. next press the minutes button(portc.6) & set it similarly. Onceboth value are set press both these buttons(portc.6 & portc.7) simultaneously.It will immediately jump to the clock routine and the clock will start totick( you can see the seconds segment increment).*/ #include <system.h> // Set configuration word #pragma CLOCK_FREQ 4000000 #pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _CP_OFF & _PWRTE_OFF /*all of the below variables are made global for easy access in our functions.*/ bit updatesec = 0; bit updatemin = 0; bit updatehrs = 0; unsigned char seconds = 0; unsigned char minutes = 0; unsigned char hours = 0; unsigned char unitsec = 0; unsigned char tensec = 0; unsigned char unitmin = 0; unsigned char tenmin = 0; unsigned char unithrs = 0; unsigned char tenhrs = 0; //timer0 interrupt service routine. void interrupt( void ) { unsigned char tick; unsigned char tick1; tmr0 +=9; // add 9 to generate interrupt every 250us. tick++; if(tick>19) { tick=0; tick1++; if(tick1>199) { tick1=0; seconds++; //a flag to indicate that seconds has been updated updatesec=1; if(seconds>59) { seconds=0; minutes++; //a flag to indicate that minutes has been updated updatemin=1; if(minutes>59) { minutes=0; hours++; //a flag to indicate that hours has been updated updatehrs=1; if(hours>23) { hours=0; } } } } } intcon.2=0; //clear TMR0 overflow flag } //function to get segment values. unsigned char get_value(unsigned char y) { unsigned char segments[10]={0xDE,0x50,0xE6,0xF4,0x78,0xBC,0xBE,0x54,0xFE,0xFC}; return segments[y]; } //a function to get tens & units place for seconds. void sec(void) { tensec = get_value(seconds/10); unitsec= get_value(seconds%10); } //a function to get tens & units place for minutes. void min(void) { tenmin = get_value(minutes/10); unitmin = get_value(minutes%10); } //a function to get tens & units place for hours. void hrs(void) { tenhrs = get_value(hours/10); unithrs = get_value(hours%10); } //main program starts here. void main() { unsigned char a; trisb = 0; //configure port B portb = 0; //clear port B //portc.7 & portc.6 are made as inputs & the rest as outputs. trisc = 0b11000000; portc = 0; while(1) { //set time by pressing the appropriate button. //if both switches are closed start clock. if((portc.6 == 0) && (portc.7 == 0)) { goto clock; } //if switch in portc.6 is pressed increment minutes if(portc.6 == 0) { minutes++; if(minutes>59) { minutes=0; } } //call function min() to get units & tens value for minutes. min(); for(a=0;a<250;a++) { portb = unitmin; portc.2=1; delay_ms(2); portc.2=0; portb = tenmin; portc.3=1; delay_ms(2); portc.3=0; } //again check for both switches to be closed. if((portc.6 == 0) && (portc.7 == 0)) { goto clock; } //if switch in portc.7 is pressed increment hours. if(portc.7 == 0) { hours++; if(hours>23) { hours=0; } } //call function min() to get units & tens value for hours. hrs(); for(a=0;a<250;a++) { portb = unithrs; portc.4=1; delay_ms(2); portc.4=0; portb = tenhrs; portc.5=1; delay_ms(2); portc.5=0; } if((portc.6 == 0) && (portc.7 == 0)) { goto clock; } } //start clock clock: updatesec=1; updatemin=1; updatehrs=1; //assign prescaler to wdt & start tmr0. option_reg = 8; // enable interrupts intcon.5=1; //enable tmr0 overflow interrupt intcon.7=1; //enable global interrupt //set tmr0 to genterate interrupt at every 250us. tmr0=6; while( 1 ) //endless loop { if(updatesec==1) //check for update flag,if set { updatesec=0; //clear the flag & call function sec sec(); // to get units & tens value } //for seconds. for(a=0;a<60;a++) { portb = unitsec; portc.0=1; } portc.0=0; for(a=0;a<60;a++) { portb = tensec; portc.1=1; } portc.1=0; if(updatemin==1) { updatemin=0; min(); } for(a=0;a<60;a++) { portb = unitmin; portc.2=1; } portc.2=0; for(a=0;a<60;a++) { portb = tenmin; portc.3=1; } portc.3=0; if(updatehrs==1) { updatehrs=0; hrs(); } for(a=0;a<60;a++) { portb = unithrs; portc.4=1; } portc.4=0; for(a=0;a<60;a++) { portb = tenhrs; portc.5=1; } portc.5=0; } } /*In the ISR see how the tick, tick1 gets incremented. Also see howthe seconds minutes and hours gets incremented. See how these updateflag bits are set and cleared.This code compiles to 397 words*/ Edited July 26, 2013 by Pavel Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.