单片机的C51编程
C51单片机实战100例

目录目录 1函数的使用和熟悉 6实例3:用单片机控制第一个灯亮7实例4:用单片机控制一个灯闪烁:认识单片机的工作频率7实例5:将P1口状态分别送入P0、P2、P3口:认识I/O口的引脚功能8实例6:使用P3口流水点亮8位LED 9实例7:通过对P3口地址的操作流水点亮8位LED 11实例8:用不同数据类型控制灯闪烁时间13实例9:用P0口、P1 口分别显示加法和减法运算结果15实例10:用P0、P1口显示乘法运算结果15实例11:用P1、P0口显示除法运算结果16实例12:用自增运算控制P0口8位LED流水花样17实例13:用P0口显示逻辑"与"运算结果18实例14:用P0口显示条件运算结果18实例15:用P0口显示按位"异或"运算结果 19实例16:用P0显示左移运算结果19实例17:"万能逻辑电路"实验20实例18:用右移运算流水点亮P1口8位LED 20实例19:用if语句控制P0口8位LED的流水方向 22实例20:用swtich语句的控制P0口8位LED的点亮状态23 实例21:用for语句控制蜂鸣器鸣笛次数25实例22:用while语句控制LED 27实例23:用do-while语句控制P0口8位LED流水点亮29 实例24:用字符型数组控制P0口8位LED流水点亮30实例25:用P0口显示字符串常量 32实例26:用P0 口显示指针运算结果33实例27:用指针数组控制P0口8位LED流水点亮34实例28:用数组的指针控制P0 口8 位LED流水点亮35实例29:用P0 、P1口显示整型函数返回值37实例30:用有参函数控制P0口8位LED流水速度38实例31:用数组作函数参数控制流水花样40实例32:用指针作函数参数控制P0口8位LED流水点亮41 实例33:用函数型指针控制P1口灯花样44实例34:用指针数组作为函数的参数显示多个字符串45实例35:字符函数ctype.h应用举例48实例36:内部函数intrins.h应用举例48实例37:标准函数stdlib.h应用举例49实例38:字符串函数string.h应用举例 51实例39:宏定义应用举例2 52实例40:宏定义应用举例2 52实例41:宏定义应用举例3 53中断、定时器54实例42:用定时器T0查询方式P2口8位控制LED闪烁54 实例43:用定时器T1查询方式控制单片机发出1KHz音频55 实例44:将计数器T0计数的结果送P1口8位LED显示56 实例45:用定时器T0的中断控制1位LED闪烁57实例46:用定时器T0的中断实现长时间定时59实例47:用定时器T1中断控制两个LED以不同周期闪烁60 实例48:用计数器T1的中断控制蜂鸣器发出1KHz音频62实例49:用定时器T0的中断实现"渴望"主题曲的播放64 实例50-1:输出50个矩形脉冲69实例50-2:计数器T0统计外部脉冲数70实例51-2:定时器T0的模式2测量正脉冲宽度71实例52:用定时器T0控制输出高低宽度不同的矩形波72 实例53:用外中断0的中断方式进行数据采集75实例54-1:输出负脉宽为200微秒的方波76实例54-2:测量负脉冲宽度77实例55:方式0控制流水灯循环点亮78实例56-1:数据发送程序80实例56-2:数据接收程序83实例57-1:数据发送程序84实例57-2:数据接收程序86实例58:单片机向PC发送数据88实例59:单片机接收PC发出的数据90数码管显示 92实例60:用LED数码显示数字5 92实例61:用LED数码显示器循环显示数字0~9 92实例62:用数码管慢速动态扫描显示数字"1234" 94实例63:用LED数码显示器伪静态显示数字1234 95实例64:用数码管显示动态检测结果96实例65:数码秒表设计100实例66:数码时钟设计103实例67:用LED数码管显示计数器T0的计数值110实例68:静态显示数字“59”112键盘控制113实例69:无软件消抖的独立式键盘输入实验113实例70:软件消抖的独立式键盘输入实验114实例71:CPU控制的独立式键盘扫描实验115实例72:定时器中断控制的独立式键盘扫描实验121实例73:独立式键盘控制的4级变速流水灯128实例74:独立式键盘的按键功能扩展:"以一当四" 132实例75:独立式键盘调时的数码时钟实验135实例76:独立式键盘控制步进电机实验143实例77:矩阵式键盘按键值的数码管显示实验148实例78:矩阵式键盘按键音154实例79:简易电子琴157实例80:矩阵式键盘实现的电子密码锁169液晶显示LCD 175实例81:用LCD显示字符'A' 175实例82:用LCD循环右移显示"Welcome to China" 182 实例83:用LCD显示适时检测结果188实例84:液晶时钟设计196一些芯片的使用*****24c02 DS18B20 X5045 ADC0832 DAC0832 DS1302 红外遥控 208实例85:将数据"0x0f"写入AT24C02再读出送P1口显示208实例86:将按键次数写入AT24C02,再读出并用1602LCD显示216 实例87:对I2C总线上挂接多个AT24C02的读写操作231实例88:基于AT24C02的多机通信读取程序242实例88:基于AT24C02的多机通信写入程序249实例90:DS18B20温度检测及其液晶显示271实例91:将数据"0xaa"写入X5045再读出送P1口显示 289实例92:将流水灯控制码写入X5045并读出送P1口显示296实例93:对SPI总线上挂接多个X5045的读写操作303实例94:基于ADC0832的数字电压表312实例95:用DAC0832产生锯齿波电压324实例96:用P1口显示红外遥控器的按键值 325实例97:用红外遥控器控制继电器 330实例98:基于DS1302的日历时钟335实例99:单片机数据发送程序353实例100:电机转速表设计 355//模拟霍尔脉冲 365函数的使用和熟悉实例3:用单片机控制第一个灯亮#include<reg51.h> //包含51单片机寄存器定义的头文件void main(void){P1=0xfe; //P1=1111 1110B,即P1.0输出低电平}实例4:用单片机控制一个灯闪烁:认识单片机的工作频率#include<reg51.h> //包含单片机寄存器的头文件/****************************************函数功能:延时一段时间*****************************************/void delay(void) //两个void意思分别为无需返回值,没有参数传递{unsigned int i; //定义无符号整数,最大取值范围65535for(i=0;i<20000;i++) //做20000次空循环; //什么也不做,等待一个机器周期}/*******************************************************函数功能:主函数(C语言规定必须有也只能有1个主函数)********************************************************/void main(void){while(1) //无限循环{P1=0xfe; //P1=1111 1110B,P1.0输出低电平delay(); //延时一段时间P1=0xff; //P1=1111 1111B,P1.0输出高电平delay(); //延时一段时间}}实例5:将P1口状态分别送入P0、P2、P3口:认识I/O口的引脚功能#include<reg51.h> //包含单片机寄存器的头文件/*******************************************************函数功能:主函数(C语言规定必须有也只能有1个主函数)********************************************************/void main(void){while(1) //无限循环{P1=0xff; // P1=1111 1111B,熄灭LEDP0=P1; // 将P1口状态送入P0口P2=P1; // 将P1口状态送入P2口P3=P1; // 将P1口状态送入P3口}}实例6:使用P3口流水点亮8位LED#include<reg51.h> //包含单片机寄存器的头文件/****************************************函数功能:延时一段时间*****************************************/void delay(void){unsigned char i,j;for(i=0;i<250;i++)for(j=0;j<250;j++);}/******************************************************* 函数功能:主函数********************************************************/ void main(void){while(1){P3=0xfe; //第一个灯亮delay(); //调用延时函数P3=0xfd; //第二个灯亮delay(); //调用延时函数P3=0xfb; //第三个灯亮delay(); //调用延时函数P3=0xf7; //第四个灯亮delay(); //调用延时函数P3=0xef; //第五个灯亮 delay(); //调用延时函数P3=0xdf; //第六个灯亮delay(); //调用延时函数P3=0xbf; //第七个灯亮 delay(); //调用延时函数P3=0x7f; //第八个灯亮 delay(); //调用延时函数}}实例7:通过对P3口地址的操作流水点亮8位LED#include<reg51.h> //包含单片机寄存器的头文件sfr x=0xb0; //P3口在存储器中的地址是b0H,通过sfr可定义8051内核单片机//的所有内部8位特殊功能寄存器,对地址x的操作也就是对P1口的操作/****************************************函数功能:延时一段时间*****************************************/void delay(void){unsigned char i,j;for(i=0;i<250;i++)for(j=0;j<250;j++); //利用循环等待若干机器周期,从而延时一段时间}/*****************************************函数功能:主函数******************************************/void main(void){while(1){x=0xfe; //第一个灯亮delay(); //调用延时函数x=0xfd; //第二个灯亮delay(); //调用延时函数x=0xfb; //第三个灯亮delay(); //调用延时函数x=0xf7; //第四个灯亮delay(); //调用延时函数x=0xef; //第五个灯亮 delay(); //调用延时函数x=0xdf; //第六个灯亮delay(); //调用延时函数x=0xbf; //第七个灯亮 delay(); //调用延时函数x=0x7f; //第八个灯亮 delay(); //调用延时函数}}实例8:用不同数据类型控制灯闪烁时间#include<reg51.h> //包含单片机寄存器的头文件/******************************************************函数功能:用整形数据延时一段时间******************************************************/void int_delay(void) //延时一段较长的时间{unsigned int m; //定义无符号整形变量,双字节数据,值域为0~65535 for(m=0;m<36000;m++); //空操作}/******************************************************函数功能:用字符型数据延时一段时间******************************************************/void char_delay(void) //延时一段较短的时间{unsigned char i,j; //定义无符号字符型变量,单字节数据,值域0~255 for(i=0;i<200;i++)for(j=0;j<180;j++); //空操作}/****************************************************** 函数功能:主函数******************************************************/ void main(void){unsigned char i;while(1){for(i=0;i<3;i++){P1=0xfe; //P1.0口的灯点亮int_delay(); //延时一段较长的时间P1=0xff; //熄灭int_delay(); //延时一段较长的时间}for(i=0;i<3;i++){P1=0xef; //P1.4口的灯点亮char_delay(); //延时一段较长的时间P1=0xff; //熄灭char_delay(); //延时一段较长的时间}}}实例9:用P0口、P1 口分别显示加法和减法运算结果#include<reg51.h>void main(void){unsigned char m,n;m=43; //即十进制数2x16+11=43n=60; //即十进制数3x16+12=60P1=m+n; //P1=103=0110 0111B,结果P1.3、P1.4、P1.7 口的灯被点亮P0=n-m; //P0=17=0001 0001B,结果P0.0、P0.4的灯被熄灭}实例10:用P0、P1口显示乘法运算结果#include<reg51.h> //包含单片机寄存器的头文件void main(void){unsigned char m,n;unsigned int s;n=71;s=m*n; //s=64*71=4544,需要16位二进制数表示,高8位送P1口,低8位送P0口//由于4544=17*256+192=H3*16*16*16+H2*16*16+H1*16+H0//两边同除以256,可得17+192/256=H3*16+H2+(H1*16+H0)/256//因此,高8位16进制数H3*16+H2必然等于17,即4544除以256的商//低8位16进制数H1*16+H0必然等于192,即4544除以256的余数P1=s/256; //高8位送P1口,P1=17=11H=0001 0001B, P1.0和P1.4口灭,其余亮P0=s%256; //低8位送P0口, P3=192=c0H=11000000B,P3.1,P3.6,P3.7口灭,其余亮}实例11:用P1、P0口显示除法运算结果#include<reg51.h> //包含单片机寄存器的头文件void main(void){P1=36/5; //求整数P0=((36%5)*10)/5; //求小数while(1); //无限循环防止程序“跑飞”}实例12:用自增运算控制P0口8位LED流水花样#include<reg51.h> //包含单片机寄存器的头文件/****************************************************** 函数功能:延时一段时间******************************************************/ void delay(void){unsigned int i;for(i=0;i<20000;i++);}/****************************************************** 函数功能:主函数******************************************************/void main(void){unsigned char i;for(i=0;i<255;i++) //注意i的值不能超过255{P0=i; //将i的值送P0口delay(); //调用延时函数}}实例13:用P0口显示逻辑"与"运算结果#include<reg51.h> //包含单片机寄存器的头文件void main(void){P0=(4>0)&&(9>0xab);//将逻辑运算结果送P0口while(1); //设置无限循环,防止程序“跑飞”}实例14:用P0口显示条件运算结果#include<reg51.h> //包含单片机寄存器的头文件void main(void){P0=(8>4)?8:4;//将条件运算结果送P0口,P0=8=0000 1000B while(1); //设置无限循环,防止程序“跑飞”}实例15:用P0口显示按位"异或"运算结果#include<reg51.h> //包含单片机寄存器的头文件void main(void){P0=0xa2^0x3c;//将条件运算结果送P0口,P0=8=0000 1000B while(1); //设置无限循环,防止程序“跑飞”}实例16:用P0显示左移运算结果#include<reg51.h> //包含单片机寄存器的头文件void main(void){P0=0x3b<<2;//将左移运算结果送P0口,P0=1110 1100B=0xec while(1); //无限循环,防止程序“跑飞”}实例17:"万能逻辑电路"实验#include<reg51.h> //包含单片机寄存器的头文件sbit F=P1^4; //将F位定义为P1.4sbit X=P1^5; //将X位定义为P1.5sbit Y=P1^6; //将Y位定义为P1.6sbit Z=P1^7; //将Z位定义为P1.7void main(void){while(1){F=((~X)&Y)|Z; //将逻辑运算结果赋给F;}}实例18:用右移运算流水点亮P1口8位LED#include<reg51.h> //包含单片机寄存器的头文件/*****************************函数功能:延时一段时间*****************************/void delay(void){unsigned int n;for(n=0;n<30000;n++);}/*****************************函数功能:主函数*****************************/void main(void){unsigned char i;while(1){P1=0xff;delay();for(i=0;i<8;i++)//设置循环次数为8{P1=P1>>1; //每次循环P1的各二进位右移1位,高位补0delay(); //调用延时函数}}}实例19:用if语句控制P0口8位LED的流水方向#include<reg51.h> //包含单片机寄存器的头文件sbit S1=P1^4; //将S1位定义为P1.4sbit S2=P1^5; //将S2位定义为P1.5/*****************************函数功能:主函数*****************************/void main(void){while(1){if(S1==0) //如果按键S1按下P0=0x0f; //P0口高四位LED点亮if(S2==0) //如果按键S2按下P0=0xf0; //P0口低四位LED点亮}}实例20:用swtich语句的控制P0口8位LED的点亮状态#include<reg51.h> //包含单片机寄存器的头文件sbit S1=P1^4; //将S1位定义为P1.4/*****************************函数功能:延时一段时间*****************************/void delay(void){unsigned int n;for(n=0;n<10000;n++);}/*****************************函数功能:主函数*****************************/void main(void){unsigned char i;i=0; //将i初始化为0while(1){if(S1==0) //如果S1键按下{delay(); //延时一段时间if(S1==0) //如果再次检测到S1键按下i++; //i自增1if(i==9) //如果i=9,重新将其置为1i=1;}switch(i) //使用多分支选择语句{case 1: P0=0xfe; //第一个LED亮break;case 2: P0=0xfd; //第二个LED亮break;case 3:P0=0xfb; //第三个LED亮break;case 4:P0=0xf7; //第四个LED亮break;case 5:P0=0xef; //第五个LED亮break;case 6:P0=0xdf; //第六个LED亮break;case 7:P0=0xbf; //第七个LED亮break;case 8:P0=0x7f; //第八个LED亮break;default: //缺省值,关闭所有LEDP0=0xff;}}}实例21:用for语句控制蜂鸣器鸣笛次数#include<reg51.h> //包含单片机寄存器的头文件sbit sound=P3^7; //将sound位定义为P3.7/****************************************函数功能:延时形成1600Hz音频****************************************/void delay1600(void){unsigned char n;for(n=0;n<100;n++);}/**************************************** 函数功能:延时形成800Hz音频****************************************/ void delay800(void){unsigned char n;for(n=0;n<200;n++);}/**************************************** 函数功能:主函数****************************************/ void main(void){unsigned int i;while(1){for(i=0;i<830;i++){sound=0; //P3.7输出低电平delay1600();sound=1; //P3.7输出高电平delay1600();}for(i=0;i<200;i++){sound=0; //P3.7输出低电平delay800();sound=1; //P3.7输出高电平delay800();}}}实例22:用while语句控制LED#include<reg51.h> //包含单片机寄存器的头文件/****************************************函数功能:延时约60ms (3*100*200=60000μs)****************************************/void delay60ms(void){unsigned char m,n;for(m=0;m<100;m++)for(n=0;n<200;n++);}/****************************************函数功能:主函数****************************************/void main(void){unsigned char i;while(1) //无限循环{i=0; //将i初始化为0while(i<0xff) //当i小于0xff(255)时执行循环体{P0=i; //将i送P0口显示delay60ms(); //延时i++; //i自增1}}}实例23:用do-while语句控制P0口8位LED流水点亮#include<reg51.h> //包含单片机寄存器的头文件/****************************************函数功能:延时约60ms (3*100*200=60000μs)****************************************/void delay60ms(void){unsigned char m,n;for(m=0;m<100;m++)for(n=0;n<200;n++);}/****************************************函数功能:主函数****************************************/void main(void){do{P0=0xfe; //第一个LED亮delay60ms();P0=0xfd; //第二个LED亮delay60ms();P0=0xfb; //第三个LED亮delay60ms();P0=0xf7; //第四个LED亮delay60ms();P0=0xef; //第五个LED亮delay60ms();P0=0xdf; //第六个LED亮delay60ms();delay60ms();P0=0xbf; //第七个LED亮delay60ms();P0=0x7f; //第八个LED亮delay60ms();}while(1); //无限循环,使8位LED循环流水点亮}实例24:用字符型数组控制P0口8位LED流水点亮#include<reg51.h> //包含单片机寄存器的头文件/****************************************函数功能:延时约60ms (3*100*200=60000μs)****************************************/void delay60ms(void){unsigned char m,n;for(m=0;m<100;m++)for(n=0;n<200;n++);}/****************************************函数功能:主函数****************************************/void main(void){unsigned char i;unsigned char code Tab[ ]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; //定义无符号字符型数组while(1){for(i=0;i<8;i++){P0=Tab[i];//依次引用数组元素,并将其送P0口显示delay60ms();//调用延时函数}}}实例25:用P0口显示字符串常量#include<reg51.h> //包含单片机寄存器的头文件/*************************************************函数功能:延时约150ms (3*200*250=150 000μs=150ms*************************************************/void delay150ms(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/*************************************************函数功能:主函数*************************************************/void main(void){unsigned char str[]={"Now,Temperature is :"}; //将字符串赋给字符型全部元素赋值unsigned char i;while(1){i=0; //将i初始化为0,从第一个元素开始显示while(str[i]!='\0') //只要没有显示到结束标志'\0'{P0=str[i]; //将第i个字符送到P0口显示delay150ms(); //调用150ms延时函数i++; //指向下一个待显字符}}}实例26:用P0 口显示指针运算结果#include<reg51.h>void main(void){unsigned char *p1,*p2; //定义无符号字符型指针变量p1,p2 unsigned char i,j; //定义无符号字符型数据i=25; //给i赋初值25j=15;p1=&i; //使指针变量指向i ,对指针初始化p2=&j; //使指针变量指向j ,对指针初始化P0=*p1+*p2; //*p1+*p2相当于i+j,所以P0=25+15=40=0x28 //则P0=0010 1000B,结果P0.3、P0.5引脚LED熄灭,其余点亮while(1); //无限循环,防止程序“跑飞”}实例27:用指针数组控制P0口8位LED流水点亮#include<reg51.h>/*************************************************函数功能:延时约150ms (3*200*250=150 000μs=150ms*************************************************/void delay150ms(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/*************************************************函数功能:主函数void main(void){unsigned char code Tab[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; unsigned char *p[ ]={&Tab[0],&Tab[1],&Tab[2],&Tab[3],&Tab[4],&Tab[5], &Tab[6],&Tab[7]};unsigned char i; //定义无符号字符型数据while(1){for(i=0;i<8;i++){P0=*p[i];delay150ms();}}}实例28:用数组的指针控制P0 口8 位LED流水点亮#include<reg51.h>/*************************************************函数功能:延时约150ms (3*200*250=150 000μs=150msvoid delay150ms(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/*************************************************函数功能:主函数*************************************************/void main(void){unsigned char i;unsigned char Tab[ ]={0xFF,0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE,0xFE,0xFC,0xFB,0xF0,0xE0,0xC0,0x80,0x00,0xE7,0xDB,0xBD,0x7E,0x3C,0x18,0x00,0x81,0xC3,0xE7,0x7E,0xBD,0xDB,0xE7,0xBD,0xDB};//流水灯控制码unsigned char *p; //定义无符号字符型指针p=Tab; //将数组首地址存入指针pwhile(1){for(i=0;i<32;i++) //共32个流水灯控制码{P0=*(p+i); //*(p+i)的值等于a[i]delay150ms(); //调用150ms延时函数}}}实例29:用P0 、P1口显示整型函数返回值#include<reg51.h>/************************************************* 函数功能:计算两个无符号整数的和*************************************************/ unsigned int sum(int a,int b){unsigned int s;s=a+b;return (s);}/************************************************* 函数功能:主函数*************************************************/ void main(void){unsigned z;z=sum(2008,2009);P1=z/256; //取得z的高8位P0=z%256; //取得z的低8位while(1);}实例30:用有参函数控制P0口8位LED流水速度#include<reg51.h>/************************************************* 函数功能:延时一段时间*************************************************/ void delay(unsigned char x){unsigned char m,n;for(m=0;m<x;m++)for(n=0;n<200;n++);}/*************************************************函数功能:主函数*************************************************/void main(void){unsigned char i;unsigned char code Tab[ ]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};//流水灯控制码while(1){//快速流水点亮LEDfor(i=0;i<8;i++) //共8个流水灯控制码{P0=Tab[i];delay(100); //延时约60ms, (3*100*200=60 000μs)}//慢速流水点亮LEDfor(i=0;i<8;i++) //共8个流水灯控制码{P0=Tab[i];delay(250); //延时约150ms, (3*250*200=150 000μs)}}}实例31:用数组作函数参数控制流水花样#include<reg51.h>/*************************************************函数功能:延时约150ms*************************************************/void delay(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/*************************************************函数功能:流水点亮P0口8位LED*************************************************/void led_flow(unsigned char a[8]){unsigned char i;for(i=0;i<8;i++){P0=a[i];delay();}}/*************************************************函数功能:主函数*************************************************/void main(void){unsigned char code Tab[ ]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F};//流水灯控制码led_flow(Tab);}实例32:用指针作函数参数控制P0口8位LED流水点亮#include<reg51.h>/*************************************************函数功能:延时约150ms*************************************************/void delay(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/*************************************************函数功能:流水点亮P0口8位LED*************************************************/void led_flow(unsigned char *p) //形参为无符号字符型指针{unsigned char i;while(1){i=0; //将i置为0,指向数组第一个元素while(*(p+i)!='\0') //只要没有指向数组的结束标志{P0=*(p+i);// 取的指针所指变量(数组元素)的值,送P0口delay(); //调用延时函数i++; //指向下一个数组元素}}}/*************************************************函数功能:主函数*************************************************/void main(void){unsigned char code Tab[ ]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F,0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE, 0xFF,0xFE,0xFC,0xFB,0xF0,0xE0,0xC0,0x80,0x00,0xE7,0xDB,0xBD,0x7E,0xFF,0xFF,0x3C,0x18,0x0,0x81,0xC3,0xE7,0xFF, 0xFF,0x7E};//流水灯控制码unsigned char *pointer;pointer=Tab;led_flow(pointer);}实例33:用函数型指针控制P1口灯花样#include<reg51.h> //包含51单片机寄存器定义的头文件unsigned char code Tab[]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F}; //流水灯控制码,该数组被定义为全局变量/**************************************************************函数功能:延时约150ms**************************************************************/void delay(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/**************************************************************函数功能:流水灯左移**************************************************************/void led_flow(void){unsigned char i;for(i=0;i<8;i++) //8位控制码{P0=Tab[i];delay();}}/**************************************************************函数功能:主函数**************************************************************/void main(void){void (*p)(void); //定义函数型指针,所指函数无参数,无返回值p=led_flow; //将函数的入口地址赋给函数型指针pwhile(1)(*p)(); //通过函数的指针p调用函数led_flow()}实例34:用指针数组作为函数的参数显示多个字符串#include<reg51.h> //包含51单片机寄存器定义的头文件unsigned char code str1[ ]="Temperature is tested by DS18B20";//C语言中,字符串是作为字符数组来处理的unsigned char code str2[ ]="Now temperature is:"; //所以,字符串的名字就是字符串的首地址unsigned char code str3[ ]="The Systerm is designed by Zhang San"; unsigned char code str4[ ]="The date is 2008-9-30";unsigned char *p[ ]={str1,str2,str3,str4}; //定义p[4]为指向4个字符串的字符型指针数组/**************************************************************函数功能:延时约150ms**************************************************************/void delay(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/**************************************************************函数功能:流水点亮P0口8位LED**************************************************************/void led_display(unsigned char *x[ ]) //形参必须为指针数组{unsigned char i,j;for(i=0;i<4;i++) //有4个字符串要显示{j=0; //指向待显字符串的第0号元素while(*(x[i]+j)!='\0') //只要第i个字符串的第j号元素不是结束标志{P0=*(x[i]+j); //取得该元素值送到P0口显示delay(); //调用延时函数j++; //指向下一个元素}}}/**************************************************************函数功能:主函数**************************************************************/void main(void){unsigned char i;while(1){for(i=0;i<4;i++)led_display(p); //将指针数组名作实际参数传递}}实例35:字符函数ctype.h应用举例#include<reg51.h> //包含51单片机寄存器定义的头文件#include<ctype.h>void main(void){while(1){P3=isalpha('_')?0xf0:0x0f;//条件运算,若'_'是英文字母,P3=0xf0 }}实例36:内部函数intrins.h应用举例#include<reg51.h> //包含51单片机寄存器定义的头文件#include<intrins.h> //包含函数isalpha()声明的头文件/*************************************************函数功能:延时约150ms*************************************************/void delay(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/*************************************************函数功能:主函数*************************************************/void main(void){P3=0xfe; //P3=1111 1110Bwhile(1){P3=_crol_(P3,1);// 将P3的二进制位循环左移1位后再赋给P3 delay(); //调用延时函数}}实例37:标准函数stdlib.h应用举例#include<reg51.h> //包含51单片机寄存器定义的头文件#include<stdlib.h> //包含函数isalpha()声明的头文件/*************************************************函数功能:延时约150ms*************************************************/void delay(void){unsigned char m,n;for(m=0;m<200;m++)for(n=0;n<250;n++);}/*************************************************函数功能:主函数*************************************************/void main(void){unsigned char i;while(1){for(i=0;i<10;i++) //产生10个随机数{P3=rand()/160; //将产生的随机数缩小160倍后送P3显示。
c51单片机c语言常用指令 -回复

c51单片机c语言常用指令-回复C51单片机C语言常用指令C51单片机是一种广泛应用于嵌入式系统的微控制器,其C语言编程常用指令为开发者提供了便利。
本文将逐步回答关于C51单片机C语言常用指令的问题,涵盖了常用的输入输出指令、控制流指令、算术指令和逻辑指令等方面,帮助读者全面了解和掌握这些重要的指令。
一、输入输出指令1. 如何在C51单片机上进行输入操作?答:可以使用P1口进行输入操作,需要将P1口配置为输入模式,并使用P1口的位操作函数来读取具体的引脚输入值。
2. 如何在C51单片机上进行输出操作?答:可以使用P2口进行输出操作,需要将P2口配置为输出模式,并使用P2口的位操作函数来设置具体的引脚输出值。
3. 如何控制C51单片机的LED灯?答:可以使用P0口进行LED灯的控制,通过设置P0口的引脚为高电平或低电平来点亮或关闭LED灯。
二、控制流指令1. 如何使用条件语句控制程序的执行顺序?答:可以使用if-else语句或switch语句来进行条件判断,并根据判断结果执行不同的代码块。
2. 如何使用循环语句进行重复操作?答:可以使用for循环、while循环或do-while循环来实现重复操作,根据循环条件控制代码块的执行次数。
三、算术指令1. 如何进行加法运算?答:可以使用加法运算符"+"来进行加法运算,例如:a = b + c;表示将变量b和c的值相加,然后将结果赋值给变量a。
2. 如何进行减法运算?答:可以使用减法运算符"-"来进行减法运算,例如:a = b - c;表示将变量b减去变量c的值,然后将结果赋值给变量a。
四、逻辑指令1. 如何进行逻辑与运算?答:可以使用逻辑与运算符"&&"来进行逻辑与运算,例如:if(a > 0 && b < 10) {...}表示当变量a大于0且变量b小于10时执行相应的操作。
单片机c51汇编语言51单片机汇编语言

单片机c51汇编语言51单片机汇编语言单片机C51汇编语言单片机(C51)是指一种集成电路上只包含一个集中式控制器的微处理器,具有完整的CPU指令集、RAM、ROM、I/O接口等功能。
汇编语言是一种低级语言,是用于编写单片机指令的一种语言。
汇编语言能够直接操作单片机的寄存器和输入/输出端口,因此在嵌入式系统的开发中非常重要。
本文将介绍单片机C51的汇编语言编程。
一、了解单片机C51单片机C51是目前应用最广泛的一种单片机系列,广泛用于各种电子设备和嵌入式系统的开发。
C51指的是Intel公司推出的一种基于MCS-51架构的单片机。
该系列单片机具有较高的性能和低功耗的特点,可用于各种控制和通信应用。
二、汇编语言的基本概念汇编语言是一种低级语言,与机器语言紧密相关。
它使用助记符来代替机器指令的二进制表示,使程序的编写更加易读。
在单片机C51汇编语言中,每一条汇编指令都对应着特定的机器指令,可以直接在单片机上执行。
三、汇编语言的基本指令在单片机C51汇编语言中,有一些基本的指令用于控制程序的执行和操作寄存器。
以下是一些常用的指令:1. MOV指令:用于将数据从一个寄存器或内存单元复制到另一个寄存器或内存单元。
2. ADD指令:用于将两个操作数相加,并将结果存储到目的寄存器中。
3. SUB指令:用于将第一个操作数减去第二个操作数,并将结果存储到目的寄存器中。
4. JMP指令:用于无条件跳转到指定的地址。
5. JZ指令:用于在条件为零时跳转到指定的地址。
6. DJNZ指令:用于将指定寄存器的值减一,并根据结果进行跳转。
四、编写单片机C51汇编程序的步骤编写单片机C51汇编程序需要按照以下步骤进行:1. 确定程序的功能和目标。
2. 分析程序的控制流程和数据流程。
3. 设计算法和数据结构。
4. 编写汇编指令,实现程序的功能。
5. 调试程序,并进行测试。
六、实例演示以下是一个简单的单片机C51汇编程序的示例,用于实现两个数的相加,并将结果输出到LED灯上:org 0H ; 程序的起始地址为0mov a, 05H ; 将05H赋值给累加器mov b, 07H ; 将07H赋值给B寄存器add a, b ; 将A寄存器和B寄存器的值相加mov P1, a ; 将相加结果输出到P1口end ; 程序结束在这个例子中,首先将05H赋值给累加器A,然后将07H赋值给B寄存器,接着使用ADD指令将A和B的值相加,将结果存储到累加器A中,最后将累加器A的值输出到P1口。
第4章单片机原理及应用(C51编程)

4.3 C51的函数
4.3.1
返回值类型 { 函数体 }
C51函数的定义
函数名(形式参数列表)[编译模式][reentrant][interrupt n][using n]
一般形式:
编译模式为SMALL、COPACT或LARGE reentrant用于定义可重入函数 interrupt n 用于定义中断函数,n为中断号,可以为0~31 using n 确定工作寄存器组,取值为0~3
从而使DBYTE用于以字节形式对data区访问,可以写成:
与此类似: CBYTE用于以字节形式对code区进行访问; PBYTE用于以字节形式对pdata区进行访问; XBYTE用于以字节形式对xdata区进行访问。
CWORD、DWORD、PWORD和XWORD用于以字形式对 code区、data区、pdata区和xdata区进行访问。
4.2.4
C51程序编写示例
C51源程序
C51编译器
浮动目标码模块 系统库 连接器
列表文件 用户库
绝对定位目标码文件
映像文件
软件模拟器
转换器
硬件仿真器
OMF51格式文件 写入程序存储器 编程器
【例4-1】将30H至3FH共16个RAM单元初始化为“55H”。 #include <reg52.h> #include <absacc.h> void main(void) { unsigned char i; for (i=0;i<=15;i++) { DBYTE[0x30+i]=0x55; } while(1); } 编译系统自动连接了 startup.a51生成代码 一是将内部RAM的 00H~7FH清0; 二是设置堆栈指针SP。 有全局变量赋值时 编译系统会自动连接 init.a51生成代码
第3章_C51语言编程基础

.
3
2、Keil C51语言简介
对于51单片机,目前广泛使用的是Keil C51语言,简称C51语言。
Keil C51语言是在标准C的基础上,针对51单片机的硬件特点进行 扩展,并向51单片机上移植的高效、简洁的实用高级语言。
与汇编语言相比的特点: (1)可读性好。 (2)可模块化开发。 (3)可移植性好。 (4)生成的代码效率较低。
unsigned char j ;
for(j=0; j<8; j++) {
buffer[j]=0; }
}
.
8
33
3、C51的基本运算 C51语言的基本运算与标准C类似,主要包括算术运算、关系运算、 逻辑运算、位运算和赋值运算及其表达式等。
1)算术运算符
.
34
2)关系运算符
关系表达式
int x=3; int y=6; int R;
bit的值可以是1(true),或0(false)。
格式: bit 变量名;
例如:
bit
flag;
flag = 0;
.
8
(2)特殊功能寄存器sfr 地址单元80H——FFH之间的片内数据存储区; “sfr” 数据类型占用一个内存单元; 利用它可以访问51单片机内部的所有特殊功能寄存器。 格式: sfr 寄存器变量名 = 字节地址常数;
01000000 | 11111111
00001000 << 3
.
38
【例】以字节操作方式对I/O口P1的P1.5清0 ,P1.1置为1, 其他位保持不变。
例如:
sfr
PSW = 0xd0;
//定义PSW寄存器地址为0xd0
C51单片机编程基本知识

C51单片机编程基本知识C51单片机编程是指使用C语言对C51系列单片机进行编程的过程。
这种编程方式广泛应用于嵌入式系统开发中,具有灵活性高、可靠性强的特点。
本文将介绍C51单片机编程的基本知识,包括单片机结构、编程语言、编译器以及编程流程等。
一、单片机结构C51单片机是由Intel公司开发的一种嵌入式微控制器,由中央处理器、存储器、输入输出接口和外设等部分组成。
其中,中央处理器用于执行程序指令,存储器用于存储程序和数据,输入输出接口用于与外部设备进行交互。
了解单片机的基本结构对于进行C51单片机编程至关重要。
二、编程语言C语言是一种高级编程语言,广泛应用于嵌入式系统开发中。
C语言具备结构化编程的特点,能够提高程序的可读性和可维护性。
在C51单片机编程中,使用C语言可以更加方便地编写程序,并且兼容性强,可以在不同的平台上使用。
三、编译器编译器是将C语言源代码转换为机器语言的工具。
在C51单片机编程中,常用的编译器有Keil C51、SDCC等。
不同的编译器具有不同的特点和使用方法,开发人员需要选择适合自己需求的编译器,并且熟悉其使用方法。
四、编程流程C51单片机编程的流程一般包括以下几个步骤:1. 确定需求:根据实际应用需求,明确单片机的功能和性能要求。
2. 掌握硬件特性:了解单片机的硬件特性,包括引脚功能、外设接口和中断等。
3. 编写代码:使用C语言编写单片机的程序代码,包括初始化设置、主程序和中断服务程序等。
4. 编译代码:使用编译器将C语言源代码编译为可执行的机器语言文件。
5. 烧录程序:将机器语言文件通过烧录工具烧录到单片机的存储器中。
6. 调试测试:连接单片机和外部设备,进行功能测试和调试,确保程序的正确性和稳定性。
7. 优化改进:根据实际运行情况,对程序进行优化和改进,提高性能和效率。
五、常见问题与解决方法在C51单片机编程的过程中,常常会遇到一些问题,下面介绍几个常见问题及其解决方法:1. 编译错误:根据编译器给出的错误提示信息,检查代码语法和逻辑错误,并进行相应的修正。
C51单片机实战100例

C51单片机实战100例C51单片机作为最常用的单片机芯片之一,具有性能稳定、资源丰富、易于学习和开发等优势。
本文将介绍C51单片机实战100例,旨在帮助读者更好地理解和应用C51单片机。
第一例:LED灯闪烁首先,我们以最简单的LED灯闪烁为例,来体验一下C51单片机的编程过程。
首先我们需要准备一个开发板、几个电阻和电源。
然后,根据单片机的引脚图,将LED灯连接好。
接下来,我们需要编写简单的C语言程序来控制LED灯的闪烁。
例如,我们可以使用内置的延时函数来调整灯亮的时间,实现闪烁效果。
经过编译和下载,我们就可以看到LED灯以一定的频率闪烁,一闪一闪的。
第二例:数码管显示除了控制LED灯闪烁外,C51单片机还可以用来控制各种数码管显示。
例如,我们可以编写程序实现数字的倒计时功能。
在倒计时过程中,我们可以通过数码管的显示,直观地观察到时间的变化。
在编写程序时,我们需要根据数码管的接口电路来控制引脚的输出,并使用定时器中断来实现秒数的递减。
通过不断循环调用显示函数,我们可以将倒计时的数字显示在数码管上,并实时更新。
第三例:温湿度检测C51单片机还可以用来进行温湿度的检测。
我们可以连接温湿度传感器到单片机的引脚上,并编写相应的程序来读取传感器的数据。
在编写程序时,我们可以使用串口通信来与PC机进行数据的交互。
通过串口发送指令,单片机可以将温湿度的数据发送回PC机进行实时显示。
这样,我们就可以通过C51单片机来实现温湿度的实时监测功能。
......通过以上几个实例,可以清楚地看到C51单片机的强大功能和灵活性。
C51单片机实战100例可以涵盖更多的应用场景,如蜂鸣器控制、电机驱动、红外遥控等。
读者可以根据自己的需求和兴趣选择相应的实例进行学习和实践。
结语总而言之,C51单片机作为一种常见且广泛使用的单片机芯片,具有强大的功能和灵活性。
通过实战100例的学习和实践,读者可以更加深入地理解和掌握C51单片机的编程方法和应用技巧。
CH14(单片机C51模块化编程)

新语新知—建立头文件的步骤
第二步 防重复包含处理
例如对于delay.h文件,其内容如下: #ifndef __DELAY_H__ #define __DELAY_H__ ... //此处添加代码 #endif
新语新知—建立头文件的步骤
第二步 防重复包含处理 因为在同一个工程内,文件名都是唯一 的,因此这种命名规则可以保证XXX不会重 复。之后要添加到.h文件的代码都放在第3行 的位置。
新语新知—模块化编程的三种手段
函数、宏定义与头文件
实现模块化编程的三个主要手段是函数、 宏定义与头文件,对于函数与宏定义之前我 们有所讲解,通过几个例子使大家进一步加 深对其的理解。下面讲解一下头文件操作的 详细步骤。
新语新知—建立头文件的步骤
第一步 创建头文件 建立一个.c文件(源文件)和一个.h文 件 (头文件)。原则上文件名可以任意 命名,但强烈推荐如下原则: .c 文件与 .h 文件同名 ;文件名要有意义,最好能 够体现该文件代码的功能。例如延时函 数相关的源文件与头文件命名为delay.c 与delay.h。
设置中间过程产生的文件的放置位置
编写主函数,编译 编译之后,可以发现编译器编译出错,说找不到led.h 于是,我们还必须进行一项设置(编译路径)
编译路径我们添加进去了,再重新编译,
可以看到没有报错,(一个警告是因为我们编写的另 外一个函数LED_OFF()函数没有调用),如果想不要 这个警告可以这样设置
延时相关函数的头文件
流程简介:在之前的几讲当中,我们定义过几种延时函
数,现在我们将延时函数统一为两种形式:微秒级延时函数 _delay_us(unsigned int n)与毫秒级延时函数 _delay_ms(unsigned int n)。注意对于单片机C语言,进出 一个函数所消耗的时间都是几个微秒级的,因此微秒级的延 时函数不可能做的非常精确,尤其是延时长度小于10uS时 基本已经无法使用。此处我们采用带参数的宏定义代替函数 形式来实现微秒级延时,可以适当提高定时精度。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
以写若干条语句,一个语句也可以写成几行,不
管一行写几个语句,每个语句须以“;”结尾。
2.程序由一个主函数和若干个其他函数组
成,主函数的名字必须为main。程序的执行总是
从main函数开始的,其位置无特殊规定。
3.C语言程序通过函数调用去执行指定的工
作。源程序文件需要包含其他源程序文件的内容
时,则要在本程序文件头部用包含命令#include
目前针对8051系列单片机开发出来的编译器有 多种,包括Franklin C51、Keil C51 for windows等
3
第二节 程序的格式
先从几个实例,了解C语言的程序格式。
例9-1 能输出“Welcome to use C51”的C语言程序 #include“stdio.h” main() { printf(“Welcome to use C51 \n”); }
其中main( )为主函数,printf为输出函数,stdio.h 为头文件,执行这个程序的目的,是在屏幕上输出以下 一行信息:
Welcome to use C51
4
例9-2 求三个数a、b、c的和。 #include“stdio.h”
main( )
/*主函数*/
{
int a,b,c,sum;
/*定义变量*/
m=max(a,b);
/*调用max函数,将返回值m*/
printf(“max=%d”,m); /*输出m的值*/
}
程序执行结果是在输入a,b值后,可求出较大的数并
赋予变量m 。如输入a=3,b=5,则执行结果可显示出 m=5。
7
从三个例子可看出C语言或C51源程序的基
本格式有如下特点:
1. C语言程序的书写格式比较自由,一行可
间接寻址片内数据存储区,可访问片内全部RAM地 址空间(256字节)
分页寻址片外数据存储区(256字节)由MOVX @R0, A指令访问
片外数据存储区(64K),由MOVX @DPTR,A指令 访问
代码存储区(64K),由MOVC A,@A+DPTR指令访
问
11
C51中定义变量除了定义数据类型外,还应 定义存储类型
例:int data x , y ; 表示变量x , y 为16位整数并 指定存储在片内数据存储区。 1.若未定义存储类型,则C51编译器自动选择默 认存储类型如下表:
存储模式
默认的存储类型
SMALL
默认的存储类型为data,最大为128字节
COMPACT 默认的存储类型为pdata,每页256字节
数据长度 1位 8位 8位 16位 16位 32位 32位 32位 8~24 ? 1 8 16
值域范围 0,1 -128~+127 0~255 -32768~+32767 0~65535 -231~231-1 0~232-1 3.4E-38~3.4E+38 对象地址 0或1 0~255 0~65535
制一些简单的单片机应用程序,并能在 Windows环境下使用C51编译器进行编译 操作。 • 了解C51编译器与标准C语言在存储模 式、片内硬件资源使用等方面的差别。
2
第一节 概述
随着开发工具及集成电路技术的发展,在开发 大型的单片机应用系统时,使用高级语言更加有利
专门针对8051系列单片机开发出来的C51编译 器(简称C51) 可编译生成能够在 8051系列单片机上 运行的目标程序。
10
二、存储类型
存储类型是指该数据在单片机系统中存放的位置,也
就是数据的定位方式。
表 C51存储类型
存储类型 data bdata idata pdata xdata code
与存储空间的对应关系
直接寻址片内数据存储区,访问速度快(128字节)
可位寻址片内数据存储区,允许位与字节混合访问 (16字节)
单片机的C51编程
第一节 概述 第二节 程序的格式 第三节 数据类型和存储类型 第四节 运算符和表达式 第五节 指针与函数 第六节 片内硬件资源的定义 第七节 程序的基本结构 第八节 C51程序举例 第九节 Windows环境下C51编译器的操作
1
本章要点
• 介绍C语言的基础知识。 • 掌握C语言程序的基本结构,学会编
整型、实型、字符、字符串
9
2.变量类型
变量名称 符号
位型量
ቤተ መጻሕፍቲ ባይዱ
字符型
有符号 无符号
整数型
有符号
无符号
长整型
有符号
无符号
浮点型
指针型
特殊位型
8位特殊功能寄存器型 16位特殊功能寄存器型
表 C51变量类型
类型 bit signed char unsigned char signed int unsigned int signed long unsigned long float 指针 sbit sfr sfr16
进行“文件包含”处理。
8
第三节 数据类型和存储类型
一、数据类型
C语言中的数据分为常量和变量,不论常量还 是和变量都有几种不同类型,不同类型的数据占用 的存储长度不同。
1.常量和符号常量的类型
常量指程序运行时其值不能被改变的量,常 量可以用一个标识符表示,并称为符号常量。C语言 中的常量分为如下几种类型:
a=12;b=34;c=56;
/*给变量赋值*/
sum=a+b+c;
/*求和*/
printf(“sum is %d\n”,sum);/*显示结果*/
} 执行以上程序,可在屏幕上输出a、b、c的和,并显示:
sum is 102
5
例9-3 从输入的两个数a,b中,求出较大的 数的程序。
#include“stdio.h”
int max(int x,int y) /*定义max函数,函数返回
值为整型;x,y为形式参
数,整型*/
{ int z;
if(x>y) z=x;
else z=y;
return(z);
/*将z的值返回到调用
处*/
}
6
main()
/*主函数*/
{
int a,b,m; /*定义三个整型变量*/ scanf(“%d,%d,”&a,&b);/*输入变量a和b的值*/
LARGE
默认的存储类型为xdata,最大为64K
12
2.选择变量类型时应尽量选用无符号型,可 以减少测试符号的额外操作,可以提高代码效率。
3.为使编程时书写简化,数据类型允许用缩 写。
例: #define uchar unsigned char #define ulong unsigned long
13
第四节 运算符和表达式