//=========================
//Project: EEPROM Write/Read program I
//Author: Leo.Tseng
//Date: 2011/11/02
//MCU: W78E054D
//CRYSTAL: 25Mhz
//Description: Use uart for input/output, set boudrate=9600,
// Input Hexadecimal data to write to EEPROM
// and read out for verify
// EEPROM 24C64 address write is 0xA0, address read is 0xA1
// Write mode: Byte write, Read mode: Random read.
//=========================
#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);
unsigned char I2C_read(int i);
sbit SDA = P2^0; //SDA
sbit SCL = P2^1; //SCL
//sbit SDA = P0^0; //SDA
//sbit SCL = P0^1; //SCL
//======================================
//主程式開始
void main(void)
{
unsigned int data_buf[6]={0};
unsigned char uart_data[6];
unsigned char I2C_DATA=0xff;
unsigned char F_ADDRESS,S_ADDRESS;
unsigned long i=0;
int device_ACK;
int index=0;
int temp=0;
unsigned int temp_buf;
TIMER1_initinal(9600); // 使用UART,baudrate=9600
printf("\n輸入6個16進制字元,前兩字元為資料,後4字元為寫入起始位址: ");
RI=0;
TI=0;
while(1)
{
if(RI == 1)
{ // 接收到uart字元
RI = 0; // 清除接收接收旗號,準備接收下一個字元
uart_data[i] = SBUF; // 讀取輸入字元
SBUF = uart_data[i]; // 接收到的字元送回uart
i++;
}
else TI = 0; // 準備傳送下個接收字元
if ((i==6)) break;
}
for(i=0;i<6;i++) // 輸入字元限定判斷與轉換成16進位數值
{ //
if((uart_data[i]>='0')&&(uart_data[i]<='9')) // 限定0~9
{ //
data_buf[i]=uart_data[i]-0x30; //
} //
else if((uart_data[i]>='A')&&(uart_data[i]<='F')) // 限定A~F
{ //
data_buf[i]=uart_data[i]-0x37; //
} //
else if((uart_data[i]>='a')&&(uart_data[i]<='f')) // 限定a~f
{ //
data_buf[i]=(uart_data[i]-0x57); //
} //
}
//I2C_DATA=((data_buf[0]<<4)+(data_buf[1]&0x0f)); // 轉換輸入值
printf("\n按任何鍵開始寫入EEPROM\n");
_getkey();
I2C_DATA=((data_buf[0]<<4)+(data_buf[1]& 0x0f)); // 轉換要寫入資料值
F_ADDRESS=((data_buf[2]<<4)+(data_buf[3]& 0x0f)); // 轉換要寫入的高8位元位址
S_ADDRESS=((data_buf[4]<<4)+(data_buf[5]& 0x0f)); // 轉換要寫入的低8位元位址
index=(int)F_ADDRESS*256+(int)S_ADDRESS; // 計算要開始寫入的位址
//printf("\nindex in d =%d\n",index);
//printf("\nindex in x =%x\n",index);
//printf("\nindex in u =%u\n",index);
//=========== EEPROM Byte Write =========================
I2C_START(); // 開始I2C command
delay(5);
I2C_write(0xa0,8); // 寫入device address write
device_ACK=I2C_ACK(); // 取得device 狀態
//printf("device_ACK=%d\n\n",device_ACK);
if(device_ACK)
{
device_ACK=0; // 清除ACK旗號
//printf("Slave device is ACK!!\n\n");
I2C_write(F_ADDRESS,8); // 寫入第一字組位址
device_ACK=I2C_ACK();
device_ACK=0; // 清除ACK旗號
I2C_write(S_ADDRESS,8); // 寫入第二字組位址
device_ACK=I2C_ACK();
device_ACK=0; // 清除ACK旗號
I2C_write(I2C_DATA,8); // byte write data, 寫入資料
device_ACK=I2C_ACK();
I2C_STOP(); // 寫入完成, byte write 需要此停止命令
if(device_ACK) printf("\nByte write finished!!\n");
else printf("\nByte write not finished!!\n");
}
else
{
printf("Slave device is no ACK!!\n\n") ; // 否, device no ACK
}
//========== End of EEPROM Byte Write =========================
//=========== EEPROM Random Read =========================
printf("\n輸入4個16進制字元為讀出起始位址: ");
i=0;
RI=0;
TI=0;
while(1)
{
if(RI == 1)
{ // 接收到uart字元
RI = 0; // 清除接收接收旗號,準備接收下一個字元
uart_data[i] = SBUF; // 讀取輸入字元
SBUF = uart_data[i]; // 接收到的字元送回uart
i++;
}
else TI = 0; // 準備傳送下個接收字元
if ((i==4)) break;
}
for(i=0;i<4;i++) // 輸入字元限定判斷與轉換成16進位數值
{ //
if((uart_data[i]>='0')&&(uart_data[i]<='9')) // 限定0~9
{ //
data_buf[i]=uart_data[i]-0x30; //
} //
else if((uart_data[i]>='A')&&(uart_data[i]<='F')) // 限定A~F
{ //
data_buf[i]=uart_data[i]-0x37; //
} //
else if((uart_data[i]>='a')&&(uart_data[i]<='f')) // 限定a~f
{ //
data_buf[i]=(uart_data[i]-0x57); //
} //
}
printf("\n按任何鍵開始寫入EEPROM\n");
_getkey();
F_ADDRESS=((data_buf[0]<<4)+(data_buf[1]&0x0f)); // 轉換要讀出的高8位元位址
S_ADDRESS=((data_buf[2]<<4)+(data_buf[3]&0x0f)); // 轉換要讀出的低8位元位址
index=(int)F_ADDRESS*256+(int)S_ADDRESS; // 計算要開始讀出的位址
//printf("\nindex in d =%d\n",index);
//printf("\nindex in x =%x\n",index);
//printf("\nindex in u =%u\n",index);
I2C_START(); // 開始I2C command
delay(5);
I2C_write(0xa0,8); // 寫入device address write, DUMMY write
device_ACK=I2C_ACK(); // 取得device 狀態
if(device_ACK)
{
device_ACK=0; // 清除ACK旗號
I2C_write(F_ADDRESS,8); // First word address, DUMMY write
device_ACK=I2C_ACK();
device_ACK=0; // 清除ACK旗號
I2C_write(S_ADDRESS,8); // second word address, DUMMY write
device_ACK=I2C_ACK();
if(device_ACK)
{
I2C_START(); // 開始I2C command
delay(5);
I2C_write(0xa1,8); // 寫入device address read,
device_ACK=I2C_ACK(); // 取得device 狀態
I2C_DATA=I2C_read(8); // 讀取資料
device_ACK=0; // 清除ACK旗號
I2C_STOP(); // 讀取完成
}
}
//Read Data 轉換
if (((I2C_DATA/16)>=10)&&((I2C_DATA/16)<=15)) //位址高半位元組是大於9?
{
temp_buf=I2C_DATA/16+0x37; //轉換成A~F
uart_data[0]=(char)temp_buf;
//printf("\n11_Device Read address is %c\n",uart_data[0]);
}
else
{
temp_buf=I2C_DATA/16+0x30; //位址高半位元組小於等於9,轉換成0~9
uart_data[0]=(char)temp_buf;
//printf("\n12_Device Read address is %c\n",uart_data[0]);
}
if (((I2C_DATA%16)>=10)&&((I2C_DATA%16)<=15)) //位址低半位元組是大於9?
{
temp_buf=I2C_DATA%16+0x37; //轉換成A~F
uart_data[1]=(char)temp_buf;
//printf("\n21_Device Read address is %c\n",uart_data[1]);
}
else
{
temp_buf=I2C_DATA%16+0x30; //位址低半位元組小於等於9,轉換成0~9
uart_data[1]=(char)temp_buf;
//printf("\n22_Device Read address is %c\n",uart_data[1]);
}
printf("\nDevice Read address is 0x%c%c\n",uart_data[0],uart_data[1]);
// printf("\nR_I2C_DATA=%c\n",I2C_DATA);
//============ End of EEPROM Random Read =========
} //end of main
//=======================================
//延時副程式
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
}
//I2C Read副程式
unsigned char I2C_read(int i)
{
unsigned char SDA_BUF=0x00;
while(i--)
{
SCL = 1; //確認SCL=1
//delay(1); //等待SDA穩定
SDA_BUF = (SDA_BUF << 1)|SDA; //讀取SDA暫存
delay(4);
SCL = 0;
delay(2);
}
//printf("\nR_SDA_BUF=%c\n",SDA_BUF);
return(SDA_BUF);
}
2011年11月9日 星期三
2011年10月31日 星期一
PWM generation
//=========================
//Project: PWM generation
//Author: Leo.Tseng
//Date: 2011/10/28
//MCU: W78E054D
//CRYSTAL: 25Mhz
//Description: Use uart for input/output, set boudrate=9600,
// Press "a" to increase PWM high duty, Press "d" to
// decrease PWM high duty.
// initination is working in 20% duty.
//=========================
#include <reg52.h>
#include <stdio.h>
void uart_initinal(int boudrate);
int TIMES=65536; // 16bit counter
int FREQ=10400; // 200HZ = 10400 機械週期
int PWMHIGH=2080; // 高電位佔20%=10400*0.2=2080個機械週期
int PWMLOW=8320; // 低電位佔80%=10400*0.8=8320個機械週期
int PERIOD;
char ch;
sbit PWMOUT = P1^2;
sbit PWMOUT1 = P2^0;
sbit PWMOUT2 = P2^1;
//------------------------------------------------
//MAIN C function
//------------------------------------------------
void main (void)
{
uart_initinal(9600); // 起始 UART 設定,baudrate=9600
//PWMOUT = 0;
TMOD = (TMOD & 0xF0) | 0x01; // 設定 T/C0 Mode
PERIOD = TIMES-PWMHIGH;
TH0 = PERIOD/256;
TL0 = PERIOD%256;
ET0 = 1; // 致能 Timer 0 Interrupts
TR0 = 1; // 啟動 Timer 0 計時
EA = 1; // Global Interrupt Enable
PWMOUT = 1;
PWMOUT1 = 1;
PWMOUT2 = 1;
printf("按 ""a"" 增加PWM工作週期20%%,按 ""d"" 減少PWM工作週期20%%\n"); //顯示操作訊息
//printf("Press ""a"" to increase duty cycle, ""d"" to decrease duty cycle\n"); //顯示操作訊息
while (1)
{
switch (ch=_getkey())
{
case '+': // 增加高電位20/%
case 'A': //
case 'a':if(PWMHIGH==300) //
PWMHIGH=2080;
else if(PWMHIGH <= 6240)
PWMHIGH+=2080;
else if(PWMHIGH >= 8320)
PWMHIGH=10100;
PWMLOW=FREQ-PWMHIGH;
//printf("a_PWMHIGH is %u\n",PWMHIGH);
break;
case '-': // 減少高電位20/%
case 'D': //
case 'd':if(PWMHIGH==10100) //
PWMHIGH=8320;
else if(PWMHIGH >= 4160)
PWMHIGH-=2080;
else if(PWMHIGH <= 2080)
PWMHIGH=300;
PWMLOW=FREQ-PWMHIGH;
//printf("d_PWMHIGH is %u\n",PWMHIGH);
break;
default: break;
}
}
}
//UART副程式使用timer1
void uart_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 = (TMOD & 0x0f) | 0x20; // TMOD: timer 1, mode 2, 8-bit reload; keeps timer0 default.
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
}
//計時器0中斷1
void timer0_ISR(void) interrupt 1
{
if(PWMOUT==1)
{
TR0=0;
PERIOD = TIMES-PWMLOW;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
PWMOUT=0;
PWMOUT1=0;
PWMOUT2=0;
}
else
{
TR0=0;
PERIOD = TIMES-PWMHIGH;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
PWMOUT=1;
PWMOUT1=1;
PWMOUT2=1;
}
}
//Project: PWM generation
//Author: Leo.Tseng
//Date: 2011/10/28
//MCU: W78E054D
//CRYSTAL: 25Mhz
//Description: Use uart for input/output, set boudrate=9600,
// Press "a" to increase PWM high duty, Press "d" to
// decrease PWM high duty.
// initination is working in 20% duty.
//=========================
#include <reg52.h>
#include <stdio.h>
void uart_initinal(int boudrate);
int TIMES=65536; // 16bit counter
int FREQ=10400; // 200HZ = 10400 機械週期
int PWMHIGH=2080; // 高電位佔20%=10400*0.2=2080個機械週期
int PWMLOW=8320; // 低電位佔80%=10400*0.8=8320個機械週期
int PERIOD;
char ch;
sbit PWMOUT = P1^2;
sbit PWMOUT1 = P2^0;
sbit PWMOUT2 = P2^1;
//------------------------------------------------
//MAIN C function
//------------------------------------------------
void main (void)
{
uart_initinal(9600); // 起始 UART 設定,baudrate=9600
//PWMOUT = 0;
TMOD = (TMOD & 0xF0) | 0x01; // 設定 T/C0 Mode
PERIOD = TIMES-PWMHIGH;
TH0 = PERIOD/256;
TL0 = PERIOD%256;
ET0 = 1; // 致能 Timer 0 Interrupts
TR0 = 1; // 啟動 Timer 0 計時
EA = 1; // Global Interrupt Enable
PWMOUT = 1;
PWMOUT1 = 1;
PWMOUT2 = 1;
printf("按 ""a"" 增加PWM工作週期20%%,按 ""d"" 減少PWM工作週期20%%\n"); //顯示操作訊息
//printf("Press ""a"" to increase duty cycle, ""d"" to decrease duty cycle\n"); //顯示操作訊息
while (1)
{
switch (ch=_getkey())
{
case '+': // 增加高電位20/%
case 'A': //
case 'a':if(PWMHIGH==300) //
PWMHIGH=2080;
else if(PWMHIGH <= 6240)
PWMHIGH+=2080;
else if(PWMHIGH >= 8320)
PWMHIGH=10100;
PWMLOW=FREQ-PWMHIGH;
//printf("a_PWMHIGH is %u\n",PWMHIGH);
break;
case '-': // 減少高電位20/%
case 'D': //
case 'd':if(PWMHIGH==10100) //
PWMHIGH=8320;
else if(PWMHIGH >= 4160)
PWMHIGH-=2080;
else if(PWMHIGH <= 2080)
PWMHIGH=300;
PWMLOW=FREQ-PWMHIGH;
//printf("d_PWMHIGH is %u\n",PWMHIGH);
break;
default: break;
}
}
}
//UART副程式使用timer1
void uart_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 = (TMOD & 0x0f) | 0x20; // TMOD: timer 1, mode 2, 8-bit reload; keeps timer0 default.
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
}
//計時器0中斷1
void timer0_ISR(void) interrupt 1
{
if(PWMOUT==1)
{
TR0=0;
PERIOD = TIMES-PWMLOW;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
PWMOUT=0;
PWMOUT1=0;
PWMOUT2=0;
}
else
{
TR0=0;
PERIOD = TIMES-PWMHIGH;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
PWMOUT=1;
PWMOUT1=1;
PWMOUT2=1;
}
}
2011年10月24日 星期一
Auto detect I2C slave device read/write address program
//=========================
//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
}
//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
}
2011年10月18日 星期二
I2C device read/write command program
//=========================
//Project: I2C device read/write command program
//Author: Leo.Tseng
//Date: 2011/09/30
//MCU: W78E054D
//CRYSTAL: 25Mhz
//Description: Use uart for input/output, set boudrate=9600,
// input Hexadecimal data as your 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[2];
unsigned int data_buf[2]={0,0};
int i=0;
unsigned char I2C_DATA=0xff;
int device_ACK;
TIMER1_initinal(9600); // 使用UART,baudrate=9600
printf("\nInput Device Address : ");
RI=0;
TI=0;
while(1)
{
if(RI == 1)
{ // 接收到uart字元
RI = 0; // 清除接收接收旗號,準備接收下一個字元
uart_data[i] = SBUF; // 讀取輸入字元
SBUF = uart_data[i]; // 接收到的字元送回uart
i++;
}
else TI = 0; // 準備傳送下個接收字元
if ((i==2)) break;
}
printf("\nEnd!!\n");
for(i=0;i<2;i++) // 輸入字元限定判斷與轉換成16進位數值
{ //
if((uart_data[i]>='0')&&(uart_data[i]<='9')) // 限定0~9
{ //
data_buf[i]=uart_data[i]-0x30; //
} //
else if((uart_data[i]>='A')&&(uart_data[i]<='F')) // 限定A~F
{ //
data_buf[i]=uart_data[i]-0x37; //
} //
else if((uart_data[i]>='a')&&(uart_data[i]<='f')) // 限定a~f
{ //
data_buf[i]=(uart_data[i]-0x57); //
} //
}
I2C_DATA=((data_buf[0]<<4)+(data_buf[1]&0x0f)); // 轉換輸入值
I2C_START(); // 開始I2C command
delay(5);
I2C_write(I2C_DATA,8); // 寫入device address
device_ACK=I2C_ACK(); // 取得device 狀態
I2C_STOP(); // 停止I2C command
//printf("device_ACK=%d\n\n",device_ACK);
if(device_ACK) // 判斷device是否有回應
printf("Slave device is ACK!!\n\n"); // 是, device ACK
else printf("Slave device is no ACK!!\n\n") ; // 否, device no ACK
//printf("I2C stop!!\n");
}
//=======================================
//延時副程式
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(5);
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-(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
}
//Project: I2C device read/write command program
//Author: Leo.Tseng
//Date: 2011/09/30
//MCU: W78E054D
//CRYSTAL: 25Mhz
//Description: Use uart for input/output, set boudrate=9600,
// input Hexadecimal data as your 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[2];
unsigned int data_buf[2]={0,0};
int i=0;
unsigned char I2C_DATA=0xff;
int device_ACK;
TIMER1_initinal(9600); // 使用UART,baudrate=9600
printf("\nInput Device Address : ");
RI=0;
TI=0;
while(1)
{
if(RI == 1)
{ // 接收到uart字元
RI = 0; // 清除接收接收旗號,準備接收下一個字元
uart_data[i] = SBUF; // 讀取輸入字元
SBUF = uart_data[i]; // 接收到的字元送回uart
i++;
}
else TI = 0; // 準備傳送下個接收字元
if ((i==2)) break;
}
printf("\nEnd!!\n");
for(i=0;i<2;i++) // 輸入字元限定判斷與轉換成16進位數值
{ //
if((uart_data[i]>='0')&&(uart_data[i]<='9')) // 限定0~9
{ //
data_buf[i]=uart_data[i]-0x30; //
} //
else if((uart_data[i]>='A')&&(uart_data[i]<='F')) // 限定A~F
{ //
data_buf[i]=uart_data[i]-0x37; //
} //
else if((uart_data[i]>='a')&&(uart_data[i]<='f')) // 限定a~f
{ //
data_buf[i]=(uart_data[i]-0x57); //
} //
}
I2C_DATA=((data_buf[0]<<4)+(data_buf[1]&0x0f)); // 轉換輸入值
I2C_START(); // 開始I2C command
delay(5);
I2C_write(I2C_DATA,8); // 寫入device address
device_ACK=I2C_ACK(); // 取得device 狀態
I2C_STOP(); // 停止I2C command
//printf("device_ACK=%d\n\n",device_ACK);
if(device_ACK) // 判斷device是否有回應
printf("Slave device is ACK!!\n\n"); // 是, device ACK
else printf("Slave device is no ACK!!\n\n") ; // 否, device no ACK
//printf("I2C stop!!\n");
}
//=======================================
//延時副程式
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(5);
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-(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
}
訂閱:
文章 (Atom)