#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int //float fosc=12000000; //系統時鐘頻率
sbit key1=P1^1; //控制周期的增加
sbit key2=P1^2; //控制周期的減少
sbit key3=P1^3; //控制占空比的增加
sbit key4=P1^4; //控制占空比的減少
sbit clk=P1^0; //pwm輸出
sbit wei=P2^7;
sbit duan=P2^6;
sbit RS = P3^5;
sbit RW = P3^6;
sbit EN = P3^4;
uint zkb=50; //占空比初值,取值范圍為1到99
uint shi,ge;
uint period=35; //周期初值,取值范圍為5ms到60ms
uint time0_H,time0_L,time1_H,time1_L; //延時程序
void delayms(uint z)
{ uint i,j;
for(i=z;i--;i>0)
for(j=110;j--;j>0);
}
//系統初始化
/*uint code leddata[]={
0x3F, //"0"
0x06, //"1"
0x5B, //"2"
0x4F, //"3"
0x66, //"4"
0x6D, //"5"
0x7D, //"6"
0x07, //"7"
0x7F, //"8"
0x6F, //"9"
0x77, //"A"
0x7C, //"B"
0x39, //"C"
0x5E, //"D"
0x79, //"E"
0x71, //"F"
0x76, //"H"
0x38, //"L"
0x37, //"n"
0x3E, //"u"
0x73, //"P"
0x5C, //"o"
0x40, //"-"
0x00, //熄滅
0x00 //自定義
}; */
//void display(uint i)
/*{
uint shi,ge;
shi=i/10;
ge=i%10;
P0=0xff;
wei=1;
P0=0xfe;//1111 1110
wei=0;
duan=1;
P0=leddata[shi];
duan=0;
delayms(10);
P0=0xff;
wei=1;
P0=0xfd;//1111 1101
wei=0;
duan=1;
P0=leddata[ge];
duan=0;
delayms(10);
}*/
void init()
{ TMOD=0x11; //定時器0和1都工作在方式1
time0_H=(65536-35000)/256;
time0_L=(65536-35000)%256; //35ms定時
time1_H=(65536-17500)/256;
time1_L=(65536-17500)%256; //17.5ms定時,50%占空比
TH0=time0_H;
//定時器0裝入初值,計數器計數35000次,35ms
TL0=time0_L;
TH1=time1_H; //定時器1裝入初值,計數器計數17500次,17.5ms
TL1=time1_L;
IT0=1; //外部中斷0為下降沿觸發
EX0=1; //開外部中斷0允許位
ET0=1; //定時器T0中斷允許
ET1=1; //定時器T1中斷允許
EA=1; //開啟總中斷
TR0=1; //開啟定時器0
}
//判斷液晶忙,如果忙則等待 第一步:讀狀態
void Read_Busy()
{
uchar busy;
P0 = 0xff; //給P0送1111 1111
RS = 0;
RW = 1;
do
{
EN = 1;
busy = P0;
EN = 0;
}while(busy & 0x80);//讀寫檢測,判斷STA7為是否位1,為1,則忙,循環等待。
}
//寫LCD1602一個字節命令
void Write_Cmd(uchar cmd) //第二步:寫指令
{
Read_Busy();//判斷忙
RS = 0;
RW = 0;
P0 = cmd;
EN = 1;
EN = 0;
}
//寫一個字節數據
void Write_Dat(uint dat) //第三步:寫數據
{
Read_Busy();
RS = 1;
RW = 0;
P0 = dat;
EN = 1;
EN = 0;
}
void LCD_init()
{
Write_Cmd(0x38);//設置16*2顯示
Write_Cmd(0x0c);//開顯示 顯示光標,光標閃爍
Write_Cmd(0x01);//清屏
Write_Cmd(0x06);//地址指針移位命令
}
//主程序
void main()
{
uint num[2];
init( );
shi=zkb/10;
ge=zkb%10;
num[0]=shi;
num[1]=ge;
LCD_init();
//Write_Cmd(0x80 | 0x00);//顯示地址
while(1)
{
shi=zkb/10;
ge=zkb%10;
num[0]=shi;
num[1]=ge;
Write_Cmd(0x80 | 0x00);//顯示地址
Write_Dat(25 + 'A'); //z
Write_Dat(10 + 'A'); //k
Write_Dat(1 + 'A'); //b
Write_Dat(0x3A); //:
Write_Dat(num[0]+'0'); //十位
Write_Dat(num[1]+'0'); //個位
delayms(10);
}
}
//TO中斷程序
void T0_time() interrupt 1 //控制PWM波的周期
{
TR1=1; //開定時器1
TH0=time0_H;
TL0=time0_L;
clk=1;
} //T1中斷程序
void T1_time() interrupt 3 //控制PWM波的占空比
{ TR1=0; //關定時器1
TH1=time1_H;
TL1=time1_L;
clk=0;
} //鍵盤掃描程序
void keyscan() interrupt 0 //外部中斷0,用來查詢是否有按鍵按下
{ float TX,TZ; //定義浮點型變量,4字節長度
EX0=0; //關中斷
delayms(10); //延時消抖
if(P1!=0x1e) //延時消抖完畢,判斷的確有按鍵按下
if(key1==0) //判斷是哪個按鍵按下
{
period=period+5;
if(period>60)
period=5;
}
if(key2==0)
{ period=period-5;
if(period<5)
period=60;
}
if(key3==0)
{
zkb=zkb+1;
if(zkb>99)
zkb=1;
}
if(key4==0)
{
zkb=zkb-1;
if(zkb<1)
zkb=99;
}
TX=(65536-(period)*1000);//周期計算 。。!
TZ=(65536-(period/2)*1000+(50-zkb)*period*10);//占空比計算???
time0_H=(uint)TX/256;
time0_L=(uint)TX%256;
time1_H=(uint)TZ/256;
time1_L=(uint)TZ%256;
P1=0x1e; //P1口重新賦值,以便下次按鍵判斷
EX0=1; //開外部中斷
TR0=1; //開定時器0
TR1=1; //開定時器1
}
|