2015-06-02 2 views
1

Я пытаюсь отобразить свой вход на микроконтроллере Дисплеи ATmega16 до 7 сегментов.Цифры отображаются неправильно, Невозможно управлять выходом на конкретный вывод

Я нашел следующий код на http://www.avr-tutorials.com/projects/atmega16-based-digital-clock, но когда я имплицировал его, он не работает. Я получаю флуктуирующий выход i.e Я не могу контролировать вывод на конкретных контактах. У меня есть два входа temp1 и temp2, и я хочу отображать каждый из них на трех 7-сегментных дисплеях. Кроме того, я не использовал Pins 2 & 3, поскольку они являются прерывистыми контактами, и я использовал их где-то в другом месте. Pin0,1,4,5,6,7.

Код отлично работает при добавлении некоторой задержки, в противном случае вывод генерируется случайными выводами. т.е. выход, который я полагаю, чтобы отобразить из PIND1 отображается на всех выводах,

Мой код:

#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; 
}} 
+0

Не обижайтесь, но вы сами поняли логику? Если вы не понимаете логику, почти невозможно отладить код _inspired_. –

+0

Функция DigitTo7SegEncoder вызывается, когда отображается конкретная цифра. Сегвал говорит, что он должен оставаться включенным. – Yash

+0

Какие константы ?? Я изменил значения порта, так как вы можете заметить. – Yash

ответ

0

Вы не устанавливаете DDR для вывода в любом месте. Выводы, которые вы хотите использовать в качестве выходов, должны иметь соответствующий бит в DDRx, установленный в 1. В противном случае он остается входным выводом.

Входной вывод будет показывать выход, но с более низким током и более медленным нарастающим фронтом. Использование этого тока с ЖК-дисплеем может привести к падению напряжения.

+0

Спасибо, некоторое улучшение после этого, но все же вывод не отображается должным образом. – Yash

+0

Код отлично работает, когда добавляется некоторая задержка, в противном случае вывод генерируется случайными выводами. – Yash

0

При условии, что эти компоненты 7-сегментных не содержат какой-либо последовательной логики внутри это то, что происходит на самом деле:

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

Так на самом деле 7-сегментных компонентов отображаются предыдущие и последующие цифры сразу за короткий промежуток времени.

Что относительно этого? (только псевдокод)

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(); 

И так далее.

+0

Я хочу отобразить весь вывод сразу, если добавлена ​​какая-то задержка, тогда он отобразит 1, а затем подождать некоторое время, а затем отобразит другой номер. и так далее. Кроме того, я пробовал это, выход не так, как хотелось бы. – Yash

+0

Затем вам нужно полностью замедлить весь цикл, чтобы отлаживать отдельные операции. Что происходит, когда вы пишете что-то в 'SegCntrlPort'? Что происходит, когда вы пишете что-то в 'SegDataPort'? Сделайте одну операцию записи, подождите, например. 1 секунду, затем сделайте другую запись и так далее. Только в этом случае вы можете видеть, что на самом деле происходит там. – dlask

+1

Ваша проблема, похоже, выходит из области программного обеспечения. – dlask