Dag iedereen,

Ik ben net begonnen met mc's en als oefening probeer ik met een tiny2313 een 7 segment teller met 2 segmenten te maken.

in men code probeer ik een waarde af te ronden, maar AVRstudio geeft een error als ik wil compilen. Heeft iemand een idee wat ik verkeerd doe?

segment2 = floor (count/10);
segment1 = count - segment2;

dit is men volledige code


/* 
verbindngen 7segment:

a->PD5
b->PD4
c->PD1
d->PD2

e->PD3
f->PD6
g->PD7
DP->PD0


*/


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

#define SEVEN_SEGMENT_PORT PORTB
#define SEVEN_SEGMENT_DDR DDRB


void SevenSegment(uint8_t n,uint8_t dp)
{
/*
This function writes a digit given by n to the display

the decimal point is displayed if dp=1

Note:
n must be less than 9
*/
   if(n<10)
   {
      switch (n)
      {
         case 0:
         SEVEN_SEGMENT_PORT=0b01111110;
         break;

         case 1:
         SEVEN_SEGMENT_PORT=0b00010010;
         break;

         case 2:
         SEVEN_SEGMENT_PORT=0b10111100;
         break;

         case 3:
         SEVEN_SEGMENT_PORT=0b10110110;
         break;

         case 4:
         SEVEN_SEGMENT_PORT=0b11010010;
         break;

         case 5:
         SEVEN_SEGMENT_PORT=0b11100110;
         break;

         case 6:
         SEVEN_SEGMENT_PORT=0b11101110;
         break;

         case 7:
         SEVEN_SEGMENT_PORT=0b01110010;
         break;

         case 8:
         SEVEN_SEGMENT_PORT=0b11111110;
         break;

         case 9:
         SEVEN_SEGMENT_PORT=0b11110110;
         break;

		 case 10:
         SEVEN_SEGMENT_PORT=0b00011110;
         break;

		 case 11:
         SEVEN_SEGMENT_PORT=0b10001110;
         break;

		 case 12:
         SEVEN_SEGMENT_PORT=0b00000010;
         break;

		 case 13:
         SEVEN_SEGMENT_PORT=0b10001010;
         break;

		 case 14:
         SEVEN_SEGMENT_PORT=0b11001100;
         break;
      }
      if(dp)
      {
         //if decimal point should be displayed

         //make 0th bit Low
         SEVEN_SEGMENT_PORT&=0b11111110;
      }
   }
   else
   {
      //This symbol on display tells that n was greater than 9
      //so display can't handle it

      SEVEN_SEGMENT_PORT=0b11111101;
   }
}


void main()
{
  int count;
  int segment1;
  int segment2;
   SEVEN_SEGMENT_DDR=0xFF;    //All output
   SEVEN_SEGMENT_PORT=0x00;   //All segments off 
  count=0; 
  // oneindige lus
  while(1)
  {
    segment2 = floor (count/10);
	segment1 = count - segment2;
    SevenSegment(count,0);
	// PB0 hoog niveau (decimal point)
    PORTB |= (1 << PB0);
    // teller +1
    count++;
    // 0.5 sec delay
    _delay_ms(500);
    // PB0 laag niveau
    PORTB &= ~(1 << PB0);
    if(count==100)
	  {
	  count=0;
	  }   
    // 0.5 sec delay
    _delay_ms(500);
    
  }
}

alvast bedankt

Wat was de foutmelding?

Edit: misschien moet je math.h includen

[Bericht gewijzigd door RobHoi op (48%)]

floor() is een functie die met floats werkt. Niet aan te bevelen voor een µC, dus.
Je kan het ook zo doen:


    unsigned char getal;        // Max 99!
    unsigned char tientallen = 0;

    while (getal > 9) {
	tientallen++;
	getal -= 10;
    }
    // getal bevat nu de eenheden

Dat neemt enkele regels meer in beslag, maar de uiteindelijke code zal heel wat kleiner zijn.

Daarnaast kan je beter een opzoek-tabel gebruiken om te weten welke segmenten moeten oplichten.

En wat is er mis met

tientallen = getal / 10;
getal = getal % 10;

Jouw code neemt 10 bytes extra in beslag... :-)

het resultaat van een deling mag je niet in een integer opslaan.

en dus heeft de TS netjes de Floor functie gebruikt, wat kennelijk ook niet werkt.

beter is het om de div en mod functies te gebruiken (de mod functie heet inderdaad % in C)
en dan met 2 variabelen werken, zoals pros zegt.

p.s. waarom heb je 14 cases als je n maar tot 9 gaat?

Op 14 mei 2010 16:36:15 schreef Progger:
het resultaat van een deling mag je niet in een integer opslaan.

En waarom dan niet? Je moet alleen weten wat er gebeurt.

Op 14 mei 2010 16:35:48 schreef pros:
Jouw code neemt 10 bytes extra in beslag... :-)

Maar ik bespaar 10 toetsaanslagen :)

[Bericht gewijzigd door JoWi op (29%)]

if(n<10)
{...
	case 10:
         SEVEN_SEGMENT_PORT=0b00011110;
         break;
 
	case 11:
         SEVEN_SEGMENT_PORT=0b10001110;
         break;
...
}

lijkt me niet echt nuttig..

int count;
count=0;

mag je gerust vervangen door:

int count = 0;
int segment2;
segment2 = floor (count/10);

Vervang deze integer eens in een float of double variabele, dan zou het moeten werken.

Bedankt voor de tips iedereen

Ik heb het als volgt opgelost

  int count = 0;
  int tientallen;
  int eenheden;
   SEVEN_SEGMENT_DDR=0xFF;
   SEVEN_SEGMENT_PORT=0x00;
  while(1)
  {
    tientallen = count / 10;
    tientallen = tientallen % 10;
	eenheden = count - (10*tientallen);

p.s. waarom heb je 14 cases als je n maar tot 9 gaat?

Dat zijn nog restanten van één van mijn probeersels. Er komen nog stukken code bij en er gaan ook nog stukken uit.

Hoe accuraat is de interne timer van de tiny2313 trouwens. Ik heb in men project settings de frequentie op 10Mhz gezet, maar men teller wijkt per seconde toch nog een paar tienden af.

volledige code

/* 
verbindngen 7segment:

a->PD5
b->PD4
c->PD1
d->PD2

e->PD3
f->PD6
g->PD7
DP->PD0


*/


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

#define SEVEN_SEGMENT_PORT PORTB
#define SEVEN_SEGMENT_DDR DDRB


void SevenSegment(uint8_t n,uint8_t dp)
{
/*
This function writes a digit given by n to the display

the decimal point is displayed if dp=1

Note:
n must be less than 9
*/
   if(n<10)
   {
      switch (n)
      {
         case 0:
         SEVEN_SEGMENT_PORT=0b01111110;
         break;

         case 1:
         SEVEN_SEGMENT_PORT=0b00010010;
         break;

         case 2:
         SEVEN_SEGMENT_PORT=0b10111100;
         break;

         case 3:
         SEVEN_SEGMENT_PORT=0b10110110;
         break;

         case 4:
         SEVEN_SEGMENT_PORT=0b11010010;
         break;

         case 5:
         SEVEN_SEGMENT_PORT=0b11100110;
         break;

         case 6:
         SEVEN_SEGMENT_PORT=0b11101110;
         break;

         case 7:
         SEVEN_SEGMENT_PORT=0b01110010;
         break;

         case 8:
         SEVEN_SEGMENT_PORT=0b11111110;
         break;

         case 9:
         SEVEN_SEGMENT_PORT=0b11110110;
         break;

		 case 10:
         SEVEN_SEGMENT_PORT=0b00011110;
         break;

		 case 11:
         SEVEN_SEGMENT_PORT=0b10001110;
         break;

		 case 12:
         SEVEN_SEGMENT_PORT=0b00000010;
         break;

		 case 13:
         SEVEN_SEGMENT_PORT=0b10001010;
         break;

		 case 14:
         SEVEN_SEGMENT_PORT=0b11001100;
         break;
      }
      if(dp)
      {
         //if decimal point should be displayed

         //make 0th bit Low
         SEVEN_SEGMENT_PORT&=0b11111110;
      }
   }
   else
   {
      //This symbol on display tells that n was greater than 9
      //so display can't handle it

      SEVEN_SEGMENT_PORT=0b11111101;
   }
}


void main()
{
  int count = 0;
  int tientallen;
  int eenheden;
   SEVEN_SEGMENT_DDR=0xFF;    //All output
   SEVEN_SEGMENT_PORT=0x00;   //All segments off ; 
  // oneindige lus
  while(1)
  {
    tientallen = count / 10;
    tientallen = tientallen % 10;
	eenheden = count - (10*tientallen);
    SevenSegment(eenheden,0);
	// PB0 hoog niveau (decimal point)
    PORTB |= (1 << PB0);
    // teller +1
    count++;
    // 0.5 sec delay
    _delay_ms(500);
    // PB0 laag niveau
    PORTB &= ~(1 << PB0);
    if(count==100)
	  {
	  count=0;
	  }   
    // 0.5 sec delay
    _delay_ms(500);
    
  }
}

Op 14 mei 2010 17:58:31 schreef retro man:


    tientallen = count / 10;
    tientallen = tientallen % 10;
    eenheden = count - (10*tientallen);

Moet dus zijn:


  tientallen = count / 10;
  eenheden = count % 10;

Je tweede regel doet niks (aannemende dat het getal < 100 is)

Hoe accuraat is de interne timer van de tiny2313 trouwens.

Met de interne R/C-oscillator is dat allesbehalve accuraat. Maar als je een extern kristal gebruikt, ziet het er al heel wat beter uit.

Ik heb in men project settings de frequentie op 10Mhz gezet.

Hoe heb je dat gedaan?

Nog een tip voor die segmenten. Ik doe dat meestal zo:


#define seg_a	_BV(PB7)
#define seg_b	_BV(PB5)
#define seg_c	_BV(PB3)
#define seg_d	_BV(PB0)
#define seg_e	_BV(PB2)
#define seg_f	_BV(PB6)
#define seg_g	_BV(PB4)
#define seg_dp	_BV(PB1)

#define NUL   	0xFF & ~(seg_a | seg_b | seg_c | seg_d | seg_e | seg_f)
#define EEN   	0xFF & ~(seg_b | seg_c)
#define TWEE  	0xFF & ~(seg_a | seg_b | seg_d | seg_e | seg_g)
#define DRIE  	0xFF & ~(seg_a | seg_b | seg_c | seg_d | seg_g)
#define VIER  	0xFF & ~(seg_b | seg_c | seg_f | seg_g)
#define VIJF  	0xFF & ~(seg_a | seg_c | seg_d | seg_f | seg_g)
#define ZES   	0xFF & ~(seg_a | seg_c | seg_d | seg_e | seg_f | seg_g)
#define ZEVEN 	0xFF & ~(seg_a | seg_b | seg_c)
#define ACHT  	0xFF & ~(seg_a | seg_b | seg_c | seg_d | seg_e | seg_f | seg_g)
#define NEGEN 	0xFF & ~(seg_a | seg_b | seg_c | seg_d | seg_f | seg_g)

unsigned char   CIJFERS[] = { NUL, EEN, TWEE, DRIE, VIER, VIJF, ZES, ZEVEN, ACHT, NEGEN};

// Voorbeeld
unsigned char x = 5;
PORTB = CIJFERS[x];

In dit geval gaat het om common-anode displays, waarbij de segmenten een laag niveau moeten krijgen om op te lichten. Voor common-kathode displays laat je die "0xFF & ~" weg.
En "_BV(PBx) kan je vervangen door "(1 << PBx)", als je dat wenst.