单片机c语言基本控制程序(单片机C语言程序设计实训)
单片机c语言基本控制程序(单片机C语言程序设计实训)/* 名称:8 只数码管闪烁显示数字串 说明:数码管闪烁显示由 0~7 构成的一串数字 本例用动态刷新法显示一串数字,在停止刷新时所有数字显示消失。 */ #include<reg51.h> #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() {
《单片机C语言程序设计实训 100 例—基于 C51 Proteus仿真》案例
第 01 篇 基础程序设计
1 闪烁的 LED/* 名称:闪烁的 LED 说明:LED 按设定的时间间隔闪烁 */ #include<reg51.h> #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); } }
2 从左到右的流水灯
/* 名称:从左到右的流水灯
说明:接在P0 口的8 个LED从左到右循环依次点亮,产生走马灯效果
*/
#include<reg51.h> #include<intrins.h> #define uchar unsigned char #define uint unsigned int 1 //延时 void DelayMS(uint x) { uchar i; while(x--) { for(i=0;i<120;i ); } } //主程序 void main() { P0=0xfe; while(1) { P0=_crol_(P0 1); //P0 的值向左循环移动 DelayMS(150); } } 3 8 只 LED 左右来回点亮
/* 名称:8 只 LED 左右来回点亮 说明:程序利用循环移位函数_crol_和_cror_形成来回滚动的效果 */
#include<reg51.h> #include<intrins.h> #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 的值向左循环移动 DelayMS(150); } for(i=0;i<7;i ) { P2=_cror_(P2 1); //P2 的值向右循环移动 DelayMS(150); } } } 4 花样流水灯
/* 名称:花样流水灯 说明:16 只 LED 分两组按预设的多种花样变换显示 */ #include<reg51.h> #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) { uchar i; 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); } }
/* 名称:LED 模拟交通灯 说明:东西向绿灯亮若干秒,黄灯闪烁 5 次后红灯亮, 红灯亮后,南北向由红灯变为绿灯,若干秒后南北向黄灯闪烁 5 此后变红灯,东西向变绿灯,如此重复。 */ #include<reg51.h> #define uchar unsigned char #define uint unsigned int 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(); } 6 单只数码管循环显示 0~9 /* 名称:单只数码管循环显示 0~9 说明:主程序中的循环语句反复将 0~9 的段码送至 P0 口,使数字 0~9 循环显示 */ #include<reg51.h> #include<intrins.h> #define uchar unsigned char #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) { P0=~DSY_CODE[i]; i=(i 1); DelayMS(300);
}
}
7 . 8 只数码管滚动显示单个数字/* 名称:8 只数码管滚动显示单个数字 说明:数码管从左到右依次滚动显示0~7,程序通过每次仅循环选通一只数码 管 */ #include<reg51.h> #include<intrins.h> #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; //关闭显示 wei=_crol_(wei 1); P0=DSY_CODE[i]; //发送数字段码 P2=wei; //发送位码 DelayMS(300); } } } 8 8 只数码管动态显示多个不同字符 电路如上图 /* 名称:8 只数码管动态显示多个不同字符 说明:数码管动态扫描显示 0~7。 */ #include<reg51.h> #include<intrins.h> #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 ) { P0=0xff; P0=DSY_CODE[i]; //发送段码 wei=_crol_(wei 1); P2=wei; //发送位码 DelayMS(2); } } } 8 8 只数码管闪烁显示数字串
电路如上图
/* 名称:8 只数码管闪烁显示数字串 说明:数码管闪烁显示由 0~7 构成的一串数字 本例用动态刷新法显示一串数字,在停止刷新时所有数字显示消失。 */ #include<reg51.h> #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); } } 9 8 只数码管滚动显示数字串
电路如上图
/* 名称:8 只数码管滚动显示数字串 说明:数码管向左滚动显示 3 个字符构成的数字串 */ #include<reg51.h> #include<intrins.h> #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)]]; m=_crol_(m 1); P2=m; //发送位码 DelayMS(2); } } k=(k 1); //环形队列首支针 k 递增,Num 下标范围 0~10,故对 11 取余 } } 11 K1-K4 控制 LED 移位 /* 名称:K1-K4 控制 LED 移位 说明:按下 K1 时,P0 口 LED 上移一位; 按下 K2 时,P0 口 LED 下移一位; 按下 K3 时,P2 口 LED 上移一位; 按下 K4 时,P2 口 LED 下移一位; */
#include<reg51.h> #include<intrins.h> #define uchar unsigned char #define uint unsigned int //延时 void DelayMS(uint x) { uchar i; while(x--) for(i=0;i<120;i ); } · 根据 P1 口的按键移动 LED void Move_LED() { } //主程序 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 点亮,再次按下并释放时熄灭; */
#include<reg51.h> #define uchar unsigned char #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<reg51.h> #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<reg51.h> #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<reg51.h> #include<intrins.h> #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; Num_Buffer[0]=Key_Counts; 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: case 0xfd: case 0xfb: if(Key_Counts<255) Key_Counts ; break; if(Key_Counts>0) Key_Counts--; break; Key_Counts=0; } Key_Code=0xff; }
}
16 4X4 矩阵键盘控制条形 LED 显示/* 名称:4X4 矩阵键盘控制条形 LED 显示 说明:运行本例时,按 下的按键值越大点亮的 LED 越多。 */ #include<reg51.h> #include<intrins.h> #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<reg51.h> #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; //延时 void DelayMS(uint x) { 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<reg51.h> sbit S1=P1^0; sbit S2=P1^1; sbit LED1=P0^0; sbit LED2=P0^1; //主程序 void main() { while(1) { LED1=S1; LED2=S2; }
}
{ BEEP=~BEEP; DelayMS(t); } BEEP=0; }
void main() { P1=0xff; BEEP=0; while(1) { if(K1==0) Play(1); if(K2==0) Play(2); if(K3==0) Play(3); if(K4==0) Play(4); } }
46 单片机之间双向通信
/* 名称:甲机串口程序
说明:甲机向乙机发送控制命令字符,甲机同时接收乙机发送的数字,并显示在数码管上。
*/
#include<reg51.h> #define uchar unsigned char #define uint unsigned int sbit LED1=P1^0; sbit LED2=P1^3; sbit K1=P1^7; uchar Operation_No=0; //操作代码 //数码管代码 uchar code DSY_CODE[]={0x3f 0x06 0x5b 0x4f 0x66 0x6d 0x7d 0x07 0x7f 0x6f}; //延时 void DelayMS(uint ms) { uchar i; while(ms--) for(i=0;i<120;i ); } //向串口发送字符 void Putc_to_SerialPort(uchar c) { SBUF=c; while(TI==0); TI=0; } //主程序 void main() { LED1=LED2=1; P0=0x00; SCON=0x50; //串口模式 1,允许接收 TMOD=0x20; //T1 工作模式 2 PCON=0x00; //波特率不倍增 TH1=0xfd; TL1=0xfd; TI=RI=0; TR1=1; IE=0x90; //允许串口中断 while(1) { DelayMS(100); if(K1==0) //按下 K1 时选择操作代码 0,1,2,3 { while(K1==0); Operation_No=(Operation_No 1)%4; switch(Operation_No) //根据操作代码发送 A/B/C 或停止发送 { case 0: Putc_to_SerialPort('X'); LED1=LED2=1; break; case 1: Putc_to_SerialPort('A'); LED1=~LED1;LED2=1; break; case 2: Putc_to_SerialPort('B'); LED2=~LED2;LED1=1; break; case 3: Putc_to_SerialPort('C'); LED1=~LED1;LED2=LED1; break; } } } } //甲机串口接收中断函数 void Serial_INT() interrupt 4 { if(RI) { RI=0; if(SBUF>=0&&SBUF<=9) P0=DSY_CODE[SBUF]; else P0=0x00; } } /* 名称:乙机程序接收甲机发送字符并完成相应动作 说明:乙机接收到甲机发送的信号后,根据相应信号控制 LED 完成不同闪烁动作。 */ #include<reg51.h> #define uchar unsigned char #define uint unsigned int sbit LED1=P1^0; sbit LED2=P1^3; sbit K2=P1^7; uchar NumX=-1; //延时 void DelayMS(uint ms) { uchar i; while(ms--) for(i=0;i<120;i ); } //主程序 void main() { LED1=LED2=1; SCON=0x50; TMOD=0x20; //串口模式 1,允许接收 //T1 工作模式 2 TH1=0xfd; //波特率 9600 TL1=0xfd; PCON=0x00; //波特率不倍增 RI=TI=0; TR1=1; IE=0x90; while(1) { DelayMS(100); if(K2==0) { while(K2==0); NumX= NumX; //产生 0~10 范围内的数字,其中 10 表示关闭 SBUF=NumX; while(TI==0); TI=0; } } } void Serial_INT() interrupt 4 { if(RI) //如收到则 LED 则动作 { RI=0; switch(SBUF) //根据所收到的不同命令字符完成不同动作 { }
}
}
47 单片机向主机发送字符串
/* 名称:单片机向主机发送字符串 说明:单片机按一定的时间间隔向主机发送字符串,发送内容在虚拟终端显示。 */ #include<reg51.h> #define uchar unsigned char #define uint unsigned int //延时 void DelayMS(uint ms) { uchar i; while(ms--) for(i=0;i<120;i ); } //向串口发送字符 void Putc_to_SerialPort(uchar c) { SBUF=c; while(TI==0); TI=0; } //向串口发送字符串 void Puts_to_SerialPort(uchar *s) { while(*s!='\0') { Putc_to_SerialPort(*s); s ; DelayMS(5); } } //主程序 void main() { uchar c=0; SCON=0x40; //串口模式 1 TMOD=0x20; //T1 工作模式 2 TH1=0xfd; //波特率 9600 TL1=0xfd; PCON=0x00; //波特率不倍增 TI=0; TR1=1; DelayMS(200); //向主机发送数据 Puts_to_SerialPort("Receiving From 8051...\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) //每输出一遍后加横线 { Puts_to_SerialPort("\r\n-------------------------------\r\n"); DelayMS(100); } c=(c 1)&; if(c==0) { //每输出 10 个字符后换行 Puts_to_SerialPort("\r\n"); DelayMS(100);
} } }
48 单片机与 PC 通信
/* 名称:单片机与 PC 通信 说明:单片机可接收 PC 发送的数字字符,按下单片机的 K1 键后,单片机可向 PC 发送 字符串。在 Proteus 环境下完成本实验时,需要安装 Virtual Serial Port Driver 和串口调试助手。本例缓冲 100 个数字字符, 缓冲满后新数字从前面开始存放(环形缓冲)。 */ #include<reg51.h> #define uchar unsigned char #define uint unsigned int uchar Receive_Buffer[101]; uchar Buf_Index=0; //数码管编码 //接收缓冲 //缓冲空间索引 uchar code DSY_CODE[]={0x3f 0x06 0x5b 0x4f 0x66 0x6d 0x7d 0x07 0x7f 0x6f 0x00}; //延时 void DelayMS(uint ms) { uchar i; while(ms--) for(i=0;i<120;i ); } //主程序 void main() { uchar i; P0=0x00; Receive_Buffer[0]=-1; SCON=0x50; //串口模式 1,允许接收 TMOD=0x20; TH1=0xfd; TL1=0xfd; //T1 工作模式 2 //波特率 9600 PCON=0x00; //波特率不倍增 EA=1;EX0=1;IT0=1; ES=1;IP=0x01; TR1=1; while(1) { for(i=0;i<100;i ) { //收到-1 为一次显示结束 if(Receive_Buffer[i]==-1) break; P0=DSY_CODE[Receive_Buffer[i]]; DelayMS(200); } DelayMS(200); } } //串口接收中断函数 void Serial_INT() interrupt 4 { uchar c; if(RI==0) return; ES=0; //关闭串口中断 RI=0; //清接收中断标志 c=SBUF; if(c>='0'&&c<='9') { //缓存新接收的每个字符,并在其后放-1 为结束标志 Receive_Buffer[Buf_Index]=c-'0'; Receive_Buffer[Buf_Index 1]=-1; Buf_Index=(Buf_Index 1)0; } ES=1; } void EX_INT0() interrupt 0 //外部中断 0 { uchar *s="这是由 8051 发送的字符串!\r\n"; uchar i=0; while(s[i]!='\0') { SBUF=s[i]; while(TI==0); TI=0; i ; } }
第 02 篇 硬件应用
19 用 ADC0808 控制 PWM 输出
/* 名称:用 ADC0808 控制 PWM 输出
说明:使用数模转换芯片 ADC0808,通过调节可变电阻 RV1 来调节脉冲宽度,运行程序时,通过虚拟示波器观察占空比的变化。
*/
#include<reg51.h> #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<reg51.h> #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)(P1.4~P1.6) while(1) { ST=0;ST=1;ST=0; while(EOC==0); //启动 A/D 转换 //等待转换完成 OE=1; Display_Result(P3); OE=0; } } //T0 定时器中断给 ADC0808 提供时钟信号 void Timer0_INT() interrupt 1 { CLK=~CLK; }