semih_s
Hobici
- Katılım
- 16 Aralık 2020
- Mesajlar
- 1,922
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ı.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
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.