单片机经典试题及答案
1.循环显示学号,循环起点为学号后四位,最大值为9999.
2.利用三位数码管显示电路,显示学号的后三位;
要求使用定时器中断进行三位数码管扫描显示。
所有文件放置在一个文件夹中,文件夹名称为学号+姓名;(如:20102814***###,)电路图和程序工程文件用学号命名。
3.利用298驱动一个直流电机;
利用定时计数器的计数方式,在计数引脚上接一个按键,按键按下2次,电机更换旋转方向,循环往复。
所有文件放置在一个文件夹中,文件夹名称为学号+姓名;(如:20102814***###,)电路图和程序工程文件用学号命名。
4.利用一个L298驱动一个直流电机;
利用定时器中断实现该直流电机,正转6秒然后翻转六秒循环往复。
所有文件放置在一个文件夹中,文件夹名称为学号+姓名;(如:20102814***###,)电路图和程序工程文件用学号命名。
5.设计电路有上下(或左右排列)的四个发光二极管和2*2的矩阵键盘;
扫描按键,当按下某个按键时,与之对应的发光二极管点亮。
所有文件放置在一个文件夹中,文件夹名称为学号+姓名;(如:20102814***###,)电路图和程序工程文件用学号命名。
6.利用一位数码管显示学号后三位;
将一个开关接到外部中断引脚上,每进一次中断更换所显示的学号位数。
所有文件放置在一个文件夹中,文件夹名称为学号+姓名;(如:20102814***###,)电路图和程序工程文件用学号命名。
循环显示学号
#include
#define unit unsigned int
#define uchar unsigned char
sbit P20=P2^0;
sbit P21=P2^1;
sbit P22=P2^2;
sbit P23=P2^3;
unit count=4425,i,j,a;
unit ge,shi,bai,qian;
const uchar tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x00}; void delay()
{
for(i=0;i<256;i++);
}
void time0(void) interrupt 1 using 1
{
TH0=0x3c;
TL0=0xb0;
j++;
if(j==10)
{
j=0;
a++;
}
if(a==4)
{
a=0;
}
}
void main(void)
{
P2=0x00;
a=0;
count=425;
TMOD=0x01;
TH0=0x3c;
TL0=0xb0;
EA=1;
ET0=1;
TR0=1;
while(1)
{
ge=count%10;
shi=count/10%10;
bai=count/100%10;
if(a==0)
{
P1=tab[ge];
P23=1;
delay();
P23=0;
}
if(a==1)
{
P1=tab[shi];
P22=1;
delay();
P22=0;
}
if(a==2)
{
P1=tab[bai];
P21=1;
delay();
P21=0;
}
}
}
两次按键电机反转
#include
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define CLK_WISE 0
#define INVERSE 1
sbit CTRL0=P2^0;
sbit CTRL1=P2^1;
uchar levelflag=0,i;
bit direction=CLK_WISE;
uchar highcount;
/****改变转向标志*****/
void int1_srv (void) interrupt 2 using 2 {
if(INT1==0)
{
i++;
if(i==2)
{
i=0;
while(!INT1);
direction=!direction;
}
}
}
/****延时****/
void delay(uchar i)
{
while(i--)
;
}
/*****改变转向*****/
void run(void)
{
if(direction==CLK_WISE) //顺时针转
{
CTRL1=0;
CTRL0=1;
}
if(direction==INVERSE) //逆时针转
{
CTRL0=0;
CTRL1=1;
}
}
void main()
{
EA=1;
EX1=1;
IT1=1;//外部中断1
while(1)
{
run();
}
}
六秒反转
#include
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
#define CLK_WISE 0
#define INVERSE 1
sbit CTRL0=P2^0;
sbit CTRL1=P2^1;
uchar levelflag=0;
bit direction=CLK_WISE;
uchar i;
/***定时器t0***/
void time0(void) interrupt 1 using 1 {
TH0=0x3c;
TL0=0xB0;
i++;
if(i==120)
{
i=0;
direction=!direction;
}
}
/****延时****/
void delay(uchar i)
{
while(i--)
;
}
/*****改变转向*****/
void run(void)
{
if(direction==CLK_WISE) //顺时针转
{
CTRL1=0;
CTRL0=1;
}
if(direction==INVERSE) //逆时针转
{
CTRL0=0;
CTRL1=1;
}
}
void main()
{
EA=1;
TMOD=0x01;
ET0=1;//定时器0初始化
TR0=1;
TH0=0x3c;
TL0=0xB0;
while(1)
{
run();
}
}
键盘led
#include
extern void Timer0_Init(void);
extern void Delay(unsigned int n);
extern void Scan_Key(void);
unsigned char ptr,m;
sbit P20=P2^0;
sbit P21=P2^1;
sbit P22=P2^2;
sbit P23=P2^3;
void main(void)
{
while(1)
{
Scan_Key(); //扫描键盘
}
}
void Delay(unsigned int n) //延时
{
unsigned int i,j;
for(i=0;i { for(j=0;j<80;j++); } } void Scan_Key(void) // 键盘扫描程序{ char a1,i; bit FLAG0=0; a1=0xfd; //列扫描初值ptr=0; for(i=0;i<2;i++) //键盘4个扫描列 { P1=a1; Delay(10); m=P1; switch(m&0xd0) //取行的高4位,侦测哪一行有按键被按下 { case 0x50: ptr=i*2; if(ptr==0) P20=!P20; else P22=!P22; break; case 0x90: ptr=i*2+1; if(ptr==1) P21=!P21; else P23=!P23; break; } a1=a1>>1 | 0x80; //高位补1,由于P1.4~P1.7未接+5V, //通过指令加载高电平 } } 学号单位显示 #include #define uint unsigned int #define uchar unsigned char sbit P20=P2^0; uchar count; uchar GE,SHI,BAI; uint XUEHAO=425; const uchar tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,}; /*显示0~9*/ void delay() { uint i,j; for(i=0;i<256;i++); for(j=0;j<256;j++); } void int0() interrupt 0 using 1 { count++; if (count==3) count=0; } void main(void) { IT0=1; EX0=1; EA=1; while(1) { GE=XUEHAO%10; SHI=XUEHAO/10%10; BAI=XUEHAO/100; if(count==0) { P1=tab[BAI]; P20=1; delay(); P20=0; } if(count==1) { P1=tab[SHI]; P20=1; delay(); P20=0; } if(count==2) { P1=tab[GE]; P20=1; delay(); P20=0; } } } 自加循环 #include #define unit unsigned int #define uchar unsigned char sbit P20=P2^0; sbit P21=P2^1; sbit P22=P2^2; sbit P23=P2^3; unit count=425,i,j; unit ge,shi,bai,qian,wan ; const uchar tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,}; void delay() { for(i=0;i<256;i++); } void time0(void) interrupt 1 using 1 { TH0=0x3c; TL0=0xb0; j++; if(j==10) { j=0; count++; } if(count==9999) { count=425; } } void main(void) { count=425; TMOD=0x01; TH0=0x3c; TL0=0xb0; EA=1; ET0=1; TR0=1; while(1) { ge=count%10; shi=count/10%10; bai=count/100%10; qian=count/1000; P1=tab[ge]; P23=1; delay(); P23=0; P1=tab[shi]; P22=1; delay(); P22=0; P1=tab[bai]; P21=1; delay(); P21=0; P1=tab[qian]; P20=1; delay(); P20=0; } } 串口 程序一#include //初始化串行口void csh() { SM0=0; SM1=1; REN=1; TI=0; RI=0; PCON=0; TH1=0xF3; TL1=0XF3; TMOD=0X20; EA=1; ET1=0; ES=1; TR1=1; } void main() { int i,j; char c=0; csh(); while(1) { ES=0; TI=0; P0=c; SBUF=c; while(!TI); TI=0; ES=1; for(j=0;j<50;j++) for(i=0;i<5000;i++); c++; if (c>9) c=0; } } void intrr() interrupt 4 { char temp; temp=SBUF; P2=temp; RI=0; } 程序二 #include //初始化串行口 void csh() { SM0=0; SM1=1; REN=1; TI=0; RI=0; PCON=0; TH1=0xF3; TL1=0XF3; TMOD=0X20; EA=1; ET1=0; ES=1; TR1=1; } void main() { csh(); while(1) {;} } void intrr() interrupt 4 { char temp; temp=SBUF; P2=temp; RI=0; temp++; if (temp>9) temp=0; ES=0; TI=0; P0=temp; SBUF=temp; while(!TI); TI=0; ES=1; } 简单电机 #include #include #define unit unsigned int #define uchar unsigned char #define AD XBYTE [0x7FF8] #define CLK_WISE 0 //顺时针方向转动 #define INVERSE 1 //逆时针方向转动 #define HIGH 2 //高电平 #define LOW 1 //低电平 #define NULL 0 //低电平 sbit CTRL0=P3^0; //CTRL0为高电平,CTRL1为低电平时顺时针方向转动 sbit CTRL1=P3^1; //CTRL0为低电平,CTRL1为高电平时逆时针方向转动uchar levelflag=0; //高低电平标志,取值为HIGH或LOW,分别代表高电平和低电平,或为NULL bit direction=CLK_WISE; /***方向标志,取值为CLK_WISE 或INVERSE*/ int i; sbit ad_busy=P3^2; //P3.2用于检测EOC信号,判断是否转换结束 static uchar speedcount=0; //加速标志,越大转速越快,最大到10,然后回归到0,循环。 //程序中可以依据它来改变占空比 uchar highcount=0; //记录高电平定时次数 unsigned char ad_data; /***定时器t0***/ void time0(void) interrupt 1 using 1 { TH0=0xff; TL0=0xCE; highcount++; //记录一出次数 //频率为固定的2kHZ左右,只是占空比发生变化if(highcount<=ad_data) levelflag=HIGH; //高电平次数 if((highcount>ad_data)&&(highcount<=255)) levelflag=LOW; //低电平次数 if(highcount==255) //最大为10,然后从0开始循环。 highcount=0; } /****改变转向标志*****/ void int1_srv (void) interrupt 2 using 2 { if(INT1==0) { while(!INT1); direction=!direction; } } /*****改变转向*****/ void run(void) { if(direction==CLK_WISE) //顺时针转 { CTRL1=1; if(levelflag==HIGH) //高电平 { levelflag=NULL; CTRL0=0; } if(levelflag==LOW) //低电平 { levelflag=NULL; CTRL0=1; } } if(direction==INVERSE) //逆时针转 { CTRL0=1; if(levelflag==HIGH) //高电平 { levelflag=NULL; CTRL1=0; } if(levelflag==LOW) //低电平 { levelflag=NULL; CTRL1=1; } } } void delay(unsigned int i) { while( i ) { i--; } } void ad0808(void) interrupt 0 //中断0响应函数 { EA=0; EX0=0; ad_data=AD; //将AD转换数据送给变量ad_data EA=1; EX0=1; } void main(void) { EA=1; //中断总允许 EX0=1; //打开外部中断0 PT0=1; PX1=1; TMOD=0x01; ET0=1; //定时器0初始化TR0=1; TH0=0xff; TL0=0xCE; //定时器0初始值 //外部中断1 EX1=1; IT1=1; highcount=0; ad_data=0; ad_busy=0; while(1) { P2=0xff; delay(40); run(); AD=0; } }