TEKNİK YAZI

Tiva Not-6 : Tiva C Serisi TM4C123G LaunchPad – ADC Kullanımı ve Grafik Arayüz

Herkese tekrardan merhabalar;

Tiva C serisi için yazılarımıza devam ediyoruz. Bu yazımızda çoğumuzun devamlı olarak kullandığı ADC modülünün kullanımına değineceğiz. Alışılagelmiş ADC yapısından biraz farklı bir yapıya sahip olan Tiva işlemcilerde gerekli ayarları yapıp daha sonra belirlediğimiz bir protokolle PC’ye gönderip orada oluşturmuş olduğumuz grafik arayüzüyle değerlerimizi göreceğiz.

Tiva Launcpad üzerinde bulunan TM4C123GH6PM mikrodenetleyici 12 bitlik çözünürlüğe sahip 12 girişe sahiptir. Aynı zamanda modül içerisinde bir adet sıcaklık sensör modülü içermektedir.

adc

Her bir adc modülü 4 adet Sequencer modül içermektedir ve bu modüller sayesinde bir anda bir veya birden fazla ADC girişinden örnek alabilirsiniz. Sequencer modüller alınan örnekleri fifo kapasitelerine göre depolarlar.

adc2

Yukarıdaki tabloda gördülüğü gibi 1 ila 8 arasında depoya sahip olan sequencer modüller yer almaktadır. Eğer ki biz tek ADC girişinden örnek almak istiyorsak SS3 (Sample Sequencer 3) bizim işimizi görecektir. Biz örneğimizde 4 girişten örnekler alacağız o sebeple SS1’i kullanacağız.

adc3

Şimdi koda gelelim. Kod üzerinde gerekli tüm açıklamalar yapılmıştır.

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/adc.h"
 
void UARTAyarla(void)
{
	SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0); //UART modülünü aktif hale getiriyoruz.
 
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); //UART için A0 ve A1 pinlerini kullanacağımız için A portunu aktif hale getiriyoruz.
 
	UARTConfigSetExpClk(UART0_BASE, SysCtlClockGet(), 115200, (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | UART_CONFIG_PAR_NONE)); // UART'ı 115200 hızına ayarlıyoruz.
 
	GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); //PA0 - U0RX, PA1 = U0TX
 
	UARTFIFOEnable(UART0_BASE); // UART FIFO Aktif hale getiriyoruz.
 
	UARTEnable(UART0_BASE); // UART Aktif hale getiriyoruz
}
 
void ADCAyarla(void)
{
	SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); //ADC0 Modülünü aktif hale getiriyoruz.
 
	ADCHardwareOversampleConfigure(ADC0_BASE, 64); // Daha iyi çözünürlük için, donanımsal olarak 
																								 // 64 tane örneğin ortalamasını alıp bize o sonucu dönmesini sağlıyoruz
 
	ADCSequenceDisable(ADC0_BASE, 1); //Sample Sequencer 1 ile işlem yapacağımız için öncelikle kapatıyoruz.
 
	ADCSequenceConfigure(ADC0_BASE, 1, ADC_TRIGGER_PROCESSOR, 0); // Sample Sequencer 1 için kullanılacak olan 
																															  // interrupt'ın değerini 0 yaparak en yüksek önceliği veriyoruz.
 
	//Belirttiğimiz gibi SS1 4 tane fifoya sahiptir ve şimdi bu fifoya gelecek değerleri ayarlayacağız.
 
	ADCSequenceStepConfigure(ADC0_BASE, 1, 0, ADC_CTL_CH0); //Sequencer Adım 0 : PE3
	ADCSequenceStepConfigure(ADC0_BASE, 1, 1, ADC_CTL_CH1); //Sequencer Adım 1 : PE2
	ADCSequenceStepConfigure(ADC0_BASE, 1, 2, ADC_CTL_CH2); //Sequencer Adım 2 : PE1
	ADCSequenceStepConfigure(ADC0_BASE, 1, 3, ADC_CTL_TS | ADC_CTL_IE | ADC_CTL_END); //Sequencer Adım 3 : Sıcaklık sensörünün değeri ve 
																																									//interrupt'ın açılarak konfigürasyonun tamamlanması
 
	ADCSequenceEnable(ADC0_BASE, 1); //Sample Sequencer 1'i tekrar açıyoruz.
}
 
int main(void) 
{
	uint32_t ulADC0Value[8]; // Sample Sequencer 1 için fifo değerlerinin saklanacağı dizi
 
	char a[4],b[4],c[4],d[4]; //Datalarımızı UART üzerinden gönderirken kullanacağımız dizi
 
	SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ); // islemcimizi 40 Mhz'e ayarlıyoruz.
 
	UARTAyarla();
 
	ADCAyarla();
 
	while(1)
	{
		ADCIntClear(ADC0_BASE, 1); // ADC interrupt flag'ini temizliyoruz.
		ADCProcessorTrigger(ADC0_BASE, 1); // ADC'yi tetikliyoruz.
 
		while(!ADCIntStatus(ADC0_BASE, 1, false)) //ADC'nin interrupt flag'ini kontrol ediyoruz ve data almasını bekliyoruz.
		{
		}
 
		ADCSequenceDataGet(ADC0_BASE, 1, ulADC0Value); //Alınan dataları fifoya yerleştiriyoruz.
 
		UARTCharPutNonBlocking(UART0_BASE, '@'); // Başlangıç karakterini gönderiyoruz.
		UARTCharPutNonBlocking(UART0_BASE, ','); // Ayraç
 
		//Datalarımızı basamaklarına ayırarak gönderiyoruz. 
 
		a[3] = ulADC0Value[0]%10 + 48;
		ulADC0Value[0] = ulADC0Value[0]/10 ;
		a[2] = ulADC0Value[0]%10 + 48;
		ulADC0Value[0] = ulADC0Value[0]/10 ;
		a[1] = ulADC0Value[0]%10 + 48;
		a[0] = ulADC0Value[0]/10 + 48;
 
		b[3] = ulADC0Value[1]%10 + 48;
		ulADC0Value[1] = ulADC0Value[1]/10 ;
		b[2] = ulADC0Value[1]%10 + 48;
		ulADC0Value[1] = ulADC0Value[1]/10 ;
		b[1] = ulADC0Value[1]%10 + 48;
		b[0] = ulADC0Value[1]/10 + 48;
 
		c[3] = ulADC0Value[2]%10 + 48;
		ulADC0Value[2] = ulADC0Value[2]/10 ;
		c[2] = ulADC0Value[2]%10 + 48;
		ulADC0Value[2] = ulADC0Value[2]/10 ;
		c[1] = ulADC0Value[2]%10 + 48;
		c[0] = ulADC0Value[2]/10 + 48;
 
		d[3] = ulADC0Value[3]%10 + 48;
		ulADC0Value[3] = ulADC0Value[3]/10 ;
		d[2] = ulADC0Value[3]%10 + 48;
		ulADC0Value[3] = ulADC0Value[3]/10 ;
		d[1] = ulADC0Value[3]%10 + 48;
		d[0] = ulADC0Value[3]/10 + 48;
 
		UARTCharPutNonBlocking(UART0_BASE, a[0]); // Karakterleri UART üzerinden tek tek gönderiyoruz.
		UARTCharPutNonBlocking(UART0_BASE, a[1]);
		UARTCharPutNonBlocking(UART0_BASE, a[2]);
		UARTCharPutNonBlocking(UART0_BASE, a[3]);
 
		UARTCharPutNonBlocking(UART0_BASE, ','); // Ayraç
 
		SysCtlDelay(5000);
 
		UARTCharPutNonBlocking(UART0_BASE, b[0]); 
		UARTCharPutNonBlocking(UART0_BASE, b[1]);
		UARTCharPutNonBlocking(UART0_BASE, b[2]);
		UARTCharPutNonBlocking(UART0_BASE, b[3]);
 
		UARTCharPutNonBlocking(UART0_BASE, ','); // Ayraç
 
		SysCtlDelay(5000);
 
		UARTCharPutNonBlocking(UART0_BASE, c[0]); 
		UARTCharPutNonBlocking(UART0_BASE, c[1]);
		UARTCharPutNonBlocking(UART0_BASE, c[2]);
		UARTCharPutNonBlocking(UART0_BASE, c[3]);
 
		UARTCharPutNonBlocking(UART0_BASE, ','); // Ayraç
 
		SysCtlDelay(5000);
 
		UARTCharPutNonBlocking(UART0_BASE, d[0]);
		UARTCharPutNonBlocking(UART0_BASE, d[1]);
		UARTCharPutNonBlocking(UART0_BASE, d[2]);
		UARTCharPutNonBlocking(UART0_BASE, d[3]);
 
		SysCtlDelay(5000);
 
		UARTCharPutNonBlocking(UART0_BASE, '\n'); // Bitiş karakterini gönderiyoruz.
 
		SysCtlDelay(1000000); // Örneklemeler arası bekleme
	}
}

Arayüzümüz üzerinde görünüm:

adc4

NOT 1: Herhangi bir mikrodenetleyiciden seriport ile beraber @,DEĞER1,DEĞER2,DEĞER3,DEĞER4\n ( Örneğin: @,5896,4568,2354,0000\n ) şeklinde veri gönderdiğinizde program üzerinde grafiğini görebilirsiniz. Programı hızlıca yazdım. Eğer ki ekleme istekleri ve hatalar varsa , söylerseniz düzeltebilirim.

NOT 2: Programı kullanabilmeniz için bilgisayarınızda .NET Framework 4.0 kurulu olması gerekmektedir.

Programın Linki : teknikyazi.com_DataGrapher

  • hakan

    Metin bey acaba arayüzün kodlarını da sayfada paylaşmanız mümkünmüdür çünkü bu gerçek zamanla grafik çizdirmede çok az kaynak var ve kodu kimse paylaşmıyor koddan yararlanarak kendı projelerimizde de yarar sağlar bizlere.

  • CemS

    Merhaba data grapherin kaynak kodlarınıda paylaşmanız mümkün müdür

  • 慮威承

    thank you ,it help very mcuh

  • Alperen Akküncü

    SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_OSC_MAIN|SYSCTL_XTAL_16MHZ);
    Burda işlemciyi 40 MHz’e ayarlıyorsunuz 80MHz’e değil.

    • saucompeng

      Başka bir uygulamadan kopyala/yapıştır yaptığım için öyle kalmış, uyarı için teşekkürler.

      • Alperen Akküncü

        önemli değil Yazı için teşekkür ederim