View Single Post
Old 09-04-2007, 01:41 AM   #32
ngohaibac
Đệ tử 9 túi
 
ngohaibac's Avatar
 
Tham gia ngày: Oct 2005
Nơi Cư Ngụ: BKHN
Bài gửi: 231
:
Send a message via Yahoo to ngohaibac
Thư viện I2C Master.

Tiếp theo là về module I2C, một chuẩn giao tiếp quan trọng khi giao tiếp với ngoại vi như EEPROM, RTS(DS1307),...

Do đó, mình xin cung cấp cho các bạn các hàm và thực thi của các hàm này trên HTPIC. Mình có tham khảo cả ở bọn htsoft nhưng nó viết sai một số hàm không chạy được, mình đã viết lại toàn bộ.

Đầu tiên là hàm I2C.h:

Code:
//I2C.h
//Declare some functions
void I2C_Init(void);          // khởi tạo I2C ở chế độ Master, Baud = 100 Khz
void I2C_waitForIdle(void); // Chờ khi nào đường bus ở chế độ Idle (rảnh rỗi)
void I2C_Start(void);        // Khởi động I2C - Master chiếm đường bus
void I2C_repStart(void);   // Chế độ Restart
void I2C_stop(void);         // Stop I2C - Master nhường đường bus cho thiết bị khác
unsigned char I2C_write( unsigned char I2CWriteData ); // ghi một byte lên đường SDA
unsigned char I2C_read( unsigned char ack ); // Đọc một byte với mã ACK (ACK = 0 nếu ack = 1, và ACK = 1 nếu ack = 0) -> dùng xác nhận từ master đối với slave.
void I2C_NACK(void);  // tạo bít Not Ack
Và sau đây là thực thi của các hàm này:

Code:
// I2C.c
# include "pic.h"
# include "I2C.h"
//======================================================================================================
void I2C_Init(void){
/*	// Configure for Master Mode
	SSPM3 = 1;
	SSPM2 = 0;
	SSPM1 = 0;
	SSPM0 = 0;				ss	// I2C Master Mode, clock = Fosc/(4*(SSPADD + 1));
	
	WCOL = 0;					//No conllision
	
	SSPEN = 1;					// Enables the serial port and 
*/	
	SSPCON = 0b00101000;		// set IIC port to Master mode with BRG	
	SSPSTAT = 0b00000000;		// Standard speed mode - 100Hz
	SSPCON2 = 0;
	
	//TRIS_SCL = 0;
	//TRIS_SDA = 0;				// configure SDA and SCL as Output
	
	SSPADD = 9;			   	 // BAUD = 100KHz
	SSPIF = 0;      				// clear SSPIF interrupt flag
 	BCLIF = 0;      				// clear bus collision flag
	STAT_CKE  = 0;     			// use I2C levels      worked also with '0'
 	STAT_SMP = 1;     			// disable slew rate control  worked also with '0'
}
//=============================================================================
void I2C_waitForIdle(void)
{
 	while (( SSPCON2 & 0x1F ) | STAT_RW) ; //CLRWDT(); // wait for idle and not writing
}

//=============================================================================
void I2C_Start(void){
	//SSPIF = 0;
	SEN = 1;
	//while(!SSPIF);
	while(SEN);
}
//==============================================================================
void I2C_repStart(void)
{
	 I2C_waitForIdle();
	 RSEN = 1;
}
//=============================================================================
void I2C_stop(void)	
{
	 I2C_waitForIdle();
	 PEN = 1; 
}
//==============================================================================
unsigned char I2C_write( unsigned char I2CWriteData ){
	 I2C_waitForIdle();
	 SSPBUF = I2CWriteData;
	 I2C_waitForIdle();
	  return (!ACKSTAT); // function returns '1' if transmission is acknowledged	
	// 1: Success
	// 0: Fail to send 
}
//============================================================================
unsigned char I2C_read( unsigned char ack ){
	unsigned char I2C_ReadData;
	 I2C_waitForIdle();
	 RCEN = 1;
	 I2C_waitForIdle();
	 I2C_ReadData = SSPBUF;
	 I2C_waitForIdle();
	 if ( ack )  	ACKDT=0;
    	 else             ACKDT = 1;
 	 ACKEN = 1;               // send acknowledge sequence
	 I2C_waitForIdle();
	 return( I2C_ReadData );
}
/******************************************************************************************/

void I2C_NACK(void)
{
	I2C_waitForIdle();
	if (ACKSTAT){
		PEN=1;						//Stop
   		I2C_waitForIdle();			//Wait until action is finished
		while(PEN);
   	};
}
Còn việc dùng nó quá đơn giản, ví dụ với Ds1307 thì đầu tiên bạn phải:

- Khởi tạo I2C bằng I2C_Start();
- Start bằng I2C_Start();
- Chọn slave giao tiếp bằng cách ghi địa chỉ và bit RW tương ứng với chế độ đọc hay ghi.
- Ghi dữ liệu lựa chọn byte nào cần ghi hay cần đọc trong bảng RAM của DS1307.
- Ghi dữ liệu hay là đọc dữ liệu.

Chú ý: khi ghi xong, muốn đọc thì phải làm lại tức là phải restart nhé.

Chúc các bạn thành công.
ngohaibac vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn