单片机程序源代码
第二章
任务一:闪烁广告灯的设计
利用89c51单片机的端口控制两个LED(D0和D1),编写程序,实现两个LED互闪。
#include
#define uint unsigned int
#define uchar unsigned char
sbit LED1=P0^0;
sbit LED2=P0^1;
void delayms(uint ms)
{
uint i;
while(ms--)
{
for(i=0;i<120;i++);
}
}
void main()
{
while(1)
{
LED1=0;
LED2=1;
delayms(500);
LED1=1;
LED2=0;
delayms(500);
}
}
任务二:流水广告灯的设计
利用89c51单片机的端口控制8个LED(D0~D7)循环点亮,刚开始时D0点亮,延时片刻
后,接着D1点亮,然后依次点亮D2->D3->D4->D5 ->D6->D7 ,然后再点亮D7->D6->D5->D4
->D3->D2->D1->D0,重复循环。
#include
#include
#define uint unsigned int #define uchar unsigned char uint i;
uchar temp;
uint a[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
void delayms(uint ms) {
while(ms--)
{ uint j;
for(j=0;j<120;j++);
}
}
void main()
{
while(1)
{
P0=0xfe;
while(P0!=0x7f)
{
//P1=temp;
//delayms(500);
P0=_crol_(P0,1);
delayms(250);
}
temp=0x7f;
while(P0!=0xfe)
{
P0=temp;
delayms(500);
temp=_cror_(temp,1);
}
}
}
任务三:拉幕式与闭幕式广告灯的设计
利用89c51单片机的P0端口实现8个LED D0~D7的拉幕式与闭幕式广告灯设计。
拉幕式: 开始D0~D7全灭,延时片刻后首先D3和D4亮,其次是 D2和D5亮,再是D1
和D6亮,最后是D0和D7亮。
闭幕式:开始D0~D7全亮,延时片刻后首先D0和D7灭,其次是 D1和D6灭,再是D2
和D5灭,最后是D3和D4灭。
#include
#define uint unsigned int #define uchar unsigned char
uchar code table[]={0xe7,0xc3,0x81,0x00};
void delay(uint x) {
uint i,j;
for(i=x;i>0;i--)
for(j=120;j>0;j--); }
void main()
{
uint i;
while(1)
{
P1=0xff;
delay(500);
for(i=0;i<4;i++)
{
P1=table[i];
delay(500);
}
for(i=3;i>0;i--)
{
P1=table[i-1];
delay(500);
}
}
}
任务四:复杂广告灯的设计
利用89c51单片机的端口实现8个LED(D0~D7)复杂广告灯的控制,要求显示规律为:
正向流水->反向流水->隔灯闪烁3次->高四盏、低四盏闪烁2次->隔两盏闪烁3次,再重复
循环。
#include
#define uint unsigned int
#include
void delayms(uint ms)
{
uint i;
while(ms--)
{
for(i=0;i<110;i++);
}
}
void main()
{
uint i,j,xx[2]={0xaa,0xff},yy[2]={0xf0,0x0f},zz[2]={0xb6,0xff};
unsigned char aa;
while(1)
{
aa=0xfe;
for(i=0;i<7;i++)
{
P0=aa;
aa=_crol_(aa,1);
delayms(500);
}
for(i=0;i<8;i++)
{
P0=aa;
aa=_cror_(aa,1);
delayms(500);
}
for(i=0;i<3;i++)
for(j=0;j<2;j++)
{
P0=xx[j];
delayms(500);
}
for(i=0;i<2;i++)
for(j=0;j<2;j++)
{
P0=yy[j] ;
delayms(500);
}
for(i=0;i<3;i++)
for(j=0;j<2;j++)
{
P0=zz[j] ;
delayms(500);
}
}
}
任务五:单个LED数码管显示设计
使用89c51的P0口作为输出口,外接LED数码管,编写程序,使数码管循环显示从0~9
的加1计数。
#include
#define uint unsigned int
#define uchar unsigned char
uchar table[10]={ 0XC0,0XF9,0XA4,0XB0,
0X99,0X92,0X82,0XF8,
0X80,0X90};
uint key=0;
void int_int()
{
EA=1;
IT0=1;
EX0=1;
}
void count_num() interrupt 0 {
if(key==9)key=0;
else key++;
}
void main()
{
int_int();
while(1)
{
P0=table[key];
}
}
任务六:多个LED数码管显示设计
使用单片机P0和P2口作为输出口,外接一个8位LED数码管,编写程序,使数码管显示
“872AF635”。
#include
#include #define uint unsigned int #define uchar unsigned char delay(ms)
{
while(ms--)
{ int i;
for(i=0;i<110;i++);
}
}
main()
{
uchar
a[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
uchar b[8]={0x08,0x07,0x02,0x0a,0x0f,0x06,0x03,0x05},j;
uint i;
while(1)
{ j=0x01;
for(i=0;i<8;i++)
{
P2=j;
P0=a[b[i]];
j=_crol_(j,1);
delay(3);
}
}
}
任务七:查询式按键设计
将8个按键从1~8进行编号,如果其中一个键被按下,则在LED数码管上显示相应的键值。
#include
#define uint unsigned int #define uchar unsigned char main()
{
uchar
a[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
P0=0xff;
while(P0!=0xff)
{ switch(P0)
{case 0xfe:
P2=a[1]; break;
case 0xfd:
P2=a[2]; break;
case 0xfb:
P2=a[3]; break;
case 0xf7:
P2=a[4]; break;
case 0xef:
P2=a[5]; break;
case 0xdf:
P2=a[6]; break;
case 0xbf:
P2=a[7]; break;
case 0x7f:
P2=a[8];
}
}
}
任务八:LED数码管显示矩阵键盘按键的设计 设计一个4*4的矩阵键盘,以P1.0~P1.3作为行线,以P1.4~P1.7作为列线。要求:未按下
按键时,LED数码管显示“-”,按下按键时,在数码管上显示相应的键值。
#include
#define uchar unsigned char #define uint unsigned int uchar
table[17]={0xbf,0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x8
6,0x8e};
uint num=0;
void delay(uint x) {
uchar i,j;
for(i=x;i>0;i--)
for(j=120;j>0;j--); }
keyscan()
{ uint temp;
temp=P2;
temp&=0x0f;
if(temp==0x0e)
{
P2=0xf0;
temp=P2;
temp&=0xf0;
switch(temp)
{
case 0xe0:num=1;break;
case 0xd0:num=2;break;
case 0xb0:num=3;break;
case 0x70:num=4;
}
}
if(temp==0x0d)
{
P2=0xf0;
temp=P2;
temp&=0xf0;
switch(temp)
{
case 0xe0:num=5;break;
case 0xd0:num=6;break;
case 0xb0:num=7;break;
case 0x70:num=8;
}
}
if(temp==0x0b)
{
P2=0xf0;
temp=P2;
temp&=0xf0;
switch(temp)
{
case 0xe0:num=9;break;
case 0xd0:num=10;break;
case 0xb0:num=11;break;
case 0x70:num=12;
}
}
if(temp==0x07)
{
P2=0xf0;
temp=P2;
temp&=0xf0;
switch(temp)
{
case 0xe0:num=13;break;
case 0xd0:num=14;break;
case 0xb0:num=15;break;
case 0x70:num=16;
}
}
return num;
}
void display(uint num) { if(num==0)
P0=0xbf;
P0=table[num] ; }
main()
{
uint temp;
while(1)
{
P2=0x0f;
temp=P2;
if(temp!=0x0f)
keyscan();
display(num);
}
}
(2)
#include
#define uchar unsigned char #define uint unsigned int sbit LED1=P2^0;
sbit LED2=P2^1;
uchar num;
uchar code LED_code[]=
{
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e };//数码管字形码编码
void delay(uint x) {
uchar i,j;
for(i=x;i>0;i--)
for(j=120;j>0;j--); }//延时函数
void display(uchar num)
{
P0=LED_code[num]; }//数码管显示函数
void keyscan()//键盘扫描函数
{
uchar temp;
P1=0xfe;//key1-key4第一行按下
temp=P1;
temp&=0xf0;
if(temp!=0xf0)
{
delay(10);//消除抖动
temp=P1;
temp&=0xf0;
if(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xee:
num=1;
break;
case 0xde:
num=2;
break;
case 0xbe:
num=3;
break;
case 0x7e:
num=4;
break;
}
}
while(temp!=0xf0)//等待按键释放
{
temp=P1;
temp&=0xf0;
}
}
P1=0xfd;//key5-key8第二行按下
temp=P1;
temp&=0xf0;
if(temp!=0xf0)
{
delay(10);//消除抖动
temp=P1;
temp&=0xf0;
if(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xed:
num=5;
break;
case 0xdd:
num=6;
break;
case 0xbd:
num=7;
break;
case 0x7d:
num=8;
break;
}
}
while(temp!=0xf0)//等待按键释放
{
temp=P1;
temp&=0xf0;
}
}
P1=0xfb;//key9-key12第三行按下
temp=P1;
temp&=0xf0;
if(temp!=0xf0)
{
delay(10);//消除抖动
temp=P1;
temp&=0xf0;
if(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xeb:
num=9;
break;
case 0xdb:
num=10;
break;
case 0xbb:
num=11;
break;
case 0x7b:
num=12;
break;
}
}
while(temp!=0xf0)//等待按键释放
{
temp=P1;
temp&=0xf0;
}
}
P1=0xf7;//key13-key16第四行按下
temp=P1;
temp&=0xf0;
if(temp!=0xf0)
{
delay(10);//消除抖动
temp=P1;
temp&=0xf0;
if(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xe7:
num=13;
break;
case 0xd7:
num=14;
break;
case 0xb7:
num=15;
break;
case 0x77:
num=16;
break;
}
}
while(temp!=0xf0)//等待按键释放
{
temp=P1;
temp&=0xf0;
}
}
}
void main()
{
while(1)
{
keyscan();
if(num==0)
P0=0xbf;
else
display(num-1);
}
}
任务九:简单拨号键盘的设计
使用4*4的矩阵式键盘及8位共阳极LED数码管设计一个简单拨号键盘,要求在初始状态
时,8位数码管均显示“-”,每按下一个号码后,原8位LED数码管显示的内容向左移动1
位。
#include #include #define uint unsigned int
#define uchar unsigned char
uchar keycount=0,num; uchar code LED1_code[]=
{
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e };//数码管字形码编码
uchar LED2_duan[8]={0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf};//8段共阳数码管编码
uchar LED2_wei[8]= {0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
void delay(uint x) {
uchar i,j;
for(i=x;i>0;i--)
for(j=120;j>0;j--); }
void display()
{
uchar i;
//P2=0x80;
for(i=0;i<8;i++)
{
P2=LED2_wei[i];
P0=LED2_duan[7-i];
delay(1);
}
}
void keyscan()
{
uchar temp;
P3=0xfe;
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xee:keycount++;num=0;break;
case 0xde:keycount++;num=1;break;
case 0xbe:keycount++;num=2;break;
case 0x7e:keycount++;num=3;break;
}
}
while(temp!=0xf0)
{
temp=P3;
temp&=0xf0;
}
}
P3=0xfd;
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xed:keycount++;num=4;break;
case 0xdd:keycount++;num=5;break;
case 0xbd:keycount++;num=6;break;
case 0x7d:keycount++;num=7;break;
}
}
while(temp!=0xf0)
{
temp=P3;
temp&=0xf0;
}
}
P3=0xfb;
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xeb:keycount++;num=8;break;
case 0xdb:keycount++;num=9;break;
case 0xbb:keycount++;num=10;break;
case 0x7b:keycount++;num=11;break;
}
}
while(temp!=0xf0)
{
temp=P3;
temp&=0xf0;
}
}
P3=0xf7;
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P3;
temp&=0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xe7:keycount++;num=12;break;
case 0xd7:keycount++;num=13;break;
case 0xb7:keycount++;num=14;break;
case 0x77:keycount++;num=15;break;
}
}
while(temp!=0xf0)
{
temp=P3;
temp&=0xf0;
}
}
}
void main()
{
uchar i;
while(1)
{
display();
keyscan();
if(keycount!=0)
{
for(i=0;i<7;i++)
LED2_duan[i]=LED2_duan[i+1];
LED2_duan[7]=LED1_code[num];
keycount=0;
}
}
}
第五章
任务一:带中断控制的LED花样灯
P0端口作为输出口,外接8只LED,P3.2外接按键K。编写程序,当K未按下时,8只LED
进行默认显示,其显示规律为左移流水->右移流水->隔灯闪烁3次花样显示;如果按下K键
后,8只LED暂停默认显示,而进行闪烁显示,当显示达到5次后,继续按默认规律显示。
#include
#define uint unsigned int
#define uchar unsigned char
uint LED_table[14]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd};
void delayms(uint ms)
{
uint i;
while(ms--)
for(i=0;i<120;i++);
}
void int_int()
{
EA=1;
EX0=1;
IT0=1;
}
void LED_shan() interrupt 0
{
uint k;
for(k=0;k<5;k++)
{
P0=0xaa;
delayms(500);
P0=0xff;
delayms(500);
}
}
void main()
{
int_int();
while(1)
{
uint i;
for(i=0;i<14;i++)
{
P0=LED_table[i];
delayms(500);
}
for(i=0;i<3;i++)
{
P0=0xaa;
delayms(500);
P0=0xff;
delayms(500);
}
}
}
任务二:采用外中断控制的条形LED彩灯设计 P0端口作为输出口,外接条形LED。编写程序,当按键K未按下时,LED进行循环左移显
示。如果第1次按下按键K后,LED进行循环右移显示。如果第2次按下按键K后,LED
进行拉幕式与闭幕式花样显示。如果第3次按下按键K后,又恢复循环左移显示。
#include unsigned char flag=0; //状态标志位 unsigned char led =0; //LED映射位 unsigned char table[]={ //花样数组 0x00,0x81,0xc3,0xe7, 0xff,0xe7,0xc3,0x81};//先闭幕式再开幕式 void delayms(unsigned int ms); //延时函数 void sysInit(void); //系统初始化 void step0(void); //状态0
void step1(void); //状态1
void step2(void); //状态2
void main(void) {
sysInit(); //初始化系统
while(1)
{
switch(flag)
{
case 0: step0();break;
case 1: step1();break;
case 2: step2();break;
default:break;
}
P0 = ~led; //将led值映射到LED灯
delayms(500); //延时500ms
}
}
void delayms(unsigned int ms)
{
unsigned char i;
for (;ms;ms--)
for (i=110;i;i--); }
void sysInit(void) {
EX0 = 1; //打开外部中断0
EA = 1; //打开总中断
IT0 = 1; //外部中断0下降沿触发 }
void step0(void) {
led <<=1; //左移
if (led==0) //溢出处理
led = 0x01; }
void step1(void) {
led >>=1; //右移
if (led==0) //溢出处理
led = 0x80;
}
void step2(void) {
static char t;
led = table[t++]; //开幕闭幕花样显示
if (t==8)
t = 0;
}
void EX_0() interrupt 0 //外部中断0服务函数 {
flag++;
if (flag==3)
flag = 0;
}
(2)
#include//头文件
#define uchar unsigned char
#define uint unsigned int //宏定义 uchar temp,key_count; uchar code tab[]={ //开幕式闭幕式编码 0x00,0x81,0xc3,0xe7, 0xff,0xe7,0xc3,0x81};
void delay(uint ms) //延时子函数
{
uint i,j;
for(i=ms;i>0;i--)
for(j=0;j<110;j++); }
void loop_leftmove() {
temp=temp<<1;
if(temp==0)
temp=0x01;
}
void loop_rightmove() {
temp=temp>>1;
if(temp==0)
temp=0x80;
}
void open_close() {
uchar count;
temp=tab[count];
count++;
if(count>=8)
count=0;
}
void init()
{
EA=1;
EX0=1;
IT0=1;
temp=0;
key_count=0;
}
void main()
{
init();
while(1)
{
switch(key_count)
{
case 0:loop_leftmove();break;
case 1:loop_rightmove();break;
case 2:open_close();break;
default:break;
}
P0=~temp;
delay(250);
}
}
void key_interrupt() interrupt 0//外部中断INT0中断服务程序 {
key_count++;
key_count%=3;
/*if(key_count==3)
key_count=0;*/
}
任务三:采用两个外中断的LED彩灯控制
P0端口作为输出口,外接8只LED,P3.2外接按键K1,P3.3外接按键K2。编写程序,没
有按下任何按键时,LED隔灯闪烁,当按键K1为奇数次时,LED进行左移流水->右移流水
显示。当按下按键K1为偶数次时,LED进行拉幕式显示;当按下按键K2时,LED暂停显
示,蜂鸣器发出“叮咚”的开门声音,然后LED继续花样显示(K2按键优先)。
#include
#include
#define uchar unsigned char #define uint unsigned int sbit key1=P3^2;
sbit key2=P3^3;
sbit beep=P1^0;
uchar code tab[]={
0xff,0xe7,0xc3,0x81, 0x00,0x81,0xc3,0xe7};//开幕式编码
uchar temp=0x01,key_count,flag,right,beep_FG;
void delay(uint ms) {
uint i,j;
for(i=ms;i>0;i--)
for(j=110;j>0;j--); }
void init()
{
EA=1;//打开总中断
EX0=1;//打开外部中断INT0
EX1=1;//打开外部中断INT1
IT0=1;//下降沿触发方式
IT1=1;//下降沿触发方式
PX0=0;//设置INT0为低中断优先级
PX1=1;//设置INT1为高中断优先级 }
void interval_LED() {
P0=0xff;
delay(500);
P0=0xaa;
delay(500);
}
void left_right_move() {
if(!right)
temp=_crol_(temp,1);
else
temp=_cror_(temp,1);
if(temp==0x01)
{
right=0;
}
if(temp==0x80)
right=1;
}
void open_LED() {
uchar count;
temp=tab[count++];
if(count==8)
count=0;
}
void Beep()
{
uchar i,j,k;
for(i=100;i;i--)
for(j=20;j;j--)
{
for(k=1000;k;k--)
beep=~beep;
}
/*for(i=100;i;i--)
for(j=200;j;j--)
{
for(k=1000;k;k--)
beep=~beep;
}*/
beep_FG=0;
}
void main()
{
init();
beep=0;
while(1)
{
if(!flag)
interval_LED();
else
{
if(beep_FG)
{
Beep();
}
else
{
switch(key_count%2)
{
case 1:
left_right_move();
break;//奇数次按键左移右移显示
case 0:
open_LED();
break;//偶数次按键拉幕式显示
default:break;
}
P0=~temp;
delay(400);
}
}
}
}
void key1_interrupt() interrupt 0
{
flag=1;
key_count++;
}
void key2_interrupt() interrupt 2
{
flag=1;
beep_FG=1;
}
任务四:采用两个外中断实现LED键控移位 P0端口作为输出口,外接8只LED,P3.2外接按键K1,P3.3外接按键K2。编写程序,要
求实现LED键控移位,按下按键K1时,8只LED左移1位;按下按键K2时,8只LED
右移1位。
#include
#include #define uint unsigned int #define uchar unsigned char uchar key1=0,key2=0,temp1=0,temp2=0,temp11=0,temp12=0;
/*void delayms(uint ms) {
uint i;
while(ms--)
{
for(i=0;i<120;i++);
}
} */
void int_int()
{
EA=1;
EX0=1;
EX1=1;
IT0=1;
IT1=1;
}
void int0() interrupt 0 {
key1++;
}
void int1() interrupt 2 {
key2++;
}
void main()
{
uchar a;
int_int();
a=0xfe;
while(1)
{
if(temp1!=key1)
{
P0 = a;
a=_crol_(a,1);
temp1=key1;
}
if(temp2!=key2)
{
P0 = a;
a=_cror_(a,1);
key2=temp2;
}
}
}
(2)
#include #define uint unsigned int
#define uchar unsigned char
uchar key1=0,key2=0,m,n,k;
uchar table[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
void int_int()
{
EA=1;
EX0=1;
IT0=1;
EX1=1;
IT1=1;
}
void int0() interrupt 0 {
key1++;
m=key1%8;
}
void int2() interrupt 2
{
key2++;
n=key2%8;
}
void main()
{
int_int();
while(1)
{
k=(m-n+8)%8;
P0=table[k];
}
}
任务五:采用外中断实现计数
使用单片机P0、P2端口作为输出口,外接一个2位LED数码管,P3.2外接按键K1,P3.3
外接按键K2。编写程序,每次按下K1时,LED数码管进行加1显示;每次按下按键K2
时,LED数码管进行减1显示,计数范围为0~99。
#include//头文件
#define uint unsigned int //宏定义 #define uchar unsigned char //宏定义 uchar table[]={0xc0,0xf9,0xa4,0xb0,0x99,
0x92,0x82,0xf8,0x80,0x90};//0-9共阳字型码编码
char count=0;
uchar shi,ge;
void LED_scan()//数码管扫描子函数 {
shi=count/10;//分离十位
ge=count%10;//分离个位
P2=table[ge];//显示个位
P0=table[shi];//显示十位
}
void int_int() //初始化
{
EA=1; //打开总中断
EX0=1; //打开外部中断0
EX1=1; //打开外部中断1
IT0=1; //设置下降沿触发方式
IT1=1; //设置下降沿触发方式 }
void main() //主函数
{
int_int(); //调用初始化函数
while(1)
{
LED_scan(); //调用数码管扫描函数
}
}
void int0() interrupt 0//外部中断0服务程序 {
count++; //计数加1
if(count==100) //溢出操作
count=0;
}
void int2() interrupt 2 //外部中断1服务程序 {
count--; //计数减1
if(count<0) //溢出操作
count=99;
}
(2)
#include//头文件
#define uint unsigned int //宏定义 #define uchar unsigned char //宏定义 uchar table[]={0xc0,0xf9,0xa4,0xb0,0x99,
0x92,0x82,0xf8,0x80,0x90};//0-9共阳字型码编码
char count=0;
uchar shi,ge;
void delay(uint ms)//延时子函数 {
uchar i;
for(;ms;ms--)
for(i=120;i;i--); }
void LED_scan()//数码管扫描子函数 {
shi=count/10;//分离十位
ge=count%10;//分离个位
P2=0x01; //个位对应的数码管点亮
P0=table[ge];//显示个位
delay(1);
P2=0x02; //十位对应的数码管点亮
P0=table[shi];//显示十位
delay(1);
}
void int_int() //初始化
{
EA=1; //打开总中断
EX0=1; //打开外部中断0
EX1=1; //打开外部中断1
IT0=1; //设置下降沿触发方式
IT1=1; //设置下降沿触发方式
}
void main() //主函数
{
int_int(); //调用初始化函数
while(1)
{
LED_scan(); //调用数码管扫描函数
}
}
void int0() interrupt 0//外部中断0服务程序
{
count++; //计数加1
if(count==100) //溢出操作
count=0;
}
void int2() interrupt 2 //外部中断1服务程序
{
count--; //计数减1
if(count<0) //溢出操作
count=99;
}
任务六:采用外中断进行计数和清零控制
使用单片机P0、P2端口作为输出口,外接一个2位LED数码管,P3.2外接按键K1,P3.3
外接按键K2。编写程序,按键K2作为“加1/暂停/清零”控制;按键K1作为加1计数控
制。当按键K2没有按下时,按键K1按下后LED数码管总显示为0;第1次按下键K2时,
每次按下K1,LED数码管进行加1显示;第二次按下按键K2时,暂停加1计数,按键K1
按下后LED数码管显示暂停前的数值;第3次按下按键K2时,LED数码管显示为0;第4
次按下按键K2时,与第1次类似。
#include
#define uint unsigned int #define uchar unsigned char uchar key1=0,temp1=0,key2=0,temp2=0,key=0;
uchar table[]={0XC0,0XF9,0XA4,0XB0,
0X99,0X92,0X82,0XF8,
0X80,0X90};
void delayms(uint ms)
{
while(ms--)
{
uint i=0;
for(i;i<120;i++) ;
}
}
void int_int() {
EA=1;
EX0=1;
EX1=1;
IT0=1;
IT1=1;
}
void int1() interrupt 0
{
key2++;
}
void int0() interrupt 2
{
key1++;
}
void display() {
P2=0xfe;
P0=table[temp1];
delayms(2);
P2=0xfd;
P0=table[temp2];
delayms(2);
}
void main()
{
int_int();
while(1)
{
temp1=key1%10;
temp2=key1/10;
switch(key2%3)
{
case 0:{
while(1)
{
if(key2%3!=0) break;
P2=0xfe;
P0=table[0];
delayms(2);
P2=0xfd;
P0=table[0];
delayms(2);
}
key1=0;
break;
}
case 1: display();
break;
case 2: key=key1;
while(1)
{
if(key2%3!=2) break;
P2=0xfe;
P0=table[temp1];
delayms(2);
P2=0xfd;
P0=table[temp2];
delayms(2);
}
key1=key;
break;
}
}
}
第六章
任务一:简单计数器的设计
使用单片机P0,P2端口作为输出口,外接一个2位LED数码管,P3.4外接按键K。编写
程序,每次按键K按下时LED数码管进行加1显示,计数范围为0~99。
#include
#define uint unsigned int #define uchar unsigned char uchar table[]={0XC0,0XF9,0XA4,0XB0,
0X99,0X92,0X82,0XF8,
0X80,0X90};
uchar key=0;
void delayms(uint ms) {
uint i;
while(ms--)
{
for(i=0;i<120;i++);
}
}
void int_int()
{
EA=1;
ET0=1; //开定时器0中断
TR0=1; //启动定时器0
TMOD=0x05;//设置工作方式为1 选择计数功能
TH0=0xff;
TL0=0xff; //装初值使得按一下就中断
}
void int1() interrupt 1
{
TH0=0xff;
TL0=0xff;
key++;
}
void display()
{
P2=0xfe;
P0=table[key%10];
delayms(3);
P2=0xfd;
P0=table[key/10];
delayms(3);
}
void main()
{
int_int();
while(1)
{
display();
if(key%10==9&key/10==9)key=0;
}
}
(2)
#include #define uint unsigned int
#define uchar unsigned char
uchar table[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90};
num1=0;num2=0; void delay(uint ms) {
uint i;
while(ms--)
{
for(i=0;i<120;i++);
}
}
void int_int() {
EA=1;
ET0=1; //开定时器0中断
TR0=1; //启动定时器0
TMOD=0x05;//设置工作方式为1
TH0=0xff;
TL0=0xff; //装初值使得按一下就中断
}
void jishu()
{
if(num1<=9)
num1++;
if(num1>9)
{
num1=0;
if(num2!=9)
num2++;
else num2=0;
}
}
void int1() interrupt 1
{
TH0=0xff;
TL0=0xff;
jishu();
}
void scan ()
{
P2=0xfe;
P0=table[num1];
delay(3);
P2=0xfd;
P0=table[num2];
delay(3);
}
main()
{ int_int();
while(1)
{scan();}
}
任务二:方波信号发生器
假设单片机晶振频率为12MHz,使用T1,在方式1下控制P1.0输出1ms的等宽方波信号。
#include #define uint unsigned int #define uchar unsigned char
sbit wave=P1^0;
void int_int()
{
EA=1;
ET1=1; //开定时器1中断
TR1=1; //启动定时器1
TMOD=0X10; //设置工作方式为1,选择定时功能
TH1=(65536-500)/256;
TL1=(65536-500)%256; }
void int3() interrupt 3 {
wave=~wave;
TH1=(65536-500)/256;
TL1=(65536-500)%256;
}
void main()
{
int_int();
while(1);
}
任务三:用T2实现流水灯控制
假设单片机晶振频率为12MHz, 设计1个硬件延时1s的流水灯。要求使用T2实现此功能。
#include//头文件
#include//左移右移函数头文件
#define uint unsigned int //宏定义
#define uchar unsigned char//宏定义
uchar num=0;
void init() //初始化子函数
{
EA=1; //打开总中断
ET2=1;//打开定时器2中断
TR2=1;//启动定时器2
RCAP2H=(65536-50000)/256; //重装载计数器赋初值
RCAP2L=(65536-50000)%256;
P1=0xfe;//初始状态点亮第一个LED }
void main()
{
init();//调用初始化函数
while(1);
}
void Timer2() interrupt 5 //T2定时器的中断服务子程序 {
static uchar t2=0;
TF2=0; //溢出标志位软件清零
t2++; //每50ms进一次中断
if(t2==20)//定时时间1s
{
P1=_crol_(P1,1); //流水
t2=0; //t2清零
}
}
任务四:59s计时器的设计
假设单片机晶振频率为12MHz, 设计一个59s计时器,要求使用T0工作在方式1下进行
硬件延时。
#include
#define uchar unsigned char #define uint unsigned int uchar code table[]= {
0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,0x7f,0x6f };
uchar shi,ge,num;
void delay(uint ms) {
uchar i;
while(ms--)
for(i=110;i;i--); }
init()
{
EA=1; //打开总中断
ET0=1;//打开定时器0中断
TR0=1; //启动定时器0
TMOD=0x01;//设置定时器0工作方式1
TH0=(65536-50000)/256;//高8位赋初值
TL0=(65536-50000)%256;//低8位赋初值
num=0;
//num=58;
}
void display()
{
shi=num/10;//分离十位
ge=num%10; //分离个位
P3=0xfe; //送位选点亮个位数码管
P2=table[ge];//送段选显示个位
delay(1);
P3=0xfd;//送位选点亮十位数码管
P2=table[shi];//送段选显示十位
delay(1);
}
void main()
{
init(); //调用初始化函数
while(1) //循环
display(); //扫描数码管
}
void timer0() interrupt 1
{
static uchar t0=0;
t0++;
if(t0==20)
{
t0=0;
num++;
num=num%60;
}
TH0=(65536-50000)/256;//高8位赋初值
TL0=(65536-50000)%256;//低8位赋初值
}
任务五:LED滚动闪烁控制
假设单片机晶振频率为12MHz, 设计1个LED滚动闪烁控制。要求使用定时器作为计时,
使当前LED闪烁几次后灭,下一个LED再闪烁,达到滚动闪烁的效果。
任务六:简单门铃设计
假设单片机晶振频率为12MHz, 设计1个简单门铃控制系统。要求按下按键K时,蜂鸣器
发出“叮咚”的声音。
#include
#define uint unsigned int #define uchar unsigned char uchar table[15]={
0xfe,0xfd,0xfb,0xf7,
0xef,0xdf,0xbf,0x7f,
0xbf,0xdf,0xef,0xf7,
0xfb,0xfd,0xfe};
uint count,i,num;
void int_int()
{
EA=1;
EX0=1;//允许外部中断
EX1=1;
IT0=1;//下降沿有效
IT1=1;
TL0=(65535-50000)%256;
TH0=(65535-50000)/256;
TMOD=0X01;//方式
TR0=1;
ET0=1;
num=10000;
}
void key1_1() interrupt 0 {
num=num-2000;
if(num<=2000)num=2000; }
void key2_2() interrupt 2 {
num=num+2000;
if(num>=60000)num=60000;
}
void timer_0() interrupt 1
{
TL0=(65535-num)%256;
TH0=(65535-num)/256;
count++;
if(count==20)
{
count=0;
if(i!=15)
{
P0=table[i];
i++;
}
else
i=1;
}
}
void main()
{
int_int();
while(1);
}
(2)
#include #define uchar unsigned char
#define uint unsigned int #define a2 0xFDF4 // 880.000Hz a2
#define e2 0xFD45 // 659.255Hz e2
#define T 1000
sbit key=P3^7;
sbit SPEAKER=P2^3; typedef struct //定义音符结构 { unsigned int mFreq; //发声频率(对应的定时器初值)
unsigned int mDelay; //发声时值 }CNote;
CNote table1[]={{a2,T/2},{e2,T},{0,0}};
uchar ReloadH;
uchar ReloadL;
void init()
{
TMOD=0x01;
ET0=1;
EA=1;
TR0=0;
}
void delayms(uint z) {
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--); }
void sound(CNote *note) {
if(note->mFreq!=0)
{
ReloadH=(uchar)(note->mFreq>>8);
ReloadL=(uchar)(note->mFreq);
TR0=1;
}
delayms(note->mDelay);
TR0=0;
delayms(5);
}
void play(CNote music[]) {
uchar n=0;
while(1)
{
if(music[n].mDelay==0)
break;
else
{
sound(&music[n]);
n++ ;
}
}
}
void main()
{
init();
while(1)
{
if(key==0)
{
delayms(5);
play(table1);
}
SPEAKER=1;
}
}
void inter() interrupt 1
{
TH0 = ReloadH;
TL0 = ReloadL;
SPEAKER = !SPEAKER; //音乐声频的半个波
}
(3)
#include//头文件
#define uint unsigned int
#define uchar unsigned char//宏定义 sbit beep=P1^0;//按键位声明 void Beep() //“叮咚”子函数 {
uint i,j;
for(i=300;i;i--)//持续时间
{
beep=~beep;
for(j=240;j;j--);//频率
}
for(i=200;i;i--)//持续时间
{
beep=~beep;
for(j=180;j;j--);//频率
}
}
void init() //初始化子函数 {
EA=1; //打开总中断
TMOD=0x05;//设置计数器0 工作方式1
ET0=1; //打开计数器0中断
TR0=1;//启动定时器0
TH0=0xff;
TL0=0xff;//计数器赋初值 }
void beep_interrupt() interrupt 1 //计数器0中断服务子程序
{
TH0=0xff;
TL0=0xff;//计数器初值
Beep();//调用“叮咚”子函数
}
void main()//主函数
{
init();//调用初始化函数
while(1);//等待按键按下
}
任务七:速度可调流水灯控制
假设单片机晶振频率为12MHz, 单片机P0口外接8只LED,P3.2外接按键K1,P3.3外
接按键K2。编写程序,每次按下按键K1时,加快8只LED的流水显示速度;每次按下按
键K2时,降低8只LED的流水显示速度。 #include
#define uint unsigned int #define uchar unsigned char uchar table[15]={
0xfe,0xfd,0xfb,0xf7,
0xef,0xdf,0xbf,0x7f,
0xbf,0xdf,0xef,0xf7,
0xfb,0xfd,0xfe};
uint count,i,num;
void int_int()
{
EA=1;
EX0=1;//允许外部中断
EX1=1;
IT0=1;//下降沿有效
IT1=1;
TL0=(65535-50000)%256;
TH0=(65535-50000)/256;
TMOD=0X01;//方式
TR0=1;
ET0=1;
num=10000;
}
void key1_1() interrupt 0 {
num=num-2000;
if(num<=2000)num=2000; }
void key2_2() interrupt 2 {
num=num+2000;
if(num>=60000)num=60000;
}
void timer_0() interrupt 1
{
TL0=(65535-num)%256;
TH0=(65535-num)/256;
count++;
if(count==20)
{
count=0;
if(i!=15)
{
P0=table[i];
i++;
}
else
i=1;
}
}
void main()
{
int_int();
while(1);
}
(2)
#include
//#define uint unsigned int
#include
int num=0;
int time=0;
int aa=0xfe;
void init()
{
EA=1; //打开总中断
ET0=1;//打开定时器0中断
TR0=1; //启动定时器0
TMOD=0x01;//设置定时器0工作方式1
TH0=(65536-50000)/256;//高8位赋初值
TL0=(65536-50000)%256;//低8位赋初值
num=0;
//num=58;
}
void Incre_time() interrupt 0
{
time+=2;
}
void Decre_time() interrupt 2
{
time-=2;
}
void timer0() interrupt 1 {
num++;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
}
void main()
{
init();
P0=aa ;
while (1)
{ P0=0xfd ;
//P0=aa;
if(num==(10+time))
{aa=_crol_(aa,1);num=0;}
}
}
任务八:PWM调光
假设单片机晶振频率为12MHz, 单片机P0,P2口作为输出口,外接一个2位LED数码管,
P1.0外接LED,P3.2外接按键K1,P3.3外接按键K2,P3.7外接蜂鸣器。编写程序,每次
按下按键K1时,LED数码管显示加1,LED变暗;每次按下按键K2时,LED数码管显示
数据减1,LED变亮;当LED数码管显示为0A时,再次按下按键K1时,则蜂鸣器发出报
警声。
任务九:简单电子频率计
假设单片机晶振频率为12MHz, 单片机P0,P2端口作为输出口,外接4位LED数码管。
编写程序,测量由P3.4输入脉冲的频率。
#include
#define uint unsigned int
#define uchar unsigned char
uchar table[]={
0XC0,0XF9,0XA4,0XB0,
0X99,0X92,0X82,0XF8,
0X80,0X90};
uint num=0,num0=0;num1=0,num2=0,num3=0,count=0,new_num=0;
void delayms(uint ms)
{
uint i;
while(ms--)
for(i=0;i<120;i++); }
void int_int()
{
EA=1;
EX1=1;
IT1=1;
TMOD=0X01;
ET0=1;
TL0=(65535-62500)%256;
TH0=(65535-62500)/256; }
void display()
{
num3=new_num/1000;
num2=(new_num%1000)/100;
num1=(new_num%100)/10;
num0=new_num%10;
P2=0x08;
P0=table[num0];
delayms(1);
P2=0X04;
P0=table[num1];
delayms(1);
P2=0X02;
P0=table[num2];
delayms(1);
P2=0X01;
P0=table[num3];
delayms(1);
}
void key_key() interrupt 2 {
num++;
if(num==1)
TR0=1;
}
void timer() interrupt 1 {
TL0=(65535-62500)%256;
TH0=(65535-62500)/256;
count++;
if(count==16)//定时时间1s
{
count=0;
new_num=num;
num=0;
TR0=0;
}
}
void main()
{
int_int();
while(1)
{
display();
}
}
第七章
任务一:甲机通过串口控制乙机LED显示状态
单片机甲机P1端口外接8位拨码开关;乙机P0外接8只LED。要求使用单片机串行通信,在查询状态下使单片机乙机8只LED能够显示单片机甲机8位拨码开关的状态。 任务二:甲机通过串口控制乙机计时
单片机甲机的P3.2外接按键K1,P3.3外接按键;单片机乙机P0、P2端口作为输出口,外接一个2位LED数码管。要求使用单片机串行通信,使甲机的按键K1作为乙机计时的“开始/暂停”控制按键,甲机的按键K2作为乙机计时的“复位”控制按键。 任务三:单片机双机通信
单片机甲机的P3.3外接按键K2,P0、P2端口作为输出口,外接一个2位LED数码管;乙机P3.3外接按键K1,P0端口外接8位LED。要求使用单片机串行通信,甲机按键K2每按下1次,乙机的LED移位1次;乙机K1每按下1次,甲机的LED数码管加1显示。 任务四:单片机与PC通信
单片机通过串行口向PC发送字符串,且能接收由PC发送过来的0~9的数字,并将接受的数字通过LED数码管显示出来。