7 SEGMENT DISPLAY ILE KRONOMETRE

Bende hastalık var abi.

Tampon, sigorta, filtre, direnç kullanmadan devre kuramıyorum
Bunlar olmadan kurduğum devrenin sorun çıkaracağına ömrünun uzun olmayacağına kuvvetli düşüncelerim var
Bu 7 segmenti SPI ile sürme işinin mcu'ya maliyetini hiç ölçmemiştim. Bunu merak ettiğimden oyuncak kutumdan oyuncaklarımı çıkarıp ölçüyorum şimdi. Kod çok karmaşık, tam anımsayamıyorum teferruatını, arduino için düzenleyip seri monitöre yazdırıyorum sonuçları.

7segment:
/*

spi ile 74HC595 kullanımı

seri bağlı hc595 ile kullanılabilir.

hc595'in data ve clock pinleri sırasıyla spi MOSI ve SCK pinlerine bağlanır.
hc595 latch inputu mcu'nun başka bir çıkışıyla kontrol edilerek
8'in katları uzunluktaki ardışık veri transferinden sonra çıkışlar açılır.
hc595'in biri 7segment verisi diğeri gösterilecek basamak verisini alır. basamak multiplex metoduyla gösterilir

*/


#define F_CPU 16000000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>





#define MAKS 99999999      // gösterilebilir en büyük sayı

//#define MOD2X4
#define MOD1X4
//#define MOD1X8


#define DDR_SPI   DDRB          //
#define PORT_SPI  PORTB         //
#define SPI_SCK   PINB5         // 595 clock pinine D13
#define SPI_MOSI  PINB3         // 595 data pinine D11
#define SPI_SS    PINB2         //


#define DDR_LATCH DDRB     
#define PORT_LATCH  PORTB
#define PIN_LATCH 0             //// arduino D8


#define PORT_ENABLE
#define DDR_ENABLE
#define PIN_ENABLE

uint8_t bi;
uint8_t shiftest;

uint16_t  mask[9],seg[11];
volatile uint16_t disp_spi[9],birim;
uint8_t bas,disp_i;
int32_t gost[10];
volatile uint8_t secup,t0ofv;
uint32_t t0,t1,t2,t3,t00,t01,t10,t11;
int bufint=1000;



/**
  7SEGMENTS
    A
    F   B
    G 
    E   C
    D   DP

**/


// hangi segmentin hangi "595" bacağına bağlandığı

#define SEGA  1   //
#define SEGB  2 //      1-|''U''|-0
#define SEGC  4 //      2-|     |-  74HC595
#define SEGD  6 //      3-|     |-
#define SEGE  7 //      4-|     |-
#define SEGF  0 //      5-|     |-
#define SEGG  3 //      6-|     |-
#define SEGDP 5 //      7-|     |-

  // 1*8 disp
 
/*
#define SEGB0 8 //      9-|''U''|-8
#define SEGB1 11  //      10|   |-
#define SEGB2 10  //      11|   |-
#define SEGB3 9 //      12|   |-
#define SEGB4 12  //      13|   |-
#define SEGB5 13  //      14|   |-
#define SEGB6 14  //      15|.....|-
#define SEGB7 15  // 

*/

// 2*4 disp
#ifdef MOD2X4     // 4 basamaklı iki satır basamak karşılıkları
#define SEGB0 12  //      9-|''U''|-8
#define SEGB1 14  //      10|     |-
#define SEGB2 15  //      11|     |-
#define SEGB3 13  //      12|     |-
#define SEGB4 8   //      13|     |-
#define SEGB5 11  //      14|     |-
#define SEGB6 10  //      15|.....|-
#define SEGB7 9   // 
#endif


#ifdef MOD1X4   //4 basamaklı pcb için basamak karşılıkları
#define SEGB0 8 //        9-|''U''|-8
#define SEGB1 11  //      10|     |-
#define SEGB2 10  //      11|     |-
#define SEGB3 9 //        12|     |-
#define SEGB4 12  //      13|     |-
#define SEGB5 14  //      14|     |-
#define SEGB6 15  //      15|.....|-
#define SEGB7 13  //
#endif

#define A 1<<(15-SEGA)    //
#define B 1<<(15-SEGB)  //      1-|''U''|-0
#define C 1<<(15-SEGC)  //      2-|     |-  74HC595
#define D 1<<(15-SEGD)  //      3-|     |-
#define E 1<<(15-SEGE)  //      4-|     |-
#define F 1<<(15-SEGF)  //      5-|     |-
#define G 1<<(15-SEGG)  //      6-|     |-
#define DP  1<<(15-SEGDP) //    7-|     |-


#define B0  1<<(15-SEGB0) //      9-|''U''|-8
#define B1  1<<(15-SEGB1) //      10|   |-
#define B2  1<<(15-SEGB2) //      11|   |-
#define B3  1<<(15-SEGB3) //      12|   |-
#define B4  1<<(15-SEGB4) //      13|   |-
#define B5  1<<(15-SEGB5) //      14|   |-
#define B6  1<<(15-SEGB6) //      15|.....|-
#define B7  1<<(15-SEGB7) //   
 
/*

*/
#define La A|B|C|D|E|G
#define LA A|B|C|E|F|G
#define LB Lb
#define Lb C|D|E|F|G
#define Lc D|E|G
#define LC A|D|E|F
#define LD Ld
#define Ld B|C|D|E|G
#define LE A|D|E|F|G
#define Le A|B|D|E|F|G
#define LF Lf
#define Lf A|E|F|G
#define Lg LG
#define LG A|C|D|E|F
#define Lh C|E|F|G
#define LH B|C|E|F|G
#define LI Li
#define Li C
#define LJ Lj
#define Lj B|C|D
#define LK Lk
#define Lk F|G|E
#define LL Ll
#define Ll F|E|D
#define LN Ln
#define Ln E|G|C
#define LO Lo
#define Lo C|D|E|G
#define LP Lp
#define Lp A|B|E|F|G
#define LR Lr
#define Lr E|G
#define LS Ls
#define Ls A|C|D|F|G
#define LT Lt
#define Lt D|E|F|G
#define LU B|C|D|E|F
#define Lu E|D|C
#define LV Lv
#define Lv Lu
#define Ly LY
#define LY B|C|D|F|G
#define Lz LZ
#define LZ A|B|D|E|G
#define BLANK 0

void SPI_MasterInit(void);
void latch(void);
void basamak(int16_t sayi);
void seg_init(void);
void setdisp_spi(uint16_t l0,uint16_t l1,uint16_t l2,uint16_t l3,uint16_t l4,uint16_t l5,uint16_t l6,uint16_t l7,uint16_t l8);
void seg7 (void);









ISR(TIMER2_COMPA_vect) //7 segment ekranına(hc595'e) 16bitlik veriyi(8bit basamak değeri, 8bit açık-kapalı basamaklar) iki parça halinde gönderir.
{
  TCNT2=0;
 
 
  switch (disp_i)
  {
    case 0:
      latch();// bir öncegönderilen verinin hc595 çıkışlarına yansıtılması için latch pine sinyal gönder
      /*PORT_LATCH &= ~(1<<PIN_LATCH);
      PORT_LATCH |= (1<<PIN_LATCH);
      
      PORT_LATCH &= ~(1<<PIN_LATCH);
      */
      //Serial.println("latch");
      //basamak verisi
      //SPDR=(0b10000000);
      SPDR=(~disp_spi[bi])&0xff;
      disp_i++;
      break;
    case 1:
      //segment verisi
      //SPDR=(0b0);
      SPDR=(~disp_spi[bi])>>8;
      disp_i=0;
      bi++;
      if(bi>bas-1)
      {
        bi=0;
      }
      break;
  }
  secup++;//secup display fonksiyonunun periyodu için delay sayacı
  if(birim<64000){birim++;}
}


void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Basla");

 
  seg_init();
  SPI_MasterInit();
  sei();
}

void loop() {
  //
  if(millis()>(t1+1)){
    t2=micros();
    t1=millis();
    
    // 16 bit veriyi 8bitlik iki ayrı paket olarak göndermekte fayda var
    // eğer 16 biti kütüphane ile göndermeye kalkılırsa ilk 8 bitin gönderilmesini beklemek gerekir.
    switch (disp_i)
    {
      case 0:
        latch();// bir öncegönderilen verinin hc595 çıkışlarına yansıtılması için latch pine sinyal gönder
        /*PORT_LATCH &= ~(1<<PIN_LATCH);
        PORT_LATCH |= (1<<PIN_LATCH);
        
        PORT_LATCH &= ~(1<<PIN_LATCH);
        */
        //Serial.println("latch");
        //basamak verisi
        //SPDR=(0b10000000);
        SPDR=(~disp_spi[bi])&0xff;
        disp_i++;
        break;
      case 1:
        //segment verisi
        //SPDR=(0b0);
        SPDR=(~disp_spi[bi])>>8;
        disp_i=0;
        bi++;
        if(bi>bas-1)
        {
          bi=0;
        }
        break;
    }
    t2=micros()-t2;
    // spi'ye 8 bitlik veri gönderme süresi serial yazdırılır,
    // her basamak için iki gönderim yapılacak.
    // sonuç ortalama 6 microsaniye çıkıyor.
    // Bu süreç her milisaniye çalışarak 8 basamağı temiz sürebiliyor
    // ekran sürme yükü kabaca %0.1 oluyor işlemci için
    Serial.print("SPI = ");
    Serial.println(t2);
  }
  if(millis()>(t0+1000))
  {
    t00=micros();
    t0=millis();
    
    basamak (bufint++);
    t00=micros()-t00;
    // 4 basamaklı bir sayıyı basamaklarına ayırıp spi verisini hazırlama süresi 180 microsaniye
    Serial.print("Basamak = ");
    Serial.println(t00);
  }
 
 
}

void SPI_MasterInit(void)
{
  // Set MOSI and SCK output, all others input
  DDR_SPI = (1<<SPI_SCK)|(1<<SPI_MOSI)|(1<<SPI_SS);
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<DORD);//| (1<<SPR1);//| (1<<SPR0);
  SPSR |= 1<<SPI2X;
  DDR_LATCH |=(1<<PIN_LATCH);
}


void latch(void)
{
  PORT_LATCH &= ~(1<<PIN_LATCH);
  PORT_LATCH |= (1<<PIN_LATCH);
  PORT_LATCH &= ~(1<<PIN_LATCH);
}

void basamak(int16_t sayi)//basamakları hesaplar basamak değerlerini b[i] array değişkene atar ve 7segment display için binary registerlarını tayin eder
{
  uint8_t i,b[8];

  {
    gost[0]=sayi;
    for(i=0;i<9;i++)//bas:basamak sayısını mod için yardımcı değerleri hesaplar
    {
      gost[i+1]=gost[i]/10;
      
      if(gost[i+1]==0){bas=i+1;i=8;}
    }
    for(i=0;i<bas;i++)// 2^i basamağının değerlerini hesaplar
    {
      b[i]=gost[i]-gost[i+1]*10;
    }
    
    //basamak sayısı,işaret ve basamak değerleri hesaplandı
    for(i=0;i<bas;i++)
    {
      disp_spi[i]=seg[b[i]]|mask[i];
    }
    
  }
}

//set disp fonksiyonu, harf gösterimi içindir. parantez içindeki "makro harfler"i yazıldığı sırada gösterir
void setdisp_spi(uint16_t l0,uint16_t l1,uint16_t l2,uint16_t l3,uint16_t l4,uint16_t l5,uint16_t l6,uint16_t l7,uint16_t l8)
{
  disp_spi[8]=l0;disp_spi[7]=l1;disp_spi[6]=l2;disp_spi[5]=l3;disp_spi[4]=l4;disp_spi[3]=l5;disp_spi[2]=l6;
  disp_spi[1]=l7;disp_spi[0]=l8;
}

void seg_init(void)
{
  // timer2 CTC modda değiştirilebilir interrupt periyodu için
  // yeterli segment sürüş hızı için OCR2A ile timer top değeri ayarlanabilir
  //
  OCR2A = 10;
  TCCR2A |=  1<<WGM21 ;
  TCCR2B |=  0b111; // prscl: 0b10>>8 0b11>>32 0b100>>64 0b101>>128 0b110>>256 0b111>>1024 stepStarta ayarlanır
  //TIMSK2 |= 1<<OCIE2A ; //
 
  DDRD |= 1<<PIND6;
  /*
  TCCR2B = 0b11;//prscl 0b1=1
  TCCR2A|=1<<COM0A1|1<<WGM01|1<<WGM00;//fastpwm
 
  //PORTD|=1<<PIND6;
  TIMSK2 |= (1<<TOIE2); //Timer 0 overflov int. reg enab
  */

  seg[0]|=(A|B|C|D|E|F);
  seg[1]|=(B|C);
  seg[2]|=(A|B|G|E|D);
  seg[3]|=(A|B|G|C|D);
  seg[4]|=(B|C|G|F);
  seg[5]|=(A|F|G|C|D);//(1<<F)|(1<<G)|(1<<C)|(1<<D);
  seg[6]|=(A|F|G|C|D|E);//(1<<F)|(1<<G)|(1<<C)|(1<<D)|(1<<E);
  seg[7]|=(A|B|C);//(1<<C);
  seg[8]|=(A|B|C|G|E|D|F);//(1<<C)|(1<<G)|(1<<E)|(1<<D)|(1<<F);
  seg[9]|=(A|B|C|D|F|G);//(1<<C)|(1<<D)|(1<<F)|(1<<G);
  seg[10]|=(1<<DP);
 
  mask[0]=B0;//(1<<B0);
  mask[1]=B1;//(1<<B1);
  mask[2]=B2;//(1<<B2);
  mask[3]=B3;//(1<<B3);
  mask[4]=B4;//(1<<B4);
  mask[5]=B5;//(1<<B5);
  mask[6]=B6;//(1<<B6);
  mask[7]=B7;//(1<<B7);
  uint8_t i=0;
  for(i=0;i<8;i++){mask[8]|=mask[i];}
  for(i=0;i<8;i++){mask[i]=mask[8]&~mask[i];}
  //sec[2]|=DP;sec[4]|=DP;
 
}

Kod karmaşık, avr için yazmıştım ve içinde bolca çöp var. Ama bahsettiğim ölçümü yapmaya yetecek kadar düzenleyip arduinoya uyarladım. süreleri seri monitöre yazdırarak yakaladım.

Buna göre bu kodla

4 basamaklı bir sayıyı basamaklarına ayırıp spi verisini hazırlama süresi 184 mikrosaniye oluyor

8 basamaklı 7 segment ekranı düzgün sürmek için gereken spi'ya veri gönderme süresi, her milisaniyede ortalama 7 mikrosaniye oluyor.

Bu kodu 6 basamak için hazırlamışım ve iki satır displaylari bassamda kodu bunun için düzenlememişim.

LCD ekranı i2c ile sürünce sadece setcursor komutunu 1 milisaniye ölçmüştüm. Eğer ölçerken hata yapmadıysam güzel geldi bana sonuçlar.
 

Ekler

  • VID20220619004556.mp4
    8.8 MB
Bu 7 segmenti SPI ile sürme işinin mcu'ya maliyetini hiç ölçmemiştim. Bunu merak ettiğimden oyuncak kutumdan oyuncaklarımı çıkarıp ölçüyorum şimdi. Kod çok karmaşık, tam anımsayamıyorum teferruatını, arduino için düzenleyip seri monitöre yazdırıyorum sonuçları.

7segment:
/*

spi ile 74HC595 kullanımı

seri bağlı hc595 ile kullanılabilir.

hc595'in data ve clock pinleri sırasıyla spi MOSI ve SCK pinlerine bağlanır.
hc595 latch inputu mcu'nun başka bir çıkışıyla kontrol edilerek
8'in katları uzunluktaki ardışık veri transferinden sonra çıkışlar açılır.
hc595'in biri 7segment verisi diğeri gösterilecek basamak verisini alır. basamak multiplex metoduyla gösterilir

*/


#define F_CPU 16000000
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>





#define MAKS 99999999      // gösterilebilir en büyük sayı

//#define MOD2X4
#define MOD1X4
//#define MOD1X8


#define DDR_SPI   DDRB          //
#define PORT_SPI  PORTB         //
#define SPI_SCK   PINB5         // 595 clock pinine D13
#define SPI_MOSI  PINB3         // 595 data pinine D11
#define SPI_SS    PINB2         //


#define DDR_LATCH DDRB    
#define PORT_LATCH  PORTB
#define PIN_LATCH 0             //// arduino D8


#define PORT_ENABLE
#define DDR_ENABLE
#define PIN_ENABLE

uint8_t bi;
uint8_t shiftest;

uint16_t  mask[9],seg[11];
volatile uint16_t disp_spi[9],birim;
uint8_t bas,disp_i;
int32_t gost[10];
volatile uint8_t secup,t0ofv;
uint32_t t0,t1,t2,t3,t00,t01,t10,t11;
int bufint=1000;



/**
  7SEGMENTS
    A
    F   B
    G
    E   C
    D   DP

**/


// hangi segmentin hangi "595" bacağına bağlandığı

#define SEGA  1   //
#define SEGB  2 //      1-|''U''|-0
#define SEGC  4 //      2-|     |-  74HC595
#define SEGD  6 //      3-|     |-
#define SEGE  7 //      4-|     |-
#define SEGF  0 //      5-|     |-
#define SEGG  3 //      6-|     |-
#define SEGDP 5 //      7-|     |-

  // 1*8 disp
 
/*
#define SEGB0 8 //      9-|''U''|-8
#define SEGB1 11  //      10|   |-
#define SEGB2 10  //      11|   |-
#define SEGB3 9 //      12|   |-
#define SEGB4 12  //      13|   |-
#define SEGB5 13  //      14|   |-
#define SEGB6 14  //      15|.....|-
#define SEGB7 15  //

*/

// 2*4 disp
#ifdef MOD2X4     // 4 basamaklı iki satır basamak karşılıkları
#define SEGB0 12  //      9-|''U''|-8
#define SEGB1 14  //      10|     |-
#define SEGB2 15  //      11|     |-
#define SEGB3 13  //      12|     |-
#define SEGB4 8   //      13|     |-
#define SEGB5 11  //      14|     |-
#define SEGB6 10  //      15|.....|-
#define SEGB7 9   //
#endif


#ifdef MOD1X4   //4 basamaklı pcb için basamak karşılıkları
#define SEGB0 8 //        9-|''U''|-8
#define SEGB1 11  //      10|     |-
#define SEGB2 10  //      11|     |-
#define SEGB3 9 //        12|     |-
#define SEGB4 12  //      13|     |-
#define SEGB5 14  //      14|     |-
#define SEGB6 15  //      15|.....|-
#define SEGB7 13  //
#endif

#define A 1<<(15-SEGA)    //
#define B 1<<(15-SEGB)  //      1-|''U''|-0
#define C 1<<(15-SEGC)  //      2-|     |-  74HC595
#define D 1<<(15-SEGD)  //      3-|     |-
#define E 1<<(15-SEGE)  //      4-|     |-
#define F 1<<(15-SEGF)  //      5-|     |-
#define G 1<<(15-SEGG)  //      6-|     |-
#define DP  1<<(15-SEGDP) //    7-|     |-


#define B0  1<<(15-SEGB0) //      9-|''U''|-8
#define B1  1<<(15-SEGB1) //      10|   |-
#define B2  1<<(15-SEGB2) //      11|   |-
#define B3  1<<(15-SEGB3) //      12|   |-
#define B4  1<<(15-SEGB4) //      13|   |-
#define B5  1<<(15-SEGB5) //      14|   |-
#define B6  1<<(15-SEGB6) //      15|.....|-
#define B7  1<<(15-SEGB7) //  
 
/*

*/
#define La A|B|C|D|E|G
#define LA A|B|C|E|F|G
#define LB Lb
#define Lb C|D|E|F|G
#define Lc D|E|G
#define LC A|D|E|F
#define LD Ld
#define Ld B|C|D|E|G
#define LE A|D|E|F|G
#define Le A|B|D|E|F|G
#define LF Lf
#define Lf A|E|F|G
#define Lg LG
#define LG A|C|D|E|F
#define Lh C|E|F|G
#define LH B|C|E|F|G
#define LI Li
#define Li C
#define LJ Lj
#define Lj B|C|D
#define LK Lk
#define Lk F|G|E
#define LL Ll
#define Ll F|E|D
#define LN Ln
#define Ln E|G|C
#define LO Lo
#define Lo C|D|E|G
#define LP Lp
#define Lp A|B|E|F|G
#define LR Lr
#define Lr E|G
#define LS Ls
#define Ls A|C|D|F|G
#define LT Lt
#define Lt D|E|F|G
#define LU B|C|D|E|F
#define Lu E|D|C
#define LV Lv
#define Lv Lu
#define Ly LY
#define LY B|C|D|F|G
#define Lz LZ
#define LZ A|B|D|E|G
#define BLANK 0

void SPI_MasterInit(void);
void latch(void);
void basamak(int16_t sayi);
void seg_init(void);
void setdisp_spi(uint16_t l0,uint16_t l1,uint16_t l2,uint16_t l3,uint16_t l4,uint16_t l5,uint16_t l6,uint16_t l7,uint16_t l8);
void seg7 (void);









ISR(TIMER2_COMPA_vect) //7 segment ekranına(hc595'e) 16bitlik veriyi(8bit basamak değeri, 8bit açık-kapalı basamaklar) iki parça halinde gönderir.
{
  TCNT2=0;
 
 
  switch (disp_i)
  {
    case 0:
      latch();// bir öncegönderilen verinin hc595 çıkışlarına yansıtılması için latch pine sinyal gönder
      /*PORT_LATCH &= ~(1<<PIN_LATCH);
      PORT_LATCH |= (1<<PIN_LATCH);
     
      PORT_LATCH &= ~(1<<PIN_LATCH);
      */
      //Serial.println("latch");
      //basamak verisi
      //SPDR=(0b10000000);
      SPDR=(~disp_spi[bi])&0xff;
      disp_i++;
      break;
    case 1:
      //segment verisi
      //SPDR=(0b0);
      SPDR=(~disp_spi[bi])>>8;
      disp_i=0;
      bi++;
      if(bi>bas-1)
      {
        bi=0;
      }
      break;
  }
  secup++;//secup display fonksiyonunun periyodu için delay sayacı
  if(birim<64000){birim++;}
}


void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  Serial.println("Basla");

 
  seg_init();
  SPI_MasterInit();
  sei();
}

void loop() {
  //
  if(millis()>(t1+1)){
    t2=micros();
    t1=millis();
   
    // 16 bit veriyi 8bitlik iki ayrı paket olarak göndermekte fayda var
    // eğer 16 biti kütüphane ile göndermeye kalkılırsa ilk 8 bitin gönderilmesini beklemek gerekir.
    switch (disp_i)
    {
      case 0:
        latch();// bir öncegönderilen verinin hc595 çıkışlarına yansıtılması için latch pine sinyal gönder
        /*PORT_LATCH &= ~(1<<PIN_LATCH);
        PORT_LATCH |= (1<<PIN_LATCH);
       
        PORT_LATCH &= ~(1<<PIN_LATCH);
        */
        //Serial.println("latch");
        //basamak verisi
        //SPDR=(0b10000000);
        SPDR=(~disp_spi[bi])&0xff;
        disp_i++;
        break;
      case 1:
        //segment verisi
        //SPDR=(0b0);
        SPDR=(~disp_spi[bi])>>8;
        disp_i=0;
        bi++;
        if(bi>bas-1)
        {
          bi=0;
        }
        break;
    }
    t2=micros()-t2;
    // spi'ye 8 bitlik veri gönderme süresi serial yazdırılır,
    // her basamak için iki gönderim yapılacak.
    // sonuç ortalama 6 microsaniye çıkıyor.
    // Bu süreç her milisaniye çalışarak 8 basamağı temiz sürebiliyor
    // ekran sürme yükü kabaca %0.1 oluyor işlemci için
    Serial.print("SPI = ");
    Serial.println(t2);
  }
  if(millis()>(t0+1000))
  {
    t00=micros();
    t0=millis();
   
    basamak (bufint++);
    t00=micros()-t00;
    // 4 basamaklı bir sayıyı basamaklarına ayırıp spi verisini hazırlama süresi 180 microsaniye
    Serial.print("Basamak = ");
    Serial.println(t00);
  }
 
 
}

void SPI_MasterInit(void)
{
  // Set MOSI and SCK output, all others input
  DDR_SPI = (1<<SPI_SCK)|(1<<SPI_MOSI)|(1<<SPI_SS);
  SPCR = (1<<SPE)|(1<<MSTR)|(1<<DORD);//| (1<<SPR1);//| (1<<SPR0);
  SPSR |= 1<<SPI2X;
  DDR_LATCH |=(1<<PIN_LATCH);
}


void latch(void)
{
  PORT_LATCH &= ~(1<<PIN_LATCH);
  PORT_LATCH |= (1<<PIN_LATCH);
  PORT_LATCH &= ~(1<<PIN_LATCH);
}

void basamak(int16_t sayi)//basamakları hesaplar basamak değerlerini b[i] array değişkene atar ve 7segment display için binary registerlarını tayin eder
{
  uint8_t i,b[8];

  {
    gost[0]=sayi;
    for(i=0;i<9;i++)//bas:basamak sayısını mod için yardımcı değerleri hesaplar
    {
      gost[i+1]=gost[i]/10;
     
      if(gost[i+1]==0){bas=i+1;i=8;}
    }
    for(i=0;i<bas;i++)// 2^i basamağının değerlerini hesaplar
    {
      b[i]=gost[i]-gost[i+1]*10;
    }
   
    //basamak sayısı,işaret ve basamak değerleri hesaplandı
    for(i=0;i<bas;i++)
    {
      disp_spi[i]=seg[b[i]]|mask[i];
    }
   
  }
}

//set disp fonksiyonu, harf gösterimi içindir. parantez içindeki "makro harfler"i yazıldığı sırada gösterir
void setdisp_spi(uint16_t l0,uint16_t l1,uint16_t l2,uint16_t l3,uint16_t l4,uint16_t l5,uint16_t l6,uint16_t l7,uint16_t l8)
{
  disp_spi[8]=l0;disp_spi[7]=l1;disp_spi[6]=l2;disp_spi[5]=l3;disp_spi[4]=l4;disp_spi[3]=l5;disp_spi[2]=l6;
  disp_spi[1]=l7;disp_spi[0]=l8;
}

void seg_init(void)
{
  // timer2 CTC modda değiştirilebilir interrupt periyodu için
  // yeterli segment sürüş hızı için OCR2A ile timer top değeri ayarlanabilir
  //
  OCR2A = 10;
  TCCR2A |=  1<<WGM21 ;
  TCCR2B |=  0b111; // prscl: 0b10>>8 0b11>>32 0b100>>64 0b101>>128 0b110>>256 0b111>>1024 stepStarta ayarlanır
  //TIMSK2 |= 1<<OCIE2A ; //
 
  DDRD |= 1<<PIND6;
  /*
  TCCR2B = 0b11;//prscl 0b1=1
  TCCR2A|=1<<COM0A1|1<<WGM01|1<<WGM00;//fastpwm
 
  //PORTD|=1<<PIND6;
  TIMSK2 |= (1<<TOIE2); //Timer 0 overflov int. reg enab
  */

  seg[0]|=(A|B|C|D|E|F);
  seg[1]|=(B|C);
  seg[2]|=(A|B|G|E|D);
  seg[3]|=(A|B|G|C|D);
  seg[4]|=(B|C|G|F);
  seg[5]|=(A|F|G|C|D);//(1<<F)|(1<<G)|(1<<C)|(1<<D);
  seg[6]|=(A|F|G|C|D|E);//(1<<F)|(1<<G)|(1<<C)|(1<<D)|(1<<E);
  seg[7]|=(A|B|C);//(1<<C);
  seg[8]|=(A|B|C|G|E|D|F);//(1<<C)|(1<<G)|(1<<E)|(1<<D)|(1<<F);
  seg[9]|=(A|B|C|D|F|G);//(1<<C)|(1<<D)|(1<<F)|(1<<G);
  seg[10]|=(1<<DP);
 
  mask[0]=B0;//(1<<B0);
  mask[1]=B1;//(1<<B1);
  mask[2]=B2;//(1<<B2);
  mask[3]=B3;//(1<<B3);
  mask[4]=B4;//(1<<B4);
  mask[5]=B5;//(1<<B5);
  mask[6]=B6;//(1<<B6);
  mask[7]=B7;//(1<<B7);
  uint8_t i=0;
  for(i=0;i<8;i++){mask[8]|=mask[i];}
  for(i=0;i<8;i++){mask[i]=mask[8]&~mask[i];}
  //sec[2]|=DP;sec[4]|=DP;
 
}

Kod karmaşık, avr için yazmıştım ve içinde bolca çöp var. Ama bahsettiğim ölçümü yapmaya yetecek kadar düzenleyip arduinoya uyarladım. süreleri seri monitöre yazdırarak yakaladım.

Buna göre bu kodla

4 basamaklı bir sayıyı basamaklarına ayırıp spi verisini hazırlama süresi 184 mikrosaniye oluyor

8 basamaklı 7 segment ekranı düzgün sürmek için gereken spi'ya veri gönderme süresi, her milisaniyede ortalama 7 mikrosaniye oluyor.

Bu kodu 6 basamak için hazırlamışım ve iki satır displaylari bassamda kodu bunun için düzenlememişim.

LCD ekranı i2c ile sürünce sadece setcursor komutunu 1 milisaniye ölçmüştüm. Eğer ölçerken hata yapmadıysam güzel geldi bana sonuçlar.
Abi akşamdan beri okuyorum kafam karışıyor bu programda.
Registerleri daha fazla çalışmam gerek.

Bu gün 595 ve direkt sürüş ile testler yapacağım.
Teşekkür ederim yardımın için.
 
SEG.png

Bir'de böyle bir tasarım düşündüm.
Her tip display'e uyumlu olması için ortak uçlara bu şekilde jumper ile set etmek düşündüm.
 
17916 eklentisine bak
Bir'de böyle bir tasarım düşündüm.
Her tip display'e uyumlu olması için ortak uçlara bu şekilde jumper ile set etmek düşündüm.
O zaman zıt kutuplarını da yazılımsal olarak switch'lemen gerekir. Ortak anot yaptığında pinleri LOW çalışacak şekilde, Ortak katot yaptığında Pinleri HIGH çalışacak şekilde programlaman lazım. Bunu program kendi algılayıp ona göre davranabiliyorsa güzel olur.
 
Abi akşamdan beri okuyorum kafam karışıyor bu programda.
Registerleri daha fazla çalışmam gerek.

Bu gün 595 ve direkt sürüş ile testler yapacağım.
Teşekkür ederim yardımın için.
Bu kod kulağı tersten tutmak gibi yazılmış, avr'de farklı dosyalara dağılmıştı sadece performansı ölçmek için yığdım arduinoya, konsept için fikir verirse ne ala.
17916 eklentisine bak
Bir'de böyle bir tasarım düşündüm.
Her tip display'e uyumlu olması için ortak uçlara bu şekilde jumper ile set etmek düşündüm.

Bunu kodla yapmak kolay. Doğrudan hc595'lerle sürünce, gönderilecek datayı "~" (bitwise comlement ) tersine çevirerek ortak anot veya veya katoda uygun hale gelir. çip hem sink hem source yapabiliyor.
 
Bu kod kulağı tersten tutmak gibi yazılmış, avr'de farklı dosyalara dağılmıştı sadece performansı ölçmek için yığdım arduinoya, konsept için fikir verirse ne ala.


Bunu kodla yapmak kolay. Doğrudan hc595'lerle sürünce, gönderilecek datayı "~" (bitwise comlement ) tersine çevirerek ortak anot veya veya katoda uygun hale gelir. çip hem sink hem source yapabiliyor.
output.png

Böyle bir çıkış tasarımı düşündüm 2 türlü display ile kullanmak mümkün olsun diye.
 
O zaman zıt kutuplarını da yazılımsal olarak switch'lemen gerekir. Ortak anot yaptığında pinleri LOW çalışacak şekilde, Ortak katot yaptığında Pinleri HIGH çalışacak şekilde programlaman lazım. Bunu program kendi algılayıp ona göre davranabiliyorsa güzel olur.
onuda algılatabilirim abi bir dijital girişi'de ona kullanmak gerekir.

universal olması bana bir katkı sağlamaz devreyi ben yapacağım ama başka yapanlar "bendeki displayler ortak anot bu proje ortak katot ile yapılmış diyip vazgeçmesin diye."
 
17917 eklentisine bak
Böyle bir çıkış tasarımı düşündüm 2 türlü display ile kullanmak mümkün olsun diye.

Doğrudan puş pul çıkışın sürmesi lazım segmenti ve direnç değerinin de oldukça düşük olması gerekiyor. Segmentler çok kısa süreliğine yandığı için anlık yüksek akım geçirmek gerekiyor. Böyle pull up yaparsan o dirençler yeterince yüksek akım vermeyecektir display segmentlerine.
 
Doğrudan puş pul çıkışın sürmesi lazım segmenti ve direnç değerinin de oldukça düşük olması gerekiyor. Segmentler çok kısa süreliğine yandığı için anlık yüksek akım geçirmek gerekiyor. Böyle pull up yaparsan o dirençler yeterince yüksek akım vermeyecektir display segmentlerine.
Bu 2 tip 7 segman için adımları opsiyonel yapabiliriz o zaman.

Ben artak anot display'ler ile yapmaya karar verdim.
Ama hem yazılım tarafında hem donanım tarafında 2 tip ekran için yapılacakları ekleyebilirim.
Ufak telefon kazaları geçirdik o yüzden biraz aksadı bu gün proje.
 
Datasheette timer registerlerinde tablosu var. tablodaki değerlere göre farklı etkileri oluyor. değişken PWM frekansı veya timer kesme değerini ayarlamak gibi etkileri var. Amaç ne?
 
Datasheette timer registerlerinde tablosu var. tablodaki değerlere göre farklı etkileri oluyor. değişken PWM frekansı veya timer kesme değerini ayarlamak gibi etkileri var. Amaç ne?
Sayfa 111'deki tablodan anlayamadığım nasıl ayarlıyoruz
https://mekatronik.org/forum/threads/arduino-uno-r3-ile-temel-projeler.38/ #5'inci mesaj.

Bu projeyi yapıyorum daha tasarım ve ufak yazılım denemelerini yapıyorum.

Hedefim en az yardım ile bu projeyi ortaya çıkarmak.
 
OCR1A veya timer1'in registerlarini anlamak için "modes of operation" kısmını anlamak lazım. Mesela çok hassas periyotlu kesmeler ayarlamak için CTC- clear timer on compare match modunda, timer, karşılaştırma registerinine ulaşınca timeri 0'layacak şekilde kullanılabilir. Buna göre ayarlanırsa timer1 TCNT1 sayacı OCR1A'ya atanan değere geldiğinde otomatik sıfırlanıp OCIE1A kesmesi bayrağı 1 olur ve ilgili interrupt rutini çalışır, TCNT1 0'dan devam eder.
 
OCR1A veya timer1'in registerlarini anlamak için "modes of operation" kısmını anlamak lazım. Mesela çok hassas periyotlu kesmeler ayarlamak için CTC- clear timer on compare match modunda, timer, karşılaştırma registerinine ulaşınca timeri 0'layacak şekilde kullanılabilir. Buna göre ayarlanırsa timer1 TCNT1 sayacı OCR1A'ya atanan değere geldiğinde otomatik sıfırlanıp OCIE1A kesmesi bayrağı 1 olur ve ilgili interrupt rutini çalışır, TCNT1 0'dan devam eder.
Benim istediğim keseceği süreyi ayarlayan mantığı anlamak.
Baktığım örneklerde rastgele yazılan 15345 gibi değerler var nası buluyoruz bu değerleri
 
Timer prescaler'la çalışıyor, ve timer1 clock select bitleriyle ayarlanan frekansta çalışıyor
1655648942530.png

prescaler işlemci frekansını bu bitlere göre bölerek timer frekansını ayarlıyor. hatta tabloya göre timer için clock kaynağı harici T1 pininin yükselen veya alçalan kenarı olabiliyor.

Buna göre her bir timer1 saati frekansa göre değer alıyor. mesela


cs12cs11cs10
0 1 1 clkI/O/64 (From prescaler)

16 mhz ana frekans /64 = 250khz çalışır timer. Bu da her bir timer clock için 1/250.000 saniye süre geçtiği anlamına gelir.
buna göre 0,001 saniye için 0,001/(1/250.000)=250 timer clock gerekir. Hesapta bir hata yoksa OCR1A'yı 250 yaparak ctc moda 1ms'lik kesmeler elde edilebilir.
 
Timer prescaler'la çalışıyor, ve timer1 clock select bitleriyle ayarlanan frekansta çalışıyor
17919 eklentisine bak
prescaler işlemci frekansını bu bitlere göre bölerek timer frekansını ayarlıyor. hatta tabloya göre timer için clock kaynağı harici T1 pininin yükselen veya alçalan kenarı olabiliyor.

Buna göre her bir timer1 saati frekansa göre değer alıyor. mesela


cs12cs11cs10
011clkI/O/64 (From prescaler)

16 mhz ana frekans /64 = 250khz çalışır timer. Bu da her bir timer clock için 1/250.000 saniye süre geçtiği anlamına gelir.
buna göre 0,001 saniye için 0,001/(1/250.000)=250 timer clock gerekir. Hesapta bir hata yoksa OCR1A'yı 250 yaparak ctc moda 1ms'lik kesmeler elde edilebilir.

aynı sonuç prescaleri 1 ayarlayıp OCR1A'yı 250*64=16000 olarak atayıp elde edilebilir. Böyle yapınca daha yüksek çözünürlüklü kesmeler elde etmek mümkün olur. 100 mikro saniye için de OCR1A = 1600 atanabilir.

Timer1 16 bit olduğundan prescaler 1024 kullanarak insanın algılayabileceği sürelerde kesmelerle deneyler yapılabilir. 65535'te timer taşma yapar 65535*(1/16.000.000)*1024 = 4,19424 saniye sürer.
 
Bir tutarsızlık var veya seri port bu şekilde.
OCR1A'yı 250'ye ayarlayınca bu şeklide çıktı alıyorum.
pr.png

Bir dijital pin set-reset edip ona mı baksam acaba skop ile.
 
C++:
#define led 8


void setup() {
  Serial.begin(115200);
  pinMode(led, OUTPUT);

  noInterrupts();

  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  OCR1A = 250;

  TCCR1B |= (1 << WGM12);
  TCCR1B |= (1 << CS12) | (1 << CS10);
  TIMSK1 |= (1 << OCIE1A);
  interrupts();
}

ISR(TIMER1_COMPA_vect) {
 digitalWrite(8,HIGH);
 delay(1);
 digitalWrite(8,LOW);
}
 
C++:
#define led 8


void setup() {
  Serial.begin(115200);
  pinMode(led, OUTPUT);

  noInterrupts();

  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  OCR1A = 250;

  TCCR1B |= (1 << WGM12);
  TCCR1B |= (1 << CS12) | (1 << CS10);
  TIMSK1 |= (1 << OCIE1A);
  interrupts();
}

ISR(TIMER1_COMPA_vect) {
 digitalWrite(8,HIGH);
 delay(1);
 digitalWrite(8,LOW);
}
Ben de hemen hemen aynı kodu yazıp deniyorum olmuyordu, yarım saattir uğraşıyorum, kartta sıkıntı olduğunu düşündüm. Şimdi çalışıyor.

timer1 taşması 65535 tik 4,19424 saniye demiştik, 1 saniye için 65535/4,19424 =15625 OCR1A ile 1 saniyelik kesmeler denedim.
CTC 1 saniye:
#include <avr/io.h>
#include <avr/interrupt.h>

volatile byte ocr,ovf;

ISR(TIMER1_COMPA_vect)
{
  ocr++;
  Serial.println("kesme");
 
}

ISR(TIMER1_OVF_vect)
{
  ovf++;
  Serial.println("OVF");
}


void setup() {
 
  Serial.begin(115200);
  Serial.println("BASLA");

  TCCR1A=0;
  TCCR1B=0;
  TCCR1B|=1<<WGM12;
  TCCR1B|=  0b101;
  TIMSK1|= 1<< OCIE1A | 1<< TOIE1;
  OCR1A=15625;
  sei();
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:
}

1655653811735.png


edit: imla
 

Çevrimiçi personel

Forum istatistikleri

Konular
6,989
Mesajlar
119,376
Üyeler
2,836
Son üye
ridianod

Son kaynaklar

Son profil mesajları

hakan8470 wrote on Dede's profile.
1717172721760.png
Dedecim bu gul mu karanfil mi? Gerci ne farkeder onu da anlamam. Gerci bunun anlamini da bilmem :gulus2:
Lyewor_ wrote on hakan8470's profile.
Takip edilmeye başlanmışım :D ❤️
Merhaba elektronik tutsakları...
Lyewor_ wrote on taydin's profile.
Merhabalar. Elektrik laboratuvarınız varsa bunun hakkında bir konunuz var mı acaba? Sizin laboratuvarınızı merak ettim de :)
Lyewor_ wrote on taydin's profile.
Merhabalar forumda yeniyim! Bir sorum olacaktı lcr meterler hakkında. Hem bobini ölçen hemde bobin direnci ölçen bir lcr meter var mı acaba?
Back
Top