文档库 最新最全的文档下载
当前位置:文档库 › 《单片机C语言程序设计实训100例—基于8051+Proteus仿真》案例

《单片机C语言程序设计实训100例—基于8051+Proteus仿真》案例

《单片机C语言程序设计实训100例—基于8051+Proteus仿真》案例
《单片机C语言程序设计实训100例—基于8051+Proteus仿真》案例

第01 篇基础程序设计01 闪烁的LED

/* 名称:闪烁的LED

说明:LED按设定的时间间隔闪烁

*/

#include

#define uchar unsigned char

#define uint unsigned int

sbit LED=P1^0;

//延时

void DelayMS(uint x)

{

uchar i;

while(x--)

{

for(i=0;i<120;i++);

}

}

//主程序

void main()

{

while(1)

{

LED=~LED;

DelayMS(150);

}

}

02 从左到右的流水灯

/* 名称:从左到右的流水灯

说明:接在P0口的8个LED

从左到右循环依次点亮,产生走

马灯效果

*/

#include

#include

#define uchar unsigned char

#define uint unsigned int

//延时

void DelayMS(uint x)

{

while(x--)

{

for(i=0;i<120;i++);

}

}

//主程序

void main()

{

P0=0xfe;

while(1)

{

P0=_crol_(P0,1); //P0的值向左循环移动

DelayMS(150);

}

}

03 8只LED左右来回点亮

/* 名称:8只LED左右来回点亮

说明:程序利用循环移位函数_crol_和_cror_形成来回滚动的效果*/

#include

#include

#define uchar unsigned char

#define uint unsigned int

//延时

void DelayMS(uint x)

{

uchar i;

while(x--)

{

for(i=0;i<120;i++);

}

}

//主程序

void main()

{

uchar i;

P2=0x01;

while(1)

{

for(i=0;i<7;i++)

{

P2=_crol_(P2,1); //P2的值向左循环移动

for(i=0;i<7;i++)

{

P2=_cror_(P2,1); //P2的值向右循环移动

DelayMS(150);

}

}

}

04 花样流水灯

/* 名称:花样流水灯

说明:16只LED分两组

按预设的多种花样变换显示

*/

#include

#define uchar unsigned char

#define uint unsigned int

uchar code Pattern_P0[]=

{

0xfc,0xf9,0xf3,0xe7,0xcf,0x9f,0x3f,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,

0xe7,0xdb,0xbd,0x7e,0xbd,0xdb,0xe7,0xff,0xe7,0xc3,0x81,0x00,0x81,0xc3,0xe7,0xff, 0xaa,0x55,0x18,0xff,0xf0,0x0f,0x00,0xff,0xf8,0xf1,0xe3,0xc7,0x8f,0x1f,0x3f,0x7f,

0x7f,0x3f,0x1f,0x8f,0xc7,0xe3,0xf1,0xf8,0xff,0x00,0x00,0xff,0xff,0x0f,0xf0,0xff,

0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,

0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe,

0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe, 0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff

};

uchar code Pattern_P2[]=

{

0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfc,0xf9,0xf3,0xe7,0xcf,0x9f,0x3f,0xff,

0xe7,0xdb,0xbd,0x7e,0xbd,0xdb,0xe7,0xff,0xe7,0xc3,0x81,0x00,0x81,0xc3,0xe7,0xff, 0xaa,0x55,0x18,0xff,0xf0,0x0f,0x00,0xff,0xf8,0xf1,0xe3,0xc7,0x8f,0x1f,0x3f,0x7f,

0x7f,0x3f,0x1f,0x8f,0xc7,0xe3,0xf1,0xf8,0xff,0x00,0x00,0xff,0xff,0x0f,0xf0,0xff,

0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f,

0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,

0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfc,0xf8,0xf0,0xe0,0xc0,0x80,0x00,

0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,

0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff

};

//延时

void DelayMS(uint x)

while(x--)

{

for(i=0;i<120;i++);

}

}

//主程序

void main()

{

uchar i;

while(1)

{ //从数组中读取数据送至P0和P2口显示

for(i=0;i<136;i++)

{

P0=Pattern_P0[i];

P2=Pattern_P2[i];

DelayMS(100);

}

}

}

05 LED模拟交通灯

/* 名称:LED模拟交通灯

说明:东西向绿灯亮若干秒,黄

灯闪烁5次后红灯亮,红灯亮后,南

北向由红灯变为绿灯,若干秒后南北

向黄灯闪烁5此后变红灯,东西向变

绿灯,如此重复。

*/

#include

#define uchar unsigned char

#define uint unsigned int

sbit RED_A=P0^0; //东西向灯

sbit YELLOW_A=P0^1;

sbit GREEN_A=P0^2;

sbit RED_B=P0^3; //南北向灯

sbit YELLOW_B=P0^4;

sbit GREEN_B=P0^5;

uchar Flash_Count=0,Operation_Type=1; //闪烁次数,操作类型变量//延时

void DelayMS(uint x)

{

uchar i;

while(x--) for(i=0;i<120;i++);

void Traffic_Light()

{

switch(Operation_Type)

{

case 1: //东西向绿灯与南北向红灯亮

RED_A=1;YELLOW_A=1;GREEN_A=0;

RED_B=0;YELLOW_B=1;GREEN_B=1;

DelayMS(2000);

Operation_Type=2;

break;

case 2: //东西向黄灯闪烁,绿灯关闭

DelayMS(300);

YELLOW_A=~YELLOW_A;GREEN_A=1;

if(++Flash_Count!=10) return; //闪烁5次

Flash_Count=0;

Operation_Type=3;

break;

case 3: //东西向红灯,南北向绿灯亮

RED_A=0;YELLOW_A=1;GREEN_A=1;

RED_B=1;YELLOW_B=1;GREEN_B=0;

DelayMS(2000);

Operation_Type=4;

break;

case 4: //南北向黄灯闪烁5次

DelayMS(300);

YELLOW_B=~YELLOW_B;GREEN_B=1;

if(++Flash_Count!=10) return;

Flash_Count=0;

Operation_Type=1;

}

}

//主程序

void main()

{

while(1) Traffic_Light();

}

06 单只数码管循环显示0~9

/* 名称:单只数码管循环显示0~9

说明:主程序中的循环语句反复将0~9的段码送至P0口,使数字0~9循环显示*/

#include

#include

#define uint unsigned int

uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; //延时

void DelayMS(uint x)

{

uchar t;

while(x--) for(t=0;t<120;t++);

}

//主程序

void main()

{

uchar i=0;

P0=0x00;

while(1)

{ /*

for(;i<11;i++){ P0=~DSY_CODE[i];

DelayMS(300);} //注:另一方案*/

P0=~DSY_CODE[i];

i=(i+1)%10;

DelayMS(300);

}

}

07 8只数码管滚动显示单个数字

/* 名称:8只数码管滚动显示单个数字

说明:数码管从左到右依次滚动显示

0~7,程序通过每次仅循环选通一只数码

*/

#include

#include

#define uchar unsigned char

#define uint unsigned int

uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

//延时

void DelayMS(uint x)

{

uchar t;

while(x--) for(t=0;t<120;t++);

}

//主程序

void main()

{

uchar i,wei=0x80;

{

for(i=0;i<8;i++)

{

P2=0xff; //关闭显示

wei=_crol_(wei,1);

P0=DSY_CODE[i]; //发送数字段码

P2=wei; //发送位码

DelayMS(300);

}

}

}

08 8只数码管动态显示多个不同字符

电路如上图

/* 名称:8只数码管动态显示多个不同字符

说明:数码管动态扫描显示0~7。

*/

#include

#include

#define uchar unsigned char

#define uint unsigned int

uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //延时

void DelayMS(uint x)

{

uchar t;

while(x--) for(t=0;t<120;t++);

}

//主程序

void main()

{

uchar i,wei=0x80;

while(1)

{

for(i=0;i<8;i++)

{

P2=0xff;

P0=DSY_CODE[i]; //发送段码

wei=_crol_(wei,1);

P2=wei; //发送位码

DelayMS(2);

}

}

}

电路如上图

/* 名称:8只数码管闪烁显示数字串

说明:数码管闪烁显示由0~7构成的一串数字

本例用动态刷新法显示一串数字,在停止刷新时所有数字显示消失。*/

#include

#define uchar unsigned char

#define uint unsigned int

//段码表

uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};

//位码表

uchar code DSY_IDX[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

//延时

void DelayMS(uint x)

{

uchar t;

while(x--) for(t=0;t<120;t++);

}

//主程序

void main()

{

uchar i,j;

while(1)

{

for(i=0;i<30;i++)

{

for(j=0;j<8;j++)

{

P0=0xff;

P0=DSY_CODE[j]; //发送段码

P2=DSY_IDX[j]; //发送位码

DelayMS(2);

}

}

P2=0x00; //关闭所有数码管并延时

DelayMS(1000);

}

}

10 8只数码管滚动显示数字串

电路如上图

/* 名称:8只数码管滚动显示数字串

说明:数码管向左滚动显示3个字符构成的数字串

*/

#include

#define uchar unsigned char

#define uint unsigned int

//段码表

uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; //下面数组看作环形队列,显示从某个数开始的8个数(10表示黑屏)

uchar Num[]={10,10,10,10,10,10,10,10,2,9,8};

//延时

void DelayMS(uint x)

{

uchar t;

while(x--) for(t=0;t<120;t++);

}

//主程序

void main()

{

uchar i,j,k=0,m=0x80;

while(1)

{ //刷新若干次,保持一段时间的稳定显示

for(i=0;i<15;i++)

{

for(j=0;j<8;j++)

{ //发送段码,采用环形取法,从第k个开始取第j个

P0=0xff;

P0=DSY_CODE[Num[(k+j)%11]];

m=_crol_(m,1);

P2=m; //发送位码

DelayMS(2);

}

}

k=(k+1)%11; //环形队列首支针k递增,Num下标围0~10,故对11取余}

}

11 K1-K4 控制LED移位

/* 名称:K1-K4 控制LED移位

说明:按下K1时,P0

口LED上移一位;

按下K2时,P0

口LED下移一位;

按下K3时,P2

口LED上移一位;

按下K4时,P2

口LED下移一位;

*/

#define uint unsigned int

//延时

void DelayMS(uint x)

{

uchar i;

while(x--) for(i=0;i<120;i++);

}

//根据P1口的按键移动LED

void Move_LED()

{

if ((P1&0x10)==0) P0=_cror_(P0,1); //K1 else if((P1&0x20)==0) P0=_crol_(P0,1); //K2 else if((P1&0x40)==0) P2=_cror_(P2,1); //K3

else if((P1&0x80)==0) P2=_crol_(P2,1); //K4 }

//主程序

void main()

{

uchar Recent_Key; //最近按键

P0=0xfe;

P2=0xfe;

P1=0xff;

Recent_Key=0xff;

while(1)

{

if(Recent_Key!=P1)

{

Recent_Key=P1; //保存最近按键

Move_LED();

DelayMS(10);

}

}

}

12 K1-K4 按键状态显示

/* 名称:K1-K4 按键状态

显示

说明:K1、K2按下时LED

点亮,松开时熄灭,

K3、K4按下并释

放时LED点亮,再次按下并

释放时熄灭;

#define uint unsigned int

sbit LED1=P0^0;

sbit LED2=P0^1;

sbit LED3=P0^2;

sbit LED4=P0^3;

sbit K1=P1^0;

sbit K2=P1^1;

sbit K3=P1^2;

sbit K4=P1^3;

//延时

void DelayMS(uint x)

{

uchar i;

while(x--) for(i=0;i<120;i++);

}

//主程序

void main()

{

P0=0xff;

P1=0xff;

while(1)

{

LED1=K1;

LED2=K2;

if(K3==0)

{

while(K3==0);

LED3=~LED3;

}

if(K4==0)

{

while(K4==0);

LED4=~LED4;

}

DelayMS(10);

}

}

13 K1-K4 分组控制LED

/* 名称:K1-K4 分组控制LED

说明:每次按下K1时递增点亮一只LED,全亮时再次按下则再次循环开始,

K2按下后点亮上面4只LED,K3按下后点亮下面4只LED,K4按下后关闭所有LED

*/

#include

#define uchar unsigned char

#define uint unsigned int

//延时

void DelayMS(uint x)

{

uchar i;

while(x--)

for(i=0;i<120;i++);

}

//主程序

void main()

{

uchar k,t,Key_State;

P0=0xff;

P1=0xff;

while(1)

{

t=P1;

if(t!=0xff)

{

DelayMS(10);

if(t!=P1) continue;

//取得4位按键值,由模式XXXX1111(X中有一位为0,其他均为1)

//变为模式0000XXXX(X中有一位为1,其他均为0)

Key_State=~t>>4;

k=0;

//检查1所在位置,累加获取按键号k

while(Key_State!=0)

{

k++;

Key_State>>=1;

}

//根据按键号k进行4种处理

switch(k)

{

case 1: if(P0==0x00) P0=0xff;

P0<<=1;

DelayMS(200);

break;

case 2: P0=0xf0;break;

case 3: P0=0x0f;break;

case 4: P0=0xff;

}

}

}

14 K1-K4 控制数码管移位显示

/* 名称:K1-K4 控制数码管移位显示

说明:按下K1时加1计数并增加显示位,

按下K2时减1计数并减少显示位,

按下K3时清零。

*/

#include

#define uchar unsigned char

#define uint unsigned int

//段码

uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; //位码

uchar code DSY_Index[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};

//待显示到各数码管的数字缓冲(开始仅在0位显示0,其他黑屏)

uchar Display_Buffer[]={0,10,10,10,10,10,10,10};

//延时

void DelayMS(uint x)

{

uchar i;

while(x--) for(i=0;i<120;i++);

}

void Show_Count_ON_DSY()

{

uchar i;

for(i=0;i<8;i++)

{

P0=0xff;

P0=DSY_CODE[Display_Buffer[i]];

P2=DSY_Index[i];

DelayMS(2);

}

}

//主程序

void main()

{

uchar i,Key_NO,Key_Counts=0;

P0=0xff;

P1=0xff;

P2=0x00;

while(1)

Show_Count_ON_DSY();

P1=0xff;

Key_NO=P1;

//P1口按键状态分别为K1-0xfe,K2-0xfd,K3-0xfb

switch(Key_NO)

{

case 0xfe: Key_Counts++;

if(Key_Counts>8) Key_Counts=8;

Display_Buffer[Key_Counts-1]=Key_Counts;

break;

case 0xfd: if(Key_Counts>0)Display_Buffer[--Key_Counts]=10;

break;

case 0xfb: Display_Buffer[0]=0;

for(i=1;i<8;i++) Display_Buffer[i]=10;

Key_Counts=0;

}

//若键未释放则仅刷新显示,不进行键扫描

while(P1!=0xff) Show_Count_ON_DSY();

}

}

15 K1-K4 控制数码管加减演示

/* 名称:K1-K4 控制数码管加减演示

说明:按下K1后加1计数,按下K2

后减1计数,按下K3后清零。

*/

#include

#include

#define uchar unsigned char

#define uint unsigned int

//段码

uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff}; //待显示的3位缓冲

uchar Num_Buffer[]={0,0,0};

//按键代码,按键计数

uchar Key_Code,Key_Counts=0;

//延时

void DelayMS(uint x)

{

uchar i;

while(x--) for(i=0;i<120;i++);

}

//显示函数

void Show_Counts_ON_DSY()

uchar i,j=0x01;

Num_Buffer[2]=Key_Counts/100;

Num_Buffer[1]=Key_Counts/10%10;

Num_Buffer[0]=Key_Counts%10;

for(i=0;i<3;i++)

{

j=_cror_(j,1);

P0=0xff;

P0=DSY_CODE[Num_Buffer[i]];

P2=j;

DelayMS(1);

}

}

//主程序

void main()

{

uchar i;

P0=0xff;

P1=0xff;

P2=0x00;

Key_Code=0xff;

while(1)

{

Show_Counts_ON_DSY();

P1=0xff;

Key_Code=P1;

//有键按下时,数码管刷新显示30次,该行代码同时起到延时作用

if(Key_Code!=0xff)

for(i=0;i<30;i++) Show_Counts_ON_DSY();

switch(Key_Code)

{

case 0xfe: if(Key_Counts<255) Key_Counts++;

break;

case 0xfd: if(Key_Counts>0) Key_Counts--;

break;

case 0xfb: Key_Counts=0;

}

Key_Code=0xff;

}

}

16 4X4矩阵键盘控制条

形LED显示

/* 名称:4X4矩阵键盘控

说明:运行本例时,按下的按键值越大点亮的LED越多。

*/

#include

#include

#define uchar unsigned char

#define uint unsigned int

//矩阵键盘按键特征码表

uchar code KeyCodeTable[]={0x11,0x12,0x14,0x18,0x21,

0x22,0x24,0x28,0x41,0x42,0x44,0x48,0x81,0x82,0x84,0x88};

//延时

void DelayMS(uint x)

{

uchar i;

while(x--) for(i=0;i<120;i++);

}

//键盘扫描

uchar Keys_Scan()

{

uchar sCode,kCode,i,k;

//低4位置0,放入4行

P1=0xf0;

//若高4位出现0,则有键按下

if((P1&0xf0)!=0xf0)

{

DelayMS(2);

if((P1&0xf0)!=0xf0)

{

sCode=0xfe; //行扫描码初值

for(k=0;k<4;k++) //对4行分别进行扫描

{

P1=sCode;

if((P1&0xf0)!=0xf0)

{

kCode=~P1;

for(i=0;i<16;i++) //查表得到按键序号并返回

if(kCode==KeyCodeTable[i])

return(i);

}

else

sCode=_crol_(sCode,1);

}

}

}

return(-1);

}

void main()

{

uchar i,P2_LED,P3_LED;

uchar KeyNo=-1; //按键序号,-1表示无按键

while(1)

{

KeyNo=Keys_Scan(); //扫描键盘获取按键序号KeyNo

if(KeyNo!=-1)

{

P2_LED=0xff;

P3_LED=0xff;

for(i=0;i<=KeyNo;i++) //键值越大,点亮的LED越多

{

if(i<8)

P3_LED>>=1;

else

P2_LED>>=1;

}

P3=P3_LED; //点亮条形LED

P2=P2_LED;

}

}

}

17 数码管显示4X4矩阵键盘按

键号

/* 名称:数码管显示4X4矩阵

键盘按键号

说明:按下任意键时,数码

管都会显示其键的序号,扫描程

序首先判断按键发生在哪一列,

然后根据所发生的行附加不同的

值,从而得到按键的序号。

*/

#include

#define uchar unsigned char

#define uint unsigned int

//段码

uchar code DSY_CODE[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,

0x88,0x83,0xc6,0xa1,0x86,0x8e,0x00};

sbit BEEP=P3^7;

//上次按键和当前按键的序号,该矩阵中序号围0~15,16表示无按键uchar Pre_KeyNo=16,KeyNo=16;

//延时

{

uchar i;

while(x--) for(i=0;i<120;i++);

}

//矩阵键盘扫描

void Keys_Scan()

{

uchar Tmp;

P1=0x0f; //高4位置0,放入4行

DelayMS(1);

Tmp=P1^0x0f;//按键后0f变成0000XXXX,X中一个为0,3个仍为1,通过异或把3个1变为0,唯一的0变为1

switch(Tmp) //判断按键发生于0~3列的哪一列

{

case 1: KeyNo=0;break;

case 2: KeyNo=1;break;

case 4: KeyNo=2;break;

case 8: KeyNo=3;break;

default:KeyNo=16; //无键按下

}

P1=0xf0; //低4位置0,放入4列

DelayMS(1);

Tmp=P1>>4^0x0f;//按键后f0变成XXXX0000,X中有1个为0,三个仍为1;高4位转移到低4位并异或得到改变的值

switch(Tmp) //对0~3行分别附加起始值0,4,8,12

{

case 1: KeyNo+=0;break;

case 2: KeyNo+=4;break;

case 4: KeyNo+=8;break;

case 8: KeyNo+=12;

}

}

//蜂鸣器

void Beep()

{

uchar i;

for(i=0;i<100;i++)

{

DelayMS(1);

BEEP=~BEEP;

}

BEEP=0;

}

//主程序

void main()

P0=0x00;

BEEP=0;

while(1)

{

P1=0xf0;

if(P1!=0xf0) Keys_Scan(); //获取键序号

if(Pre_KeyNo!=KeyNo)

{

P0=~DSY_CODE[KeyNo];

Beep();

Pre_KeyNo=KeyNo;

}

DelayMS(100);

}

}

18 开关控制LED

/* 名称:开关控制LED

说明:开关S1和S2分别控

制LED1和LED2。

*/

#include

sbit S1=P1^0;

sbit S2=P1^1;

sbit LED1=P0^0;

sbit LED2=P0^1;

//主程序

void main()

{

while(1)

{

LED1=S1;

LED2=S2;

}

}

19 继电器控制照明设备

/* 名称:继电器控制照明设备

说明:按下K1灯点亮,再次

按下时灯熄灭

*/

#include

#define uchar unsigned char

sbit K1=P1^0;

sbit RELAY=P2^4;

//延时

void DelayMS(uint ms)

{

uchar t;

while(ms--)for(t=0;t<120;t++);

}

//主程序

void main()

{

P1=0xff;

RELAY=1;

while(1)

{

if(K1==0)

{

while(K1==0);

RELAY=~RELAY;

DelayMS(20);

}

}

}

20 数码管显示拨码开关编码

/* 名称:数码管显示拨码开关编码

说明:系统显示拨码开关所设置的编码000~255

*/

#include

#include

#define uchar unsigned char

#define uint unsigned int

//各数字的数码管段码(共阴)

uchar code DSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //显示缓冲

uchar DSY_Buffer[3]={0,0,0};

//延时

void DelayMS(uint ms)

{

uchar t;

while(ms--)for(t=0;t<120;t++);

}

//主程序

void main()

相关文档