//=========================
//Project: I2C device read/write address detect program
//Author: Leo.Tseng
//Date: 2011/10/20
//MCU: W78E054D
//CRYSTAL: 25Mhz
//Description: Use uart for input/output, set boudrate=9600,
// auto detect I2C device read/write address.
//=========================
#include <reg52.h>
#include <stdio.h>
//副程式宣告
void I2C_START(void);
void I2C_STOP(void);
void I2C_CLOCK(int t);
void I2C_write(unsigned char I2C_DATA,int i);
void delay(unsigned int d);
int I2C_ACK(void);
void TIMER1_initinal(int boudrate);
sbit SDA = P2^0; //SDA
sbit SCL = P2^1; //SCL
//======================================
//主程式開始
void main(void)
{
unsigned char uart_data[6];
unsigned int data_buf[6]={0};
int i=0;
int index=0;
int temp=0;
unsigned char I2C_DATA=0xff;
int device_ACK;
unsigned int temp_buf;
TIMER1_initinal(9600); // 使用UART,baudrate=9600
printf("\nPress any key to start detect device I2C address!!");
_getkey(); // 等待任何按鍵
printf("\n\n");
for (i=0;i<=I2C_DATA;i++)
{
I2C_START(); // 開始I2C command
delay(5);
I2C_write(i,8); // 寫入device address
device_ACK=I2C_ACK(); // 取得device ACK 狀態
I2C_STOP(); // 停止I2C command
if(device_ACK) // 儲存 device ACK address
{
data_buf[index]=i;
// printf("\nACK ADDRESS%d is %d",index,data_buf[index]);
temp=index++;
}
}
//index=0;
//===== Address轉換成字元顯示 ==========
for(index=0;index<=temp;index++)
{
if(data_buf[index]& 0x01) //Read address 轉換
{
if (((data_buf[index]/16)>=10)&&((data_buf[index]/16)<=15)) //位址高半位元組是大於9?
{
temp_buf=data_buf[index]/16+0x37; //轉換成A~F
uart_data[0]=(char)temp_buf;
// printf("\n11_Device Read address is %c\n",uart_data[0]);
}
else
{
temp_buf=data_buf[index]/16+0x30; //位址高半位元組小於等於9,轉換成0~9
uart_data[0]=(char)temp_buf;
// printf("\n21_Device Read address is %c\n",uart_data[0]);
}
temp_buf=data_buf[index]%16+0x30; //位址低半位元組轉換成0~9
uart_data[1]=(char)temp_buf;
printf("\nDevice Read address is 0x%c%c\n",uart_data[0],uart_data[1]);
}
else //Write address 轉換
{
if (((data_buf[index]/16)>=10)&&((data_buf[index]/16)<=15)) //位址高半位元組是大於9?
{
temp_buf=data_buf[index]/16+0x37; //轉換成A~F
uart_data[0]=(char)temp_buf;
}
else
{
temp_buf=data_buf[index]/16+0x30; //位址高半位元組小於等於9,轉換成0~9
uart_data[0]=(char)temp_buf;
}
temp_buf=data_buf[index]%16+0x30; //位址低半位元組轉換成0~9
uart_data[1]=(char)temp_buf;
printf("\nDevice Write address is 0x%c%c\n",uart_data[0],uart_data[1]);
}
}
}
//=======================================
//延時副程式
void delay(unsigned int d)
{
while (--d);
}
//I2C 開始副程式
// ______
//SDA \______
// _________
//SCL \_______
// -| |-- START
void I2C_START(void)
{
if (SDA!=1) SDA=1;
if (SCL!=1) SCL=1;
delay(1);
SDA = 0;
delay(5);
SCL = 0;
}
//I2C 停止副程式
// _______
//SDA _________/
// __________
//SCL ______/
// -| |-- STOP
void I2C_STOP(void)
{
if (SDA!=0) SDA=0;
if (SCL!=0) SCL=0;
delay(1);
SCL = 1;
delay(4);
SDA = 1;
delay(10);
}
//I2C clock 產生副程式
void I2C_CLOCK(int t)
{
delay(t);
SCL = 1; //設定SCL為高位準
delay(t);
SCL = 0; //設定SCL為高位準
}
//I2C write 副程式
void I2C_write(unsigned char I2C_DATA,int i)
{
//bit data_bit;
while(i--)
{
SDA=(I2C_DATA & 0x80)? 1 : 0; //取出最高位元,並送至SDA
delay(1); //等待SDA穩定
SCL = 1;
delay(5);
//I2C_CLOCK(5);
I2C_DATA<<=1; //下個資料位元
SCL = 0;
//delay(1);
}
}
//I2C ACK副程式
// ___________ NO ACK
//SDA _____/ \_________ ACK
// ____
//SCL ______/ \________
// -| b9 |---- ACK bit
int I2C_ACK(void)
{
SDA=1;
delay(2);
SCL=1;
if(SDA==0) // 判斷ack bit是否拉low
{
delay(6);
SCL = 0;
return 1; // 是
}
else
{
delay(6);
SCL = 0;
return 0; // 否
}
}
//UART副程式
void TIMER1_initinal(int boudrate)
{
PCON = 0x00; // PCON: if SMOD=1(b7), Baud Rate is Doubled
SCON = 0x52; // SCON: mode 1, 8-bit UART, enable rcvr
TMOD = 0x20; // TMOD: timer 1, mode 2, 8-bit reload
//TH1 = 256-(11059200/384/boudrate); // TH1: reload value for baud @ 11.0592MHz, TH=0xFD
TH1 = 256-(25000000/372/boudrate); // TH1: reload value for baud @ 25MHz, TH=0xF9
TR1 = 1; // TR1: timer 1 run
//TI = 1; // TI: set TI to send first char of UART
}
沒有留言:
張貼留言