《单片机C语言程序设计实训100例—基于8051+Proteus仿真》案例
第 01 篇 基础程序设计
01 闪烁的LED
/* 名称:闪烁的LED
说明:LED按设定的时间间隔闪烁 */
#include<>
#define uchar unsigned char #define uint unsigned int sbit LED=P1^0; .\\r\\n\
Puts_to_SerialPort(\ 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 \ \ \
\ };
//显示缓冲(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]; DelayMS(5); P2=0xfb; //第3个数码管显示十位数 P0=DSY_CODE[d0/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; }