Jump to content

ra68gi

EstablishedMember
  • Content Count

    229
  • Joined

  • Last visited

Everything posted by ra68gi

  1. You can also try this.. unsigned int x = 0xf0f1; unsigned char xlo; unsigned char xhi; xlo = x; xhi = x / 256; you can check it with the simulator.
  2. Less software required, you are not tieing up the processor to some bit bashing routine. Make cyclic buffers for your RX and TX data and service in interrupt time. <{POST_SNAPBACK}> Hi Picxie, I have not used the hardware uart so far. I suppose Huart will take less code space compared to Suart. Picxie, can you explain the second advantage regarding servicing in interrut time with any example. Thanks, Raghunathan.
  3. Hi guys, Can any one tell me the advantages of using hardware uart over software uart? Raghunathan.
  4. Yes, for measuring frequency in the range you have mentioned its fine, but if your frequency is less then 15 hz then i think my technique will be better. Infact you can get very good accuracy upto 300hz with my method. Trying to use the highest possible clock frequency will result in best accuracy. Make sure that the time period of your signal is larger then the time taken to attend to the ISR.If a second capture pulse occurs before you read the value from ccpr, the old captured value is over written with the new captured value, resulting in wrong frequency value. Regards Raghunathan.
  5. OrmatEli, Why don't you start a new thread on this topic? Don't you think this thread has got a bit too old & long? In the capture mode the 16 bit value of the timer1 gets latched to the ccpr2h & ccpr2l registers every time a ccp pin senses a pulse. When do you intend to start the timer1? in the first capture interrupt or do you just wish to keep it running right from the beginning? How will you know if the timer1 has over flowed or not ? are you setting the timer1 interrupt also? I had written code for a similar project. It lacks explaination. but if you follow it closely you will understand it. I am yet to test it on a bread board. See how i use the tmr1 register values directly instead of the ccp register values. I have done this because it takes some time " T " to save the important registers before it enters to execute the ISR code. Since this time interval "T" is more or less equal every time it enters the ISR, so I decided to take the timer1 value to avoid any error. See how in the first ccp interrupt the tmr1 is reset & in the second ccp interrupt, the tmr1 is switched off and its registers read. I have also unmasked the tmr1 interrupt & i count the tmr1 ticks which i multiply with 65536. The total value is then found out by adding the above value with the tmr1 counter(tmr1l,tmr1h), from which the frequency is determined. see this thread..engine RPM using PIC16F72 See if this code is useful. Regards Raghunathan.
  6. Hi Pavel, Generally the libc.lib gets automatically linked & i have never added exept for the fp lib on my SB6.6. Then why is this happening? Does he have to add the libc.lib for every project he makes?
  7. I am sorry. I got a bit confused with the ccp module. Yes as a timer the settings for the tmr2 module looks fine. But try t2con = 0B01111111; & disable the ccp module. Regards Raghunathan.
  8. Hello emte, We can't test it until you give us your code. I can see you have used the period register(pr2) & so i assume you are using the tmr2 in the PWM mode. Have you configured which mode you are using in the ccpcon1 register in your main()? I am talking with respect to 16F pics but that should hold good even for pic18. Also bit 7 of t2con is unimplemented & the data sheet suggests that you write it as 0 instead of 1. make it.. t2con = 0b01111111; I assume you are using 1:16 post scaler & prescaler. Regards Raghunathan.
  9. 60% of your project is already here...programming pic micro in BoostC for beginners. Atleast for the rest of the project you need to make some effort. Use my code as a template & make adjustments by adding serial routines. You can use the same wiring circuit details i have mentioned. I did it on a bread board. You too can do the same. Good luck! Regards Raghunathan.
  10. Did you first check it up on a hyper-terminal? Regards Raghunathan
  11. Dave, i have version 6.6. In the above code example you have not use sprintf32 function, which is used for long. I think thats available only in version 6.7. Regards Raghunathan.
  12. Dave i got lprintf("%u",x); to work upto 65535. but i was not successful in converting it into string using sprintf32 & displaying it using lprintf. I first tried lprintf (sprintf32(x)); & it didn't work. Can you please show me how its done. <{POST_SNAPBACK}> extract from the BoostC compiler user manual: unsigned char sprintf32( char* buffer, const char *format, unsigned long val ) Outputs a numerical value to a string in the specified format. The buffer must be long enough to hold the result. Only one numerical value can be output at a time. Declared in stdio.h. This function operates as sprintf, but it handles a 32bit value. It also supports the “%l” radix specifier, which is handled the same as “%d”. long x = 123456789; char buf[ 10 ]; // must be long enough to hold the max number of digits we will get plus null terminator sprintf( buf, "%d", x ); lprintf( buf ); Regards Dave <{POST_SNAPBACK}> Thanks very much Dave. The mistake is mine because i was searching an earlier version of the user manual. I will immediately take print of the current version. Regards Raghunathan.
  13. Dave i got lprintf("%u",x); to work upto 65535. but i was not successful in converting it into string using sprintf32 & displaying it using lprintf. I first tried lprintf (sprintf32(x)); & it didn't work. Can you please show me how its done. Regards Raghunathan.
  14. Use: lprintf("%u",x); Or use sprintf32 to convert number to a string and then display using lprintf. Regards Dave <{POST_SNAPBACK}> Thanks Dave, I searched the SB user's manual but didn't find sprintf32. is it written this way... lprintf (sprintf32(x)); ? Raghunathan.
  15. Hi guys, How do i display values larger than 32767 on LCD . beyond this value the lcd displays negative numbers & it starts to wrap(+32767 to-32768). I am using the boostC lcd command lprintf("%d",x); I had declared x as unsigned int. I would like it to display upto 65535 or probably a long variable. Regards Raghunathan.
  16. Here is a example for a flow control regulator. Regards /Jörgen void DFlowPID(void) { float e; // The controller error float up; // Output signals float awc; // Anti windup compensation float IState; // I state (integrated error) float DState; // D state (last error) short Ticks; // Ticks short ScanRate; // Scan rate ScanRate = XXX; Ticks = 0; // Check if time to run if ((++Ticks % ScanRate) != 0) return; // Get current control parameters DFlowCnt.Kp = Conf.DFlowCntKp; DFlowCnt.Ti = Conf.DFlowCntTi; DFlowCnt.Td = Conf.DFlowCntTd; // Get Time DFlowCnt.Time = CLOCK; // Read PV DFlowCnt.PV = AIn(AIX); // Calculate the error e = DFlowCnt.SP - DFlowCnt.PV; e *= DFlowCnt.Kp; // P-part up = e; up += (e-DState)*DFlowCnt.Td/Conf.DFlowCnth; // D-part up += IState; // I-part // Limit output from controller DFlowCnt.Output = up; if (DFlowCnt.Output > Conf.DFlowCntUMax) DFlowCnt.Output = Conf.DFlowCntUMax; else if (DFlowCnt.Output < Conf.DFlowCntUMin) DFlowCnt.Output = Conf.DFlowCntUMin; if (!DFlowCnt.Active) DFlowCnt.Output = ReadAOut(AOX); awc = up - DFlowCnt.Output; // Update states DState = e; if (DFlowCnt.Ti > 0.01) IState = e * Conf.DFlowCnth / DFlowCnt.Ti + IState - awc; else IState = 0.0; if (DFlowCnt.Active) AOut(AOX, DFlowCnt.Output); return; } <{POST_SNAPBACK}> Hi sdujolo, I am very interested in you project. Can you explain the whole project in detail, like what flow meter you are using & what are its outputs & other detail about the flow meter, the proportional valve you control etc ? It will also be nice if you can elobrate on how the code functions. I know thats going to take a lot of time. But i would really appreciate if you can explain like you would to a beginner. Regards Raghunathan.
  17. Are you talking about proportional, integral , derivative used in feed back control systems? Rigt now i am working on a project with feed back control using PIC. If you are interested i will post it & we can discuss. Regards, Raghunathan.
  18. If you are looking for an example of multiple interrupts, i can give you an example i am right now working on. Its an frequency/RPM meter. It measures the time interval between two pulses of a optical or proximity sensor. There are two interrupt generating source, they are timer1 over flow flag & ccp capture flag. An LCD is use to display the RPM. I am using PIC16F72. I have tested it on the SB simulator & it works fine. code.. #include <system.h> #include "lcd_driver.h" // Set clock frequency to 4MHz. #pragma CLOCK_FREQ 4000000 //set configuration fuse. #pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _CP_OFF & _PWRTE_OFF #define LCD_ARGS 2, /* Interface type: mode 0 = 8bit, 1 = 4bit(low nibble), 2 = 4bit(upper nibble) */ \ 0, /* Use busy signal: 1 = use busy, 0 = use time delays */\ PORTC, TRISC, /* Data port and data port tris register */ \ PORTB, TRISB, /* Control port and control port tris register */ \ 2, /* Bit number of control port is connected to RS */ \ 7, /* Bit number of control port is connected to RW */ \ 3 /* Bit number of control port is connected to Enable */ unsigned char tick; unsigned int value1; bit frequency_update_flag; /*Interrupt service routine (ISR).On timer1 overflow or ccp pulse capture program will jump to this code location. */ void interrupt( void ) { unsigned char capture_count; if(pir1.0 == 1) //tmr1 overflow flag(tmr1if). { tick++; // count the number of tmr1 interrupts. if(tick > 15) //if frequency is too low { ccp1con = 0; t1con = 0; tmr1l = 0; tmr1h = 0; tick = 0; value1 = 0; capture_count = 0; frequency_update_flag = 1; } pir1.0 = 0; //clear tmr1if } else if(pir1.2 == 1) //ccp interrupt flag(ccp1if). { capture_count ++; if(capture_count > 1) { t1con = 0; ccp1con = 0; //switch off capture mode. value1 = tmr1l + (tmr1h * 256); capture_count = 0; frequency_update_flag = 1; } else //The first ccp interrupt resets tmr1 & starts it. { t1con = 0; tick = 0; tmr1l = 0; tmr1h = 0; t1con = 1; } pir1.2 = 0; //clear ccp flag. } } /* function to display RPM. */ void display (int x) { lcd_clear(); lprintf("%d",x); delay_s(2); } /* The main code configures the intcon, pie1, t1con & ccpcon1 registers.*/ void main() { trisb = 0; //configure port B portb = 0; //clear port B trisc = 0b00000100; //RC2/ccp1 pin as input. // enable interrupts: interrupt control register. intcon.6=1; //enable peripheral interrupts intcon.7=1; //enable global interrupt //peripheral interrupt enable register 1. pie1.2 = 1; //enable ccp1 interrupt. pie1.0 = 1; //enables tmr1 overflow interrupt. /* timer1 control register: t1ckps1:t1ckps0: input prescaler bit5-4.....select 00= 1:1 prescale tmr1cs: timer1 clock source select bit. bit1...select 0 = internal clock (Fosc/4) tmr1on: timer1 on bit bit0......1 = enable timer1 bit0......0 = stop timer1 we are not concerned about the other bits of t1con. */ //set t1con t1con = 0b00000000; //tmr1 not yet enabled. /*ccpcon1: capture/compare/pwm control register1. bit3-0.....ccpxm3:ccpxm0: ccpx mode select bits. we will use... 0100 = capture mode, every falling edge. 0101 = capture mode, every rising edge. we can choose any one of the above mode. but we will use 0100 in our project. */ /* print " RPM = " in the first line of LCD */ lcd_setup(); lcd_clear(); lprintf(" RPM = "); lcd_gotoxy(0,1); unsigned long count; while (1) { frequency_update_flag = 0; ccp1con = 0b00000101; //set capture mode. t1con = 1; //start timer1. while (frequency_update_flag == 0); count = (tick*65536) + value1; if(count == 0) //if frequency is too low. { display(count); } else { count = 100000000/count; //to find frequency. count *= 60; //for cycles per minute. count /= 100; //divide by 100 to get actual RPM. display(count); } } } see if its useful. Regards Raghunathan.
  19. Thanks guys, I will start working on this project & will inform you of its progress. Reagards Raghunathan.
  20. Hi cac001, I am not having doubt on the communication part. My doubt is about the total bit weight and how i should calculate the total adc value. In the data sheet they say that the bit weight is in two's compliment. You say that i can make the choice. Then can I store the bit value in long var & use the same binary weight to the bits instead of two's compliment ? If i were to use the two's compliment, then i need to multiply the msb with 1/2, the next significant bit with 1/4 and so on, which will be very cumbersome. Will it not alter the precision in calculation if i used the binary bit weight ? I want to write the code in boostC, so please suggest. Actally 16bit precision is enough for me. Suppose i truncate rest of the bits will there be an error between using the binary weight and that of two's compliment weight? At some stage i might have to use fp lib in the calculation i suppose. Thanks for the link, i have down loaded the c code example. Regards Raghunathan.
  21. Hi friends, I want to interface cirrus logic's cs5550 analog to digital converter to the PIC. The output adc result register is a 24 bit one. The most significant bit is the sign bit which will indicate whether the bit is + or -. The rest of the bit values are in two's compliment notation. ie. 1/2, 1/4, 1/8, 1/16, 1/32,.........& so on until the least significant bit. Is there any way in BoostC that i can load the value onto a variable at one go instead of having to multiply these value and add them up ? Like say for binary we write 0bxxxxxxxx, for hex its 0xXX . Those of you who have already worked with this chip, please be generous to spare a few minutes writing your experience and knowledge. I am connecting the adc to loadcell. Regards Raghunathan.
  22. Being instigated by an earlier post on this topic i set out to write a program for this project. I have used the capture module of PIC16F72 to capture the pulses from any sensor( optical or proximity ) connected to the engine/motor. Its connected to the ccp pin RC2. I have used the timer1 to measure the time T elapsed between two pulses from which i calculate the frequency(1/T). The RPM is calculated & displayed on a LCD. This will display the instantaneous RPM value only. I have not done any averaging to keep coding simple. This project will be posted on my thread once i have tested it fully. Before i start wiring i have a few doubts. In the code below i have used data type long for variable count & made calculations. Should i use optimization directive here? if so please show me how & where i should insert the direcitve. again in the display function you will see that i have made the argument as integer variable(x). But we will be entering the long variable "count" as the argument . I have done so because the resultant value in count is only an integer value. Do i have to change the x in display function as long? If you find any other fault please do report. code.. #include <system.h> #include "lcd_driver.h" // Set clock frequency to 4MHz. #pragma CLOCK_FREQ 4000000 //set configuration fuse. #pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _CP_OFF & _PWRTE_OFF #define LCD_ARGS 2, /* Interface type: mode 0 = 8bit, 1 = 4bit(low nibble), 2 = 4bit(upper nibble) */ \ 0, /* Use busy signal: 1 = use busy, 0 = use time delays */\ PORTC, TRISC, /* Data port and data port tris register */ \ PORTB, TRISB, /* Control port and control port tris register */ \ 2, /* Bit number of control port is connected to RS */ \ 7, /* Bit number of control port is connected to RW */ \ 3 /* Bit number of control port is connected to Enable */ unsigned char tick; unsigned int value1; bit frequency_update_flag; /*Interrupt service routine (ISR).On timer0 interrupt, program will jump to this code location. */ void interrupt( void ) { bit capture_flag; if(pir1.0 == 1) //tmr1 overflow flag(tmr1if). { tick++; // count the number of tmr1 interrupts. if(tick > 15) //if frequency is too low { ccp1con = 0; t1con = 0; tmr1l = 0; tmr1h = 0; tick = 0; value1 = 0; frequency_update_flag = 1; } pir1.0 = 0; //clear tmr1if } else if(pir1.2 == 1) //ccp interrupt flag(ccp1if). { capture_flag++; if(capture_flag > 1) { t1con = 0; ccp1con = 0; //switch off capture mode. value1 = tmr1l + (tmr1h * 256); capture_flag = 0; frequency_update_flag = 1; } else //The first ccp interrupt resets tmr1 & starts it. { t1con = 0; tmr1l = 0; tmr1h = 0; t1con = 1; } pir1.2 = 0; //clear ccp flag. } } /* function to display RPM. */ void display (int x) { lcd_clear(); lprintf("%d",x); delay_s(2); } /* The main code configures the intcon, pie1, t1con & ccpcon1 registers.*/ void main() { trisb = 0; //configure port B portb = 0; //clear port B trisc = 0b00000100; //RC2/ccp1 pin as input. // enable interrupts: interrupt control register. intcon.6=1; //enable peripheral interrupts intcon.7=1; //enable global interrupt //peripheral interrupt enable register 1. pie1.2 = 1; //enable ccp1 interrupt. pie1.0 = 1; //enables tmr1 overflow interrupt. /* timer1 control register: t1ckps1:t1ckps0: input prescaler bit5-4.....select 00= 1:1 prescale tmr1cs: timer1 clock source select bit. bit1...select 0 = internal clock (Fosc/4) tmr1on: timer1 on bit bit0......1 = enable timer1 bit0......0 = stop timer1 we are not concerned about the other bits of t1con. */ //set t1con t1con = 0b00000000; //tmr1 not yet enabled. /*ccpcon1: capture/compare/pwm control register1. bit3-0.....ccpxm3:ccpxm0: ccpx mode select bits. we will use... 0100 = capture mode, every falling edge. 0101 = capture mode, every rising edge. we can choose any one of the above mode. but we will use 0100 in our project. */ /* print " RPM = " in the first line of LCD */ lcd_setup(); lcd_clear(); lprintf(" RPM = "); lcd_gotoxy(0,1); unsigned long count; while (1) { frequency_update_flag = 0; ccp1con = 0b00000101; //set capture mode. t1con = 1; //start timer1. while (frequency_update_flag == 0); count = (tick*65536) + value1; if(count == 0) //if frequency is too low. { display(count); } else { count = 100000000/count; //to find frequency. count *= 60; //for cycles per minute. count /= 100; //divide by 100 to get actual RPM. display(count); } } } Regards Raghunathan.
  23. Hi guys, I am using the ccp module in the capture mode to measure time interval between two pulses or (frequency) of a signal. This is possible if the period is smaller than the 16 bit timer1 value. in the case of low frequency one needs to count the no.of interrupts the timer1 produces and multiply that with 65536 & add that value to the final timer1 value. So i decided to use capture module just to generate an interrupt when the ccp pin reads a pulse( either falling edge or rising edge of thepulse) & i would read the tmr1 directly instead of the ccppr1h &ccpr1l. Now the question.. Will the capture module work with the tmr1 in the off state? I wish to start the tmr1 in the ISR of the capture module. Will it work? Regards Raghunathan.
  24. /* digital_clock.c Now that you know how to configure the timer0 to generate accurate time interval, let's construct a digital clock that will display hours, minutes and seconds on six led segment display. We will use the same common cathode segment used in our earlier projects. We will use PIC16F72 for this project because it has 22 i/o pins. The main features of this project at a glance. a)Uses tmr0 for time keeping. b)We use PIC16F72 c)4MHZ crystal frequency d)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 comparing the similarity in real world like the example of calling bell ringing & that of microcontrollers hardware interrupts. Let's apply the calling bell example to our digital clock. If you look at the program below, you will see that the microcontroller spends most of its time firing the transistors to display the hours, minutes & seconds segments, this is similar to us doing our household activity. But in the background the tmr0 counter keeps ticking without any of our intervention. In fact we are not even aware that the tmr0 is ticking until an interrupt occurs when it rolls over from 255 to 0.And when the interrupt occurs we quickly update the tick, tick1, seconds, minutes, hours in the ISR and then get back to doing our usual work of lighting the segments. The interrupt generated by tmr0 can be considered similar to the ringing of the calling bell. This code may initially look more convoluted with the function sec(), min(),hrs(),but you will soon see how advantageous it would be to call them only when the data gets updated & rest of the time we simply display the old value of data. By doing this we get a flicker free display. I had made this circuit on a bread board. Since the segments are dirctly connected to the PIC via 150 ohms without any driver and since multiplexing six segments will reduce the mean led current, you will see that the segments are 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 resistor pin9-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 of seconds digit & its Emitter to ground. collector of Q2 is connected to cc of tens segment of seconds digit & its Emitter to ground. collector of Q3 is connected to cc of units segment of minutes digit & its Emitter to ground. collector of Q4 is connected to cc of tens segment of minutes digit & its Emitter to ground. collector of Q5 is connected to cc of units segment of hours digit & its Emitter to ground. collector of Q6 is connected to cc of tens segment of hours digit & its Emitter 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 and on pressing the button gets closed. Connect a 10k resistor to +5v. on the other end of the resitor is conncted both to PIC micros input pin & one of the pins of the button switch. The other pin of the button switch is grounded. When the button switch is NOT pressed the PIC micro will read a high & when pressed 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 soon as you power on the circuit you will see the hours and minutes segements flash 00 alternately. Now pressing the hours button(portc.7)will increment the hours. As soon as it reaches the right hours, stop pressing or release the button. next press the minutes button(portc.6) & set it similarly. Once both 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 to tick( 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 how the seconds minutes and hours gets incremented. See how these update flag bits are set and cleared. This code compiles to 397 words */
×
×
  • Create New...