//=========================
//Project: PWM generation for STEP motor control
//Author: Leo.Tseng
//Date: 2011/12/21
//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.
// PWM will control 3-wire step motor.
//=========================
#include <reg52.h>
#include <stdio.h>
void uart_initinal(int baudrate);
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,n_SCAN;
char ch;
sbit SCAN0 = P1^2;
sbit SCAN1 = P1^3;
sbit SCAN2 = P1^4
//------------------------------------------------
//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; // 全部致能始動
SCAN0 = 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())
{
// 增加高電位20/%
case 'A': //
case 'a':if(PWMHIGH==300) //
PWMHIGH=2080;
else if(PWMHIGH <= 6240)
PWMHIGH+=2080;
else if(PWMHIGH >= 8320)
PWMHIGH=10100; // 最高duty cycle限制97%
PWMLOW=FREQ-PWMHIGH;
//printf("a_PWMHIGH is %u\n",PWMHIGH);
break;
// 減少高電位20/%
case 'D': //
case 'd':if(PWMHIGH==10100) //
PWMHIGH=8320;
else if(PWMHIGH >= 4160)
PWMHIGH-=2080;
else if(PWMHIGH <= 2080)
PWMHIGH=300; // 最低duty cycle限制97%
PWMLOW=FREQ-PWMHIGH;
//printf("d_PWMHIGH is %u\n",PWMHIGH);
break;
default: break;
}
}
}
//UART副程式使用timer1
void uart_initinal(int baudrate)
{
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/baudrate); // TH1: reload value for baud @ 25MHz, TH=0xF9
//TH1= 256-(11059200/384/baudrate);
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((SCAN0==1)&&(SCAN1==1)&&(SCAN2==1)&&(n_SCAN==0))
{
TR0=0;
PERIOD = TIMES-PWMLOW;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
SCAN0=0;
}
else if((SCAN0==0)&&(SCAN1==1)&&(SCAN2==1)&&(n_SCAN==0))
{
TR0=0;
PERIOD = TIMES-PWMHIGH;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
SCAN0=1;
n_SCAN=1;
}
if((SCAN1==1)&&(SCAN0==1)&&(SCAN2==1)&&(n_SCAN==1))
{
TR0=0;
PERIOD = TIMES-PWMLOW;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
SCAN1=0;
}
else if((SCAN1==0)&&(SCAN0==1)&&(SCAN2==1)&&(n_SCAN==1))
{
TR0=0;
PERIOD = TIMES-PWMHIGH;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
SCAN1=1;
n_SCAN=2;
}
if((SCAN2==1)&&(SCAN0==1)&&(SCAN1==1)&&(n_SCAN==2))
{
TR0=0;
PERIOD = TIMES-PWMLOW;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
SCAN2=0;
}
else if((SCAN2==0)&&(SCAN0==1)&&(SCAN1==1)&&(n_SCAN==2))
{
TR0=0;
PERIOD = TIMES-PWMHIGH;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
SCAN2=1;
n_SCAN=0;
}
}
===================================================================
罰跪奇兵
2011年12月20日 星期二
2011年12月8日 星期四
NEC protocol IR remote TX program
//=========================
//Project: NEC protocol TX
//Author: Leo.Tseng
//Date: 2011/12/09
//MCU: W78E054D
//CRYSTAL: 25Mhz
//Description: Use uart for input/output, set boudrate=9600,
// Press Keypad to transmit NEC protocol code
// SW20=0x08E647B8, power key.
// SW15=0x08E618E7, channel up.
// SW19=0x08E610EF, channel down.
//=========================
#include <reg52.h>
#include <stdio.h>
void uart_initinal(int boudrate);
int PERIOD,i;
unsigned KEY,temp;
unsigned long ir_data;
sbit PWMOUT = P3^2;
//sbit PWMOUT1 = P2^0;
//sbit PWMOUT2 = P2^1;
sbit SCAN0 = P2^7; // KEY SCAN0
sbit SCAN1 = P2^6; // KEY SCAN1
sbit SCAN2 = P2^5; // KEY SCAN2
sbit SCAN3 = P2^4; // KEY SCAN3
sbit DET3 = P2^3; // KEY DETECT0, always high
sbit DET2 = P2^2; // KEY DETECT2
sbit DET1 = P2^1; // KEY DETECT1
sbit DET0 = P2^0; // KEY DETECT0
//副程式宣告
void TIMER1_initinal(int baudrate);
void delay (int j);
void NEC_LEADER_CODE(void);
void NEC_low(void);
void NEC_high(void);
void NEC_stop(void);
//------------------------------------------------
//MAIN C function
//------------------------------------------------
void main (void)
{
uart_initinal(9600); // 起始 UART 設定,baudrate=9600
TMOD = (TMOD & 0xF0) | 0x02; // 設定 T/C0 Mode
PERIOD = 200;
TH0 = PERIOD;
TL0 = TH0;
// ET0 = 1; // 致能 Timer 0 Interrupts
// TR0 = 1; // 啟動 Timer 0 計時
EA = 1; // 全部致能始動
PWMOUT = 0;
SCAN0=0;
SCAN1=SCAN2=SCAN3=1;
DET3=DET2=DET1=DET0=1;
//ir_data = 0x1067E21D; // for transmission 1
//ir_data = 0xB847E608; // for transmission 2
printf("NEC編碼紅外線發射程式\n"); // 顯示操作訊息
while (1)
{
if((P2&0x0F)!=0x0F) // 偵測是否按按鍵?
{
temp=P2&0xFF; // 第一次儲存按鍵值
delay(6000); // 延遲 0.48us*6000=2.88ms,防彈跳調整
KEY=P2&0xFF; // 第二次讀取按鍵值
if(KEY&&temp) // 判別是否為按鍵
{
/*
ET0 = 1;
TR0 = 1;
// ***** transmission 1 *****
NEC_LEADER_CODE();
NEC_low();NEC_low();NEC_low();NEC_high(); // 1:0001 > 8
NEC_low();NEC_low();NEC_low();NEC_low(); // 0:0000 > 0
NEC_low();NEC_high();NEC_high();NEC_low(); // 6:0110 > 6
NEC_low();NEC_high();NEC_high();NEC_high(); // 7:0111 > E
NEC_high();NEC_high();NEC_high();NEC_low(); // E:1110 > 7
NEC_low();NEC_low();NEC_high();NEC_low(); // 2:0010 > 4
NEC_low();NEC_low();NEC_low();NEC_high(); // 1:0001 > 8
NEC_high();NEC_high();NEC_low();NEC_high(); // D:1101 > B
NEC_stop(); // 停止位元
//PWMOUT=0;
ET0 = 0;
TR0 = 0;
delay(11030); // 補足108ms
//ET0 = 1;
//TR0 = 1;
*/
switch(KEY)
{
case 0x7B: printf("SW20 pressed, code=0x7B\n");
ir_data = 0xB847E608; // SW20,等於 0x08E647B8
break;
case 0x7D: printf("SW15 pressed, code=0x7D\n");
ir_data = 0xE718E608; // SW15,等於 0x08E618E7
break;
case 0x7E: printf("SW19 pressed, code=0x7E\n");
ir_data = 0xEF10E608; // SW19,等於 0x08E610EF
break;
default: break;
}
// ******* transmission 2 ********
NEC_LEADER_CODE();
for(i=0;i<32;i++ )
{
if(ir_data & 0x0001)
{
//printf("1"); // 除錯用
NEC_high();
}
else
{
//printf("0"); // 除錯用
NEC_low();
}
ir_data=ir_data>>1;
}
NEC_stop();
//PWMOUT=0;
ET0 = 0;
TR0 = 0;
delay(11030); // 補足108ms
//ET0 = 1;
//TR0 = 1;
}
}
}
}
//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, 產生38Khz 載波
void timer0_ISR(void) interrupt 1
{
PWMOUT^=1; // 設為高電位
PWMOUT&=1;
PWMOUT&=1;
PWMOUT&=1;
PWMOUT&=1;
PWMOUT&=1;
PWMOUT^=1; // 設為低電位
PWMOUT&=1;
PWMOUT&=1;
PWMOUT&=1;
PWMOUT&=1;
PWMOUT&=1;
//PWMOUT&=1;
}
void delay (int j)
{
while(j)
j--;
}
// NEC前導碼: 9ms高電位, 4.5ms低電位
void NEC_LEADER_CODE(void)
{
ET0=1;
TR0=1;
//PWMOUT1=1; // 除錯用
delay(336);
// PWMOUT1=0; // 除錯用
ET0 = 0;
TR0 = 0;
delay(1170);
}
// NEC碼0: 0.56ms高電位, 0.56ms低電位
void NEC_low(void)
{
ET0=1;
TR0=1;
//PWMOUT1=1; // 除錯用
delay(19);
//PWMOUT1=0; // 除錯用
ET0 = 0;
TR0 = 0;
delay(140);
}
// NEC碼1: 0.56ms高電位, 1.69ms低電位
void NEC_high(void)
{
ET0=1;
TR0=1;
//PWMOUT1=1; // 除錯用
delay(19);
//PWMOUT1=0; // 除錯用
ET0 = 0;
TR0 = 0;
delay(440);
}
// NEC碼,停止位元: 0.56ms高電位
void NEC_stop(void)
{
ET0 = 1;
TR0 = 1;
//PWMOUT1=1; // 除錯用
delay(19);
//PWMOUT1=0; // 除錯用
ET0 = 0;
TR0 = 0;
}
// ===== Test Result ========================
SW19, Code : 0x08E610EF
SW20, Code : 0x08E647B8
//Project: NEC protocol TX
//Author: Leo.Tseng
//Date: 2011/12/09
//MCU: W78E054D
//CRYSTAL: 25Mhz
//Description: Use uart for input/output, set boudrate=9600,
// Press Keypad to transmit NEC protocol code
// SW20=0x08E647B8, power key.
// SW15=0x08E618E7, channel up.
// SW19=0x08E610EF, channel down.
//=========================
#include <reg52.h>
#include <stdio.h>
void uart_initinal(int boudrate);
int PERIOD,i;
unsigned KEY,temp;
unsigned long ir_data;
sbit PWMOUT = P3^2;
//sbit PWMOUT1 = P2^0;
//sbit PWMOUT2 = P2^1;
sbit SCAN0 = P2^7; // KEY SCAN0
sbit SCAN1 = P2^6; // KEY SCAN1
sbit SCAN2 = P2^5; // KEY SCAN2
sbit SCAN3 = P2^4; // KEY SCAN3
sbit DET3 = P2^3; // KEY DETECT0, always high
sbit DET2 = P2^2; // KEY DETECT2
sbit DET1 = P2^1; // KEY DETECT1
sbit DET0 = P2^0; // KEY DETECT0
//副程式宣告
void TIMER1_initinal(int baudrate);
void delay (int j);
void NEC_LEADER_CODE(void);
void NEC_low(void);
void NEC_high(void);
void NEC_stop(void);
//------------------------------------------------
//MAIN C function
//------------------------------------------------
void main (void)
{
uart_initinal(9600); // 起始 UART 設定,baudrate=9600
TMOD = (TMOD & 0xF0) | 0x02; // 設定 T/C0 Mode
PERIOD = 200;
TH0 = PERIOD;
TL0 = TH0;
// ET0 = 1; // 致能 Timer 0 Interrupts
// TR0 = 1; // 啟動 Timer 0 計時
EA = 1; // 全部致能始動
PWMOUT = 0;
SCAN0=0;
SCAN1=SCAN2=SCAN3=1;
DET3=DET2=DET1=DET0=1;
//ir_data = 0x1067E21D; // for transmission 1
//ir_data = 0xB847E608; // for transmission 2
printf("NEC編碼紅外線發射程式\n"); // 顯示操作訊息
while (1)
{
if((P2&0x0F)!=0x0F) // 偵測是否按按鍵?
{
temp=P2&0xFF; // 第一次儲存按鍵值
delay(6000); // 延遲 0.48us*6000=2.88ms,防彈跳調整
KEY=P2&0xFF; // 第二次讀取按鍵值
if(KEY&&temp) // 判別是否為按鍵
{
/*
ET0 = 1;
TR0 = 1;
// ***** transmission 1 *****
NEC_LEADER_CODE();
NEC_low();NEC_low();NEC_low();NEC_high(); // 1:0001 > 8
NEC_low();NEC_low();NEC_low();NEC_low(); // 0:0000 > 0
NEC_low();NEC_high();NEC_high();NEC_low(); // 6:0110 > 6
NEC_low();NEC_high();NEC_high();NEC_high(); // 7:0111 > E
NEC_high();NEC_high();NEC_high();NEC_low(); // E:1110 > 7
NEC_low();NEC_low();NEC_high();NEC_low(); // 2:0010 > 4
NEC_low();NEC_low();NEC_low();NEC_high(); // 1:0001 > 8
NEC_high();NEC_high();NEC_low();NEC_high(); // D:1101 > B
NEC_stop(); // 停止位元
//PWMOUT=0;
ET0 = 0;
TR0 = 0;
delay(11030); // 補足108ms
//ET0 = 1;
//TR0 = 1;
*/
switch(KEY)
{
case 0x7B: printf("SW20 pressed, code=0x7B\n");
ir_data = 0xB847E608; // SW20,等於 0x08E647B8
break;
case 0x7D: printf("SW15 pressed, code=0x7D\n");
ir_data = 0xE718E608; // SW15,等於 0x08E618E7
break;
case 0x7E: printf("SW19 pressed, code=0x7E\n");
ir_data = 0xEF10E608; // SW19,等於 0x08E610EF
break;
default: break;
}
// ******* transmission 2 ********
NEC_LEADER_CODE();
for(i=0;i<32;i++ )
{
if(ir_data & 0x0001)
{
//printf("1"); // 除錯用
NEC_high();
}
else
{
//printf("0"); // 除錯用
NEC_low();
}
ir_data=ir_data>>1;
}
NEC_stop();
//PWMOUT=0;
ET0 = 0;
TR0 = 0;
delay(11030); // 補足108ms
//ET0 = 1;
//TR0 = 1;
}
}
}
}
//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, 產生38Khz 載波
void timer0_ISR(void) interrupt 1
{
PWMOUT^=1; // 設為高電位
PWMOUT&=1;
PWMOUT&=1;
PWMOUT&=1;
PWMOUT&=1;
PWMOUT&=1;
PWMOUT^=1; // 設為低電位
PWMOUT&=1;
PWMOUT&=1;
PWMOUT&=1;
PWMOUT&=1;
PWMOUT&=1;
//PWMOUT&=1;
}
void delay (int j)
{
while(j)
j--;
}
// NEC前導碼: 9ms高電位, 4.5ms低電位
void NEC_LEADER_CODE(void)
{
ET0=1;
TR0=1;
//PWMOUT1=1; // 除錯用
delay(336);
// PWMOUT1=0; // 除錯用
ET0 = 0;
TR0 = 0;
delay(1170);
}
// NEC碼0: 0.56ms高電位, 0.56ms低電位
void NEC_low(void)
{
ET0=1;
TR0=1;
//PWMOUT1=1; // 除錯用
delay(19);
//PWMOUT1=0; // 除錯用
ET0 = 0;
TR0 = 0;
delay(140);
}
// NEC碼1: 0.56ms高電位, 1.69ms低電位
void NEC_high(void)
{
ET0=1;
TR0=1;
//PWMOUT1=1; // 除錯用
delay(19);
//PWMOUT1=0; // 除錯用
ET0 = 0;
TR0 = 0;
delay(440);
}
// NEC碼,停止位元: 0.56ms高電位
void NEC_stop(void)
{
ET0 = 1;
TR0 = 1;
//PWMOUT1=1; // 除錯用
delay(19);
//PWMOUT1=0; // 除錯用
ET0 = 0;
TR0 = 0;
}
// ===== Test Result ========================
SW15, Code : 0x08E618E7
2011年12月5日 星期一
Key pad detect program
//=========================
//Project: Key pad detect program
//Author: Leo.Tseng
//Date: 2011/12/06
//MCU: W78E054D
//CRYSTAL: 25Mhz
//Description: Use uart for output, set boudrate=9600,
// Decode KEY pad, this program could support
// 4X4 KEY pad array.
//=========================
#include <reg52.h>
#include <stdio.h>
// 變數宣告
sbit UP = P1^2; // LED1
sbit DOWN = P1^3; // LED2
sbit LEFT = P1^4; // LED3
sbit RIGHT = P1^5; // LED4
sbit SCAN0 = P2^7; // KEY SCAN0
sbit SCAN1 = P2^6; // KEY SCAN1
sbit SCAN2 = P2^5; // KEY SCAN2
sbit SCAN3 = P2^4; // KEY SCAN3
sbit DET3 = P2^3; // KEY DETECT0, always high
sbit DET2 = P2^2; // KEY DETECT2
sbit DET1 = P2^1; // KEY DETECT1
sbit DET0 = P2^0; // KEY DETECT0
int n_SCAN;
int TIMES=65536; // 16位元計數器
int PWMHIGH=1;
int PWMLOW=50000;
int PERIOD;
unsigned KEY,temp;
//副程式宣告
void TIMER1_initinal(int baudrate);
void delay (int j);
//主程式開始
void main(void)
{
TIMER1_initinal(9600); // 使用UART,baudrate=9600
PERIOD=TIMES-PWMHIGH;
TMOD = (TMOD & 0xF0) | 0x01; // Set T/C0 Mode
TH0= PERIOD/256; // load sampleing rate
TL0= PERIOD%256; //
ET0 = 1; // Enable Timer 0 Interrupts
TR0 = 1; // Start Timer 0 Running
EA = 1; // Global Interrupt Enable
printf("\n7 KEY Detect Program\n\n");
SCAN0=SCAN1=SCAN2=SCAN3=1;
DET3=DET2=DET1=DET0=1; // 設定成輸入pin
n_SCAN=0;
UP=DOWN=LEFT=RIGHT=0;
while(1)
{
if((P2&0xFF)!=0xFF) // 偵測是否按按鍵?
{
temp=P2&0xFF; // 第一次儲存按鍵值
delay(6000); // 延遲 0.48us*6000=2.88ms,防彈跳調整
KEY=P2&0xFF; // 第二次讀取按鍵值
if (KEY&&temp) // 判別是否為同一鍵
{
delay(6000);
switch(KEY)
{
case 0x7B: printf("SW20 pressed, code=0x7B\n");
UP^=1;
break;
case 0x7D: printf("SW15 pressed, code=0x7D\n");
LEFT^=1;
break;
case 0x7E: printf("SW19 pressed, code=0x7E\n");
UP=DOWN=LEFT=RIGHT=1;
break;
case 0xBD: printf("SW14 pressed, code=0xBD\n");
DOWN^=1;
break;
case 0xBE: printf("SW18 pressed, code=0xBE\n");
DOWN^=!(UP^=1); // binary down counter
LEFT^=(!DOWN && !UP);
RIGHT^=(!LEFT && !DOWN && !UP);
break;
case 0xDE: printf("SW17 pressed, code=0xDE\n");
DOWN^=UP^=1; // binary up counter
LEFT^=(DOWN && UP);
RIGHT^=(LEFT && DOWN && UP);
break;
case 0xEE: printf("SW16 pressed, code=0xEE\n");
RIGHT^=1;
break;
default: break;
}
//delay(6000);
}
}
}
}
//UART副程式
void TIMER1_initinal(int baudrate)
{
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/baudrate); // TH1: reload value for baud @ 11.0592MHz, TH=0xFD
TH1 = 256-(25000000/372/baudrate); // 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((SCAN0==1)&&(SCAN1&&SCAN2&&SCAN3)&&(n_SCAN==0))
{
TR0=0;
SCAN0=0;
PERIOD = TIMES-PWMLOW;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
}
else if((SCAN0==0)&&(SCAN1&&SCAN2&&SCAN3)&&(n_SCAN==0))
{
TR0=0;
n_SCAN=1; // 準備掃瞄列1
SCAN0=1;
PERIOD = TIMES-PWMHIGH;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
}
if((SCAN1==1)&&(SCAN0&&SCAN2&&SCAN3)&&(n_SCAN==1))
{
TR0=0;
SCAN1=0;
PERIOD = TIMES-PWMLOW;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
}
else if((SCAN1==0)&&(SCAN0&&SCAN2&&SCAN3)&&(n_SCAN==1))
{
TR0=0;
n_SCAN=2; // 準備掃瞄列2
SCAN1=1;
PERIOD = TIMES-PWMHIGH;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
}
if((SCAN2==1)&&(SCAN0&&SCAN1&&SCAN3)&&(n_SCAN==2))
{
TR0=0;
SCAN2=0;
PERIOD = TIMES-PWMLOW;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
}
else if((SCAN2==0)&&(SCAN0&&SCAN1&&SCAN3)&&(n_SCAN==2))
{
TR0=0;
n_SCAN=3; // 準備掃瞄列3
SCAN2=1;
PERIOD = TIMES-PWMHIGH;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
}
if((SCAN3==1)&&(SCAN0&&SCAN1&&SCAN2)&&(n_SCAN==3))
{
TR0=0;
SCAN3=0;
PERIOD = TIMES-PWMLOW;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
}
else if((SCAN3==0)&&(SCAN0&&SCAN1&&SCAN2)&&(n_SCAN==3))
{
TR0=0;
n_SCAN=0; // 準備掃瞄列0
SCAN3=1;
PERIOD = TIMES-PWMHIGH;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
}
}
void delay (int j)
{
while(j)
j--;
}
//======== CONSOLE MESSAGE =======
7 KEY Detect Program
SW20 pressed, code=0x7B
SW14 pressed, code=0xBD
SW15 pressed, code=0x7D
SW16 pressed, code=0xEE
SW17 pressed, code=0xDE
SW18 pressed, code=0xBE
SW19 pressed, code=0x7E
//Project: Key pad detect program
//Author: Leo.Tseng
//Date: 2011/12/06
//MCU: W78E054D
//CRYSTAL: 25Mhz
//Description: Use uart for output, set boudrate=9600,
// Decode KEY pad, this program could support
// 4X4 KEY pad array.
//=========================
#include <reg52.h>
#include <stdio.h>
// 變數宣告
sbit UP = P1^2; // LED1
sbit DOWN = P1^3; // LED2
sbit LEFT = P1^4; // LED3
sbit RIGHT = P1^5; // LED4
sbit SCAN0 = P2^7; // KEY SCAN0
sbit SCAN1 = P2^6; // KEY SCAN1
sbit SCAN2 = P2^5; // KEY SCAN2
sbit SCAN3 = P2^4; // KEY SCAN3
sbit DET3 = P2^3; // KEY DETECT0, always high
sbit DET2 = P2^2; // KEY DETECT2
sbit DET1 = P2^1; // KEY DETECT1
sbit DET0 = P2^0; // KEY DETECT0
int n_SCAN;
int TIMES=65536; // 16位元計數器
int PWMHIGH=1;
int PWMLOW=50000;
int PERIOD;
unsigned KEY,temp;
//副程式宣告
void TIMER1_initinal(int baudrate);
void delay (int j);
//主程式開始
void main(void)
{
TIMER1_initinal(9600); // 使用UART,baudrate=9600
PERIOD=TIMES-PWMHIGH;
TMOD = (TMOD & 0xF0) | 0x01; // Set T/C0 Mode
TH0= PERIOD/256; // load sampleing rate
TL0= PERIOD%256; //
ET0 = 1; // Enable Timer 0 Interrupts
TR0 = 1; // Start Timer 0 Running
EA = 1; // Global Interrupt Enable
printf("\n7 KEY Detect Program\n\n");
SCAN0=SCAN1=SCAN2=SCAN3=1;
DET3=DET2=DET1=DET0=1; // 設定成輸入pin
n_SCAN=0;
UP=DOWN=LEFT=RIGHT=0;
while(1)
{
if((P2&0xFF)!=0xFF) // 偵測是否按按鍵?
{
temp=P2&0xFF; // 第一次儲存按鍵值
delay(6000); // 延遲 0.48us*6000=2.88ms,防彈跳調整
KEY=P2&0xFF; // 第二次讀取按鍵值
if (KEY&&temp) // 判別是否為同一鍵
{
delay(6000);
switch(KEY)
{
case 0x7B: printf("SW20 pressed, code=0x7B\n");
UP^=1;
break;
case 0x7D: printf("SW15 pressed, code=0x7D\n");
LEFT^=1;
break;
case 0x7E: printf("SW19 pressed, code=0x7E\n");
UP=DOWN=LEFT=RIGHT=1;
break;
case 0xBD: printf("SW14 pressed, code=0xBD\n");
DOWN^=1;
break;
case 0xBE: printf("SW18 pressed, code=0xBE\n");
DOWN^=!(UP^=1); // binary down counter
LEFT^=(!DOWN && !UP);
RIGHT^=(!LEFT && !DOWN && !UP);
break;
case 0xDE: printf("SW17 pressed, code=0xDE\n");
DOWN^=UP^=1; // binary up counter
LEFT^=(DOWN && UP);
RIGHT^=(LEFT && DOWN && UP);
break;
case 0xEE: printf("SW16 pressed, code=0xEE\n");
RIGHT^=1;
break;
default: break;
}
//delay(6000);
}
}
}
}
//UART副程式
void TIMER1_initinal(int baudrate)
{
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/baudrate); // TH1: reload value for baud @ 11.0592MHz, TH=0xFD
TH1 = 256-(25000000/372/baudrate); // 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((SCAN0==1)&&(SCAN1&&SCAN2&&SCAN3)&&(n_SCAN==0))
{
TR0=0;
SCAN0=0;
PERIOD = TIMES-PWMLOW;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
}
else if((SCAN0==0)&&(SCAN1&&SCAN2&&SCAN3)&&(n_SCAN==0))
{
TR0=0;
n_SCAN=1; // 準備掃瞄列1
SCAN0=1;
PERIOD = TIMES-PWMHIGH;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
}
if((SCAN1==1)&&(SCAN0&&SCAN2&&SCAN3)&&(n_SCAN==1))
{
TR0=0;
SCAN1=0;
PERIOD = TIMES-PWMLOW;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
}
else if((SCAN1==0)&&(SCAN0&&SCAN2&&SCAN3)&&(n_SCAN==1))
{
TR0=0;
n_SCAN=2; // 準備掃瞄列2
SCAN1=1;
PERIOD = TIMES-PWMHIGH;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
}
if((SCAN2==1)&&(SCAN0&&SCAN1&&SCAN3)&&(n_SCAN==2))
{
TR0=0;
SCAN2=0;
PERIOD = TIMES-PWMLOW;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
}
else if((SCAN2==0)&&(SCAN0&&SCAN1&&SCAN3)&&(n_SCAN==2))
{
TR0=0;
n_SCAN=3; // 準備掃瞄列3
SCAN2=1;
PERIOD = TIMES-PWMHIGH;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
}
if((SCAN3==1)&&(SCAN0&&SCAN1&&SCAN2)&&(n_SCAN==3))
{
TR0=0;
SCAN3=0;
PERIOD = TIMES-PWMLOW;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
}
else if((SCAN3==0)&&(SCAN0&&SCAN1&&SCAN2)&&(n_SCAN==3))
{
TR0=0;
n_SCAN=0; // 準備掃瞄列0
SCAN3=1;
PERIOD = TIMES-PWMHIGH;
TH0= PERIOD/256;
TL0= PERIOD%256;
TR0=1;
}
}
void delay (int j)
{
while(j)
j--;
}
//======== CONSOLE MESSAGE =======
7 KEY Detect Program
SW20 pressed, code=0x7B
SW14 pressed, code=0xBD
SW15 pressed, code=0x7D
SW16 pressed, code=0xEE
SW17 pressed, code=0xDE
SW18 pressed, code=0xBE
SW19 pressed, code=0x7E
2011年11月24日 星期四
IR Remote Control LED program
//=========================
//Project: IR Remote Controller Decode
//Author: Leo.Tseng
//Date: 2011/11/25
//MCU: W78E054D
//CRYSTAL: 25Mhz
//Description: Use uart for output, set boudrate=9600,
// Decode NEC transmission format
//=========================
#include <reg52.h>
#include <stdio.h>
// 變數宣告
sbit WAVEFORM_OUT = P2^0;
sbit IR_INT = P3^2;
sbit UP = P1^2; // LED1
sbit DOWN = P1^3; // LED2
sbit LEFT = P1^4; // LED3
sbit RIGHT = P1^5; // LED4
unsigned int ir_high;
unsigned int IR_BUFFER[33]=0;
unsigned int PERIOD_HIGH;
int index=0,i,j;
unsigned long ir_data=0;
//副程式宣告
void TIMER1_initinal(int baudrate);
//主程式開始
void main(void)
{
WAVEFORM_OUT=1;
PERIOD_HIGH=201; // Sample rate 38Khz.
TIMER1_initinal(9600); // 使用UART,baudrate=9600
IT0 = 1; // Configure interrupt 0 for falling edge on /INT0 (P3.2)
EX0 = 1; // Enable EX0 Interrupt
TMOD = (TMOD & 0xF0) | 0x0a; /* Set T/C0 Mode */
TH0= PERIOD_HIGH; // load sampleing rate
TL0= TH0; //
ET0 = 1; /* Enable Timer 0 Interrupts */
TR0 = 1; /* Start Timer 0 Running */
EA = 1; /* Global Interrupt Enable */
printf("\nPress IR remote controller to decoed\n\n");
IR_INT=1;
//WAVEFORM_OUT = IR_INT;
ir_high=0;
UP=DOWN=LEFT=RIGHT=0;
while(1)
{
//if(blinking) UP^=DOWN^=LEFT^=RIGHT^=1;
//WAVEFORM_OUT = IR_INT; // 關閉38K輸出
if(index==33)
{
//printf("index_loop index=%d\n",index);
TR0=0;
ET0=0;
EX0=0;
EA=0;
///*
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
IR_BUFFER[33]=IR_BUFFER[8*i+j];
IR_BUFFER[8*i+j]=IR_BUFFER[7+8*i-j];
IR_BUFFER[7+8*i-j]=IR_BUFFER[33];
}
for(i=0;i<32;i++)
{
if((IR_BUFFER[i]>=18)&&(IR_BUFFER[i]<=28))
{
IR_BUFFER[i]=0;
ir_data=ir_data<<1;
}
else if((IR_BUFFER[i]>=60)&&(IR_BUFFER[i]<=70))
{
IR_BUFFER[i]=1;
ir_data=(ir_data<<1)|0x01;
}
printf("%d",IR_BUFFER[i]);
}
printf(" < The Binary Code\n");
printf("The Hexadecimal Code:%lX \t",ir_data);
printf("\n\n");
//*/
/*
for(i=0;i<32;i++) // for debug
printf("[%d]:%d\n",i,IR_BUFFER[i]);
*/
//============================
switch(ir_data)
{
case 0x08e614eb:UP^=1; // 對應上鍵,亮滅LED1
break;
case 0x08e616e9:DOWN^=1; // 對應下鍵,亮滅LED2
break;
case 0x08e61de2:LEFT^=1; // 對應左鍵,亮滅LED3
break;
case 0x08e611ee:RIGHT^=1; // 對應右鍵,亮滅LED4
break;
case 0x08E65CA3:DOWN^=UP^=1; // 對應+鍵,LED做4位元上數計數器
LEFT^=(DOWN && UP);
RIGHT^=(LEFT && DOWN && UP);
break;
case 0x08E65DA2:DOWN^=!(UP^=1); // 對應-鍵,LED做4位元下數計數器
LEFT^=(!DOWN && !UP);
RIGHT^=(!LEFT && !DOWN && !UP);
break;
default: break;
}
//============================
index=0;
ir_high=0;
TL0=TH0; // 重新載入取樣頻率
TR0=1;
ET0=1;
EX0=1;
}
EA=1;
}
}
//UART副程式
void TIMER1_initinal(int baudrate)
{
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/baudrate); // TH1: reload value for baud @ 11.0592MHz, TH=0xFD
TH1 = 256-(25000000/372/baudrate); // 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
{
WAVEFORM_OUT^=1;
ir_high++;
EX0=1; // 外部中斷0致能
}
// INT0中斷0
void EXT_INT0(void) interrupt 0
{
WAVEFORM_OUT = IR_INT; // 關閉38K輸出
EX0=0; // 外部中斷0禁能
TR0=0; // 計時器0停止
ET0=0; // 計時器0中斷禁能
TL0= TH0;
IR_BUFFER[index]=ir_high; //
index++; // 指向下一個儲存區
if((ir_high>=160)&&(ir_high<=180))
index=0; // 前導碼值 68@TH0=120, 167@TH0=200
ir_high=0;
ET0=1; //
TR0=1; //
}
//Project: IR Remote Controller Decode
//Author: Leo.Tseng
//Date: 2011/11/25
//MCU: W78E054D
//CRYSTAL: 25Mhz
//Description: Use uart for output, set boudrate=9600,
// Decode NEC transmission format
//=========================
#include <reg52.h>
#include <stdio.h>
// 變數宣告
sbit WAVEFORM_OUT = P2^0;
sbit IR_INT = P3^2;
sbit UP = P1^2; // LED1
sbit DOWN = P1^3; // LED2
sbit LEFT = P1^4; // LED3
sbit RIGHT = P1^5; // LED4
unsigned int ir_high;
unsigned int IR_BUFFER[33]=0;
unsigned int PERIOD_HIGH;
int index=0,i,j;
unsigned long ir_data=0;
//副程式宣告
void TIMER1_initinal(int baudrate);
//主程式開始
void main(void)
{
WAVEFORM_OUT=1;
PERIOD_HIGH=201; // Sample rate 38Khz.
TIMER1_initinal(9600); // 使用UART,baudrate=9600
IT0 = 1; // Configure interrupt 0 for falling edge on /INT0 (P3.2)
EX0 = 1; // Enable EX0 Interrupt
TMOD = (TMOD & 0xF0) | 0x0a; /* Set T/C0 Mode */
TH0= PERIOD_HIGH; // load sampleing rate
TL0= TH0; //
ET0 = 1; /* Enable Timer 0 Interrupts */
TR0 = 1; /* Start Timer 0 Running */
EA = 1; /* Global Interrupt Enable */
printf("\nPress IR remote controller to decoed\n\n");
IR_INT=1;
//WAVEFORM_OUT = IR_INT;
ir_high=0;
UP=DOWN=LEFT=RIGHT=0;
while(1)
{
//if(blinking) UP^=DOWN^=LEFT^=RIGHT^=1;
//WAVEFORM_OUT = IR_INT; // 關閉38K輸出
if(index==33)
{
//printf("index_loop index=%d\n",index);
TR0=0;
ET0=0;
EX0=0;
EA=0;
///*
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
IR_BUFFER[33]=IR_BUFFER[8*i+j];
IR_BUFFER[8*i+j]=IR_BUFFER[7+8*i-j];
IR_BUFFER[7+8*i-j]=IR_BUFFER[33];
}
for(i=0;i<32;i++)
{
if((IR_BUFFER[i]>=18)&&(IR_BUFFER[i]<=28))
{
IR_BUFFER[i]=0;
ir_data=ir_data<<1;
}
else if((IR_BUFFER[i]>=60)&&(IR_BUFFER[i]<=70))
{
IR_BUFFER[i]=1;
ir_data=(ir_data<<1)|0x01;
}
printf("%d",IR_BUFFER[i]);
}
printf(" < The Binary Code\n");
printf("The Hexadecimal Code:%lX \t",ir_data);
printf("\n\n");
//*/
/*
for(i=0;i<32;i++) // for debug
printf("[%d]:%d\n",i,IR_BUFFER[i]);
*/
//============================
switch(ir_data)
{
case 0x08e614eb:UP^=1; // 對應上鍵,亮滅LED1
break;
case 0x08e616e9:DOWN^=1; // 對應下鍵,亮滅LED2
break;
case 0x08e61de2:LEFT^=1; // 對應左鍵,亮滅LED3
break;
case 0x08e611ee:RIGHT^=1; // 對應右鍵,亮滅LED4
break;
case 0x08E65CA3:DOWN^=UP^=1; // 對應+鍵,LED做4位元上數計數器
LEFT^=(DOWN && UP);
RIGHT^=(LEFT && DOWN && UP);
break;
case 0x08E65DA2:DOWN^=!(UP^=1); // 對應-鍵,LED做4位元下數計數器
LEFT^=(!DOWN && !UP);
RIGHT^=(!LEFT && !DOWN && !UP);
break;
default: break;
}
//============================
index=0;
ir_high=0;
TL0=TH0; // 重新載入取樣頻率
TR0=1;
ET0=1;
EX0=1;
}
EA=1;
}
}
//UART副程式
void TIMER1_initinal(int baudrate)
{
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/baudrate); // TH1: reload value for baud @ 11.0592MHz, TH=0xFD
TH1 = 256-(25000000/372/baudrate); // 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
{
WAVEFORM_OUT^=1;
ir_high++;
EX0=1; // 外部中斷0致能
}
// INT0中斷0
void EXT_INT0(void) interrupt 0
{
WAVEFORM_OUT = IR_INT; // 關閉38K輸出
EX0=0; // 外部中斷0禁能
TR0=0; // 計時器0停止
ET0=0; // 計時器0中斷禁能
TL0= TH0;
IR_BUFFER[index]=ir_high; //
index++; // 指向下一個儲存區
if((ir_high>=160)&&(ir_high<=180))
index=0; // 前導碼值 68@TH0=120, 167@TH0=200
ir_high=0;
ET0=1; //
TR0=1; //
}
2011年11月22日 星期二
NEC transmission format IR remote controller decode program
//=========================
//Project: IR Remote Controller Decode
//Author: Leo.Tseng
//Date: 2011/11/22
//MCU: W78E054D
//CRYSTAL: 25Mhz
//Description: Use uart for output, set boudrate=9600,
// Decode NEC transmission format
//=========================
#include <reg52.h>
#include <stdio.h>
// 變數宣告
sbit IR_INT = P3^2;
sbit IR_OUT = P2^0;
unsigned int IR_BUFFER[33]=0;
unsigned int i,j,index=0;
unsigned long ir_data=0;
// 副程式宣告
void UART_initinal(int baudrate);
void timer0_RUN(void);
// 主程式開始
void main(void)
{
UART_initinal(9600); // 使用UART,baudrate=9600
IT0 = 1; // 設定INT0 (P3.2)為負緣輸入中斷
EX0 = 1; // 致能INT0中斷
TMOD = (TMOD & 0xF0) | 0x01; // 設定計時器0為模式1
EA = 1; // 總中斷致能啟始
ET0 = 0; // 禁止計時器0產生中斷
TR0 = 0; // 禁止計時器0計數
printf("NEC編碼遙控器解碼程式\n\n");
//IR_INT=1;
while(1)
{
if(index==32)
{
TR0=0; // 停止計時器0
ET0=0; // 禁止計時器0產生中斷
EX0=0; // 禁止外部中斷0產生中斷
EA=0; // 禁止所有中斷
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
IR_BUFFER[33]=IR_BUFFER[8*i+j];
IR_BUFFER[8*i+j]=IR_BUFFER[7+8*i-j];
IR_BUFFER[7+8*i-j]=IR_BUFFER[33];
}
for(i=0;i<32;i++)
{
if((IR_BUFFER[i]>=7)&&(IR_BUFFER[i]<=10))
{
IR_BUFFER[i]=0;
ir_data=ir_data<<1;
}
else if((IR_BUFFER[i]>=17)&&(IR_BUFFER[i]<=20))
{
IR_BUFFER[i]=1;
ir_data=(ir_data<<1)|0x01;
}
printf("%d",IR_BUFFER[i]);
}
printf(" < 二進位碼\n");
printf("遙控器16進位全碼:%lX \t",ir_data);
printf("\n\n");
// 重置所有變數及暫存區及中斷致能
index=0;
ir_data=0;
TH0= 0;
TL0= 0;
EX0=1;
}
EA=1;
}
}
// 主程式結束
// UART副程式
void UART_initinal(int baudrate)
{
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
//TH1 = 256-(11059200/384/baudrate); // TH1: reload value for baud @ 11.0592MHz, TH=0xFD
TH1 = 256-(25000000/372/baudrate); // 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
}
// INT0中斷0
void EXT_INT0(void) interrupt 0
{
EX0=0; // 外部中斷0禁能
IR_BUFFER[index]=TH0; // 儲存計時器0的計時值
index++; // 指向下一個暫存區
if(TH0==109) index=0; // 偵測前導碼
timer0_RUN(); // 開始計時
}
//Timer0 計時副程式
void timer0_RUN()
{
TR0=0; // 停止計時器0
TH0=0; // 重設計時器0
TL0=0; //
TR0=1; // 啟動計時器0
EX0=1; // 外部中斷0重新啟動
}
============= 測試結果 ================
NEC編碼遙控器解碼程式
00001000111001100100011110111000 < 二進位碼
遙控器16進位全碼:8E647B8
00001000111001100100001110111100 < 二進位碼
遙控器16進位全碼:8E643BC
00001000111001100100001010111101 < 二進位碼
遙控器16進位全碼:8E642BD
00001000111001100100000110111110 < 二進位碼
遙控器16進位全碼:8E641BE
00001000111001100100000010111111 < 二進位碼
遙控器16進位全碼:8E640BF
00001000111001100100011010111001 < 二進位碼
遙控器16進位全碼:8E646B9
00001000111001100100010110111010 < 二進位碼
遙控器16進位全碼:8E645BA
00001000111001100100010010111011 < 二進位碼
遙控器16進位全碼:8E644BB
00001000111001100100101010110101 < 二進位碼
遙控器16進位全碼:8E64AB5
00001000111001100100100110110110 < 二進位碼
遙控器16進位全碼:8E649B6
00001000111001100100100010110111 < 二進位碼
遙控器16進位全碼:8E648B7
00001000111001100100111010110001 < 二進位碼
遙控器16進位全碼:8E64EB1
00001000111001100100110110110010 < 二進位碼
遙控器16進位全碼:8E64DB2
00001000111001100100110010110011 < 二進位碼
遙控器16進位全碼:8E64CB3
00001000111001100100101110110100 < 二進位碼
遙控器16進位全碼:8E64BB4
00001000111001100001110011100011 < 二進位碼
遙控器16進位全碼:8E61CE3
00001000111001100001101011100101 < 二進位碼
遙控器16進位全碼:8E61AE5
00001000111001100001100111100110 < 二進位碼
遙控器16進位全碼:8E619E6
00001000111001100001100011100111 < 二進位碼
遙控器16進位全碼:8E618E7
00001000111001100001000011101111 < 二進位碼
遙控器16進位全碼:8E610EF
00001000111001100001010011101011 < 二進位碼
遙控器16進位全碼:8E614EB
00001000111001100001110111100010 < 二進位碼
遙控器16進位全碼:8E61DE2
00001000111001100001010111101010 < 二進位碼
遙控器16進位全碼:8E615EA
00001000111001100001000111101110 < 二進位碼
遙控器16進位全碼:8E611EE
00001000111001100001011011101001 < 二進位碼
遙控器16進位全碼:8E616E9
00001000111001100001111011100001 < 二進位碼
遙控器16進位全碼:8E61EE1
00001000111001100001001011101101 < 二進位碼
遙控器16進位全碼:8E612ED
00001000111001100001111111100000 < 二進位碼
遙控器16進位全碼:8E61FE0
00001000111001100001101111100100 < 二進位碼
遙控器16進位全碼:8E61BE4
00001000111001100001011111101000 < 二進位碼
遙控器16進位全碼:8E617E8
00001000111001100001001111101100 < 二進位碼
遙控器16進位全碼:8E613EC
00001000111001100101110010100011 < 二進位碼
遙控器16進位全碼:8E65CA3
00001000111001100101100010100111 < 二進位碼
遙控器16進位全碼:8E658A7
00001000111001100101010010101011 < 二進位碼
遙控器16進位全碼:8E654AB
00001000111001100101000010101111 < 二進位碼
遙控器16進位全碼:8E650AF
00001000111001100101110110100010 < 二進位碼
遙控器16進位全碼:8E65DA2
00001000111001100101100110100110 < 二進位碼
遙控器16進位全碼:8E659A6
00001000111001100101010110101010 < 二進位碼
遙控器16進位全碼:8E655AA
00001000111001100101000110101110 < 二進位碼
遙控器16進位全碼:8E651AE
00001000111001100101111010100001 < 二進位碼
遙控器16進位全碼:8E65EA1
00001000111001100101101010100101 < 二進位碼
遙控器16進位全碼:8E65AA5
00001000111001100101011010101001 < 二進位碼
遙控器16進位全碼:8E656A9
00001000111001100101001010101101 < 二進位碼
遙控器16進位全碼:8E652AD
00001000111001100101111110100000 < 二進位碼
遙控器16進位全碼:8E65FA0
00001000111001100101101110100100 < 二進位碼
遙控器16進位全碼:8E65BA4
00001000111001100101011110101000 < 二進位碼
遙控器16進位全碼:8E657A8
00001000111001100101001110101100 < 二進位碼
遙控器16進位全碼:8E653AC
//Project: IR Remote Controller Decode
//Author: Leo.Tseng
//Date: 2011/11/22
//MCU: W78E054D
//CRYSTAL: 25Mhz
//Description: Use uart for output, set boudrate=9600,
// Decode NEC transmission format
//=========================
#include <reg52.h>
#include <stdio.h>
// 變數宣告
sbit IR_INT = P3^2;
sbit IR_OUT = P2^0;
unsigned int IR_BUFFER[33]=0;
unsigned int i,j,index=0;
unsigned long ir_data=0;
// 副程式宣告
void UART_initinal(int baudrate);
void timer0_RUN(void);
// 主程式開始
void main(void)
{
UART_initinal(9600); // 使用UART,baudrate=9600
IT0 = 1; // 設定INT0 (P3.2)為負緣輸入中斷
EX0 = 1; // 致能INT0中斷
TMOD = (TMOD & 0xF0) | 0x01; // 設定計時器0為模式1
EA = 1; // 總中斷致能啟始
ET0 = 0; // 禁止計時器0產生中斷
TR0 = 0; // 禁止計時器0計數
printf("NEC編碼遙控器解碼程式\n\n");
//IR_INT=1;
while(1)
{
if(index==32)
{
TR0=0; // 停止計時器0
ET0=0; // 禁止計時器0產生中斷
EX0=0; // 禁止外部中斷0產生中斷
EA=0; // 禁止所有中斷
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
IR_BUFFER[33]=IR_BUFFER[8*i+j];
IR_BUFFER[8*i+j]=IR_BUFFER[7+8*i-j];
IR_BUFFER[7+8*i-j]=IR_BUFFER[33];
}
for(i=0;i<32;i++)
{
if((IR_BUFFER[i]>=7)&&(IR_BUFFER[i]<=10))
{
IR_BUFFER[i]=0;
ir_data=ir_data<<1;
}
else if((IR_BUFFER[i]>=17)&&(IR_BUFFER[i]<=20))
{
IR_BUFFER[i]=1;
ir_data=(ir_data<<1)|0x01;
}
printf("%d",IR_BUFFER[i]);
}
printf(" < 二進位碼\n");
printf("遙控器16進位全碼:%lX \t",ir_data);
printf("\n\n");
// 重置所有變數及暫存區及中斷致能
index=0;
ir_data=0;
TH0= 0;
TL0= 0;
EX0=1;
}
EA=1;
}
}
// 主程式結束
// UART副程式
void UART_initinal(int baudrate)
{
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
//TH1 = 256-(11059200/384/baudrate); // TH1: reload value for baud @ 11.0592MHz, TH=0xFD
TH1 = 256-(25000000/372/baudrate); // 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
}
// INT0中斷0
void EXT_INT0(void) interrupt 0
{
EX0=0; // 外部中斷0禁能
IR_BUFFER[index]=TH0; // 儲存計時器0的計時值
index++; // 指向下一個暫存區
if(TH0==109) index=0; // 偵測前導碼
timer0_RUN(); // 開始計時
}
//Timer0 計時副程式
void timer0_RUN()
{
TR0=0; // 停止計時器0
TH0=0; // 重設計時器0
TL0=0; //
TR0=1; // 啟動計時器0
EX0=1; // 外部中斷0重新啟動
}
============= 測試結果 ================
NEC編碼遙控器解碼程式
00001000111001100100011110111000 < 二進位碼
遙控器16進位全碼:8E647B8
00001000111001100100001110111100 < 二進位碼
遙控器16進位全碼:8E643BC
00001000111001100100001010111101 < 二進位碼
遙控器16進位全碼:8E642BD
00001000111001100100000110111110 < 二進位碼
遙控器16進位全碼:8E641BE
00001000111001100100000010111111 < 二進位碼
遙控器16進位全碼:8E640BF
00001000111001100100011010111001 < 二進位碼
遙控器16進位全碼:8E646B9
00001000111001100100010110111010 < 二進位碼
遙控器16進位全碼:8E645BA
00001000111001100100010010111011 < 二進位碼
遙控器16進位全碼:8E644BB
00001000111001100100101010110101 < 二進位碼
遙控器16進位全碼:8E64AB5
00001000111001100100100110110110 < 二進位碼
遙控器16進位全碼:8E649B6
00001000111001100100100010110111 < 二進位碼
遙控器16進位全碼:8E648B7
00001000111001100100111010110001 < 二進位碼
遙控器16進位全碼:8E64EB1
00001000111001100100110110110010 < 二進位碼
遙控器16進位全碼:8E64DB2
00001000111001100100110010110011 < 二進位碼
遙控器16進位全碼:8E64CB3
00001000111001100100101110110100 < 二進位碼
遙控器16進位全碼:8E64BB4
00001000111001100001110011100011 < 二進位碼
遙控器16進位全碼:8E61CE3
00001000111001100001101011100101 < 二進位碼
遙控器16進位全碼:8E61AE5
00001000111001100001100111100110 < 二進位碼
遙控器16進位全碼:8E619E6
00001000111001100001100011100111 < 二進位碼
遙控器16進位全碼:8E618E7
00001000111001100001000011101111 < 二進位碼
遙控器16進位全碼:8E610EF
00001000111001100001010011101011 < 二進位碼
遙控器16進位全碼:8E614EB
00001000111001100001110111100010 < 二進位碼
遙控器16進位全碼:8E61DE2
00001000111001100001010111101010 < 二進位碼
遙控器16進位全碼:8E615EA
00001000111001100001000111101110 < 二進位碼
遙控器16進位全碼:8E611EE
00001000111001100001011011101001 < 二進位碼
遙控器16進位全碼:8E616E9
00001000111001100001111011100001 < 二進位碼
遙控器16進位全碼:8E61EE1
00001000111001100001001011101101 < 二進位碼
遙控器16進位全碼:8E612ED
00001000111001100001111111100000 < 二進位碼
遙控器16進位全碼:8E61FE0
00001000111001100001101111100100 < 二進位碼
遙控器16進位全碼:8E61BE4
00001000111001100001011111101000 < 二進位碼
遙控器16進位全碼:8E617E8
00001000111001100001001111101100 < 二進位碼
遙控器16進位全碼:8E613EC
00001000111001100101110010100011 < 二進位碼
遙控器16進位全碼:8E65CA3
00001000111001100101100010100111 < 二進位碼
遙控器16進位全碼:8E658A7
00001000111001100101010010101011 < 二進位碼
遙控器16進位全碼:8E654AB
00001000111001100101000010101111 < 二進位碼
遙控器16進位全碼:8E650AF
00001000111001100101110110100010 < 二進位碼
遙控器16進位全碼:8E65DA2
00001000111001100101100110100110 < 二進位碼
遙控器16進位全碼:8E659A6
00001000111001100101010110101010 < 二進位碼
遙控器16進位全碼:8E655AA
00001000111001100101000110101110 < 二進位碼
遙控器16進位全碼:8E651AE
00001000111001100101111010100001 < 二進位碼
遙控器16進位全碼:8E65EA1
00001000111001100101101010100101 < 二進位碼
遙控器16進位全碼:8E65AA5
00001000111001100101011010101001 < 二進位碼
遙控器16進位全碼:8E656A9
00001000111001100101001010101101 < 二進位碼
遙控器16進位全碼:8E652AD
00001000111001100101111110100000 < 二進位碼
遙控器16進位全碼:8E65FA0
00001000111001100101101110100100 < 二進位碼
遙控器16進位全碼:8E65BA4
00001000111001100101011110101000 < 二進位碼
遙控器16進位全碼:8E657A8
00001000111001100101001110101100 < 二進位碼
遙控器16進位全碼:8E653AC
2011年11月14日 星期一
EEPROM write/read program II
//=========================
//Project: EEPROM write/read command program
//Author: Leo.Tseng
//Date: 2011/11/10
//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: page write, Read mode: Sequential 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 S_I2C_ACK(void);
int M_I2C_ACK(void);
int M_I2C_NACK(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)
{ //====================Begin of Main
unsigned int data_buf[8]={0};
unsigned char uart_data[8];
unsigned char I2C_DATA=0xff;
unsigned char F_ADDRESS,S_ADDRESS;
unsigned int i;
int device_ACK;
int B_index,E_index,index;
int Byte_counter;
unsigned int temp_buf;
TIMER1_initinal(9600); // 使用UART,baudrate=9600
printf("\n輸入6個16進制字元,前兩字元為資料,後4字元為寫入起始頁位址: ");
RI=0;
TI=0;
i=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位元位址
//B_index=(int)F_ADDRESS*256+(int)S_ADDRESS; // 計算要開始寫入的位址
//printf("\nindex in d =%d\n",B_index);
//printf("\nindex in x =%x\n",B_index);
//printf("\nindex in u =%u\n",B_index);
//=========== EEPROM Page Write =========================
I2C_START(); // 開始I2C command
delay(5);
I2C_write(0xa0,8); // 寫入device address write
device_ACK=S_I2C_ACK(); // 取得device 狀態
if(device_ACK)
{
device_ACK=0; // 清除ACK旗號
//printf("Slave device is ACK!!\n\n");
I2C_write(F_ADDRESS,8); // 寫入第一字組位址
device_ACK=S_I2C_ACK();
device_ACK=0; // 清除ACK旗號
I2C_write(S_ADDRESS,8); // 寫入第二字組位址
device_ACK=S_I2C_ACK();
Byte_counter=0;
while(device_ACK)
{
device_ACK=0; // 清除ACK旗號
I2C_write(I2C_DATA,8); // page write data, 寫入資料
device_ACK=(device_ACK=S_I2C_ACK()&&((Byte_counter<31)? 1 : 0));
//printf("Byte_counter=%d\n\n",Byte_counter); //for debug
Byte_counter++;
//_getkey(); //for debug
}
I2C_STOP(); // Page write完成,每頁32Byte
if(Byte_counter==32) printf("\nPage write finished!!\n");
else printf("\nPage write not finished!!\n");
}
else
{
printf("Slave device is no ACK!!\n\n") ; // 否, device no ACK
}
//=========== End of EEPROM Page Write =========================
//=========== EEPROM Sequential Read =========================
printf("\n輸入8個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==8)) break;
}
for(i=0;i<8;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[4]<<4)+(data_buf[5]&0x0f)); // 轉換要讀出結束位址的高8位元
S_ADDRESS=((data_buf[6]<<4)+(data_buf[7]&0x0f)); // 轉換要讀出結束位址的低8位元
E_index=(int)F_ADDRESS*256+(int)S_ADDRESS; // 計算要開始讀出的結束位址
//printf("\nE_index in d =%d\n",E_index);
//printf("\nE_index in x =%x\n",E_index);
//printf("\nE_index in u =%u\n",E_index);
//== 新增程式結束 ==
F_ADDRESS=((data_buf[0]<<4)+(data_buf[1]&0x0f)); // 轉換要讀出起始位址的高8位元
S_ADDRESS=((data_buf[2]<<4)+(data_buf[3]&0x0f)); // 轉換要讀出起始位址的低8位元
B_index=(int)F_ADDRESS*256+(int)S_ADDRESS; // 計算要開始讀出的起始位址
//printf("\nB_index in d =%d\n",B_index);
//printf("\nB_index in x =%x\n",B_index);
//printf("\nB_index in u =%u\n",B_index);
//== 新增程式起始 ==
index=E_index-B_index+1; // 計算要開始讀出的總位址數
// printf("\nindex count in d =%d\n",index);
// printf("\nindex count in x =%x\n",index);
// printf("\nindex count in u =%u\n",index);
//== 新增程式結束 ==
I2C_START(); // 開始I2C command
delay(5);
I2C_write(0xa0,8); // 寫入device address write, DUMMY write
device_ACK=S_I2C_ACK(); // 取得device 狀態
if(device_ACK) // device address write ACK
{
device_ACK=0; // 清除ACK旗號
I2C_write(F_ADDRESS,8); // First word address, DUMMY write
device_ACK=S_I2C_ACK(); // First word address ACK?
device_ACK=0; // 清除ACK旗號
I2C_write(S_ADDRESS,8); // second word address, DUMMY write
device_ACK=S_I2C_ACK(); // second word address ACK?
if(device_ACK)
{
I2C_START(); // 開始I2C command
delay(5);
I2C_write(0xa1,8); // 寫入device address read,
device_ACK=S_I2C_ACK(); // 取得device 狀態
}
if(device_ACK)
{
for(index=B_index;index<=E_index;index++)
{
if(index==E_index)
{
device_ACK=0;
I2C_DATA=I2C_read(8); // 讀取資料
device_ACK=M_I2C_NACK();
I2C_STOP();
//printf("\nData Read Finish!!\n\n");
}
else
{
device_ACK=0;
I2C_DATA=I2C_read(8); // 讀取資料
device_ACK=M_I2C_ACK();
//printf("R_device_ACK=%d\n\n",device_ACK); // for debug
}
//=================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]);
}
if(device_ACK) printf("\n位址0X%X 讀出值: 0x%c%c ",index,uart_data[0],uart_data[1]);
else
{
printf("\n位址0X%X 讀出值: 0x%c%c ",index,uart_data[0],uart_data[1]);
printf("\nData Read Finish!!\n\n");
}
_getkey();
}
}
}
//============ 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 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);
}
//Slave ACK副程式
// ___________ NO ACK
//SDA _____/ \_________ ACK
// ____
//SCL ______/ \________
// -| b9 |---- ACK bit
int S_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; // 否
}
}
//Master ACK副程式
int M_I2C_ACK(void)
{
//delay(1);
SDA=0; // Master拉low ack bit
delay(1);
SCL=1;
delay(4);
//SDA=0;
SCL=0;
SDA=1;
return 1; // 是
}
//Master NACK副程式
int M_I2C_NACK(void)
{
//delay(1);
SDA=1; // Master拉high ack bit
delay(1);
SCL=1;
delay(4);
//SDA=0;
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
}
****************************************************************
Test Result :
****************************************************************
輸入6個16進制字元,前兩字元為資料,後4字元為寫入起始頁位址: 330000
按任何鍵開始寫入EEPROM
Page write finished!!
輸入8個16進制字元為讀出起始位址和終止位址: 0000001f
按任何鍵開始讀出EEPROM
位址0X0 讀出值: 0x33
位址0X1 讀出值: 0x33
位址0X2 讀出值: 0x33
位址0X3 讀出值: 0x33
位址0X4 讀出值: 0x33
位址0X5 讀出值: 0x33
位址0X6 讀出值: 0x33
位址0X7 讀出值: 0x33
位址0X8 讀出值: 0x33
位址0X9 讀出值: 0x33
位址0XA 讀出值: 0x33
位址0XB 讀出值: 0x33
位址0XC 讀出值: 0x33
位址0XD 讀出值: 0x33
位址0XE 讀出值: 0x33
位址0XF 讀出值: 0x33
位址0X10 讀出值: 0x33
位址0X11 讀出值: 0x33
位址0X12 讀出值: 0x33
位址0X13 讀出值: 0x33
位址0X14 讀出值: 0x33
位址0X15 讀出值: 0x33
位址0X16 讀出值: 0x33
位址0X17 讀出值: 0x33
位址0X18 讀出值: 0x33
位址0X19 讀出值: 0x33
位址0X1A 讀出值: 0x33
位址0X1B 讀出值: 0x33
位址0X1C 讀出值: 0x33
位址0X1D 讀出值: 0x33
位址0X1E 讀出值: 0x33
位址0X1F 讀出值: 0x33
Data Read Finish!!
輸入6個16進制字元,前兩字元為資料,後4字元為寫入起始頁位址: 88ffe0
按任何鍵開始寫入EEPROM
Page write finished!!
輸入8個16進制字元為讀出起始位址和終止位址: ffe0ffff
按任何鍵開始讀出EEPROM
位址0XFFE0 讀出值: 0x88
位址0XFFE1 讀出值: 0x88
位址0XFFE2 讀出值: 0x88
位址0XFFE3 讀出值: 0x88
位址0XFFE4 讀出值: 0x88
位址0XFFE5 讀出值: 0x88
位址0XFFE6 讀出值: 0x88
位址0XFFE7 讀出值: 0x88
位址0XFFE8 讀出值: 0x88
位址0XFFE9 讀出值: 0x88
位址0XFFEA 讀出值: 0x88
位址0XFFEB 讀出值: 0x88
位址0XFFEC 讀出值: 0x88
位址0XFFED 讀出值: 0x88
位址0XFFEE 讀出值: 0x88
位址0XFFEF 讀出值: 0x88
位址0XFFF0 讀出值: 0x88
位址0XFFF1 讀出值: 0x88
位址0XFFF2 讀出值: 0x88
位址0XFFF3 讀出值: 0x88
位址0XFFF4 讀出值: 0x88
位址0XFFF5 讀出值: 0x88
位址0XFFF6 讀出值: 0x88
位址0XFFF7 讀出值: 0x88
位址0XFFF8 讀出值: 0x88
位址0XFFF9 讀出值: 0x88
位址0XFFFA 讀出值: 0x88
位址0XFFFB 讀出值: 0x88
位址0XFFFC 讀出值: 0x88
位址0XFFFD 讀出值: 0x88
位址0XFFFE 讀出值: 0x88
位址0XFFFF 讀出值: 0x88
Data Read Finish!!
輸入6個16進制字元,前兩字元為資料,後4字元為寫入起始頁位址:
//Project: EEPROM write/read command program
//Author: Leo.Tseng
//Date: 2011/11/10
//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: page write, Read mode: Sequential 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 S_I2C_ACK(void);
int M_I2C_ACK(void);
int M_I2C_NACK(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)
{ //====================Begin of Main
unsigned int data_buf[8]={0};
unsigned char uart_data[8];
unsigned char I2C_DATA=0xff;
unsigned char F_ADDRESS,S_ADDRESS;
unsigned int i;
int device_ACK;
int B_index,E_index,index;
int Byte_counter;
unsigned int temp_buf;
TIMER1_initinal(9600); // 使用UART,baudrate=9600
printf("\n輸入6個16進制字元,前兩字元為資料,後4字元為寫入起始頁位址: ");
RI=0;
TI=0;
i=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位元位址
//B_index=(int)F_ADDRESS*256+(int)S_ADDRESS; // 計算要開始寫入的位址
//printf("\nindex in d =%d\n",B_index);
//printf("\nindex in x =%x\n",B_index);
//printf("\nindex in u =%u\n",B_index);
//=========== EEPROM Page Write =========================
I2C_START(); // 開始I2C command
delay(5);
I2C_write(0xa0,8); // 寫入device address write
device_ACK=S_I2C_ACK(); // 取得device 狀態
if(device_ACK)
{
device_ACK=0; // 清除ACK旗號
//printf("Slave device is ACK!!\n\n");
I2C_write(F_ADDRESS,8); // 寫入第一字組位址
device_ACK=S_I2C_ACK();
device_ACK=0; // 清除ACK旗號
I2C_write(S_ADDRESS,8); // 寫入第二字組位址
device_ACK=S_I2C_ACK();
Byte_counter=0;
while(device_ACK)
{
device_ACK=0; // 清除ACK旗號
I2C_write(I2C_DATA,8); // page write data, 寫入資料
device_ACK=(device_ACK=S_I2C_ACK()&&((Byte_counter<31)? 1 : 0));
//printf("Byte_counter=%d\n\n",Byte_counter); //for debug
Byte_counter++;
//_getkey(); //for debug
}
I2C_STOP(); // Page write完成,每頁32Byte
if(Byte_counter==32) printf("\nPage write finished!!\n");
else printf("\nPage write not finished!!\n");
}
else
{
printf("Slave device is no ACK!!\n\n") ; // 否, device no ACK
}
//=========== End of EEPROM Page Write =========================
//=========== EEPROM Sequential Read =========================
printf("\n輸入8個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==8)) break;
}
for(i=0;i<8;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[4]<<4)+(data_buf[5]&0x0f)); // 轉換要讀出結束位址的高8位元
S_ADDRESS=((data_buf[6]<<4)+(data_buf[7]&0x0f)); // 轉換要讀出結束位址的低8位元
E_index=(int)F_ADDRESS*256+(int)S_ADDRESS; // 計算要開始讀出的結束位址
//printf("\nE_index in d =%d\n",E_index);
//printf("\nE_index in x =%x\n",E_index);
//printf("\nE_index in u =%u\n",E_index);
//== 新增程式結束 ==
F_ADDRESS=((data_buf[0]<<4)+(data_buf[1]&0x0f)); // 轉換要讀出起始位址的高8位元
S_ADDRESS=((data_buf[2]<<4)+(data_buf[3]&0x0f)); // 轉換要讀出起始位址的低8位元
B_index=(int)F_ADDRESS*256+(int)S_ADDRESS; // 計算要開始讀出的起始位址
//printf("\nB_index in d =%d\n",B_index);
//printf("\nB_index in x =%x\n",B_index);
//printf("\nB_index in u =%u\n",B_index);
//== 新增程式起始 ==
index=E_index-B_index+1; // 計算要開始讀出的總位址數
// printf("\nindex count in d =%d\n",index);
// printf("\nindex count in x =%x\n",index);
// printf("\nindex count in u =%u\n",index);
//== 新增程式結束 ==
I2C_START(); // 開始I2C command
delay(5);
I2C_write(0xa0,8); // 寫入device address write, DUMMY write
device_ACK=S_I2C_ACK(); // 取得device 狀態
if(device_ACK) // device address write ACK
{
device_ACK=0; // 清除ACK旗號
I2C_write(F_ADDRESS,8); // First word address, DUMMY write
device_ACK=S_I2C_ACK(); // First word address ACK?
device_ACK=0; // 清除ACK旗號
I2C_write(S_ADDRESS,8); // second word address, DUMMY write
device_ACK=S_I2C_ACK(); // second word address ACK?
if(device_ACK)
{
I2C_START(); // 開始I2C command
delay(5);
I2C_write(0xa1,8); // 寫入device address read,
device_ACK=S_I2C_ACK(); // 取得device 狀態
}
if(device_ACK)
{
for(index=B_index;index<=E_index;index++)
{
if(index==E_index)
{
device_ACK=0;
I2C_DATA=I2C_read(8); // 讀取資料
device_ACK=M_I2C_NACK();
I2C_STOP();
//printf("\nData Read Finish!!\n\n");
}
else
{
device_ACK=0;
I2C_DATA=I2C_read(8); // 讀取資料
device_ACK=M_I2C_ACK();
//printf("R_device_ACK=%d\n\n",device_ACK); // for debug
}
//=================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]);
}
if(device_ACK) printf("\n位址0X%X 讀出值: 0x%c%c ",index,uart_data[0],uart_data[1]);
else
{
printf("\n位址0X%X 讀出值: 0x%c%c ",index,uart_data[0],uart_data[1]);
printf("\nData Read Finish!!\n\n");
}
_getkey();
}
}
}
//============ 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 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);
}
//Slave ACK副程式
// ___________ NO ACK
//SDA _____/ \_________ ACK
// ____
//SCL ______/ \________
// -| b9 |---- ACK bit
int S_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; // 否
}
}
//Master ACK副程式
int M_I2C_ACK(void)
{
//delay(1);
SDA=0; // Master拉low ack bit
delay(1);
SCL=1;
delay(4);
//SDA=0;
SCL=0;
SDA=1;
return 1; // 是
}
//Master NACK副程式
int M_I2C_NACK(void)
{
//delay(1);
SDA=1; // Master拉high ack bit
delay(1);
SCL=1;
delay(4);
//SDA=0;
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
}
****************************************************************
Test Result :
****************************************************************
輸入6個16進制字元,前兩字元為資料,後4字元為寫入起始頁位址: 330000
按任何鍵開始寫入EEPROM
Page write finished!!
輸入8個16進制字元為讀出起始位址和終止位址: 0000001f
按任何鍵開始讀出EEPROM
位址0X0 讀出值: 0x33
位址0X1 讀出值: 0x33
位址0X2 讀出值: 0x33
位址0X3 讀出值: 0x33
位址0X4 讀出值: 0x33
位址0X5 讀出值: 0x33
位址0X6 讀出值: 0x33
位址0X7 讀出值: 0x33
位址0X8 讀出值: 0x33
位址0X9 讀出值: 0x33
位址0XA 讀出值: 0x33
位址0XB 讀出值: 0x33
位址0XC 讀出值: 0x33
位址0XD 讀出值: 0x33
位址0XE 讀出值: 0x33
位址0XF 讀出值: 0x33
位址0X10 讀出值: 0x33
位址0X11 讀出值: 0x33
位址0X12 讀出值: 0x33
位址0X13 讀出值: 0x33
位址0X14 讀出值: 0x33
位址0X15 讀出值: 0x33
位址0X16 讀出值: 0x33
位址0X17 讀出值: 0x33
位址0X18 讀出值: 0x33
位址0X19 讀出值: 0x33
位址0X1A 讀出值: 0x33
位址0X1B 讀出值: 0x33
位址0X1C 讀出值: 0x33
位址0X1D 讀出值: 0x33
位址0X1E 讀出值: 0x33
位址0X1F 讀出值: 0x33
Data Read Finish!!
輸入6個16進制字元,前兩字元為資料,後4字元為寫入起始頁位址: 88ffe0
按任何鍵開始寫入EEPROM
Page write finished!!
輸入8個16進制字元為讀出起始位址和終止位址: ffe0ffff
按任何鍵開始讀出EEPROM
位址0XFFE0 讀出值: 0x88
位址0XFFE1 讀出值: 0x88
位址0XFFE2 讀出值: 0x88
位址0XFFE3 讀出值: 0x88
位址0XFFE4 讀出值: 0x88
位址0XFFE5 讀出值: 0x88
位址0XFFE6 讀出值: 0x88
位址0XFFE7 讀出值: 0x88
位址0XFFE8 讀出值: 0x88
位址0XFFE9 讀出值: 0x88
位址0XFFEA 讀出值: 0x88
位址0XFFEB 讀出值: 0x88
位址0XFFEC 讀出值: 0x88
位址0XFFED 讀出值: 0x88
位址0XFFEE 讀出值: 0x88
位址0XFFEF 讀出值: 0x88
位址0XFFF0 讀出值: 0x88
位址0XFFF1 讀出值: 0x88
位址0XFFF2 讀出值: 0x88
位址0XFFF3 讀出值: 0x88
位址0XFFF4 讀出值: 0x88
位址0XFFF5 讀出值: 0x88
位址0XFFF6 讀出值: 0x88
位址0XFFF7 讀出值: 0x88
位址0XFFF8 讀出值: 0x88
位址0XFFF9 讀出值: 0x88
位址0XFFFA 讀出值: 0x88
位址0XFFFB 讀出值: 0x88
位址0XFFFC 讀出值: 0x88
位址0XFFFD 讀出值: 0x88
位址0XFFFE 讀出值: 0x88
位址0XFFFF 讀出值: 0x88
Data Read Finish!!
輸入6個16進制字元,前兩字元為資料,後4字元為寫入起始頁位址:
訂閱:
文章 (Atom)