Driving a digital display using HCS08 MC9S08GB60

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Driving a digital display using HCS08 MC9S08GB60

2,612 Views
karmabobby
Contributor I
 
I am trying to drive a Digital display using the above schematic. I know how the circuit works, I am just having some trouble with C syntax...and well some of my code may well be wrong but I think I have given it a good attempt. It is meant to display 'EP2'. If anyone could help me just get the code working I would be very grateful. If anyone spots any glaring errors could someone please give me help with this. I am new to C and this course has thrown me in the deep end when it comes to programming.
 
 
 
#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */

#define  E_Display 0x79       //Digital display for 'E'
#define  P_Display 0x73       //Digital display for 'P'
#define  Two_Display 0x57       //Digital display for '2'
#define  DP_Off 0x80          //Used to turn Decimal Point off
#define  All_Off 0x00         //Used to turn all bits off
#define  All_On  0xFF         //Used toturn all bits on
#define  Drive_Segment_Bus 0x3F   //Used to drive the output
#define  Mask_Digits 0x03         //Masking bits 7-2 off '00000011'

    void main (void) {
// SET DDRs for output ports
   
 for (;:smileywink:  //Repeat forever
 {
  Output_Seven_Segments(E_Display,1) ;
  delay(1); //Call a delay subroutine
  Output_Seven_Segments(P_Display,2) ;
  delay(1);
  Output_Seven_Segments(Two_Display,3) ;
  delay(1);                         
 }
}

 void delay(long int n)
{
 long int i;
 unsigned int j;
 for (i=0; i<n; i++)
   for (j=0; j<100; j++)
     {}
}

void Output_Seven_Segments (unsigned char segments, unsigned char digit)//this doesnt work!
{
 
 segments == 0;
 digit == 0;
 
 //Remember: segments variable is formed as:
 //        DP g f e d c b a
 
 if (digit==Two_Display)   //This is the broken display
  
  segments=FixDigit2(segments); //Call a subroutine to mangle all bits
 
  PTFD == All_Off;            // TURN ALL DIGITS OFF
 
  PTBD == Drive_Segment_Bus;//DRIVE SEGMENTS BUS with segments<6:0>
 
  PTFD == Mask_Digits;//Mask digit bits <7:2> off, so we only end with bits <1:0>
  //(i.e. there are only 4 displays)

 switch (PTFD) {
  case 0: 
  
        Mask_Digits == 1;//Drive Most significant digit ON
        PTFD == Mask_Digits;
  
  break;
  case 1:
  
        Mask_Digits == 2;//Drive Next digit ON
        PTFD == Mask_Digits;
  
  break;
  case 2:
  
        Mask_Digits == 3;//Drive Least significan digit ON
        PTFD == Mask_Digits;
  
  break;
  case 3: 
  
     PTAD == 0xFF; //Drive LED bar graph ON
  
  break;
 }
   
}

//Note: if your display is broken also include the following subroutine which is called to remangle the broken bits. Otherwise just look at how the routine shuffles bit around!
 
unsigned char FixDigit2(unsigned char value) {
 
  unsigned char newval;
  newval=0;
 
  newval=newval|(value&0x01)<<6;   //Bit 0 becomes 6
  newval=newval|(value&0x02)>>1;   //Bit 1 becomes 0
  newval=newval|(value&0x04)<<5;  //Bit 2 becomes 7
  newval=newval|(value&0x40)>>4;  //Bit 6 becomes 2
  newval=newval|(value&0x80)>>6;  //Bit 7 becomes 1
  newval=newval|(value&0x38);    //And bits 543 are copied undisturbed
 
  return (newval);
}
 
 
  for(;:smileywink: {
    __RESET_WATCHDOG(); /* feeds the dog */
  } /* loop forever */
  /* please make sure that you never leave main */
}
}


Message Edited by karmabobby on 2008-03-28 02:25 PM

Message Edited by karmabobby on 2008-03-28 02:26 PM

Message Edited by karmabobby on 2008-03-28 02:26 PM

Message Edited by karmabobby on 2008-03-28 02:30 PM

Message Edited by karmabobby on 2008-03-28 02:31 PM

Message Edited by karmabobby on 2008-03-28 02:32 PM

Message Edited by karmabobby on 2008-03-28 02:33 PM
Labels (1)
0 Kudos
10 Replies

761 Views
allawtterb
Contributor IV
I haven't looked through all the code but taking a very quick glance you need to fix some problems.  Mainly you are mixing up "==" and '='.  The double equal sign "==" is a boolean operation, it returns true or false based on the evaulation of the left since equaling the value on the right side.  This is normally only when testing conditions in things like if statements, while loops, do while loops etc.  
 
Is this an exact copy of your code?  If not, copy and paste it using the source code function of the forums.  When you post, there is a button to the right of the bold, italics, underline and strike through buttons above the area where you type your text labeled "SRC".  Press this and a new window should open to let you post source code. 
 
 
0 Kudos

761 Views
karmabobby
Contributor I
It is an exact copy of my code. Ok well I will go back and edit my code and see what happens, I will also post it back up properly. Cheers
0 Kudos

761 Views
karmabobby
Contributor I
Code:
#include <hidef.h> /* for EnableInterrupts macro */#include "derivative.h" /* include peripheral declarations */#define  E_Display 0x79       //Digital display for 'E'#define  P_Display 0x73       //Digital display for 'P'#define  Two_Display 0x57       //Digital display for '2'#define  DP_Off 0x80          //Used to turn Decimal Point off#define  All_Off 0x00         //Used to turn all bits off#define  All_On  0xFF         //Used toturn all bits on#define  Drive_Segment_Bus 0x3F   //Used to drive the output#define  Mask_Digits 0x03         //Masking bits 7-2 off '00000011'    void main (void) { // SET DDRs for output ports     for (;;)  //Repeat forever {  Output_Seven_Segments(E_Display,1) ;  Delay(1); //Call a delay subroutine  Output_Seven_Segments(P_Display,2) ;  Delay(1);  Output_Seven_Segments(Two_Display,3) ;  Delay(1);                           }} void delay(long int n){ long int i; unsigned int j; for (i=0; i<n; i++)   for (j=0; j<100; j++)     {}}void Output_Seven_Segments (unsigned char segments, unsigned char digit){  segments = 0; digit = 0;   //Remember: segments variable is formed as: //        DP g f e d c b a if (digit==Two_Display)   //This is the broken display    segments=FixDigit2(segments); //Call a subroutine to mangle all bits  PTFD = All_Off;            // TURN ALL DIGITS OFF   PTBD = Drive_Segment_Bus;//DRIVE SEGMENTS BUS with segments<6:0>  PTFD = Mask_Digits;//Mask digit bits <7:2> off, so we only end with bits <1:0>   //(i.e. there are only 4 displays) switch (PTFD) {  case 0:            Mask_Digits == 1;//Drive Most significant digit ON        PTFD = Mask_Digits;    break;  case 1:           Mask_Digits == 2;//Drive Next digit ON        PTFD = Mask_Digits;    break;  case 2:           Mask_Digits == 3;//Drive Least significan digit ON        PTFD = Mask_Digits;    break;  case 3:         PTAD = 0xFF; //Drive LED bar graph ON    break; }   }//Note: if your display is broken also include the following subroutine which is called to remangle the broken bits. Otherwise just look at how the routine shuffles bit around! unsigned char FixDigit2(unsigned char value) {    unsigned char newval;  newval=0;    newval=newval|(value&0x01)<<6;   //Bit 0 becomes 6  newval=newval|(value&0x02)>>1;   //Bit 1 becomes 0  newval=newval|(value&0x04)<<5;  //Bit 2 becomes 7  newval=newval|(value&0x40)>>4;  //Bit 6 becomes 2  newval=newval|(value&0x80)>>6;  //Bit 7 becomes 1  newval=newval|(value&0x38);    //And bits 543 are copied undisturbed    return (newval);}  for(;;) {    __RESET_WATCHDOG(); /* feeds the dog */  } /* loop forever */  /* please make sure that you never leave main */}}

 
Ok heres the source code. I am still having errors when it compiles.
0 Kudos

761 Views
allawtterb
Contributor IV
You still have a for loop at the bottom that is not in any function.  This needs to be removed as well as the 2 end brackets after it. 
I am sure many people here could post code that does exactly what you want but I think it would be beneficial if you started with something
a bit more simple then worked yourself up to displaying EP2.
 
The code as it currently is can't turn on any of the segments, it can't turn anything on as you haven't configured any of the port pins as outputs.
To set these as inputs or outputs you have to write to PTXDD where X is the Port you want to set the data direction on.  Each bit of PTXDD
corresponds to one of the 8 pins on the port, but not all ports have all 8 pins. All the pins shown in the schematic should be setup as outputs.
Once oyu have set these as outputs, you then control if they are high or low by setting the according bit in PTXD where X is the port you
are accessing. From the schematic it isn't completely clear what port pins are going where.  For example, does PB1 refer to Port B pin 1 or
Port B pin 0?
 
Try getting back to basics and just turning on certain segments on one display first.  The code to do this should look something like this:
 
 
Code:
#include <hidef.h> /* for EnableInterrupts macro */#include "derivative.h" /* include peripheral declarations */void main (void) {    // Set DDRs for output ports   PTADD = 0x01; // Replace XX with the hex value to set the PA2 and PA1 as outputs      PTFDD = 0x01; // Same here, setting the inputs/outputs for port F   PTBDD = 0x01; // Setting the input/outputs for Port B      PTFD = 0x01;  // Replace XX with the hex value to select the display you want to use   PTBD = 0x01;  // Replace XX with the hex value to turn on the segments you want   /* Port A shouldn't need to have anything done to it, it only controls the decimal     point and enables some other LED's according to the schematic*/   for (;;)  //Repeat forever   {   ;                         }}

 
0 Kudos

761 Views
karmabobby
Contributor I
Ok I will have a look, thanks for pointing that out.
0 Kudos

761 Views
bigmac
Specialist III
Hello,
 
Your code still has numerous problems, even after you fix the things that allawtterb pointed out.  I
assume that your code has never compiled without warnings and errors.  I will list a few of the issues
that I observed.  However, I will leave it to you to find where the problem is located, and provide the
correction.
  1. You do not seem to have provided any function prototypes, resulting in some compile errors
  2. In some instances, the name by which a function is called does not match the name by which the
    function is defined, resulting in further compile warnings.  (Hint: C is case sensitive.)
  3. In one instance, you have passed parameters to a function, and then immediately zeroed them
    before the passed value has been used by the function.
  4. Some of the macros that define constants do not match the port output allocations you have used
    This would result in an incorrect display.
  5. There does appear to be a lack of understanding of the purpose of using a switch/case statement
    The manner in which you have used it does not make sense to me.
You will notiice that, with the present structure of your code, you will not be able to do anything else
except scan the display, unless you first blank the display.  This is because any disruption to the digit
timing will cause one digit to appear brighter than the other digits.  Ultimately you will most likely need to
use a periodic timer interrupt to display the next digit in the multiplexing sequence.  To minimize flicker,
for a 4-digit display, the period between interrupts should be less than 4 ms.  ( I have also categorized
the LED array as digit.)
 
Another suggestion is to set up a table (a constant array variable) containing the 7-segment configuration
for the numerals 0 to 9, and for each alphabetic you wiish to display.  This would provide more flexibility in
dynamically changing the contents of the display.
 
Regards,
Mac
 


Message Edited by bigmac on 2008-03-30 01:33 AM
0 Kudos

761 Views
karmabobby
Contributor I
I have looked at my code and have eliminated all of the errors. However I still am having big problems with switch statements.  Here is my code mixed with some psuedo code.
 
Code:
#include <hidef.h> /* for EnableInterrupts macro */#include "derivative.h" /* include peripheral declarations */#include <stdio.h>#define  E_Display 0x79       //Digital display for 'E'#define  P_Display 0x73       //Digital display for 'P'#define  Two_Display 0x57       //Digital display for '2'#define  DP_Off 0x80          //Used to turn Decimal Point off#define  All_Off 0x00         //Used to turn all bits off#define  All_On  0xFF         //Used toturn all bits on#define  Drive_Segment_Bus 0x3F   //Used to drive the output#define  Mask_Digits 0x03         //Masking bits 7-2 off '00000011'    void delay(long int n){ long int i; unsigned int j; for (i=0; i<n; i++)   for (j=0; j<100; j++)     {}} void Output_Seven_Segments (unsigned char segments, unsigned char digit){   //Remember: segments variable is formed as: //        DP g f e d c b a if (digit==2)   //This is the broken display    segments=FixDigit2(segments); //Call a subroutine to mangle all bits  PTFD = All_Off;            // TURN ALL DIGITS OFF   PTBD = Drive_Segment_Bus;//DRIVE SEGMENTS BUS with segments<6:0>                          //mask variable digits with Mask_Digits variable switch (digits)  {  case 0:           //Drive most significant digit on   break;  case 1:            //Drive second digit on    break;  case 2:           //Drive least significant digit on          break;   case 3:           //Drive LED display on      break; }   }    void main (void) {    // Set DDRs for output ports   SOPT_COPE = 0;//Disable watchdog timer   PTADD = 0x02; // Replace XX with the hex value to set the PA2 and PA1 as outputs      PTFDD = 0xE0; // Same here, setting the inputs/outputs for port F   PTBDD = 0x7F; // Setting the input/outputs for Port B      /* Port A shouldn't need to have anything done to it, it only controls the decimal     point and enables some other LED's according to the schematic*/     for (;;)  //Repeat forever {     Output_Seven_Segments(E_Display,1) ;  delay(1); //Call a delay subroutine  Output_Seven_Segments(P_Display,2) ;  delay(1);  Output_Seven_Segments(Two_Display,3) ;  delay(1);                           }}//Note: if your display is broken also include the following subroutine which is
//called to remangle the broken bits. Otherwise just look at how the routine
//shuffles bit around! int FixDigit2(int value) {    unsigned char newval;  newval=0;    newval=newval|(value&0x01)<<6;   //Bit 0 becomes 6  newval=newval|(value&0x02)>>1;   //Bit 1 becomes 0  newval=newval|(value&0x04)<<5;  //Bit 2 becomes 7  newval=newval|(value&0x40)>>4;  //Bit 6 becomes 2  newval=newval|(value&0x80)>>6;  //Bit 7 becomes 1  newval=newval|(value&0x38);    //And bits 543 are copied undisturbed    return (newval);}

 
I have a few questions as to my best approach to this. I know the FixDigit2 subroutine is correct as it was given to me.
The delay subroutine and main are also correct, I am just having trouble with Output_Seven_Segments
sub routine which happens to be the most important one.
 
I have checked the settings for the DDR's and they are also correct. I think my bit masking is correct also.
 
Here is where I get confused. I need to use a 4 case switch statement for displaying the appropriate outputs.
1 case will be the most significant bit, 1 will be the second digit, 1 will be the least significant bit and the last one will be to drive the LED display.
I have been asked to mask digit bits <7:2> off so there is only 2 bits for the 4 outputs (00,01,10,11).
But to what do I apply this? Should I apply this to the variable digit? This seems to me to be the best approach.
 
Could someone give me the general form of the switch I need. Is this psuedo code correct?
 
Code:
switch ( digits ) {case 0:Code to execute if digits == 0break;case 1:Code to execute if digits == 1break;
case 2:
Code to execute if digits == 2break;
case 3:
Code to execute if digits == 3
}

 Now would it be wise to manipulate variable digits at any point or just leave it alone?
I am required to use a timer for my next program.
 


Message Edited by karmabobby on 2008-04-01 02:34 PM
0 Kudos

761 Views
allawtterb
Contributor IV
The switch statement seems fine except you are switching on digits instead of digit.  The compiler would have generated an error for this.  You should not have to do anything else to digit, it is just used to select which display you want to drive. 
 
You still have a problem that bigmac pointed out, you should have function prototypes.  You are calling one function before it is declared (FixDigit2) which should generated a warning from your compiler.  All warnings should be inspected and understood before they are dismissed.  If you don't understand what it is doing then go to the help see if you can find any information on it.  The above problem should produce the following warning:
 
C1801: Implicit parameter-declaration for 'FixDigit2'
 
The C in C1801 indicates this is a compiler warning, if you go to Help -> Search then put C1801 in, it correctly describes what the problem is, a lack of a function prototype.  Without function prototypes you would have to declare a function before it is called, meaning this error would not appear if FixDigit2 appeared above Output_Seven_Segments in your .c file.  The way to get around having to re-order functions in this manner is provide a function prototype for every function you use at the top of your .c file or in an included header(.h) file.  The top of your .c file should like something like this:
 
Code:
#include <hidef.h> /* for EnableInterrupts macro */#include "derivative.h" /* include peripheral declarations */#include <stdio.h>/* Function Prototypes */void delay(long int);void Output_Seven_Segments(unsigned char, unsigned char);void main(void);int FixDigit2(int);
...

 You can put the names of the variables after the variable types, but it is not required.  Either way, stay consistent and always put the variable names or never put them.
 
Some other notes:
 
1. I don't know why you included stdio.h, it is not needed.
2. If you are required to use FixDigit2 and this way of display letters/numbers it is ok, but it is not a good way to do so in general.  The best way to do this would normally be a look-up table. 

 
0 Kudos

761 Views
karmabobby
Contributor I
Ok I will take another look. The FixDigit subroutine was provided by my lecturer, I think it was meant to show us clearly how bit manipulation works. Thanks for showing me function prototypes the examples I found on the net were pretty vague. I'm going to get the bit manipulations in this program sorted and to do this I thought it would be best to write another simple program using the LED's on Port F on this board. Anyway thanks for the help guys my knowledge of the language is expanding and I am getting better slowly! :smileyhappy:
 
 
0 Kudos

761 Views
bigmac
Specialist III
Hello,
 
Within your code, you have assumed the following bit sequence -
DP g f e d c b a
 
This means that segment A should be allocated to PTB0, through to segment G allocated to PTB6.  This
differs from your original bit assignments, where segment A starts with PTB1.  I would suggest that you
alter your hardware connections to what you have assumed within the code.
 
I can't see any need for the use of a switch statement in your code - it just complicates things.
 
#define  DIGIT_PORT  PTFD       /* Port F used for digits */
#define  DIGIT_MASK  0xF0
#define  SEG_PORT    PTBD       /* Port B used for segments */
#define  SEG_MASK    0x7F
#define  DP_BIT      PTAD_PTAD0 /* Port A used for DP */
 
void Seven_Seg_out( byte segments, byte digit)
{
   // Remember: segments variable formed as: DP g f e d c b a
 
   DIGIT_PORT &= ~DIGIT_MASK;  /* Set all digits OFF */
   SEG_PORT &= ~SEG_MASK;      /* Set all segments OFF */
   DP_BIT = 0;                 /* Set DP to OFF */
  
//   if (digit == Two_Display)   // This is the broken display
//      segments = FixDigit2( segments); // Mangle segment bits
 
   if (segments & 0x80)        /* Test DP state */
      DP_BIT = 1;              /* Set DP to ON */
  
   SEG_PORT |= segments & SEG_MASK;
   DIGIT_PORT |= (0x10 << digit);
}
 
The parameter digit would require a value 0-3.  The attached header file might also be of some use.
 
Regards,
Mac
 


Message Edited by bigmac on 2008-04-02 02:25 AM
0 Kudos