[SOLVED] PIC16F877 RTC Creating a setup mode.

Status
Not open for further replies.

WStevens_sa

Member level 2
Joined
Jan 5, 2011
Messages
47
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,286
Location
South Africa
Activity points
1,695
Hi all

Please can you point me in the correct direction. I have a PIC16f877 programmable RTC timer with 2 x 16 LCD displayed with eg "MON 14:56". I have figured out everything I need so far and have written the code for it and tested with simulator. It all works well.

I want to create a startup / program mode. When the timer is initially started up for the first time nothing will be set. For example the day and time will be displayed as "--- --:--" and the 8 configurable timers will be disabled.

Long story short. If I push the mode button it will take me through the steps of programming the timer.

  1. Press mode button for 2 seconds and it enters setup mode.
  2. Cursor moves to the LCD position where the day value is displayed.
  3. By using up down button set the day. eg (mon, tues, etc)
  4. Press mode button again it takes you to the hours. use up/down button to set hours
  5. And this will occur with the setting up of the timers too.
  6. If the setup mode is idle for more then 3 seconds it must go back to normal mode

I have know idea where to start. I would appreciate any help, links or documentation just to get an idea where to start.
 

i think in frist time when u read from RTC u read the intial values like SUN 00:00

---------- Post added at 20:40 ---------- Previous post was at 20:39 ----------

the hour is 0 and min is 0 not 00:00 but 0:0

---------- Post added at 20:43 ---------- Previous post was at 20:40 ----------

frist u ener for brust mode for RTC then u value entered from user is saved in var.
then send all the varaible(Hr-min-day-month.....) to RTC.
or u send to each register in separatly to adjust it.
 

Hi WStevens_sa,

It looks to me like you have a pretty good idea of what you want to accomplish, and that's the first (and probably hardest) step in every project. So make sure you have a perfectly clear picture of what your system should do before stepping into how to do it.
Then separate all the things to do into logically unrelated “tasks” and try to split those into smaller functional units.
For instance, taking your plan above as an example, accepting input from a key is unrelated and should be a totally independent task from keeping the current time or displaying some data.
But then, accepting key input involves reading a logic level on a port pin, filtering (in HW) and/or debouncing (in SW), figuring a short key-press from a long one, assigning a key codes (maybe allow even multiple key pressed at once) etc.
Further down the hierarchy, debouncing can be done by reading the key input one more time after about 30ms (max 50ms for a good responsiveness). And so on.
When you have broken down all the things to do, like that, in tasks and functions, you can start deciding how to best use the uC’s resources (now that you already chose one), such as serving interrupt requests as opposed to polling, or using dedicated peripherals (timers, communication etc.) instead of software delays and bit-banging.
Write your tasks to work independently or with very little interaction with each other (via shared flags/semaphores for synchronization, or to signal that data is available).
Keep ISRs simple and short (as in “read, store, signal data available, return”) and do the bulk of the work in the main loop (where you’ll run all of your other tasks in an infinite loop).
The tasks will check the flags for “data availability”, or whatever, but will probably do nothing most of the time, wating for their cue.
You can treat all tasks this way, including those that need to run periodically, at specific time intervals. Don’t do them in the ISR, instead, let the ISR count the time interval and signal some flag (basically a bit or a boolean variable) when the task should run. The task running in the in the main, infinite loop, checks the flag and runs if it finds it true then sets it to false.

Your main loop could look like this:

Code:
void main(void)
{
   clock_Init();	// init system clock etc.
   nvram_Init();	// read stored system parameters
   keyb_Init();		// init key input
   time_Init();
   state_Init();	// state machine init
   /* init other module and variables */
   while(1)
   {// this is the main loop
      alarm_task();	// check if any timer elapsed
      keyb_task();	// check and process key press
      state_task();	// evaluate and advance state machine
      disp_task();	// update display
      /* other tasks */
   }
}
…I actually run out of time myself now, but raise the questions as they pop-up and well sort them somehow…

Arthur
 
Last edited:
Hi Arthur

Here is what I have done so far. I think im on the correct path. My coding can be a bit better in the sense of not repeating functions to do tasks. I only have a few things I am struggling with. For example the " if (Button(&PORTC, 2, 1, 1))" where I am not sure how to get one button to do 2 functions. For example If I push a button it does one function. if I push the same button for 3 seconds it must do another function. I am also using multiple while do statements, which I think is also not a good thing for memory resources.

You also talk about flags. I am not sure what you mean. Do you mean a variable for example " int timer_set = 0;" So timer_set can be either 0 or 1. Is this what you mean with flags. The other thing that concerns me is that I am currently using 52.8 % of the ram and only have 47.2% left. This is obviousley all the variables declared I think. Rom is only 24.8 % used and 75.2 available. I dont want to bog down the MCU with calculations. I still need to add error checking on external devices that attach. So what would you recommend is the maximum preferred memory to use before it bogs down the MCU.

 

Hi!
WStevens_sa


unsigned int x=0;
void main(){
while(Button(&PORTC,2,1,0)){
x++;
Delay_ms(1000); //Increment value of x every second.........
}
if(x<3){/*your code*/} //If less than 3 seconds
else if(x>=3){/*your code*/} //After 3 seconds
x=0;
}
 
Last edited:
WStevens_sa,
You might get away with your little project, but I don't think you're on the correct path...
You haven't implemented anything of what I was talking about in my previous post and I have more comments than time to write it so I will keep it short and only answer to your questions.

In my previous post, I briefly suggested how I would use the key input.
First of all, you have to decide how many keys you'll need. The way you explained it, you only planned a “mode” key and 2 adjustments (“up”, “down”) keys. The less keys you’ll have, the more difficult the user experience and coding will be. If you have the possibility, assign keys for “day”, “hour”, “minute”, “alarm”, “+” and “-“.

The best way to detect a key press is with interrupts. If you can assign an interrupt requests on a port on both rising and falling edges, put your keys there. To detect “key down”, initialize the input pin to request interrupts on the falling edge (providing that the key connects the port pin to ground when pressed). In the ISR (Interrupt Service Routine) of a particular key, setup a timer to trigger an interrupt in 30ms. When the timer elapses, check the key again. If it’s still down then you consider that particular key debounced. Now setup the port to request interrupts on the rising edge, while setting up the timer to elapse after 3 seconds (if that’s your desired “long key press”). If the IRQ of the port pin is triggered before the timer’s, you got a “short press”. If it occurs after the timer, you got a “long press”.
I know it all sounds a bit complicated, but it isn’t really and, believe me, I’ve done this in all possible ways and this is the most robust way.

Another way is to poll the key-pins in the main loop and count the number of times they where found down. You will reset the counter whenever the key was found up. You still have to do the polling at specific time intervals (50ms, at most) to be able to differentiate short and long presses.

If you do it like Denshil suggested, your display (and everything else) will freeze as long as you keep the key pressed and you should absolutely avoid that...

When I say “flags”, I mean bits or variables that signal something. In that particular case, I meant a Boolean variable that can be “true” or “false” (that can be emulated with a char taking “0” or “anything else”). The whole point being that a “flag” should be easier/faster to check than accessing the actual data.

It’s probably too early to worry about memory allocation. Using a lot of memory won’t make your chip slower (it’s not Windows doing swaps on disk). Use it all, that’s why you have it! If you run out of it, you can start optimizing. Of course, you could be quite a bit more organized in your coding and that will surely help memory usage as well...

Arthur
 
Last edited:
Hi Arthur

My apologies if I have confused you. I actually wrote the code above before I posted this thread as I have been trying out different code to do different things to learn all the basics before I get stuck in with writing proper structured code. I will be re-programming the code in the structure as you explained in your first post but I am now first laying out a proper plan. As to the programming I am actually a Microsoft Developer so code complexity and optimisation is something I am familiar with. I am only struggling because I have never programmed in C for MCU's. I usually use C#.net, vb.net, javascripting, html, xml, flash and other languages. I will be trying out all your methods and will keep you updated as to my project. I appreciate all the help I get from everybody as this helps me learn

Hi Denshil

I appreciate all your responses. You have helped me a lot with all my posts. Thanks again.

I will keep you all informed with code snippets.
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…