1

I am trying to display my input at microcontroller ATmega16 to 7 segment displays.

I have found the following code on http://www.avr-tutorials.com/projects/atmega16-based-digital-clock but when I implimented it, it is not working. I am getting a fluctuating output i.e I am not able to control the output at particular pins. I have two inputs temp1 and temp2, and I want to display each of them on three 7-segment displays. Also, I have not used Pins 2 & 3 as they are interrupt pins and I have used them somewhere else. Pin0,1,4,5,6,7 are used.

The code works fine when some delay is added, otherwise output is generated at random pins. i.e. The output which I was suppose to display from PIND1 is displayed on all pins,

My code:

    #include <avr/delay.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>

    #define SegDataPort     PORTC
    #define SegDataPin      PINC
    #define SegDataDDR      DDRC

    #define SegCntrlPort    PORTD
    #define SegCntrlPin     PIND
    #define SegCntrlDDR     DDRD

/*
* Function Description:
* Encode a Decimal Digit 0-9 to its Seven Segment Equivalent.
*
* Function Arguments:
* digit - Decimal Digit to be Encoded
* common - Common Anode (0), Common Cathode(1)
* SegVal - Encoded Seven Segment Value 
*
* Connections:
* Encoded SegVal is return in the other G-F-E-D-C-B-A that is A is the least
* significant bit (bit 0) and G bit 6.
*/
unsigned char DigitTo7SegEncoder(int digit, unsigned char common)
{
    unsigned char SegVal;

    switch(digit)   
    {   
        case 0: if(common == 1) SegVal = 0b00111111;
                else            SegVal = ~0b00111111;
                break;
        case 1: if(common == 1) SegVal = 0b00000110;
                else            SegVal = ~0b00000110;
                break;
        case 2: if(common == 1) SegVal = 0b01011011;
                else            SegVal = ~0b01011011;
                break;
        case 3: if(common == 1) SegVal = 0b01001111;
                else            SegVal = ~0b01001111;
                break;
        case 4: if(common == 1) SegVal = 0b01100110;
                else            SegVal = ~0b01100110;
                break;
        case 5: if(common == 1) SegVal = 0b01101101;
                else            SegVal = ~0b01101101;
                break;
        case 6: if(common == 1) SegVal = 0b01111101;
                else            SegVal = ~0b01111101;
                break;
        case 7: if(common == 1) SegVal = 0b00000111;
                else            SegVal = ~0b00000111;
                break;
        case 8: if(common == 1) SegVal = 0b01111111;
                else            SegVal = ~0b01111111;
                break;
        case 9: if(common == 1) SegVal = 0b01101111;
                else            SegVal = ~0b01101111;       
    }       
    return SegVal;
}



int main(void)
{
int temp1,temp2;
//Suppose my input is 105 and 210, i.e. temp1=105 and temp2=210;
// it contains other information also, not required here
SegDataDDR = 0xFF;
SegCntrlDDR = 0xF3;
SegCntrlPort = 0xF3;
SegDataPort = 0x00;
  while(1){
            SegDataPort = DigitTo7SegEncoder(temp1%10,1);
        SegCntrlPort = ~0x01;
        SegDataPort = DigitTo7SegEncoder((temp1/10)%10,1); 
        SegCntrlPort = ~0x02;
        SegDataPort = DigitTo7SegEncoder(temp1/100,1);
        SegCntrlPort = ~0x10;
        SegDataPort = DigitTo7SegEncoder(temp2%10,1); 
        SegCntrlPort = ~0x20;
        SegDataPort = DigitTo7SegEncoder((temp2/10)%10,1); 
        SegCntrlPort = ~0x40;
        SegDataPort = DigitTo7SegEncoder(temp2/100,1);
        SegCntrlPort = ~0x80;
}}
Yash
  • 145
  • 9
  • No offence, but did you understand the logic yourself? If you don't understand the logic, it's near impossible to debug an _inspired_ code. – Sourav Ghosh Jun 02 '15 at 10:40
  • The DigitTo7SegEncoder function is called when a particular digit is to be displayed. Segval tells that which led is to remain on. – Yash Jun 02 '15 at 10:43
  • Which constants ?? I have changed the port values as u can notice. – Yash Jun 02 '15 at 10:56
  • No need to change that, as I have not changed the pins of 7 segment displays, instead I have changed the output pins of ATmega, thus control ports are changed, not output data. – Yash Jun 02 '15 at 11:07
  • to understand the logic, the SegCntrlPort tells which 7-segment display to set? why is it then called after setting the segments, shouldnt it be called before? Also in your description you say it there are three 7-segment displays but it seems you have 6 different in your logic (0x01,0x02,..0x80). – AndersK Jun 03 '15 at 06:36

2 Answers2

0

Provided that these 7-segment components don't contain any sequential logic inside this is what actually happens:

SegDataPort = DigitTo7SegEncoder(temp1%10,1);       // You write the data
SegCntrlPort = ~0x01;                               // You enable the first 7-segment component
// Then without any delay...
SegDataPort = DigitTo7SegEncoder((temp1/10)%10,1);  // You write other data
SegCntrlPort = ~0x02;                               // You enable the second component
// The without any delay...

So actually the 7-segment component displays previous and next digits at once for a short time.

What about this? (just a pseudocode)

SegCntrlPort = 0xFF;   // hide everything

SetDataPort = ... value1 ...;
SegCntrlPort = ~0x01;   // show it
WaitForAWhile();

SegCntrlPort = 0xFF;   // hide everything to avoid unwanted transitions

SetDataPort = ... value2 ...;
SegCntrlPort = ~0x02;   // show it
WaitForAWhile();

And so on.

dlask
  • 8,776
  • 1
  • 26
  • 30
  • I want to display all output at once, if some delay is added then it will display 1, then wait for a while, then display another no. and so on. Also, I have tried this, the output is not as desired. – Yash Jun 02 '15 at 11:05
  • Then you have to slow down the whole loop extremely to debug individual operations. What happens when you write something to the `SegCntrlPort`? What happens when you write something to the `SegDataPort`? Make a single write operation, wait e.g. 1 second, then make another write, and so on. Only in this case you can see what actually happens there. – dlask Jun 02 '15 at 11:08
  • 1
    Your problem seems to leave the area of software. – dlask Jun 02 '15 at 11:32
0

You don't set the DDRs to output anywhere. The pins you want to use as outputs must have the corresponding bit in DDRx set to 1. Otherwise it remains an input pin.

An input pin will show an output, but with a lower current and a more slowly rising edge. Drawing on that current with an LCD may cause the voltage to drop.

UncleO
  • 8,299
  • 21
  • 29
  • Thank you, some improvement after that, but still the output is not displayed properly. – Yash Jun 03 '15 at 04:47
  • The code works fine when some delay is added, otherwise output is generated at random pins. – Yash Jun 03 '15 at 04:57