Forum: Compiler & IDEs ATmega 644P/ 32 - ADC, 7-Segment, Multiplexen: Problem


von Dominik (Gast)


Lesenswert?

Hallo erstmal,

Programmierung:
Gcc, AVR Studio, Prozessor ATmega644P

Ziel:
Die Temperatur wird über einen KTY10 eingelesen und soll nun auf den 7 
Segmentanzeigen ausgegeben werden.

Den ADC hab ich zuerst alleine ohne Ausgabe geteste: Er gibt die ADC 
werte richtig aus (HTerm, UART). Nun wollte ich die drei 7 Segmente dazu 
schalten und einfach mal bis 999 zählen lassen umzu kontrolliern ob mein 
multiplexing Programm funktioniert. Jedoch tritt hier der Fehler auf: 
Compeliern funktioniert wunderbar, jedoch sieht es soaus als würden die 
7 Sgmente nun zu wenig Spannung bekommen (?), bzw. es leuchtet nur eines 
sehr schwach.
Wenn ich den ADC Init auskommentiere lauft das Programm wieder wunderbar 
(7-Segmente zählen bis 999).

An was kann das liegen?
wäre um jede Hilfe sehr dankbar :)

mfg Dominik
1
#include <avr/io.h>
2
#include <stdint.h>
3
#include <stdlib.h>
4
#include <util/delay.h>
5
#include <avr/interrupt.h>
6
#include <stdio.h>
7
8
//#include "uart.h"
9
#include "multiplexen.h"
10
11
uint8_t ADCwert;    //globale Variable für ADC wert
12
int i, k, l;
13
void init_Port()
14
{
15
  DISPLAY_DDR= 0xFF;
16
  SEGMENTS_DDR=0xFF;
17
  DISPLAY_PORT=0x00;
18
  SEGMENTS_PORT=0x00;
19
  
20
}
21
22
void init_timerA()
23
{
24
  TCCR1B |= (1<<WGM12);    //CTC mode
25
  TCCR1B |= (1<<CS12);    // Prescaler - 256 - 62500
26
          
27
  TIMSK1 |= (1<<OCIE1A);
28
  OCR1A = 625;  // 16e6/256/1000
29
}
30
31
void init_timerB()
32
{
33
                    
34
  TCCR2B |= (1<<CS22);    //Prescaler 64
35
                
36
  TIMSK2 |= (1<<TOIE2);    //Overflow enable
37
}
38
39
ISR (TIMER1_COMPA_vect){
40
  
41
  i++;
42
  
43
  if(i==1000) i=0;
44
  
45
  if(i<10)
46
  {
47
    display_array[0] = i%10;
48
  }
49
  else if(i>=10 && i<100)
50
  {
51
    display_array[0] = i%10;
52
    display_array[1] = (i%100-i%10)/10;    // z.B: 
53
  }
54
  else if(i>=100 && i<1000){
55
    display_array[0] = i%10;
56
    display_array[1] = (i%100-i%10)/10;
57
    display_array[2] = (i%1000-i%100)/100;
58
  }    
59
  else
60
  {
61
    display_array[0]=0;
62
    display_array[1]=0;
63
    display_array[2]=0;
64
  }    
65
66
}  
67
68
ISR(TIMER2_OVF_vect){
69
  refresh_display();
70
}  
71
72
void inti_ADC()
73
{
74
  int result;            //dient zur Aufwährmung des ADC
75
  
76
  ADMUX |= (1<<REFS0);          
77
  ADMUX &= ~ (1<<REFS1);          //AVCC wird als Reference eingestellt 
78
  
79
  ADCSRA |= (1<<ADEN);          //ADC wird Enabled, kann verwendet werden 
80
  ADCSRA |= (1<<ADSC);        // ADC Start Conversation, 
81
  //ADCSRA |= (1<<ADATE);          //Der ADC arbeitet im FreeRunning Mode, 
82
  ADCSRA |= (1<<ADIE);              //ADC-Interrupt aktiviert
83
  ADCSRA |= ((1<<ADPS0) | (1<<ADPS2) | (1<<ADPS1));    //Prescaler 128 
84
  
85
  while ( ADCSRA & (1<<ADSC) ) {}// auf Abschluss der Konvertierung warten}
86
    result = ADCW;          // ADCW muss einmal gelesen werden,
87
                      // sonst wird Ergebnis der nächsten Wandlung
88
                      // nicht übernommen.
89
}
90
91
uint8_t read_wert(uint8_t channel)
92
{
93
                         // Kanal waehlen, ohne andere Bits zu beeinflußen
94
  ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
95
  ADCSRA |= (1<<ADSC);                 // eine Wandlung "single conversion"
96
  while (ADCSRA & (1<<ADSC) ) {}  // auf Abschluss der Konvertierung warten
97
  return ADCW;                      // ADC auslesen und zurückgeben
98
//  adc_wert = ADCW;
99
}
100
101
int main(void)
102
{
103
  init_Port();
104
  init_timerA();
105
  init_timerB();
106
  inti_ADC();
107
  //uart_init();
108
  init_Port();
109
  
110
  DDRA &=~(1<<PA0);    //Input ADC - Temp.Sensor
111
  
112
  //**************************Varbialen************************************
113
  char text [] = "ADC-WERT:_";
114
  char wert[20];
115
  
116
  sei();
117
118
    while(1)
119
    {
120
    ADCwert = read_wert(0);
121
  /*  
122
    for (i=0;text[i];i++)
123
      uart_putchar(text[i]);
124
    
125
    sprintf (wert, "%3.1d",ADCwert);
126
    
127
    for (i=0; wert[i];i++)
128
      uart_putchar(wert[i]);
129
      
130
    _delay_ms(1000);  
131
    
132
        //TODO:: Please write your application code 
133
    */
134
  int p=0;
135
  p++;
136
    }
137
}
*****************************************************
multiplexen.h
*****************************************************
1
#ifndef MULTIPLEXEN_H_
2
#define MULTIPLEXEN_H_
3
4
5
unsigned int display_array[3];
6
7
#define SEGMENTS_DDR  DDRB
8
#define SEGMENTS_PORT  PORTB
9
#define DISPLAY_DDR    DDRD  
10
#define DISPLAY_PORT  PORTD
11
12
//****************************_Init_7_Segment_*****************************
13
#define a  0b00000001
14
#define b  0b00000010
15
#define c  0b00000100
16
#define d  0b00001000
17
#define e  0b00010000
18
#define f  0b00100000
19
#define g  0b01000000
20
#define dp  0b10000000
21
22
#define NULL  a|b|c|d|e|f
23
#define EINS  b|c
24
#define ZWEI  a|b|g|e|d
25
#define DREI  a|b|c|d|g
26
#define VIER  b|c|f|g
27
#define FUENF  a|f|g|c|d
28
#define SECHS  a|f|g|e|d|c
29
#define SIEBEN  a|b|c
30
#define ACHT  a|b|c|d|e|f|g
31
#define NEUN  a|b|c|d|f|g
32
33
//***************************_Init_von_2_Segmente_**************************
34
#define EINER    0b00000001
35
#define ZEHNER    0b00000010
36
#define HUNDERTER  0b00000100
37
38
39
void refresh_display();
40
41
42
43
44
#endif /* MULTIPLEXEN_H_ */
***************************************************
multiplexen.c
**************************************************
1
#include <avr/io.h>
2
#include "multiplexen.h";
3
4
5
unsigned int cnt=0;
6
7
void refresh_display(){
8
  
9
  //Display disable
10
  DISPLAY_PORT = 0x00;
11
  SEGMENTS_PORT= 0x00;
12
  
13
  switch (display_array[cnt]) {
14
    case 0:  SEGMENTS_PORT |= NULL;  break;
15
    case 1:  SEGMENTS_PORT |= EINS;  break;
16
    case 2:  SEGMENTS_PORT |= ZWEI;  break;
17
    case 3:  SEGMENTS_PORT |= DREI;  break;
18
    case 4:  SEGMENTS_PORT |= VIER;  break;
19
    case 5:  SEGMENTS_PORT |= FUENF;  break;
20
    case 6:  SEGMENTS_PORT |= SECHS;  break;
21
    case 7:  SEGMENTS_PORT |= SIEBEN;  break;
22
    case 8:  SEGMENTS_PORT |= ACHT;  break;
23
    case 9:  SEGMENTS_PORT |= NEUN;  break;
24
  }
25
  switch (cnt) {
26
    case 0:    DISPLAY_PORT |= EINER;  break;          //Zuschalten der jeweiligen Anzeige
27
    case 1:    DISPLAY_PORT |= ZEHNER; break;
28
    case 2:    DISPLAY_PORT |= HUNDERTER; break;
29
  }
30
  cnt++;                        //steter Wechsel zwischen Anzeigen
31
  if (cnt == 3)
32
    cnt = 0;
33
}

von Krapao (Gast)


Lesenswert?

Dein AVR stürzt dauernd ab, weil du in inti_ADC() einen IRQ frei gibst, 
für den du keine ISR hast. AVR startet, LED-Anzeige startet, AVR stürzt 
ab, LED-Anzeige ist dunkel...

von Dominik (Gast)


Lesenswert?

ah danke für die schnelle Antwort :)

hmm bin wirklich noch der Leihe im Gebiet AVR programmierung.

hab jz den: ADCSRA |= (1<<ADIE);              //ADC-Interrupt
deaktiviert.

Was wäre denn dein Lösungsvorschlag wie ich dieses Problem am besten 
bewältige?

mfg Dominik

von Krapao (Gast)


Lesenswert?

> hab jz den:
> ADCSRA |= (1<<ADIE); //ADC-Interrupt
> deaktiviert.

Welches Problem jetzt noch? Dass du ADCwert noch auf die Anzeige bringen 
musst?

1
volatile uint16_t spannung;
2
3
ISR (TIMER1_COMPA_vect)
4
{
5
  // i++;
6
  // if(i==1000) i=0;
7
  i = spannung; // Anzuzeigende Spannung kopieren, 
8
                // dann Ziffern extrahieren
9
...

in main():
[C]
...
    // Ref.: AVCC with external capacitor at AREF pin
    ADCwert = read_wert(0);
    // Anzeige der Spannung in "Centivolt",
    // da Anzeige nur dreistellig
    ADCwert = (ADCwert * 500UL) / 1024;
    cli(); // atomarer Zugriff!
    spannung = ADCwert;
    sei();
...
[C]

von Dominik (Gast)


Lesenswert?

hab vorhin vergessen zuschreiben,
Die ADC-Werte lassen sich nun auf den 7Segment Anzeigen ausgeben.
Möchte ich aber die Werte mit dem UART zusätzlich auslesen, gibts ein 
Problem.
1
  init_Port();
2
  init_timerA();
3
  init_timerB();
4
  inti_ADC();
5
  uart_init(); // Problemm
6
  init_Port();


Wenn ich uart_init(); mit einbeziehe fangen die 7 Segmente zu flakern 
an... bzw. iwas zu tun...(?)
1
#define F_CPU 16000000UL
2
#define BAUD 19200UL
3
#define UBRR_BAUD ((F_CPU/(16UL*BAUD))-1)
4
5
6
unsigned char uart_putchar(unsigned char x)
7
{
8
  //Warten bis der Sendepuffer frei ist
9
  while(!(UCSR0A & (1<<UDRE0)));
10
  //Daten in den Puffer schreiben und damit senden
11
  UDR0= x;
12
  return(x);
13
}
14
15
16
unsigned char uart_getchar()
17
{
18
  //Warten bis Daten empfangen wurden
19
  while(!(UCSR0A & (1<<RXC0)));
20
  //Empfangsregister auslesen
21
  return(UDR0);
22
}
23
24
25
//USART initialisieren
26
void uart_init(void)
27
{
28
  //Baudrate einstellen (nomal MOde)
29
  UBRR0H = (uint8_t) (UBRR_BAUD>>8);
30
  UBRR0L = (uint8_t) (UBRR_BAUD & 0x0ff); //uint8_t
31
32
  //Aktivieren von receiver und transmitter
33
  UCSR0B =(1<<RXEN0)|(1<<TXEN0);
34
35
  //Einstellen des Datenformats: 8 Datenbits, 1 Stopbit, no Parity
36
  //UCSR1C= (1<<URSEL)|(1<<UCSZ11)|(1<<UCSZ10);
37
  UCSR0C= (1<<UCSZ01)|(1<<UCSZ00);
38
}

von Krapao (Gast)


Lesenswert?

> #define DISPLAY_DDR    DDRD
> #define DISPLAY_PORT  PORTD

Die TX/RX Leitungen hängen beim Atmega644P doch auch auf Port D. Es ist 
klar, dass sich UART und Display beeinflussen. Vielleicht kannst du das 
Display auf Port C hängen und den Code umschreiben (Defines anpassen).

von Krapao (Gast)


Lesenswert?

Port C: JTAGEN Fuse abschalten nicht vergessen!

von Dominik (Gast)


Lesenswert?

super danke für deine Hilfe :)
funktiniert alles

ich werde nun noch einen kleinen 5V Computerventilator in mein kleines 
Projekt implementieren :) der in abhängigkeit der Temperatur, schneller 
oder langsamer dreht.

ich melde mich wenn es geklappt hat :)

danke nochmals
mfg Dominik

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.