Trao đổi về bài tập I2C

nút nhấn RA0 là để vào menu cài đặt thời gian. ở trong code trên mình dùng đến 6 chế độ nhấn RA0 1 lần là để cài đặt ngày giờ cho ds1307. nhấn 2 lần dùng cho hẹn giờ bật tải RB1,3 lần sẽ tắt tải RB1, lần 4 để hẹn giờ bật tải trên RB2, lần 5 để hẹn giờ tắt tải RB2, và lần 6 để hẹn giờ phát ra buzzer. còn RA1 sẽ dùng để điều chỉnh con trỏ tăng lên lần lượt từ giay cho đến năm còn RA2 dùng để điều chỉnh thời gian. 3 con so sau cùng bạn nói nó chứa 2 thông số 2 số đầu là chỉ cho bạn biết con trỏ đang nằm ở vị trí nào và số sau sẽ chỉ cho bạn biết bạn đang ở chế độ nào. khi bạn ko ở chế độ cài đặt thì 3 số này sẽ không hiển thị.
 

Leo_Asus

Trứng gà
Hình như PT có học lập trình nhúng đúng không ? Mai đi học mình hỏi bạn mấy chỗ về phần này được không ? Mình đang làm đồ án về phần này.
 

jacky_yang

Trứng gà
Chào bạn Phương Tuấn,
Code của bạn mình mô phỏng không chạy, bạn xem lại giup mình nhé, hình như trong hàm main thiếu hàm read_time(); mình có thêm vào nhưng LCd vẫn không hiển thị. Bỏ các hàm nút nhấn thì hiển thị được nhưng chỉ toàn hiển thị 00 00 00 thôi.
đây là code hoàn chỉnh có hẹn giờ bật tắt tải
Code:
/*
* Module : main.c
* Description : INT0 / PORTC toggle
* Tool : HI-TECH PIC
* Chip : 16F887
* History : 27/11/2010
* Author : nguyen khac phuong tuan, CLB NCKH
* Hardware notes :
* - Hardware: DONG HO THUC
**/
nội dung code (trang 5)
 
sao lại không có được bạn nó là dòng màu đỏ này
Code:
void main(void)
{
	lcd_init();
	i2c_init();
	init_port();
	__delay_ms(150);
	while(1)
	{
		nutnhan_RA0();
		nutnhan_RA1();
		nutnhan_RA2();
		Display(time);
		if(t==0)
		{
			a=0;
			[COLOR="red"]read_time();[/COLOR]
			if(k==1)
			{
				sosanh();
			}
		}
		if(i==1)
		{
			RB0=1;
			__delay_ms(50);
			RB0=0;
			__delay_ms(25);
		}
		else if(i==2)
		{
			RB0=1;
			__delay_ms(75);
			RB0=0;
			__delay_ms(50);
		}
		else if(i==3)
		{
			RB0=1;
			__delay_ms(75);
			RB0=0;
			__delay_ms(50);
		}
		else if(i==4)
		{
			RB0=1;
			__delay_ms(100);
			RB0=0;
			__delay_ms(75);
		}
		else if(i==5)
		{
			RB0=1;
			__delay_ms(100);
			RB0=0;
			__delay_ms(75);
		}	
	}
}
code này mình đổ lên mạch chạy rồi mà.
 
cái đô thì bạn phải xem lại đóng nút nhấn của bạn rồi bạn xem kỹ mục này nha
nút nhấn RA0 là để vào menu cài đặt thời gian. ở trong code trên mình dùng đến 6 chế độ nhấn RA0 1 lần là để cài đặt ngày giờ cho ds1307. nhấn 2 lần dùng cho hẹn giờ bật tải RB1,3 lần sẽ tắt tải RB1, lần 4 để hẹn giờ bật tải trên RB2, lần 5 để hẹn giờ tắt tải RB2, và lần 6 để hẹn giờ phát ra buzzer. còn RA1 sẽ dùng để điều chỉnh con trỏ tăng lên lần lượt từ giay cho đến năm còn RA2 dùng để điều chỉnh thời gian. 3 con so sau cùng bạn nói nó chứa 2 thông số 2 số đầu là chỉ cho bạn biết con trỏ đang nằm ở vị trí nào và số sau sẽ chỉ cho bạn biết bạn đang ở chế độ nào. khi bạn ko ở chế độ cài đặt thì 3 số này sẽ không hiển thị.
 

Leo_Asus

Trứng gà
Bạn Phương Tuấn có thể giải thích các biến và ý nghĩa của chúng ko:
char t1,t2,t3=25,t4,t5,t6=25,t7,t8,t9=25,t10,t11,t12=25,t13,t14,t15=25,h1,h2,h3,h4,h5;
 
biến t thì mình dùng để làm biến chọn module.
còn các biến t1,t2,t3=25,t4,t5,t6=25,t7,t8,t9=25,t10,t11,t12=25 ,t13,t14,t15=25, dùng để lưu trữ thời gian hẹn giờ bật tải. cho tất cả các chế độ.
còn các biến h1,h2,h3,h4,h5; thì mình dùng để lưu trữ giá trị để tắt buzzer vì khi hẹn giờ bật tải thì mình cũng có cho buzzer kêu để biết. sau đó 5s thì tắt buzzer nên phải dùng các biến h1,h2,h3,h4,h5. để lưu thời gian tắt buzzer. tại vì có lúc người dùng hẹn giờ đúng những dây cuối cùng thì sẽ bị trôi không tắt được buzzer nếu mình cộng biến giây lên 5.
 

Leo_Asus

Trứng gà
Chế độ 1 ( chỉnh thời gian cho đồng hồ,không phải hẹn giờ bật tắt tải), mình settime rồi,nhưng khi thoát khỏi chế độ settime thì thời gian vẫn không được điều chỉnh mà hiện thời gian lúc trước hiệu chỉnh.Phương tuấn coi nó có bị sao không vậy ?
 
để hẹn được giờ hay cài đặt lại giờ thì bạn phải nhấn nút RA1 14 lần tức là sau lần cài đặt số hàng chục của năm thì biến a đang bằng 13. bạn phải nhấn RA1 thêm một cái để nó bằng 14 sau đó lại nhấn nút RA2 thế là cài đặt thời gian hay hẹn giờ đều đã được thực hiện.
 

militi

Trứng gà
case 2:
{
t1=time[0];
t2=time[1];
t3=time[2];
k=1;

if(t2==0x59)
h5=0x00;
else if((t2&0x0f)<0x09)
h5=t2+1;
else
{
h5=(t2&0xf0)+0x10;
}
break;
}
case 3:
{
t4=time[0];
t5=time[1];
t6=time[2];
k=1;
if((t4&0x0f)<0x05)
h1=t4+5;
else
{
if((t4&0xf0)==0x50)
h1=(t4&0x0f)-5;
else
h1=t4+0x10-5;
}
break;
}
Anh Phương Tuấn có thể giải thích cho em hiểu đoạn này được không ? Em tự làm đồng hồ đọc đến đây không hiểu lắm !
 
như anh đã nói ở trên thì t1->t15 thì anh dùng để lưu giá trị thời gian hẹn giờ để bật tắt một tải. còn h1->h5 dùng để hẹn giờ tắt buzzer.
if(t2==0x59)
h5=0x00;
else if((t2&0x0f)<0x09)
h5=t2+1;
else
{
h5=(t2&0xf0)+0x10;
}
đoạn đó dùng trong chế độ hẹn giờ nên cho buzzer kêu 1 phút:
nếu t2==59 tức là khi phút mà người hẹn là 59 thì cho cho h5=0 tức là chờ cho hết 1 phút thì tắt buzzer.
nếu không thì cho h5=phút +1;
đoạn code
if((t4&0x0f)<0x05)
h1=t4+5;
else
{
if((t4&0xf0)==0x50)
h1=(t4&0x0f)-5;
else
h1=t4+0x10-5;
khi vào chế độ hẹn tắt tải thì chỉ cho buzzer kêu 5 giây thì tắt. khi giá trị 4 bit cuối của t4<5 (tức là hàng đơn vị của giây<5) thì cứ việc cho h1=t4+5( tức là cộng thêm hàng đơn vị của giây cho 5), còn nếu lớn hơn thì kiểm tra xem 4 bit cao của t4 tức là sô hàng chục của giây có bằng 5 hay không nếu có thì cho h1= số đơn vị của giây - cho 5 lúc này đúng 5 giây sau sẽ tắt buzzer. còn nếu hàng đơn vị của giây mà vẫn lớn hơn 5 và hàng chục nhỏ hơn 5 thì cứ việc trừ hàng đơn vi đi 5 và cộng hàng chục của giây thêm 1.
 
S

sonlamnguyenw

Guest
có ai có thể giúp mình up lên 1 project về chế độ I2C hoàn chỉnh được không .Mình đang rất cần. cảm ơn nhiều
 
S

sonlamnguyenw

Guest
xin được các pro chỉ giáo: mình làm một bài về chế độ I2C chỉ cần đọc giá trị phút từ DS1307 rồi hiển thị ra Port D nhưng nó không chạy ,
, mọi người xem hộ mình nhé.
Code:
#include<htc.h>
#include<pic16f877a.h>
__CONFIG(XT & WDTDIS & PWRTEN & UNPROTECT  & LVPDIS & DEBUGDIS); //1st config. Word



#define _XTAL_FREQ 20000000
/////////////////////////////
//dinh nghia cac bien
#define ACC 0x74h
#define MODE 0x75h
#define DEM 0x76h
#define ADDRESS 0x20h  // 
#define ADDR_EEPROM 0x0A0h

///////////////////////////
unsigned char data[10] ,data1,data2;
////////////////////////////
void khoitao(void)
{
	PORTA=0X00;
	PORTB=0X00;
	PORTD=0x00;
	
	TRISB=0X00;
	TRISD=0X00;
	
	
}
//////////////////////////////////////
///////////////////////////////////////////////
/////function start
void i2c_start(){
	SEN = 1;//gui bit start
	while(SEN);//cho bit start (SEN) gui xong
}
//////////////////////////////////////////////
////function stop
void i2c_stop(){
	PEN = 1;//gui bit stop
	while(PEN);//cho bit stop(PEN)gui xong
}
////////////////////////////////////////////
///function reset
void i2c_rsen(){
	RSEN=1;
	while(RSEN);
}
//////////////////////////////////////////
///function read
unsigned char i2c_read(unsigned char ack){
	RCEN = 1;//dung trong Receive khi master nhan tin hieu tu slave
	while(RCEN);//cho bit truyen xong 
	ACKDT = ack;//phat bit ACK
	ACKEN = 1;//
	while(ACKEN);//cho bit ACKEN gui xong
	return SSPBUF;//tra ve gia tri trong thanh ghi dem
}
///////////////////////////////////////////
////function write
unsigned char i2c_write(unsigned char d){
	WCOL = 0;//khong co su xep chong
	SSPIF = 0;//xoa co bao
	SSPBUF = d;//truyen du lieu vao thanh ghi dem
	asm("nop");
	asm("nop");
	asm("nop");
	if(WCOL) return 2;			// write collision
	else {
		while(!SSPIF);
		if(ACKSTAT) return 1;	// not acknowledge
		return 0;				// everything is ok
	}
}
////////////////////////////////////////////////
///function init
void i2c_init(){//khoi tao che do I2C
	
	RC3 = 1;
	RC4 = 1;
	TRISC3 = 1;//
	TRISC4 = 1; //	control by mssp
	////////////////////////////
	
	SSPADD = 9;		// Baudrate = Fosc/4/(SSPADDR+1);Address register
	///////////////////////
	SMP = 1; 		// slew rate control disabled for 100KHz baudrate(chon chuan baud)
	SSPCON2 = 0;	
	SSPCON = 0x28; //I2C Master Hardware mode
}



///////////////////////////////
void main(void)
{
   i2c_init();
   khoitao();
   i2c_start();
   i2c_write(0xD0);  //Gui dia chi cua slave 
   i2c_write(0x00);  //thiet lap lai con tro - set register pointer 
   i2c_stop(); 
   i2c_start(); 
   i2c_write(0xD1); /* gui lenh doc du lieu */ 
   data[0]=i2c_read(0);
   data[1]=i2c_read(0);
   data[2]=i2c_read(1);
   i2c_stop();
   ////////////////////////
   PORTD=data[0];
   __delay_ms(1);
   
	
	
	
}
 
S

sonlamnguyenw

Guest
bạn Phương Tuấn ơi cho mình hỏi sao đoạn mã của bạn khi chuyển sang pic 16f877a nó lại không chạy được?
nếu hàm main:
Code:
void main(void)
{
	lcd_init();
	i2c_init();
	init_port();
	__delay_ms(150);
	while(1)
	{
		
		read_time();
		Display(time);
		
		__delay_ms(150);
        __delay_ms(150);
        
        
	}
thì chỉ hiện lên được nhưng không set được
còn  nếu như thế này thì không chạy được:
void main(void)
{
	lcd_init();
	i2c_init();
	init_port();
	__delay_ms(150);
	
	while(1)
	{
		nutnhan_RA0();
		nutnhan_RA1();
		nutnhan_RA2();
		Display(time);
		if(t==0)
		{
			a=0;
			read_time();
			if(k==1)
			{
				sosanh();
			}
		}
		if(i==1)
		{
			RB0=1;
			__delay_ms(50);
			RB0=0;
			__delay_ms(25);
		}
		else if(i==2)
		{
			RB0=1;
			__delay_ms(75);
			RB0=0;
			__delay_ms(50);
		}
		else if(i==3)
		{
			RB0=1;
			__delay_ms(75);
			RB0=0;
			__delay_ms(50);
		}
		else if(i==4)
		{
			RB0=1;
			__delay_ms(100);
			RB0=0;
			__delay_ms(75);
		}
		else if(i==5)
		{
			RB0=1;
			__delay_ms(100);
			RB0=0;
			__delay_ms(75);
		}	
	}
}
Bạn chú ý dùng thẻ
Code:
 cho những đoạn chứa code[/COLOR]
thế là bị làm sao vậy,mong bạn giúp đỡ.cám ơn nhiều.
 

honghiep

Cố Vấn CLB
Staff member
mọi người cho e hỏi: Khi e sử dụng nguồn ngoài qua 7805 cấp cho DS1307 thì giao tiếp được với PIC nhưng DS1307 rất nóng. Còn khi sử dụng nguồn cấp từ mạch nạp thì DS1307 không nóng nhưng không giao tiếp được với PIC
 

light

Thành Viên PIF
Trước giờ chưa gặp tình trạng này nhỉ, khi nào mắc ngược nguồn DS1307 mới nóng. Bạn coi chừng bị nhiễu đó, I2C nhiễu kinh khủng.
 

honghiep

Cố Vấn CLB
Staff member
tình hình là khi cắm cả 2 jump JP_VCC và JP_GND thì đọc và ghi dữ liệu cho DS1307 tốt nhưng DS nóng. Còn chỉ cắm jump JP_VCC thì chỉ đọc được dữ liệu từ DS1307 về VĐK chứ không ghi được- DS1307 không nóng. Và mình không thể set được thanh ghi năm
 
Top