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

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

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

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

第01 篇基础程序设计

01 闪烁的LED

/* 名称:闪烁的LED

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

*/

#include<>

#define uchar unsigned char

#define uint unsigned int

sbit LED=P1^0;

K2K2K2K209-12-25.\r\n");

Puts_to_SerialPort("-------------------------------\r\n");

DelayMS(50);

while(1)

{

Putc_to_SerialPort(c+'A');

DelayMS(100);

Putc_to_SerialPort(' ');

DelayMS(100);

if(c==25) With PCB

layout now offering

automation of both component

",

"can often be the most

time consuming element of the

exercise.",

"And if you use circuit

simulation to develop your

ideas, ",

"you are going to spend

even more time working on

the schematic."

};

//显示缓冲(2行)

uchar Disp_Buffer[32];

//垂直滚动显示

void V_Scroll_Display()

{

uchar i,j,k=0;

uchar *p=Msg[0];

uchar *q=Msg[Line_Count]+strlen(Msg[Line_Count]);

//以下仅使用显示缓冲的前16字节空间

while(p

{

for(i=0;i<16&&p

{ //消除显示缓冲中待显示行首尾可能出现的空格

if((i==0||i==15)&&*p==' ') p++;

if(*p!='\0')

{

Disp_Buffer[i]=*p++;

}

else

{

if(++k>Line_Count) break;

p=Msg[k]; //p指向下一串的首地址

Disp_Buffer[i]=*p++;

}

}

//不足16个字符时空格补充

for(j=i;j<16;j++) Disp_Buffer[j]=' ';

//垂直滚动显示

while(F0) DelayMS(5);

ShowString(0,0," ");

DelayMS(150);

while(F0) DelayMS(5);

ShowString(0,1,Disp_Buffer);

DelayMS(150);

while(F0) DelayMS(5);

ShowString(0,0,Disp_Buffer);

ShowString(0,1," ");

DelayMS(150);

}

//最后清屏

ShowString(0,0," ");

ShowString(0,1," ");

}

//水平滚动显示

void H_Scroll_Display()

{

uchar i,j,k=0,L=0;

uchar *p=Msg[0];

uchar *q=Msg[Line_Count]+strlen(Msg[Line_Count]);

//将32个字符的显示缓冲前16个字符设为空格

for(i=0;i<16;i++) Disp_Buffer[i]=' ';

while(p

{

//忽略缓冲中首尾可能出现的空格

if((i==16||i==31)&&*p==' ') p++;

for(i=16;i<32&&p

{

if(*p!='\0')

{

Disp_Buffer[i]=*p++;

}

else

{

if(++k>Line_Count) break;

p=Msg[k]; //p指向下一串的首地址

Disp_Buffer[i]=*p++;

}

}

//不足32个字符时空格补充

for(j=i;j<32;j++) Disp_Buffer[j]=' ';

//水平滚动显示

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

{

while(F0) DelayMS(5);

ShowString(0,L,Disp_Buffer+i);

while(F0) DelayMS(5);

DelayMS(20);

}

L=(L==0)?1:0; //行号在0,1间交替

DelayMS(300);

}

//如果显示结束时停留在第0行,则清除第1行的内容if(L==1) ShowString(0,1," ");

}

//外部中断0,由K3控制暂停与继续显示

void EX_INT0() interrupt 0

{

F0=!F0; //暂停与继续显示控制标志位

}

//主程序

void main()

{

uint Count=0;

IE=0x81; //允许外部中断0

IT0=1; //下降沿触发

F0=0; //暂停与继续显示控制标志位

Initialize_LCD();

ShowString(0,0,Prompt);

ShowString(0,1,Prompt+16);

while(1)

{

if(K1==0)

{

V_Scroll_Display();

DelayMS(300);

}

else

if(K2==0)

{

H_Scroll_Display();

DelayMS(300);

}

}

}

//

/* 名称:液晶控制与显示程序

说明:本程序是通用的1602液晶控制程序。

*/

#include<>

#include<>

#define uchar unsigned char

#define uint unsigned int

sbit RS=P2^0;

sbit RW=P2^1;

sbit EN=P2^2;

//延时

void DelayMS(uint ms)

{

uchar i;

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

}

//忙检查

uchar Busy_Check()

{

uchar LCD_Status;

RS=0; //寄存器选择

RW=1; //读状态寄存器

EN=1; //开始读

DelayMS(1);

LCD_Status=P0;

EN=0;

return LCD_Status;

}

//写LCD命令

void Write_LCD_Command(uchar cmd)

{

while((Busy_Check()&0x80)==0x80); //忙等待

RS=0; //选择命令寄存器

RW=0; //写

EN=0;

P0=cmd;EN=1;DelayMS(1);EN=0;

}

//发送数据

void Write_LCD_Data(uchar dat)

{

while((Busy_Check()&0x80)==0x80); //忙等待

RS=1;RW=0;EN=0;P0=dat;EN=1;DelayMS(1);EN=0;

}

//LCD初始化

void Initialize_LCD()

{

Write_LCD_Command(0x38);DelayMS(1);

Write_LCD_Command(0x01);DelayMS(1); //清屏

Write_LCD_Command(0x06);DelayMS(1); //字符进入模式:屏幕不动,字符后移Write_LCD_Command(0x0c);DelayMS(1); //显示开,光标关

}

//显示字符串

void ShowString(uchar x,uchar y,uchar *str)

{

uchar i=0;

if(y==0) Write_LCD_Command(0x80|x); //设置显示起始位置

if(y==1) Write_LCD_Command(0xc0|x);

for(i=0;i<16;i++) //输出字符串

{

Write_LCD_Data(str[i]);

}

}

13

19 用ADC0808控制PWM输出

/* 名称:用ADC0808控制PWM输出

说明:使用数模转换芯片ADC0808,通过调节可变电阻RV1来调节脉冲宽度,运行程序时,通过虚拟示波器观察占空比的变化。

*/

#include<>

#define uchar unsigned char

#define uint unsigned int

sbit CLK=P2^4; //时钟信号

sbit ST=P2^5; //启动信号

sbit EOC=P2^6; //转换结束信号

sbit OE=P2^7; //输出使能

sbit PWM=P3^0; //PWM输出

//延时

void DelayMS(uint ms)

{

uchar i;

while(ms--) for(i=0;i<40;i++);

}

//主程序

void main()

{

uchar Val;

TMOD=0x02; //T1工作模式2

TH0=0x14;

TL0=0x00;

IE=0x82;

TR0=1;

while(1)

{

ST=0;ST=1;ST=0; //启动A/D转换

while(!EOC); //等待转换完成

OE=1;

Val=P1; //读转换值

OE=0;

if(Val==0) //PWM输出(占空比为0%)

{

PWM=0;

DelayMS(0xff);

continue;

}

if(Val==0xff) //PWM输出(占空比为100%)

{

PWM=1;

DelayMS(0xff);

continue;

}

PWM=1; //PWM输出(占空比为0%~100%)

DelayMS(Val);

PWM=0;

DelayMS(0xff-Val);

}

}

//T0定时器中断给ADC0808提供时钟信号

void Timer0_INT() interrupt 1

{

CLK=~CLK;

}

20 ADC0809数模转换与显示

/* 名称:ADC0809数模转换与显示

说明:ADC0809采样通道3输入的

模拟量,转换后的结果显示在数码管上。

*/

#include<>

#define uchar unsigned char

#define uint unsigned int

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

uchar code DSY_CODE[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; sbit CLK=P1^3; //时钟信号

sbit ST=P1^2; //启动信号

sbit EOC=P1^1; //转换结束信号

sbit OE=P1^0; //输出使能

//延时

void DelayMS(uint ms)

{

uchar i;

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

}

//显示转换结果

void Display_Result(uchar d)

{

P2=0xf7; //第4个数码管显示个位数

P0=DSY_CODE[d%10];

DelayMS(5);

P2=0xfb; //第3个数码管显示十位数

P0=DSY_CODE[d%100/10];

DelayMS(5);

P2=0xfd; //第2个数码管显示百位数

P0=DSY_CODE[d/100];

DelayMS(5);

}

//主程序

void main()

{

TMOD=0x02; //T1工作模式2

TH0=0x14;

TL0=0x00;

IE=0x82;

TR0=1;

P1=0x3f; //选择ADC0809的通道3(0111)(~)while(1)

{

ST=0;ST=1;ST=0; //启动A/D转换

while(EOC==0); //等待转换完成

OE=1;

Display_Result(P3);

OE=0;

}

}

//T0定时器中断给ADC0808提供时钟信号

void Timer0_INT() interrupt 1

{

CLK=~CLK;

}

相关文档