DELAY and DISPLAY in microcontroller programming

Thread Starter

mailus

Joined Jun 16, 2012
19
i have difficulty in programming with delays and 7 segment display routines;
now my doubt is,

i have data(in bytes) in a variable, i need to check the location of bit(from byte mentioned) which is zero. then i need to display in a single seven segment display(1~8). here i use for loop and bit manipulation function to find the location,on the same time i need to display which location is zero.for this i use delay function in for loop.how to avoid this delay function in for loop and the same time display the output

i put my code here:
Rich (BB code):
#include <16f877a.h>
#fuses HS,PUT,NOWDT,NOPROTECT,NOBROWNOUT 
 
#use delay(clock=4000000)
 
#define crystal 4000000
#define time 750
#define relay_time 500
#define debounce 50
 
 
unsigned int8 curr_ipt=0xff,i,sli=0,temp=0;
int1 rd_ipt=1;
 
 
 
int conv(unsigned int8 data)           //function with return value
{
   switch(data)                        //return the converted data to display in the 7-segment
   {
      case 1:
         return(0xf9);
         break;
      case 2:
         return(0xa4);
         break;
      case 3:
         return(0xb0);
         break;
      case 4:
         return(0x99);
         break;
      case 5:
         return(0x92);
         break;
      case 6:
         return(0x82);
         break;
      case 7:
         return(0xf8);
         break;
      case 8:
         return(0x80);
         break;
      case 9:
         return(0x90);
         break;
      default:
         return(0xff);
         break;
 
    }
 
}
 
 
void output()
{
   if((curr_ipt==0xff) && sliver==1)        //if all pins in portc is high
   {
      output_low(pin_A1);   
      output_low(pin_A2);
      output_high(pin_A3); //relay,error_led signal are low and ready signal is high
      delay_ms(relay_time);
 
   } else if((curr_ipt!=0xff) || sliver==0)    //any of the input is low
   {
      rd_ipt=0;
      output_high(pin_A1);   
      output_high(pin_A2);
      output_low(pin_A3);     //relay,error_led signal are high and ready signal is low
      delay_ms(relay_time);
   }
 
}
 
 
 
 
void display()
{
   if(curr_ipt!=0xff)         //check input if any change enter loop
   {
      for(i=0;i<=7;i++)
      {
         if((curr_ipt &(1<<i))==0)     //for each value of i bit location is change to ith location
         {                              //if any particular bit is zero means enter   
            delay_ms(debounce);        //debounce time
            if((curr_ipt &(1<<i))==0)  //check again if still bit 0
            {
            temp=i;                    //save the location i in temp variable
            output_B(conv(temp+1));    //call function "conv" and display in the portB
            delay_ms(time);            //time for display the content
            }
         }
      }
   }
 
   if(sli==0)                       //if sli input is zero means enter here
   {
      delay_ms(debounce);              //debounce time
      if(sli==0)                      //check again still input is zero enter
      {
      output_b((conv(9)));             //call fn"conv" and display digit '9' on display
      delay_ms(time);
      }
   }
   if((curr_ipt==0xff) && sli==1)     //if all inputs are high display empty
   {
      output_b((conv(0)));
   }
 
}
 
 
void main()
{
   while(TRUE)
   {
      start:
      if(rd_ipt==1)        //read port when rd_ipt is enabled
      {
         curr_ipt=input_c();   //assign port c value to variable curr_ipt
         sli=input(pin_a0);
      }
      output();               //call output function
      display();              //call display function
      if(input(pin_A5))
      {
      delay_ms(20);
      if(input(pin_A5)) 
      {
        rd_ipt=1;
        goto start;
        output_high(pin_E0);
      }
      }
   }
 
}
problems in my code:

"The goto and continue keywords shall not be used. The break keyword shall not be used outside
of a switch statement. These keywords lead to spaghetti code."

"i have implemented delay in a closed loop so it make my code to too lazy one,so controller wait some time until the closed loop has to complete"



so i keep on searching i found that RTOS concept.
that means time slicing or time slot method by using cooperative tasking and round-robin technique.is this technique suitable for my problem?

please give some solution to solve this problem
 

MrChips

Joined Oct 2, 2009
30,708
Your code is riddled with problems. You have not learned the concepts of Structured Programming.
It is best to begin by drawing flow charts.

1) Your conv( ) routine is wrong. You have input and output interchanged.
You don't need to use a switch/case structure.

2) Your output( ) routine is flawed.
Use a single if-then-else structure.
sliver is not declared.
Pass parameters in the function call.

3) Your display( ) routine is flawed.
Draw a flowchart.

4) Your main( ) routine is flawed.
Draw a flowchart.
output_high( ) is never reached.

You don't need RTOS.
 

Thread Starter

mailus

Joined Jun 16, 2012
19
Thank you for point out my problem.
yes, i am a beginner in microcontroller programming.


please suggest some books to learn these concepts.
(Structured Programming,flow chart design & etc.,)
 

Thread Starter

mailus

Joined Jun 16, 2012
19
i am using some books(Programming 8-bit PIC Microcontrollers in C ,The C Programming Language - Ritchie Kernighan).
 

Thread Starter

mailus

Joined Jun 16, 2012
19
what type of tutorials you have?
please post the tutorials....then i will also enjoy the programming........
 

Thread Starter

mailus

Joined Jun 16, 2012
19
i working on a industrial device.
my requirements are
1) i have totally 9 sensor inputs and one reset button input.
when any one of the input pin (or combination of any pin at a same time) falls to zero means the device produce a indication and energize a relay and stop checking the input.
2) at the same time i want to show that particular pin input is fail.so i use a single 7 segment LED to display.(for more than one input fail the display show the digit for one second and show the other digits likewise)
3) if reset button is pressed the display check the current status of input.if error exist follow step-1 and step-2 otherwise display will blank and relay de-energize
 

donpetru

Joined Nov 14, 2008
185
@mailus, now, after last post of yours, I understand much better.
In this application use one common cathode or anod 7-seg. display ?

First, in your code I don't see any program line declaring input and output pins. That would be a first mistake.

For example, you use:
Rich (BB code):
int conv(unsigned int8 data)           //function with return value 
{    switch(data)                        //return the converted data to display in the 7-segment 
   {       
case 1:          return(0xf9);          break;       
case 2:          return(0xa4);          break;       
case 3:          return(0xb0);          break;       
case 4:          return(0x99);          break; 
      case 5:          return(0x92);          break;       
case 6:          return(0x82);          break;
case 7:          return(0xf8);          break;       
case 8:          return(0x80);          break;       
case 9:          return(0x90);          break;       
default:          return(0xff);          break; 
     } 
}
but the above code does not think it's good.

Correct code, for example, for common cathode 7-segment displays is:
Rich (BB code):
unsigned short mask(unsigned short num) {
              switch (num) {
                     case 0 : return 0x3F;
                     case 1 : return 0x06;
                     case 2 : return 0x5B;
                     case 3 : return 0x4F;
                     case 4 : return 0x66;
                     case 5 : return 0x6D;
                     case 6 : return 0x7D;
                     case 7 : return 0x07;
                     case 8 : return 0x7F;
                     case 9 : return 0x6F;
                          }
                                             }
Now, if you want to display a number from 0 to 9 on the display, just assign each input pin numbers from 0 to 9.

Suppose we choose RA5 and RB0...7 as input port and port RC0...7 and RA0 as output (RA0 for relay de-energize). You have to write something like this (I use mikroC for PIC):
Rich (BB code):
bit oldstate;       // Old state flag

void main() {
  ANSELA = 0;                    // Configure PORTA pins as digital
  ANSELB = 0;                    // Configure PORTB pins as digital
  ANSELC = 0;                    // Configure PORTC pins as digital

  TRISB = 1;                     // set RB0...7 pins as input 1...8
  TRISA5_bit = 1;                // set RA5 pin as input 9

  TRISA0_bit = 0;                // Configure RA0 as output for relay de-energize 
  LATA0_bit  = 0;                // Clear PORT RA0

  TRISC = 0;                     // Configure PORTC as output
  LATC  = 0;                     // Clear PORTC

  do {

     for (i=0; i<=7; i++)
        {
               if (Button(&PORTB, i, 1, 1))                      // Detect logical one             
                  { 
                     oldstate = 1;                               // Update flag 
                     if (oldstate && Button(&PORTB, i, 1, 0))    // Detect one-to-zero transition 
                                   {
                                    TRISA0_bit = 1;  // turn off relay
                                    num = i + 1; 
                     unsigned short mask(unsigned short num) {
                                  switch (num) {
                                         case 0 : return 0x3F;
                                         case 1 : return 0x06;
                                         case 2 : return 0x5B;
                                         case 3 : return 0x4F;
                                         case 4 : return 0x66;
                                         case 5 : return 0x6D;
                                         case 6 : return 0x7D;
                                         case 7 : return 0x07;
                                         case 8 : return 0x7F;
                                         case 9 : return 0x6F;
                                                }
                                                      }
                                    LATC = num;
                                    Delay_ms(2000);              // 2 second delay

                                    }   
                  }
        }
  
     if (Button(&PORTA, 5, 1, 1))                                 // Detect logical one             
                  { 
                     oldstate = 1;                               // Update flag           
                     if (oldstate && Button(&PORTA, 5, 1, 0))    // Detect one-to-zero transition
                                   {
                                    TRISA0_bit = 1;              // turn off relay
                                    LATC = 0x6F;
                                    Delay_ms(2000);              // 2 second delay 
                                   }   
                  }

   } while(1);
}
I have not tested the code above, but can be a starting point.
 

Thread Starter

mailus

Joined Jun 16, 2012
19
@mailus, now, after last post of yours, I understand much better.
In this application use one common cathode or anod 7-seg. display ?

First, in your code I don't see any program line declaring input and output pins. That would be a first mistake.

For example, you use:
Rich (BB code):
int conv(unsigned int8 data)           //function with return value 
{    switch(data)                        //return the converted data to display in the 7-segment 
   {       
case 1:          return(0xf9);          break;       
case 2:          return(0xa4);          break;       
case 3:          return(0xb0);          break;       
case 4:          return(0x99);          break; 
      case 5:          return(0x92);          break;       
case 6:          return(0x82);          break;
case 7:          return(0xf8);          break;       
case 8:          return(0x80);          break;       
case 9:          return(0x90);          break;       
default:          return(0xff);          break; 
     } 
}
but the above code does not think it's good.

Correct code, for example, for common cathode 7-segment displays is:
Rich (BB code):
unsigned short mask(unsigned short num) {
              switch (num) {
                     case 0 : return 0x3F;
                     case 1 : return 0x06;
                     case 2 : return 0x5B;
                     case 3 : return 0x4F;
                     case 4 : return 0x66;
                     case 5 : return 0x6D;
                     case 6 : return 0x7D;
                     case 7 : return 0x07;
                     case 8 : return 0x7F;
                     case 9 : return 0x6F;
                          }
                                             }
Now, if you want to display a number from 0 to 9 on the display, just assign each input pin numbers from 0 to 9.

Suppose we choose RA5 and RB0...7 as input port and port RC0...7 and RA0 as output (RA0 for relay de-energize). You have to write something like this (I use mikroC for PIC):
Rich (BB code):
bit oldstate;       // Old state flag

void main() {
  ANSELA = 0;                    // Configure PORTA pins as digital
  ANSELB = 0;                    // Configure PORTB pins as digital
  ANSELC = 0;                    // Configure PORTC pins as digital

  TRISB = 1;                     // set RB0...7 pins as input 1...8
  TRISA5_bit = 1;                // set RA5 pin as input 9

  TRISA0_bit = 0;                // Configure RA0 as output for relay de-energize 
  LATA0_bit  = 0;                // Clear PORT RA0

  TRISC = 0;                     // Configure PORTC as output
  LATC  = 0;                     // Clear PORTC

  do {

     for (i=0; i<=7; i++)
        {
               if (Button(&PORTB, i, 1, 1))                      // Detect logical one             
                  { 
                     oldstate = 1;                               // Update flag 
                     if (oldstate && Button(&PORTB, i, 1, 0))    // Detect one-to-zero transition 
                                   {
                                    TRISA0_bit = 1;  // turn off relay
                                    num = i + 1; 
                     unsigned short mask(unsigned short num) {
                                  switch (num) {
                                         case 0 : return 0x3F;
                                         case 1 : return 0x06;
                                         case 2 : return 0x5B;
                                         case 3 : return 0x4F;
                                         case 4 : return 0x66;
                                         case 5 : return 0x6D;
                                         case 6 : return 0x7D;
                                         case 7 : return 0x07;
                                         case 8 : return 0x7F;
                                         case 9 : return 0x6F;
                                                }
                                                      }
                                    LATC = num;
                                    Delay_ms(2000);              // 2 second delay

                                    }   
                  }
        }
  
     if (Button(&PORTA, 5, 1, 1))                                 // Detect logical one             
                  { 
                     oldstate = 1;                               // Update flag           
                     if (oldstate && Button(&PORTA, 5, 1, 0))    // Detect one-to-zero transition
                                   {
                                    TRISA0_bit = 1;              // turn off relay
                                    LATC = 0x6F;
                                    Delay_ms(2000);              // 2 second delay 
                                   }   
                  }

   } while(1);
}
I have not tested the code above, but can be a starting point.
I have one more doubt,

in your program the delay is placed inside a closed loop.while execution the once program enters for loop it will not exit until the loop exit.so other function that is reset switch cannot be controlled.
 

donpetru

Joined Nov 14, 2008
185
Delay_ms of the instructions "if" from the main loop allows viewing of the display corresponding digit entry that fell. For example, if intput 5 falls to zero, then the display will show the number 5 for 2 seconds. Then repeat loop is recheck each entry and if input 5 is the problem ---> displays the number 5 only 2 seconds....
This code can be polished according to how you want. As I said, it's just a small starting point.
 
Top