Search code examples
cavrledatmegaatmega16

Digits not displayed properly, Unable to control output at particular pin


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;
}}

Solution

  • 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.