?1.设有一组数据{72,27,18,29,26,63,112,98,12,6},被定义在内部数据存储器中,用C51编程,将其拷贝到外部数据存储器中,并分别找出最大数与最小数存入外部数据存储器的max和min单元。
?#include
?#include
?#define max XBYTE [0x1000]
?#define min XBYTE [0x1001]
?unsigned char tab[]={72,27,18,29,26,63,112,98,12,6};
?void main()
?{unsigned int i,add=0x40;
?for(i=0;i<10;i++)
?{XBYTE[add+i]=tab[i];
?}
?max=XBYTE[add];
?min=XBYTE[add];
?for(i=0;i<10;i++)
?{if(XBYTE[add+i]>max)
?{max=XBYTE[add+i];}
?if(XBYTE[add+i] ?{min=XBYTE[add+i];} ?} ?while(1); ?} ? 2. 设有一组数据{0x21,0x34,0x91,0x01,0x65,0x87,0x98,0x31,0x63,0x90},被定义在内部数据存储器中,用C51编程,将其拷贝到外部数据存储器中,并求其累加和从P1口输出。 ?#include ?#include ?unsigned char tab[]={0x21,0x34,0x91,0x01,0x65,0x87,0x98,0x31,0x63,0x90}; ?void main() ?{unsigned int i,add0=0x40; ?unsigned char addx=0; ?for(i=0;i<10;i++) ?{XBYTE[add0+i]=tab[i]; ?addx+= tab[i]; ?} ?P1=addx; ?while(1) ; ? ?} 3.设有一组数据{0x6a,0x12,0x4d,0x51,0xc9},被定义在内部数据存储器中,用C51编程,分别将其转换成ASCII并存储到外部数据存储器0050H开始的单元中。 ?#include ?#include ?#define dy 0x50 ?unsigned char a[]={0x6a,0x12,0x4d,0x51,0xc9}; ?void main() ?{unsigned char i,j; ?for(j=0;j<5;j++) ?{ ?i=a[j]/16; ?if(i<10) ?{XBYTE[dy+2*j]=0x30+i;} ?else {XBYTE[dy+2*j]=0x37+i;} ?i=a[j]%16; ?if(i<10) ?{XBYTE[dy+2*j+1]=0x30+i;} ?else {XBYTE[dy+2*j+1]=0x37+i;} ?} ?while(1); ?} 4.设有一组数据{12,34,76,54,23,87,14,62,19,6},被定义在内部数据存储器中,用C51编程,先将其拷贝到内部数据存储器30H开始单元中,然后将其从小到大排序。 ?#include ?#include ?unsigned char tab[]={12,34,76,54,23,87,14,62,19,6}; ?void main() ?{unsigned int i,j,a; ?unsigned char *add0 ; ?add0=0x30; ?for(i=0;i<10;i++) ?{*(add0+i)=tab[i];} ?for(i=0;i<10;i++) ?{for(j=i+1;j<10;j++) ?{if(*(add0+i)>*(add0+j)) ?{a=*(add0+j); ?*(add0+j)=*(add0+i); ?*(add0+i)=a;} ?} ?} ?while(1) ; ? ?} 5:外部中断0引脚(P3.2)接一个开关,P1.0接一个发光二极管。开关闭合一次,发光二极管改变一次状态。 本例解决外部中断如何应用。 #include “reg51.h” #include “intrins.h” sbit p10=P1^0; void delay(void) { int a=5000; while(a--)_nop_(); } void int_srv(void)interrupt 0 using 1 { delay(); if(INT0==0) {P10= ~P10;while(INT0==0);} } void main() { P10=0; IT0=1 EA=1; EX0=1;while(1); } 6:从P1.0输出方波信号,周期为50ms。设单片机的focs=6MHz。 本例解决定时器及其中断的应用。 #include “reg51.h” void main() { TMOD=0x01; TH0=(65536-12500)/256; TL0=(65536-12500)%256; ET0=1; EA=1; TR0=1; while(1); } void T0_srv(void)interrupt 1 using 1 { TH0=(65536-12500)/256; TL0=(65536-12500)%256; P10=~P10; } 7.设晶振频率为6MHZ,要求在单片机的P2.7口上输出周期为1秒的连续方波信号,用定时器中断方式定时,请用C语言编程实现该功能。 ?#include ?sbit D1=P2^7; ?unsigned char Countor; ?void main(void) ?{ ?EA=1; ?ET0=1; ?TMOD=0X01; ?TH0=(65536-25000)/256; //定时50ms ?TL0=(65536-25000)%256; ?TR0=1; ?while(1); ?} ?void Time0(void) interrupt 1 using 0 ?{ ?Countor++; ?if(Countor==10) ?{ D1=~D1; ?Countor=0; ?} ?TH0=(65536-25000)/256; ?TL0=(65536-25000)%256; ?} 8:如图所示,单片机扩展可编程接口芯片8155,8155PA口控制8只发光二极管,形成走马灯,每位点亮的时间为0.5秒。单片机晶振为6 MHZ 8155的端口地址如下: 命令口地址(COM8155): FEF8H PA口地址(PA8155):FEF9H PB口地址(PB8155):FEFAH PC口地址(PC8155):FEFBH #include “reg51.h” #include “absacc.h” #define COM8155 XBYTE[0xfef8] #define PA8155 XBYTE[0xfef9] void delay(void)/*延时1ms*/ { TMOD=0X01 TH0=(65536-500)/256; TL0=(65536-500)%256; TR0=1; while(~TF0); TF0=0; TR0=0; } main() { unsigned int i; char disp_word=0x01;/*从第1位开始点亮*/ COM8155=0x01;/*初始化8155*/ do { PA8155= disp_word;/*输出去点亮一位*/ for(i=0;i<500;i++)/*点亮0.5秒*/ {delay();} disp_word= disp_word<<1;/*左移控制字,准备点亮下一位*/ if(disp_word==0)disp_word=0x01; } whlie(1); } 9:独立键盘,用C语言实现。 ?如图所示,P1.0~P1.3分别接开关S1~S4。S1按下时使外部20H单元内容加1;S2按下时使外部20H单元内容减1;S3按下时使外部20H单元内容清零;S4按下时使外部20H单元内容全1。用C51编程实现该功能,要求有10ms去抖动功能。系统晶振12MHZ #include “reg51.h” #include “absacc.h” void delay(void)/*延时1ms*/ { TMOD=0X01 TH0=(65536-1000)/256; TL0=(65536-1000)%256; TR0=1; while(!TF0); TF0=0; TR0=0; } main() { char x,i; P1=0xff; loop:x=P1; x=x&0x0f; if(x==0f)goto loop; for(i=0;i<10;i++)/*延时10ms去抖动*/ {delay();} x=P1; x=x&0x0f; if(x==0f)goto loop; switch(x) { case 0x0E:PBYTE[0x20]= PBYTE[0x20]+1;break;/*20单元加1*/ case 0x0D:PBYTE[0x20]= PBYTE[0x20]-1;break;/*20单元减1*/ case 0x0B:PBYTE[0x20]= 0x00;break;/*20单元清0*/ case 0x07:PBYTE[0x20]= 0xff;/*20单元置全1*/ } goto loop; } ?10.设晶振频率为6MHZ,一个共阳数码管的各段接P2口,公共端接VCC。希望在数码管上显示0~9计数,一秒钟数字加1,一秒时间用定时器0定时实现,请用C 语言编程实现该功能。共阳数码管0~9的段码表为:0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90。 ?unsigned char code Tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90} ; ?void main() ?{ unsigned char i=0; ?unsigned char Countor; ?TMOD=0x01; ?TH0=(65536-25000)/256; ?TL0=(65536-25000)%256; //定时50ms,1s=20*50ms ?TR0=1; ?Countor=0; ?while(1) ?{ Countor++; ?while(TF0==0); ?TF0=0; ?if(Countor==20) ?{ P2=Tab[i]; ?i++; ?if(i>9) i=0; ?Countor=0; ?} ?} 11.动态共阴显示,用C语言实现。单片机晶振为6MHZ #include “reg51.h” #include “intrins.h” char code dispdata[ ]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};char dis_dat[4]; void delay(void)/*延时1ms*/ { TH0=(65536-500)/256; TL0=(65536-500)%256; TR0=1; while(!TF0); TF0=0; TR0=0; } void disp(char ch1)/*显示函数*/ { static char ch=0x01; P1=ch;/*送位码 P2=dispdata[dis_dat[ch1]]; ch=ch<<1; if(ch==0x10)ch=0x01; } main() { char ch1; TMOD=0x01; while(1) { for(ch1=0;ch1<4;ch1++)/*对四位LED扫描一遍*/ {disp(ch1); delay(); } delay(); delay(); } } ?12.设晶振频率为12MHZ,用定时器T1中断控制两个LED以不同周期闪烁,用C 语言编程实现该功能。 ?#include ?sbit D1=P2^0; //将D1位定义为P2.0引脚 ?sbit D2=P2^1; //将D2位定义为P2.1引脚 ?unsigned char Countor1; //设置全局变量,存储定时器T1中断次数 ?unsigned char Countor2; //设置全局变量,存储定时器T1中断次数 ?void main(void) ?{ ?EA=1; ?ET1=1 ?TMOD=0x10; ?TH1=(65536-50000)/256; //定时50ms ?TL1=(65536-50000)%256; ?TR1=1; ?Countor1=0; //从0开始累计中断次数 ?Countor2=0; //从0开始累计中断次数 ?while(1); ?} ?void Time1(void) interrupt 3 using 0 // ?{ ?Countor1++; //Countor1自加1 ?Countor2++; //Countor2自加1 ?if(Countor1==2) //若累计满2次,即计时满100ms ?{ ?D1=~D1; //按位取反操作,将P2.0引脚输出电平取反 ?. Countor1=0; ?} ?if(Countor2==8) //若累计满8次,即计时满400ms ?{ D2=~D2; //按位取反操作,将P2.1引脚输出电平取反 Countor2=0; ?} ?TH1=(65536-50000)/256; ?TL1=(65536-50000)%256; ?} ?13.设LED指示灯为低电平点亮,P1口输出控制8只LED跑马灯,用C语言编程实现。 ?#include ?void delay(void) ?{ ?unsigned char i,j; ?for(i=0;i<250;i++) ?for(j=0;j<250;j++) ?; ?} ?void main(void) ?{ ?while(1) ?{ p1=0xfe; ?delay(); ?p1=0xfd; ?delay(); ?p1=0xfb; ?delay(); ?p1=0xf7; ?delay(); ?p1=0xef; ?delay(); ?p1=0xdf; ?delay(); ?p1=0xbf; ?delay(); ?p1=0x7f; ?delay(); } 14.如图所示,对8个通道轮流采集一次,采集的结果放在数组ad中。 #include “reg51.h” #include “absacc.h” sbit ad_busy=P3^2; main() { static char idata ad[8]; char i; char pdata *ad_chl; ad_chl=0x78;/*设置初始通道地址*/ for(i=0;i<8;i++) { *ad_chl=0;/*启动A/D转换*/ i=i;/*等待EOC信号变低*/ i=i; while(ad_busy==1); /*查询*/ ad[i]=*ad_chl;/*存放结果*/ ad_chl++ ; } while(1); } 15:如图所示,要求DAC0832输出锯齿波电压信号,信号周期自由,用C语言写出相应程序。 #include “reg51.h” #include “absacc.h” #define DA0832 PBYTE[0x7f] void delay(void) { unsigned char i,j; for(i=0;i<250;i++) for(j=0;j<250;j++) } main() { char i; do { for(i=0;i<255;i++) {DAC0832=i;delay(); } } while(1); } 16:编写一个计数器程序,将T0作为计数器来使用,对外部信号计数,将计数字显示在数码管上。 ?#include "reg51.h" ?#define uchar unsigned char ?#define uint unsigned int ?uchar code BitTab[]={0x7F,0xBF,0xDF,0xEF,0xF7,0xFB};//位驱动码 ?uchar code DispTab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0 xA1,0x86,0x8E,0xFF};//字形码 ?uchar DispBuf[6]; //显示缓冲区 ?void Timer1() interrupt 3 ?{ uchar tmp; ?Static uchar Count; //计数器,显示程序通过它得知现正显示哪个数码管 ?TH1=(65536-3000)/256; ?TL1=(65536-3000)%256; //重置初值 ?tmp=BitTab[Count]; //取位值 ?P2=P2|0xfc; //P2与11111100B相或 ?P2=P2&tmp; //P2与取出的位值相与 ?tmp=DispBuf[Count];//取出待显示的数 ?tmp=DispTab[tmp]; //取字形码 ?P0=tmp; ?Count++; ?if(Count==6) ?Count=0; ?} ?void main() ?{ uint tmp; ?P1=0xff; ?P0=0xff; ?TMOD=0x15; //定时器0工作于计数方式1,定时器1工作于定时方式1 ?TH1=(65536-3000)/256; ?TL1=(65536-3000)%256; //定时时间为3000个周期 ?TR0=1; //计数器0开始运行 ?TR1=1; ?EA=1; ?ET1=1; ?for(;;) ?{ tmp=TL0|(TH0<<8);//tmp=TH0*256+TL0取T0中的数值 ?DispBuf[5]=tmp%10; ?tmp/=10; ?DispBuf[4]=tmp%10; ?tmp/=10; ?DispBuf[3]=tmp%10; ?tmp/=10; ?DispBuf[2]=tmp%10; ?DispBuf[1]=tmp/10; ?DispBuf[0]=0; ?}} 17:矩阵键盘扫描。p3.7~p3.4是行线,用于输出。P3.3~P3.0是列线,用于输入。 ?#include "at89x52.h" ?typedef unsigned char uchar; ?typedef unsigned int uint; ?void mDelay(uint j) ?{ uint i; ?for(;j>0;j--) ?for(i=0;i<125;i++); ?} ?uchar GetKey() ?{ uchar KeyValue,tmp; ?uchar i; ?P3=0x0f; //用于输入的P3口的I/O线置高,用于输出的I/O口线全部为低 ?KeyValue=P3; //获得P3口的值 ?KeyValue|=0xf0; //低4位置高 ?if(KeyValue==0xff) ?return 0; //无键按下 ?else ?mDelay(10); //否则延时10ms去键抖动 ?P3=0x0f; //用于输入的P3口的I/O线置高,用于输出的I/O口线全部为低 ?KeyValue=P3; //获得P3口的值 ?KeyValue|=0xf0; //低4位置高 ?if(KeyValue==0xff) ?return 0; else ?{ for(i=0;i<4;i++) ?{ P3=0xff; //P3口全部置高 ?P3&=~(0x80>>i); ?/*0x80就是10000000B,当i=0时,0x80>>i即为该数本身,~为取反,即P3和01111111B相与 ?如果i=1,那么0x80>>i的结果是01000000,取反后是10111111,即P3和该数相与 ?KeyValue=P3; //取键值 ?KeyValue|=0xf0; ?if(KeyValue!=0xff) ?break; ?} ?KeyValue&=~(0x10< ?for(;;) //以下等待键释放 ?{ P3=0x0f; ?tmp=P3; ?tmp|=0xf0; ?if(tmp==0xff) ?break; } ?return KeyValue; ?} ?} ?void main() ?{ ?uchar KeyValue; ?for(;;) ?KeyValue=GetKey(); ?} ?以下是按下各键后返回的键值:? ?E7,EB,ED,EE ?D7,DB,DD,DE ?B7,BB,BD,BE ?77,7B,7D,7E