Stránka 1 z 1

pic16f877a + SMT160-30 + I2C display (C)

Napsal: ned 11. pro 2011, 11:16
od tmaven
Cau,
nevim jestli se tu hodi, ale mozna ze se najde nekdo kdo me dokaze nakopnout spravnym smerem :). Protoze ja jsem u toho zamrzl...

Mam zadani (pro pic16f887a):
Na I2C displeji bude teplota ve stupních Celsia s přesností na jedno desetinné místo. Pro
zápornou teplotu zobrazte znaménko -. Program musí využívat CCP modul a přerušení pro měření z
teplotního čídla SMT160-30.

Schema: http://homen.vsb.cz/~jah01/mt/Schemata.pdf

Nejak proste nedokazu zjistit, kdy mam mit preruseni aby nedoslo k preteceni.. ucitel mi zatim na vsechno rekl ne ci me ignoroval..

Re: pic16f877a + SMT160-30 + I2C display (C)

Napsal: ned 11. pro 2011, 13:56
od OndraSter
http://www.hw.cz/Teorie-a-praxe/Program ... 30-92.html

Ten čip sis vybral sám, nebo ho máš zadaný? Takový DS18B20 je daleko lepší (OneWire sběrnice).

Re: pic16f877a + SMT160-30 + I2C display (C)

Napsal: ned 11. pro 2011, 15:47
od tmaven
byl mi zadan:
No dokazal jsem nejakym zpusobem vygooglit tip&tricks od microchipu tak jsem napsal:

Kód: Vybrat vše

#include <pic.h>

float t1, t2, t3, W, T, temp, Duty;
int i, x;

char CountandShow()
{
	T=(Duty-0.320)/0.00470;		//vypocet teploty 		
	// neco neco na vypis na display
}

void interrupt CCPpreruseni()
{
	if(CCP1CON==0b00000101)
	{
		t1=TMR1;					//zapis hodnoty TMR1 do t1
		CCP1CON=0b00000100;		//zachytavani sestupne hrany
			if(i==1)
			{
				T=t1-temp;
				Duty=T/W;
				i=0;	
				CountandShow();
			}
		CCP1IF=0;
	}
	if(CCP1CON==0b00000100)
	{
		i=1;
		temp=0;
		temp=t1;
		t2=TMR1;
		W=t2-t1;
		CCP1CON=0b00000101;
		CCP1IF=0;
	}
}


void main()
{	
	CCP1CON=0b00000101;		//zachytavani vzestupne hrany	
	T1CON=0b00110001;			//preddelicka 1:8
	CCP1IE=1;					//zapnuti CCP preruseni
	
	
	while(1)
	{
	}
}

Zitra jdu za jinym ucitelem, ktery mi alespon snad rekne jak na to napoji poradne i2c at mam zdroj toho signalu z cidla :)

Re: pic16f877a + SMT160-30 + I2C display (C)

Napsal: ned 1. led 2012, 21:07
od helium

Re: pic16f877a + SMT160-30 + I2C display (C)

Napsal: ned 1. led 2012, 22:03
od tmaven
Uz to mam hotove ale diiky :) Nakonec jsem prisel do skoly s hotovym program, ale profak mi oznamil, ze tu cidlo je znicene (jedine na vsb...) a tak jsem to predelall na simulator.. pak mi oznamil ze ho spravil.. takze jsem to predelal zpet... pak ze meri blbe.. a druhy den merilo dobre tak se to dodelalo.. no slava konecne

Re: pic16f877a + SMT160-30 + I2C display (C)

Napsal: ned 1. led 2012, 22:04
od tmaven

Kód: Vybrat vše

// Na I2C displeji bude teplota ve stupních Celsia s přesností na jedno desetinné místo. Pro
// zápornou teplotu zobrazte znaménko -. Program musí využívat CCP modul a přerušení pro měření z
// teplotního čídla SMT160-30. 

// 33/RB0 vstupni port cidla 

#include <pic.h>

#define CrystalFreq   18432000
#define	Misto	PORTA
#define Display	PORTD
#define SCL           RC3
#define SDA           RC4
#define TSCL          TRISC3
#define TSDA          TRISC4
#define W_TEMP	0x7F
#define STATUS_TEMP	0x7E

unsigned char DispPos,DisData[4];
unsigned char abc[20];
char Cekani, Count, Bity, Cas, I2CHodn;
bit I2CStarted, I2CError;
float rofl=0.0;
int a=0,b=0,c=0,d=0;
float t1=0.0, t2=0.0, t3=0.0, W=0.0, T=0.0, temp=0.0, Duty=0.0;
int j=0, x,pocet=0;
float PICrlz=0.0;

void Delay()
{
	unsigned char Cas;
	while(Cas--);
}

void DelayUs(unsigned char time)  // Funguje docela dobře pro krystal 20MHz
{
	if(!time--) return;
	if(!time--) return;
	while(time--)
	{
		asm("nop");
		asm("nop");
		asm("nop");
		asm("nop");
	}
}

void I2CSetup(void)
{
	char i;
	SSPCON=0x38;                  // I2C master mode
	I2CStarted=0;                 // Zatím se nic neděje
	I2CError=0;
	SSPSTAT=0x80;             		// 100 kHz sběrnice (no slew rate control)
	SSPCON2=0;                    // Vynulovat informační bity
	SSPADD=1.0*CrystalFreq/(400000.0);  // 100 kHz sběrnice, SSPADD = fosc/(4.100kHz)-1
		if(SDA) return;               // Pokud bez chyby, tak konec
	PORTC&=0xE7;                  // Nastavení SDA a SCL na nulu
	SSPEN=0;                      // Zákaz I2C
		for(i=9;i!=0;i--)             // Maximálně 9 impulsů,pak už chyba nejde opravit
		{
			TSCL=0;                     // Hodiny dolů
			DelayUs(40);                // Chvilku čekej (40us)
			TSCL=1;                     // Hodiny nahodu
			DelayUs(40);                // Chvilku čekej (40us)
				if(SDA) break;
		}
	SSPEN=1;                      // Povol I2C
}

void I2CWait()
{
	while(!SSPIF);
	SSPIF=0;
}

void I2CSta03()
{
	I2CError=1;
	return;
}

void I2CSta02()
{
	I2CStarted=1;
	I2CWait();
}

void I2CSta01()
{
	if(SDA==1)
	{
		if(SCL==1)
		{
			SEN=1;
			I2CSta02();
		}
	I2CSta03();
	}
I2CSta03();
}

void I2CStart()
{
	if(I2CStarted==1)
	{
		RSEN=0;
		I2CSta02();
	}
I2CSta01();
}

void I2COut(char Znak)
{
	SSPBUF=Znak;
	I2CWait();
	return;
}

void I2CStop()
{
	PEN=1;
	I2CStarted=0;
	I2CWait();		
}

void ConfSAA1064()
{
	I2CStart();
	I2COut(0x70);
	I2COut(0x00);
	I2COut(0x77);
	I2CStop();
}
const unsigned char PrevodZnaky[10]=
{0b00000000,
 0b00000110,
 0b01011011,
 0b01001111,
 0b01100110,
 0b01101101,
 0b01111100,
 0b00000111,
 0b01111111,
 0b01100111};

const unsigned char PrevodZnakyTecka[10]=
{0b10000000,
 0b10000110,
 0b11011011,
 0b11001111,
 0b11100110,
 0b11101101,
 0b11111100,
 0b10000111,
 0b11111111,
 0b11100111};

char n, number;

void Numero()				// prepis pole na display
{	

	if(n<4)
	{
		n++;	
		return;
	} 
}

void WrDis()		// sem to dostane hodnotu z mainu
{
	I2CStart();
	I2COut(0x70);		// adresa SAA1064
	I2COut(0x01);		// subadresa
	
	asm("NOP");
	asm("NOP");
	asm("NOP");
	asm("NOP");
	asm("NOP");

	n=0;
	if(n==0)
	{	
		number=PrevodZnaky[d];	
		Numero();
		I2COut(number);
	}
	
	if(n==1)
	{	
		number=PrevodZnakyTecka[c];	
		Numero();
		I2COut(number);
	}
	
	if(n==2)
	{	
		number=PrevodZnaky[b];	
		Numero();
		I2COut(number);
	}
	
	if(n==3)
	{	
		if(rofl<0)
		{
			Numero();
			number = 0b01000000;
			I2COut(number);
		}
	}
I2CStop();
return;
}


void Prevod(float rofl)
{
	asm("NOP");
	PICrlz=rofl*10.0;
	asm("NOP");
	a=(int)PICrlz;
	asm("NOP");
	if(a>100)					// kladne >100 
	{
		b=a/100;
		c=(a-(100*b))/10;
		d=(a-100*b-10*c);
	}
	else if(a<100 && a>10)		// kladne 10 ~ 100
	{
		b=0;
		c=(a-(100*b))/10;
		d=(a-100*b-10*c);
	}
	else if(a<10 && a>0)		// kladne 0 ~ 10
	{
		b=0;
		c=0;
		d=(a-100*b-10*c);
	}
	else if(a<0 && a>-10)		// zapor 0 ~ -10
	{
		a=-1*a;
		b=0;
		c=0;
		d=(a-100*b-10*c);
	}
	else if(a<0 && a>-100)		// zapor -10 ~ -100 
	{
		a=-1*a;
		b=0;
		c=(a-(100*b))/10;
		d=(a-100*b-10*c);
	}
	else if(a<-100)				// zapor <100
	{
		a=-1*a;
		b=a/100;
		c=(a-(100*b))/10;
		d=(a-100*b-10*c);
	}
	else if(a==0)		// 0
	{
		b=0;
		c=0;
		d=0;
	}
	WrDis();
}

char CountandShow()
{
	rofl=(Duty-0.320)/0.00470;
	Prevod(rofl);		//vypocet teploty
}

void interrupt CCPpreruseni()
{
	CCP1IF=0;
	if(CCP1CON==0b00000101)
	{
		t1=TMR1;					//zapis hodnoty TMR1 do t1
		CCP1CON=0b00000100;		//zachytavani sestupne hrany
			if(j==1)
			{
				T=t1-temp;
				Duty=W/T;
				j=0;
				CountandShow();
				return;
			}		
	}
	if(CCP1CON==0b00000100)
	{
		j=1;
		temp=0;
		temp=t1;
		t2=TMR1;
		W=t2-t1;
		CCP1CON=0b00000101;
		return;
	}
}

//----------------------------------------------------------------------------

void main()
{	
	PORTD=0xFF;         // Výstupy PORTu D budou v jedničce
  	TRISD=0x00;         // Vývody budou výstupní
  	TRISD0=1;
	ADCON1=0x07;
  	TRISA=0b11000011;   // Výstupní piny pro display
  	PORTA=0xFF;
  	PORTE=0;
  	TRISE2=0;
	TRISB=0b11111111;
	TRISC=0b11111111;		//RC3 - SCL; RC4 - SDA 
	
	RB0=1;
	
	I2CSetup();
	ConfSAA1064();


	PORTC = 0;
	CCP1CON=0b00000101;		//zachytavani vzestupne hrany	
	T1CON=0b00110001;		//preddelicka 1:8
	CCP1IE=1;					//zapnuti CCP preruseni
	GIE=1;
//	TMR1IE=1;					// nechat zakomentovane
	
	
	PEIE=1;
/*
	t1=22124;
	t2=29499;
	t3=51622;
	W=t2-t1;
	T=t3-t1;
	Duty=W/T;
	a=0;
	b=0;
	c=0;
	*/

	while(1)
	{
		asm("NOP");
		asm("NOP");
		asm("NOP");
		asm("NOP");
		asm("NOP");
		WrDis();
	}
}