PSoC Real Time Clock
PSoC CY8C27443-24PXI, DS1337 RTC ve TMP04 çipleri kullanılarak yapılmış dijital saat örneğidir. Saatin yanı sıra tarih ve gün bilgileride LCD den okunabilir. Dijital saatin bir alarmı, ortam seviyesine göre değişebilen ekran aydınlatması, TMP04 ile gerçekleştirilmiş birde termometresi bulunmaktadır. Saatin tüm ayarları sadece 2 buton ile yapılır.
PSoC RTC örneğinde 7 adet dijital PSoC bloğu ve 2 adet analog PSoC bloğu kullanılmaktadır.
Dijital bloklardan biri yaklaşık 2kHz üreten saat başı beep görevini üstlenen PWM bloğudur. Alarm anında ise bir başka PWM bloğu üzerinden modüle edilerek kesik beep sesleri elde edilir. Bir diğer PWM modülü ise ekram parlaklığını ayarlanması için kullanılmıştır. LDR üzerinden alınan analog gerilim bilgisi bir analog blok olan ve kazancı 1 olan PGA üzerinden diğer bir analog bloğu olan ADC a beslenir. ADC çıkış değeri ekran parlaklığını ayarlayan PWM modülünün darbe boşluk oranını belirler. Ayrıca ADC 1 analog blok kullandığı gibi 2 dijital bloğu da işgal eder. Geriye kalan 2 dijital bloğu ise 16 bitlik bir sayıcı kullanır. TMR04 sensöründen gelen sıcaklık bilgisinin çözümlenmesi için kullanılır.
Kaynak kodları:
//—————————————————————————-
// C main line
//—————————————————————————-
/*GPIO interruptini gerçeklestirmek için
-boot.tpl dosyasinda 1Ch adresine "ljmp PSoC_GPIO_ISR"
-psocgpioint.asm dosyasinda PSoC_GPIO_ISR: ve reti arasina "ljmp _PSoC_GPIO_ISR_C"
-main.c dosyasinda "#pragma interrupt_handler PSoC_GPIO_ISR_C" interrupt fonksiyonunda ise
"void PSoC_GPIO_ISR_C()" ifadesini kullanın!!!
*/
//—————————————————————————–
#include <m8c.h>
#include "PSoCAPI.h"
#include <string.h>
#include <stdlib.h>
#pragma interrupt_handler PSoC_GPIO_ISR_C
char lcdclear=0;
char set=0;
char buffer[8];
float temperature;
float T1;
float T2;
BYTE rxBuf[8];
BYTE setBuf[];
BYTE almBuf[]={0x00,0x00,0x00,0x00}; //alarm saat, alarm dakika, alarm set, alarm aktif
BYTE i; //geçici değişken
const BYTE txCBuf[] = { 0x00, // DS1337 internal sub-address
0x55,0x59,0x23, // saniye dakika saat
0x06, // haftanın günü
0x24,0x11,0x06, // gün ay yıl
0x93}; // Enable RTC
#define ALM_SET almBuf[2]
#define ALM_ACTIVE almBuf[3]
void PSoC_GPIO_ISR_C()
{
//string eşleme
setBuf[0]=0x00;
setBuf[8]=0x93;
for(i = 0; i < 6; i++) setBuf[i+1]=rxBuf[i];
if((PRT1DR&0x04)==4)
{
//ayarlar
//saat ayarı
if(set==1) {
setBuf[3]++;
if(setBuf[3]==0x0A) setBuf[3]=0x10;
if(setBuf[3]==0x1A) setBuf[3]=0x20;
if(setBuf[3]==0x24) setBuf[3]=0x00;
}
//dakika ayarı
if(set==2) {
setBuf[2]++;
if(setBuf[2]==0x0A) setBuf[2]=0x10;
if(setBuf[2]==0x1A) setBuf[2]=0x20;
if(setBuf[2]==0x2A) setBuf[2]=0x30;
if(setBuf[2]==0x3A) setBuf[2]=0x40;
if(setBuf[2]==0x4A) setBuf[2]=0x50;
if(setBuf[2]==0x5A) setBuf[2]=0x00;
}
//saniye ayarı
if(set==3) {
setBuf[1]++;
if(setBuf[1]==0x0A) setBuf[1]=0x10;
if(setBuf[1]==0x1A) setBuf[1]=0x20;
if(setBuf[1]==0x2A) setBuf[1]=0x30;
if(setBuf[1]==0x3A) setBuf[1]=0x40;
if(setBuf[1]==0x4A) setBuf[1]=0x50;
if(setBuf[1]==0x5A) setBuf[1]=0x00;
}
//haftanın günü
if(set==4) {
setBuf[4]++;
if(setBuf[4]==0x08) setBuf[4]=0x01;
}
//gün ayarı
if(set==5) {
//31 çeken aylar
if((setBuf[6]==0x01)||(setBuf[6]==0x03)||(setBuf[6]==0x05)||
(setBuf[6]==0x07)||(setBuf[6]==0x08)||(setBuf[6]==0x10)||(setBuf[6]==0x12))
{
setBuf[5]++;
if(setBuf[5]==0x0A) setBuf[5]=0x10;
if(setBuf[5]==0x1A) setBuf[5]=0x20;
if(setBuf[5]==0x2A) setBuf[5]=0x30;
if(setBuf[5]==0x32) setBuf[5]=0x01;
}
//30 çeken aylar
if((setBuf[6]==0x04)||(setBuf[6]==0x06)||(setBuf[6]==0x09)||(setBuf[6]==0x11))
{
setBuf[5]++;
if(setBuf[5]==0x0A) setBuf[5]=0x10;
if(setBuf[5]==0x1A) setBuf[5]=0x20;
if(setBuf[5]==0x2A) setBuf[5]=0x30;
if(setBuf[5]==0x31) setBuf[5]=0x01;
}
//28 çeken aylar
if(setBuf[6]==0x02)
{
setBuf[5]++;
if(setBuf[5]==0x0A) setBuf[5]=0x10;
if(setBuf[5]==0x1A) setBuf[5]=0x20;
if(setBuf[5]==0x29) setBuf[5]=0x01;
}
}
//ay ayarı
if(set==6) {
setBuf[6]++;
if(setBuf[6]==0x0A) setBuf[6]=0x10;
if(setBuf[6]==0x13) setBuf[6]=0x01;
}
//yıl ayarı
if(set==7) {
setBuf[7]++;
if(setBuf[7]==0x0A) setBuf[7]=0x10;
if(setBuf[7]==0x1A) setBuf[7]=0x20;
if(setBuf[7]==0x2A) setBuf[7]=0x30;
if(setBuf[7]==0x3A) setBuf[7]=0x40;
if(setBuf[7]==0x4A) setBuf[7]=0x50;
if(setBuf[7]==0x5A) setBuf[7]=0x00;
}
I2Cm_1_bWriteBytes(0x68, setBuf, 9, I2Cm_1_CompleteXfer);
lcdclear=1;
//alarm ayarı saat
if(set==8) {
almBuf[0]++;
if(almBuf[0]==0x0A) almBuf[0]=0x10;
if(almBuf[0]==0x1A) almBuf[0]=0x20;
if(almBuf[0]==0x24) almBuf[0]=0x00;
ALM_SET=0x01;
}
//alarm ayarı dakika
if(set==9) {
almBuf[1]++;
if(almBuf[1]==0x0A) almBuf[1]=0x10;
if(almBuf[1]==0x1A) almBuf[1]=0x20;
if(almBuf[1]==0x2A) almBuf[1]=0x30;
if(almBuf[1]==0x3A) almBuf[1]=0x40;
if(almBuf[1]==0x4A) almBuf[1]=0x50;
if(almBuf[1]==0x5A) almBuf[1]=0x00;
ALM_SET=0x01;
}
}
else set++;
// alarm çalma anında herhangi bir butona basılırsa alarmı sustur
if(ALM_ACTIVE==0x01) { ALM_SET=0x00; ALM_ACTIVE=0x00; PWM8_2_Stop(); set=0; }
if(set==10) set=0;
lcdclear=1;
return;
}
void main()
{
//modülleri başlat
PGA_1_Start(PGA_1_LOWPOWER);
ADCINC12_1_Start(ADCINC12_1_HIGHPOWER);
ADCINC12_1_GetSamples(0);
M8C_EnableIntMask(INT_MSK0, INT_MSK0_GPIO);
M8C_EnableGInt;
Counter16_1_EnableInt();
Counter16_1_Start();
PWM8_1_Start();
PWM8_3_Start();
LCD_1_Start();
LCD_1_Init();
//I2C haberleşmesi
I2Cm_1_Start();
I2Cm_1_bWriteCBytes(0x68, txCBuf, 9, I2Cm_1_CompleteXfer);
//sonsuz döngü
do{
I2Cm_1_bWriteCBytes(0x68, txCBuf, 1, I2Cm_1_NoStop);
I2Cm_1_fReadBytes(0x68, rxBuf, 7, I2Cm_1_RepStart);
I2Cm_1_fSendStart(0x68, I2Cm_1_WRITE);
I2Cm_1_fWrite(0x00);
I2Cm_1_fSendRepeatStart(0x68, I2Cm_1_READ);
for(i = 0; i < 6; i++)
{
rxBuf[i] = I2Cm_1_bRead(I2Cm_1_ACKslave);
}
rxBuf[7] = I2Cm_1_bRead(I2Cm_1_NAKslave);
I2Cm_1_SendStop();
//LCD ye yazmaya başla
if((set==1)||(set==2)||(set==3)||(set==8)||(set==9)) LCD_1_Position(0, 3);
else LCD_1_Position(0, 1);
//zamanı yaz
for(i=0;i<3;i++)
{
if(((set==1)||(set==8))&&(i==0)) LCD_1_PrCString("[");
if(((set==2)||(set=
=9))&&(i==1)) LCD_1_PrCString("[");
if((set==3)&&(i==2)) LCD_1_PrCString("[");
//if(rxBuf[2-i]<10) LCD_1_PrCString("0");
if(set==8||set==9) {if((almBuf[i]<10)&&(i<2)) LCD_1_PrCString("0");
itoa(buffer, almBuf[i], 16);}
else { if(rxBuf[2-i]<10) LCD_1_PrCString("0");
itoa(buffer, rxBuf[2-i], 16); }
if(((set==8)||(set==9))&&(i==2)) {}
else LCD_1_PrString(buffer);
if(((set==1)||(set==8))&&(i==0)) LCD_1_PrCString("]");
if(((set==2)||(set==9))&&(i==1)) LCD_1_PrCString("]");
if((set==3)&&(i==2)) LCD_1_PrCString("]");
//if(i!=2) LCD_1_PrCString(":");
if((set<8)&&(i!=2)) LCD_1_PrCString(":");
if((set>7)&&(i==0)) LCD_1_PrCString(":");
}
//gün değişimlerini LCD de kayan yazı şeklinde göster
LCD_1_Position(1,0);
if(set==4) LCD_1_PrCString("[");
if(rxBuf[3]==1) {
if((rxBuf[2]==0x23)&&(rxBuf[1]==0x59)&&(rxBuf[0]==0x59)) LCD_1_PrCString(" ");
if((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==0)) LCD_1_PrCString("n ");
if((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==1)) LCD_1_PrCString("on ");
if(!((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==0))&&
!((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==1))&&
!((rxBuf[2]==0x23)&&(rxBuf[1]==0x59)&&(rxBuf[0]==0x59))) LCD_1_PrCString("Mon");
}
if(rxBuf[3]==2) {
if((rxBuf[2]==0x23)&&(rxBuf[1]==0x59)&&(rxBuf[0]==0x59)) LCD_1_PrCString(" ");
if((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==0)) LCD_1_PrCString("e ");
if((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==1)) LCD_1_PrCString("ue ");
if(!((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==0))&&
!((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==1))&&
!((rxBuf[2]==0x23)&&(rxBuf[1]==0x59)&&(rxBuf[0]==0x59))) LCD_1_PrCString("Tue");
}
if(rxBuf[3]==3) {
if((rxBuf[2]==0x23)&&(rxBuf[1]==0x59)&&(rxBuf[0]==0x59)) LCD_1_PrCString(" ");
if((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==0)) LCD_1_PrCString("d ");
if((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==1)) LCD_1_PrCString("ed ");
if(!((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==0))&&
!((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==1))&&
!((rxBuf[2]==0x23)&&(rxBuf[1]==0x59)&&(rxBuf[0]==0x59))) LCD_1_PrCString("Wed");
}
if(rxBuf[3]==4) {
if((rxBuf[2]==0x23)&&(rxBuf[1]==0x59)&&(rxBuf[0]==0x59)) LCD_1_PrCString(" ");
if((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==0)) LCD_1_PrCString("u ");
if((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==1)) LCD_1_PrCString("hu ");
if(!((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==0))&&
!((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==1))&&
!((rxBuf[2]==0x23)&&(rxBuf[1]==0x59)&&(rxBuf[0]==0x59))) LCD_1_PrCString("Thu");
}
if(rxBuf[3]==5) {
if((rxBuf[2]==0x23)&&(rxBuf[1]==0x59)&&(rxBuf[0]==0x59)) LCD_1_PrCString(" ");
if((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==0)) LCD_1_PrCString("i ");
if((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==1)) LCD_1_PrCString("ri ");
if(!((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==0))&&
!((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==1))&&
!((rxBuf[2]==0x23)&&(rxBuf[1]==0x59)&&(rxBuf[0]==0x59))) LCD_1_PrCString("Fri");
}
if(rxBuf[3]==6) {
if((rxBuf[2]==0x23)&&(rxBuf[1]==0x59)&&(rxBuf[0]==0x59)) LCD_1_PrCString(" ");
if((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==0)) LCD_1_PrCString("t ");
if((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==1)) LCD_1_PrCString("at ");
if(!((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==0))&&
!((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==1))&&
!((rxBuf[2]==0x23)&&(rxBuf[1]==0x59)&&(rxBuf[0]==0x59))) LCD_1_PrCString("Sat");
}
if(rxBuf[3]==7) {
if((rxBuf[2]==0x23)&&(rxBuf[1]==0x59)&&(rxBuf[0]==0x59)) LCD_1_PrCString(" ");
if((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==0)) LCD_1_PrCString("n ");
if((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==1)) LCD_1_PrCString("un ");
if(!((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==0))&&
!((rxBuf[2]==0)&&(rxBuf[1]==0)&&(rxBuf[0]==1))&&
!((rxBuf[2]==0x23)&&(rxBuf[1]==0x59)&&(rxBuf[0]==0x59))) LCD_1_PrCString("Sun");
}
if(set==4) LCD_1_PrCString("]");
if((set==4)||(set==5)||(set==6)||(set==7)) LCD_1_PrCString(" ");
else LCD_1_PrCString(" ");
//tarih
for(i=4;i<7;i++)
{
if((set==5)&&(i==4)) LCD_1_PrCString("[");
if((set==6)&&(i==5)) LCD_1_PrCString("[");
if((set==7)&&(i==6)) LCD_1_PrCString("[");
if((rxBuf[i]<10)&&(i!=6)) LCD_1_PrCString("0");
if((i==6)&&rxBuf[6]<10) LCD_1_PrCString("200");
if((i==6)&&rxBuf[6]>9) LCD_1_PrCString("20");
itoa(buffer, rxBuf[i], 16);
LCD_1_PrString(buffer);
if((set==5)&&(i==4)) LCD_1_PrCString("]");
if((set==6)&&(i==5)) LCD_1_PrCString("]");
if((set==7)&&(i==6)) LCD_1_PrCString("]");
if(i!=6) LCD_1_PrCString(".");
}
//set veya LCD takılı kalırsa ekranı temizle
if((rxBuf[0]==0)&&(set!=0))
{
LCD_1_Start();
set=0;
}
if(lcdclear==1)
{
LCD_1_Start();
lcdclear=0;
}
//saat başı beep
if((rxBuf[0]==0)&&(rxBuf[1]==0))
{
PWM8_2_WritePulseWidth(100);
PWM8_2_Start();
}
else if(ALM_ACTIVE==0) PWM8_2_Stop();
//alarm ayarlanmış ise LCD de göster
if(ALM_SET==0x01)
{
LCD_1_Position(0,0);
LCD_1_PrCString("`");
}
if(set==8||set==9)
{
LCD_1_Position(0,13);
LCD_1_PrCString("alm");
}
//alarm çalma rutini
if((rxBuf[2]==almBuf[0])&&(rxBuf[1]==almBuf[1])&&(ALM_SET==0x01)&&(set==0))
{
PWM8_2_WritePulseWidth(5);
PWM8_2_Start();
ALM_ACTIVE=0x01;
}
if((ALM_SET==0x01)&&(rxBuf[0]==0x59)&&(ALM_ACTIVE==0x01))
{
LCD_1_Start();
ALM_SET=0x00;
ALM_ACTIVE=0x00;
PWM8_2_Stop();
}
//sıcaklık ölçme rutini
if((PRT0DR&0x80)==0x80)
{
while((PRT0DR&0x80)==0x80);
T1=Counter16_1_wReadCounter();
while((PRT0DR&0x80)==0x00);
T1=T1-Counter16_1_wReadCounter();
T2=Counter16_1_wReadCounter();
while((PRT0DR&0x80)==0x80);
T2=T2-Counter16_1_wReadCounter();
if((rxBuf[0]==0x00)||(rxBuf[0]==0x15)||(rxBuf[0]==0x30)||(rxBuf[0]==0x45))
temperature=235-(400*T2/T1);
}
//15 saniyede bir sıcaklık bilgisini ta
zele
if((set==0)&&(rxBuf[0]!=0x00)&&(rxBuf[0]!=0x15)&&(rxBuf[0]!=0x30)&&(rxBuf[0]!=0x45))
{
if(temperature<10) LCD_1_Position(0,13);
else LCD_1_Position(0,12);
itoa(buffer, temperature, 10);
LCD_1_PrString(buffer);
LCD_1_WriteData(0xDF);
LCD_1_PrCString("C");
}
//LCD parlaklığı
while(ADCINC12_1_fIsDataAvailable()==0);
ADCINC12_1_ClearFlag();
PWM8_3_WritePulseWidth(ADCINC12_1_iGetData()/16);
} while(1);
}
PSoC designer projesi olarak kaynak kodlarını indir. ( hex dosyası içerir! )
Saat 2 butonla ayarlanır. Bir buton ile ayarlara girilir diğeri ile artırma yöntemiyle saat istenilen değerlere ayarlanır. Alarmın kurulması için alarm değişkenleri olan saat veya dakikanın değiştirilmesi yeterlidir. bu durumda alarm kurulmuş olacak ve LCD de "`" şeklinde gösterilecektir. Alarm zamanı geldiğinde saat çalacaktır. Çalma herhangi bir butona basıldığında ise alarm susturulur. Her 15 saniyede bir ortam sıcaklık bilgisi tazelenir ve saat ayar modunda olmadığı sürece gösterilir. Gün değişimleri kısaltılmış gün ismi LCD de kayarak değiştirilir. LCD arka plan aydınlatması LDR üzerine düşen ışık şiddetiyle ters orantılı olarak değişim gösterir. Aydınlık ortamda LCD arka plan ışık şiddeti azaltılırken karanlık ortamda artırılır. Yaklaşık çözünürlüğü 100 dür.
PSoC RTC örneği için donanım kısmı bağlantı şeması yukarıda verilmiştir.
Tegin Yücel Mayadağlı
r2d2droids@yahoo.co.uk