|
![](static/image/common/ico_lz.png)
楼主 |
发表于 2012-9-28 10:18:52
|
显示全部楼层
本帖最后由 choi 于 2012-9-28 10:21 编辑
匆匆將 《从单片机初学者到单片机工程师》這文章看完了 受益匪浅!
修改了文章中的程序 寫了以下的程序 發現還是弄不懂如何將一個io腳單獨定時 就像程序中的蜂鳴器響閙 我想將io腳定時500ms翻轉 就不是很成功 請問應如何修改
完整程序如下
/*要實現的效果
1、led作流水效果閃動
2、數碼管顯示0-9數字
3、3個按鍵 數字加 數字減 數字清零
數碼管刷新頻率=40Hz 按鍵刷新頻率=50Hz led閃爍頻率=2Hz
定時器=5ms
*/
#include<reg52.h>
#include<intrins.h>
#define time_per_sec 200 //定義任務時鐘頻率 200hz
#define clock 11059200 //定義時鐘晶振 單位 Hz
#define max_task 3 //定義任務數量
#define key_state 0 //按鍵初始
#define key_wobble 1 //按鍵抖動
#define key_press 2 //按鍵壓下
#define key_release 3 //按鍵釋放
unsigned char code dsp[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67}; //0,1,2,3,4,5,6,7,8,9
void display(unsigned int number);
void scankey(); //鍵盤掃描
void beep(); //蜂鳴器響閙
void task0(); //led閃爍
void task1(); //數碼管
void task2(); //按鍵
void keyactive(); //鍵值對應功能
sbit k20=P2^7; //數字加
sbit k21=P2^6; //數字減
sbit k22=P2^5; //數字清零
sbit bp=P3^4; //蜂鳴器響閙控制
unsigned char task_delay[3]; //任務延時變量定義
unsigned char n;
unsigned scan_led;
unsigned int num;
unsigned char keytemp; //按鍵掃描設置
unsigned char keystate;
unsigned char keylast;
unsigned char keynull;
unsigned char timecount;
unsigned char m;
unsigned char l;
void timer0_init() //定時器0初始化
{
unsigned char i;
for(i=0;i<max_task;i++)task_delay=0; //任務延時量清零
TMOD=0x01; //定時器0工作在模式1,16bit定時器模式
TH0=255-clock/time_per_sec/12/256; //設為5ms定時
TL0=255-clock/time_per_sec/12%256;
TR0=1;
ET0=1;
}
void timer0() interrupt 1
{
unsigned char i;
TH0=255-clock/time_per_sec/12/256;
TL0=255-clock/time_per_sec/12%256;
/*設蜂鳴器響閙時長 */
if(l==1)
{
m++;
if(m>50)
{
m=0;
bp=1;
}
}
for(i=0;i<max_task;i++)
{
if(task_delay)
{
task_delay--;
}
}
}
void main()
{
keynull=0xf0; //沒有按鍵按下的鍵值
keystate=key_state; //按鍵狀態
timer0_init();
EA=1;
P1=0x7f; //led閃動初值
while(1)
{
if(task_delay[0]==0) //led閃動
{
task0();
task_delay[0]=time_per_sec/2; //500ms頻率閃動
}
if(task_delay[1]==0) //數碼管掃描
{
task1();
task_delay[1]=time_per_sec/200; //5ms頻率掃描
}
if(task_delay[2]==0) //按鍵掃描
{
task2();
task_delay[2]=time_per_sec/50; //20ms判斷一個按鍵
}
}
}
void task0() //led閃爍效果
{
if(n==0) //判斷n=0時 led左移
{
P1=_crol_(P1,1);
if(P1==0x7f) //判斷led是否到頭了(P1^7 led點亮了)
{
n=1;
P1=0xfe; //重新定義P1口數值 給右移作準備
}
}
if(n==1) //判斷n=1 led右移
{
P1=_cror_(P1,1);
if(P1==0xfe)
{
n=0;
}
}
}
void task1() //數碼管顯示掃描
{
display(num);
scan_led++;
if(scan_led>3)
{
scan_led=0;
}
}
void task2() //按鍵掃描
{
scankey();
}
void display(unsigned int number) //數碼管顯示
{
unsigned char bai,shi,ge;
bai=number/100; //分離數字
shi=number%100/10;
ge=number%10;
if(scan_led==0)
{
P2=0xfe; //百位顯示打開
P0=dsp[bai]; //顯示百位的數字
}
if(scan_led==1)
{
P2=0xfb; //十位顯示打開
P0=dsp[shi];
}
if(scan_led==2)
{
P2=0xf7; //個位顯示打開
P0=dsp[ge];
}
}
void beep() //蜂鳴器響閙
{
bp=0;
l=1; //打開計時
}
void scankey() //鍵盤掃描
{
keytemp=P2&0xf0; //檢測是否有鍵按下
switch(keystate)
{
case key_state:
{
if(keynull!=keytemp)
{
keystate=key_wobble;
}
}
break;
case key_wobble: //去抖動
{
keystate=key_press;
}
break;
case key_press: //檢測是否有鍵按下
{
if(keynull!=keytemp)
{
keylast=keytemp; //存鍵值
keystate=key_release;
}
}
break;
case key_release: //檢測鍵是否鬆開
{
if(keytemp==keynull)
{
keyactive();
keystate=key_state;
}
}
break;
}
}
void keyactive() //鍵值對應功能
{
if(keylast==0x70) //數字加
{
num++;
if(num==1000)
{
num=0;
}
beep();
keylast=keynull;
}
if(keylast==0xb0) //數字減
{
if(num==0)
{
num=1000;
}
num--;
beep();
keylast=keynull;
}
if(keylast==0xd0) //清零
{
num=0;
beep();
keylast=keynull;
}
}
|
|