热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

单片机基础项目(上):如何学习单片机?

本文主要介绍关于单片机,c语言,proteus的知识点,对【单片机基础项目(上)】和【如何学习单片机?】有兴趣的朋友可以看下由【小罗のdiary】投稿的技术文章,希望该技术和经验能帮到你解决你所遇的【

本文主要介绍关于单片机,c语言,proteus的知识点,对【单片机基础项目(上)】和【如何学习单片机?】有兴趣的朋友可以看下由【小罗のdiary】投稿的技术文章,希望该技术和经验能帮到你解决你所遇的【单片机原理】相关技术问题。

如何学习单片机?

掌握的一定的单片机理论基础之后,那么应该要实战练习一下,接下来,我会将自己所学到的知识记录下来,方便自己和他人的学习,若不会创建项目没装软件,请看一下往期教程

proteus7.6和keil4的安装_mxzzzr的博客-CSDN博客基于AT89系列单片机的第一个项目-点亮LED灯_mxzzzr的博客-CSDN博客

注:要资源的请点赞加关注,Thanks?(?ω?)?!


目录

一、文章图解

二、流水灯制作

三、数码管原理

1.静态数码管部分

2.动态数码管部分

四、键盘,中断和定时器/计数器

?1.独立式键盘和中断部分

2.矩阵式键盘和定时器

五、定时器

六.lcd灯

1602lcd灯?(只能显示字符,不能显示汉字)


一、文章图解

五、定时器

前面我们几乎都是用延时函数来对电子钟来进行定时,这就导致了我们的延时和真实的秒数有一定的差别,但我们也可以通过更改delay的值来减少这种差别。

delay和定时器的差别

????????1.delay和显示是在同一个cpu上运行的,也就是说,我们的delay和显示是连在一起的

????????2.定时器和显示是在不同的cpu上运行的,也就是说我们的定时器和显示是独立运行的

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP572X44GuZGlhcnk=,size_20,color_FFFFFF,t_70,g_se,x_16

?类似于java的多线程机制。

下面的项目是毫秒级别的计时,精度很高,所以说delay函数来计时的话,误差太大,不适用,那就采用定时器吧!

定时器的使用步骤:

????????有2种运行方式

????????1.不进入中断函数,也叫软件清零方式(写入TF=0)跟delay差不多。

#include
   
     void main(){ TM0D = 0x01;//设置T0为方式1 TR0 = 1;//启动T0 while(1){ TH0=0xfc;//设置T0高8位初值 TL0=0x18;//设置T0低8位初值 while(!TF0){}//判断TF0是否为1,否则一直循环,这一段类似于delay; TF0 = 0;//输入清0代码(以软件的方式) } }
   

????????2.进入中断函数,也叫硬件清零方式,执行完之后TF自动清0。(多线程机制)

#include
   
     void main(){ EA = 1;//开启中断总开关 ET0 = 1;//运行T0中断 TMOD = 0x01;//设置T0工作方式为工作方式1 TH0=0xfc;//设置T0高8位初值 TL0=0x18;//设置T0低8位初值 TR0 = 1;//启动定时器 while(1); } void _T0_ interrupt 1{ //TR0 = 0;如果没让TR0置0,那么中断函数会不断被调用 TH0=0xfc;//设置T0高8位初值 TL0=0x18;//设置T0低8位初值 } 
   

1.仿真图0-99.9s

用到的元器件:

1.7SEG-MPX4-CC

2.74LS138

3.74LS245

4.BUTTON

5.RES

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP572X44GuZGlhcnk=,size_19,color_FFFFFF,t_70,g_se,x_16

2.流程图

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP572X44GuZGlhcnk=,size_16,color_FFFFFF,t_70,g_se,x_16

?3.代码

代码讲解:先在main开启定时器,分为2个过程,main中的while死循环一直更新数码管的值

计数器,对value的值进行加1操作,这2个是不同的过程,多线程。

#include
  
    unsigned char code seg[]={0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f}; unsigned int val=0; unsigned int jl=0;//记录秒数 int value = 0;//当前的值0-999如果用unsigned char的话,会有一定的错误,因为unsigned char的范围为0-255 unsigned char temp; sbit A0=P2^0; sbit A1=P2^1; sbit A2=P2^2; void delay(unsigned int x){ unsigned int i,j; for(i = 0; i 

4.结果

计数器完整视频

六.lcd灯

lcd灯是常用的显示元件,它可以动态显示和静态显示,他比起数码管的显示更丰富,所以说,我们需要记忆的东西也相对来说很多。

我们必须先熟练记住他们的引脚所对应的功能,还有一些指令的命令字,才能得心应手的进行编程,控制。

1602lcd灯?(只能显示字符,不能显示汉字)

我们要对lcd灯进行编程,首先我们需要背下,或者拿起有关的书本来看,才能正确的执行命令。

1602字符的显示位置地址????????

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP572X44GuZGlhcnk=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP572X44GuZGlhcnk=,size_20,color_FFFFFF,t_70,g_se,x_16

? ? ? ????????? 图1是1602的地址,图2是显示字符的ASSCLL码?以上2个图必须要记住或者收藏起来,不然无法在指定位置显示字符

1602引脚

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP572X44GuZGlhcnk=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP572X44GuZGlhcnk=,size_20,color_FFFFFF,t_70,g_se,x_16

LCD1602命令字?(字节操作)? ? ? ?

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP572X44GuZGlhcnk=,size_20,color_FFFFFF,t_70,g_se,x_16

? ? ? ? ?命令1:清屏,光标回到地址00H位置(屏幕的左上角)

? ? ? ? ?命令2:光标返回到00H位置(屏幕的左上角)

? ? ? ? ?命令3:显示屏幕之后的设置

????????????????I/D=1,写完字符后地址右移,I/D=0,写完字符后地址左移

? ? ? ? ? ? ? ? S=1,写入字符后地址移动,S=0,写入字符后地址不移动

? ? ? ? 命令4:显示屏的开关和光标

? ? ? ? ? ? ? ? D=0,关显示,D=1,开显示

? ? ? ? ? ? ? ? C=0,无光标,C=1,有光标

? ? ? ? ? ? ? ? B=0,光标不闪烁,B=1,光标闪烁

? ? ? ? 命令5:光标和字符移动

? ? ? ? ? ? ? ? S/C=1,移动显示的字符,S/C=0,移动光标

? ? ? ? ? ? ? ? R/L=1,左移,R/L=0,右移

? ? ? ? 命令6:功能设置

? ? ? ? ? ? ? ? DL=1,8位数据接口,DL=0,4位数据接口

? ? ? ? ? ? ? ? N=0,单行显示,N=1,两行显示

? ? ? ? ? ? ? ? F=0,5*7点阵,F=1,5*10点阵

? ? ? ? 命令7:CGROM地址设置

? ? ? ? 命令8:显示RAM地址设置(屏幕的位置)

? ? ? ? 命令9:读忙标志或地址

? ? ? ? ? ? ? ? BF=1,不能读取指令或数据

? ? ? ? ? ? ? ? BF=0,能够读取指令或数据

? ? ? ? 命令10:写数据

? ? ? ? 命令11:读数据?

显示指令的步骤?

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP572X44GuZGlhcnk=,size_20,color_FFFFFF,t_70,g_se,x_16

? ? ? ? ????????正脉冲:E=0,E=1,E=0,//正脉冲图像为凸状

????????读状态->写命令->写数据->自动显示。4个步骤,步骤1时加时不加

? ? ? ? ????????读状态代码:

void check(){
	unsigned char dt;
	do{
		dt = 0xff;//无执行命令初始值为0
		E = 0;
		RS = 0;
		RW = 1;
		E = 1;
		dt = P0;//读取P0状态
		}while(dt & 0x80);//检测BF的值命令9
		E = 0;
}

? ? ? ? ????????写命令代码:

????????????????

void command(uchar com){//写命令
	check();//检测显示屏是否忙命令9
    //对照读写操作规定表
	E = 0;
	RS = 0;
	RW = 0;
    //对照命令字表进行设值
	P0 = com;//将命令写入
	E = 1;
	_nop_();//延时1个机械周期
	E = 0;
	delay(1);//延时
}

????????????????写数据

void write(unsigned char dat){
	check();
	E = 0;
	RS = 1;
	RW = 0;
	P0 = dat;//将字符对应的ASSCLL码写入P0总线
	E = 1;
	_nop_();//延时一个机器周期
	E = 0;
	delay(1);//延时
}

一.1602静态显示?

1.仿真图

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP572X44GuZGlhcnk=,size_20,color_FFFFFF,t_70,g_se,x_16

?2.流程图

用到的元器件:

1.74LS245

2.LM016L

3.AT89C51

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5bCP572X44GuZGlhcnk=,size_9,color_FFFFFF,t_70,g_se,x_16

3.代码

代码讲解:首先先写入最基本的几个LCD灯的操作函数,状态函数,命令函数,写入数据函数,写完之后,main先调用init函数,然后看我直接调用了string函数,显示屏就直接显示,下面就去看我的string函数代码段,注释很详细,

#include
  
    #include
   
     //包含——nop()空函数指令的头文件 unsigned int i;//string函数里面用于写入数据 sbit RS = P1^0; sbit RW = P1^1; sbit E = P1^2; //屏幕初始化函数 void init(); //命令函数 void command(unsigned char com); //写入数据函数 void write(unsigned char dat); //检查屏幕是否忙函数 void check(); //显示输入字符串函数 void string(unsigned char ad,unsigned char s[]); //延时函数 void delay(unsigned int j); void main(void){ init(); while(1){ string(0x85,"Hello"); string(0xc2,"Stefanie Sun"); } } void init(){ command(0x38);//命令6;2行显示,5*7点阵,8位数据接口 command(0x0c);//命令4;开2行显示,光标关,无闪烁 //command(0x06);//命令3:写入1个字符整屏显示右移 //command(0x01);//命令1:清屏 //write_command(0x08);//滚动指令 delay(1); } void command(unsigned char com){//写命令 check();//检测显示屏是否忙命令9 //对照读写操作规定表 E = 0; RS = 0; RW = 0; //对照命令字表进行设值 P0 = com;//将命令写入 E = 1; _nop_();//延时1个机械周期 E = 0; delay(1);//延时 } void write(unsigned char dat){ check(); E = 0; RS = 1; RW = 0; P0 = dat;//将字符对应的ASSCLL码写入P0总线 E = 1; _nop_();//延时一个机器周期 E = 0; delay(1);//延时 } void check(){ unsigned char dt; do{ dt = 0xff;//无执行命令初始值为0 E = 0; RS = 0; RW = 1; E = 1; dt = P0;//读取P0状态 }while(dt & 0x80);//检测BF的值命令9 E = 0; } void string(unsigned char ad,unsigned char s[]){ command(ad);//命令8,写入显示的位置 for(i = 0; s[i]!='\0';i++){//遍历字符数组利用for循环一个一个写入字符(字符自动转换为ASSCLL码) write(s[i]);//写入数据 } } void delay(unsigned int x){ unsigned int i,j; for(i = 0; i 
  

4.结果

STC89Cx开发板LCD模块

?二.1602动态显示(电子钟)

1.仿真图

用到的元器件:

1.74LS245

2.LM016L

3.AT89C51

2.流程图

?3.代码

代码讲解:写入状态函数,命令函数,数据函数,string函数,动态显示函数ddisplay(下面代码段有解释),mian中陆续调用init,string,并且启动了T0定时器,是为了更新时分秒的值,在while死循环中一直调用ddisplay以达到更新lcd显示屏的目的。注意:main函数和定时器是2个线程

#include
  
    #include
   
     //包含——nop()空函数指令的头文件 unsigned int i;//string函数里面用于写入数据 sbit RS = P2^6; sbit RW = P2^5; sbit E = P2^7; unsigned char hour = 0;//小时 unsigned char min = 0;//分钟 unsigned char secOnd= 0;//秒 unsigned char temp;//替换常量 unsigned char cishu = 20;//50ms*20=1s //屏幕初始化函数 void init(); //命令函数 void command(unsigned char com); //写入数据函数 void write(unsigned char dat); //检查屏幕是否忙函数 void check(); //显示输入字符串函数 void string(unsigned char ad,unsigned char s[]); //延时函数 void delay(unsigned int j); //动态显示函数 void ddisplay(unsigned char ad, unsigned char value); void main(void){ init(); //给显示屏设置初值 string(0x81,"Day 2022-4-22");//13 string(0xc1,"Time 00:00:00");//13 EA = 1;//开启中断总开关 ET0 = 1;//运行T0中断 TMOD = 0x01;//设置T0工作方式为工作方式1 //50ms TH0 = (65536 - 50000) / 256;//设置T0高8位初值 TL0 = (65536 - 50000) % 256;//设置T0低8位初值 TR0 = 1;//启动定时器 while(1){ ddisplay(0xc6, hour);//小时 ddisplay(0xc9, min);//分钟 ddisplay(0xcc, second);//秒 } } void NowTime() interrupt 1{ //5ms TH0 = 15536 / 256; TL0 = 15536 % 256; cishu--; if(cishu == 0){ second++; cishu = 20;}//50ms*20=1000ms=1s if(secOnd== 60){ secOnd= 0; min++; } if(min == 60){ min = 0; hour++; } if(hour == 24){ hour = 0; } } void init(){ command(0x38);//命令6;2行显示,5*7点阵,8位数据接口 command(0x0c);//命令4;开2行显示,光标关,无闪烁 //command(0x06);//命令3:写入1个字符整屏显示右移 //command(0x01);//命令1:清屏 //write_command(0x08);//滚动指令 delay(1); } void command(unsigned char com){//写命令 check();//检测显示屏是否忙命令9 //对照读写操作规定表 E = 0; RS = 0; RW = 0; //对照命令字表进行设值 P0 = com;//将命令写入 E = 1; _nop_();//延时1个机械周期 E = 0; delay(1);//延时 } void write(unsigned char dat){ check(); E = 0; RS = 1; RW = 0; P0 = dat;//将字符对应的ASSCLL码写入P0总线 E = 1; _nop_();//延时一个机器周期 E = 0; delay(1);//延时 } void check(){ unsigned char dt; do{ dt = 0xff;//无执行命令初始值为0 E = 0; RS = 0; RW = 1; E = 1; dt = P0;//读取P0状态 }while(dt & 0x80);//检测BF的值命令9 E = 0; } void string(unsigned char ad,unsigned char s[]){ command(ad); for(i = 0; s[i]!='\0';i++){ write(s[i]); } } void ddisplay(unsigned char ad, unsigned char value){ command(ad); temp = value / 10 + '0';//十位数转换成ASSCLL码 write(temp);//十位数写入显示屏 temp = value % 10 + '0';//个位数转换成ASSCLL码 write(temp);//个位数写入显示屏 } void delay(unsigned int x){ unsigned int i,j; for(i = 0; i 
  

4.结果

三.电子钟(有功能键)

1.仿真图

用到的元器件

1.74LS245

2.AT89C51

3.BUTTON

4.LM016L

5.NPN

6.RES

7.BUZZER

?2.流程图

?3.代码

代码分析:main函数中调用init,string函数,开启外部中断0和启动计时器T0,进入while死循环,用ddispaly实时更新。进入闹钟设置的关键代码写到main中,因为,如果写到中断里面,那么T0会被阻断,时分秒不再更新。而设置当前时间的关键代码写到外部中断0里面去,因为当你在设置时间,时分秒是不会更新的

#include
  
    #include
   
     sbit RS = P2^0; sbit RW = P2^1; sbit E = P2^2; sbit k2 = P1^0;//进入设置现在的时间中断 sbit k3 = P1^1;//进入设置现在的时间中断小时加1操作 sbit k4 = P1^2;//进入设置现在的时间中断分钟加1操作 sbit secOndadd= P1^3;//进入设置闹钟按下按钮秒数加1 sbit minadd = P1^4;//进入设置闹钟按下按钮分钟加1 sbit houradd = P1^5;//进入设置闹钟按下按钮小时加1 sbit re = P1^6;//退出闹钟设置 sbit buzz = P1^7;//到点了闹钟响 sbit clock = P2^7;//设置闹钟(main里面) unsigned char clocksecOnd= 0;//记录闹钟的秒 unsigned char clockmin = 1;//记录闹钟的分钟 unsigned char clockhour = 0;//记录闹钟的小时 unsigned char secOnd= 0;//记录当前的秒 unsigned char min = 0;//记录当前的分钟 unsigned char hour = 0;//记录当前的小时 unsigned char temp;//中间变量 unsigned char count = 5;//喇叭响的次数 unsigned char cishu = 20;//50ms*20=1s unsigned int i;//string函数里面用于写入数据 //命令函数 void command(char com); //写入数据函数 void write(char dat); //初始化函数 void init(); //显示当前设置的闹钟时间函数 void clockdisplay(); //检查显示屏是否忙 void check(); //显示输入字符串函数 void string(unsigned char ad,unsigned char s[]); //延时函数 void delay(unsigned int x); //动态显示函数 void ddisplay(unsigned char ad, unsigned char value); void main(){ init(); //初始化显示屏 string(0x81,"Day 2022-4-22");//13 string(0xc1,"Time 00:00:00");//13 //T0用来计时,外部中断0用来设置当前的时间 //打开中断总开关 EA = 1; //允许外部中断0中断 EX0 = 1; //中断方式为下降沿方式 IT0 = 1; //允许定时器T0中断 ET0 = 1; //T0的工作方式为工作方式1 TMOD = 0x01; //初始化喇叭 buzz = 0; //初始化定时器初值 TH0 = 15536 / 256;//0.05s TL0 = 15536 % 256;//0.05s TR0 = 1;//T0开始定时 while(1){ ddisplay(0xc6, hour);//小时 ddisplay(0xc9, min);//分钟 ddisplay(0xcc, second);//秒; //到点闹钟响 if(clocksecOnd== second && clockmin == min && clockhour == hour){ while(count--){ ddisplay(0xc6, clockhour);//小时 ddisplay(0xc9, clockmin);//分钟 ddisplay(0xcc, clocksecond);//秒; buzz = 1; delay(500); ddisplay(0xc6, clockhour);//小时 ddisplay(0xc9, clockmin);//分钟 ddisplay(0xcc, clocksecond);//秒; buzz = 0; delay(500); } count = 5; } if(clock == 0){//进入闹钟设置不阻断T0进入当前时间设置阻断T0 while(re != 0){ ddisplay(0xc6, clockhour);//小时 ddisplay(0xc9, clockmin);//分钟 ddisplay(0xcc, clocksecond);//秒; if(secOndadd== 0){ delay(300);//去抖 clocksecond++; if(clocksecOnd== 60) clocksecOnd= 0; } if(minadd == 0){ delay(300); clockmin++; if(clockmin == 60) clockmin = 0; } if(houradd == 0){ delay(300); clockhour++; if(clockhour == 60) clockhour = 0; } } } } } void delay(unsigned int x){ unsigned int i, j; for(i = 0; i 
  

4.结果

AT89CX开发板外部中断0是K3按钮

用开发板实现的话,和仿真差别有点大

1.按键不够,必须用到矩阵式键盘(上面的使用方法,可看函数)

2.喇叭无法使用,因为喇叭和矩阵式键盘的P口都是一样都是P1服了

解决方案

自己买材料按照仿真图焊接一个

下面是模块图(我的开发板喇叭是P1.5,外部中断0是P32->K3

#include
  
    #include
   
     //矩阵键盘的列 sbit S1 = P1^3; sbit S2 = P1^2; sbit S3 = P1^1; sbit S4 = P1^0; sbit buzz = P1^5;//蜂鸣器和按键的P0一样写不了响的功能 //一共四行起到扫描行的作用 int line; unsigned char flag; sbit RS = P2^6; sbit RW = P2^5; sbit E = P2^7; sbit clock = P3^0;//clock是独立式键盘按钮K3->P3.0 unsigned char clocksecOnd= 0;//记录闹钟的秒 unsigned char clockmin = 1;//记录闹钟的分钟 unsigned char clockhour = 0;//记录闹钟的小时 unsigned char secOnd= 0;//记录当前的秒 unsigned char min = 0;//记录当前的分钟 unsigned char hour = 0;//记录当前的小时 unsigned char temp;//中间变量 unsigned char count = 5;//喇叭响的次数 unsigned char cishu = 20;//50ms*20=1s unsigned int i;//string函数里面用于写入数据 //命令函数 void command(char com); //写入数据函数 void write(char dat); //初始化函数 void init(); //显示当前设置的闹钟时间函数 void clockdisplay(); //检查显示屏是否忙 void check(); //显示输入字符串函数 void string(unsigned char ad,unsigned char s[]); //延时函数 void delay(unsigned int x); //动态显示函数 void ddisplay(unsigned char ad, unsigned char value); //扫描函数 void saomiao(); void main(){ init(); //初始化显示屏 string(0x81,"Day 2022-4-22");//13 string(0xc1,"Time 00:00:00");//13 //T0用来计时,外部中断0用来设置当前的时间 //打开中断总开关 EA = 1; //允许外部中断0中断 EX0 = 1; //中断方式为下降沿方式 IT0 = 1; //允许定时器T0中断 ET0 = 1; //T0的工作方式为工作方式1 TMOD = 0x01; //初始化喇叭 buzz = 0; //初始化定时器初值 TH0 = 15536 / 256;//0.05s TL0 = 15536 % 256;//0.05s TR0 = 1;//T0开始定时 while(1){ ddisplay(0xc6, hour);//小时 ddisplay(0xc9, min);//分钟 ddisplay(0xcc, second);//秒; //到点闹钟响 if(clocksecOnd== second && clockmin == min && clockhour == hour){ while(count--){ ddisplay(0xc6, clockhour);//小时 ddisplay(0xc9, clockmin);//分钟 ddisplay(0xcc, clocksecond);//秒; buzz = 1; delay(500); ddisplay(0xc6, clockhour);//小时 ddisplay(0xc9, clockmin);//分钟 ddisplay(0xcc, clocksecond);//秒; buzz = 0; delay(500); } count = 5; } if(clock == 0){//进入闹钟设置不阻断T0进入当前时间设置阻断T0 flag = 1;//如果flag=0跳出闹钟 while(flag){ ddisplay(0xc6, clockhour);//小时 ddisplay(0xc9, clockmin);//分钟 ddisplay(0xcc, clocksecond);//秒; P1=0xef;//按行扫描键盘初始化 for(line=0;line<4;line++){ if(S1 == 0 && line == 2) { delay(300); clockhour++; if(clockhour == 60) clockhour = 0;}//按到S5代表闹钟小时设置 if(S2 == 0 && line == 2) { delay(300); clockmin++; if(clockmin == 60) clockmin = 0;}//按到S6代表闹钟分钟设置 if(S3 == 0 && line == 2) { delay(300); clocksecond++; if(clocksecOnd== 60) clocksecOnd= 0;}//按到S7代表闹钟秒设置 if(S4 == 0 && line == 2) { delay(300); flag=0;}//按到S8代表退出闹钟设置 //P1进行左移操作为什么要与运算呢?若P1=10111011,temp=~p->左移后01110111这样行扫描会出现低电平 temp=~(P1|0x0f);//注意:与数码管部分的左右移代码不同,原因是由于我们按钮按下导致P1口前4个口有低电平(代表按下)->显示对面的字符 temp=temp<<1;//数码管项目有解释说明 P1=~temp; } } } } } void delay(unsigned int x){ unsigned int i, j; for(i = 0; i 左移后01110111这样行扫描会出现低电平 temp=~(P1|0x0f);//注意:与数码管部分的左右移代码不同,原因是由于我们按钮按下导致P1口前4个口有低电平(代表按下)->显示对面的字符 temp=temp<<1;//数码管项目有解释说明 P1=~temp; } } } void ddisplay(unsigned char ad, unsigned char value){ command(ad); temp = value / 10 + '0';//十位数转换成ASSCLL码 write(temp);//十位数写入显示屏 temp = value % 10 + '0';//个位数转换成ASSCLL码 write(temp);//个位数写入显示屏 } //下面是扫描函数的逻辑 /* void saomiao(){ P1=0xef;//按行扫描键盘初始化 for(line=0;line<4;line++){ if(S1 == 0 && line == 3) { delay(300);delay(300);hour++; if(hour == 24) hour = 0; }//按到S1代表当前时间小时设置 if(S2 == 0 && line == 3) { delay(300); min++; if(min == 60) min = 0;}//按到S2代表当前时间分钟设置 if(S3 == 0 && line == 3) { delay(300); string(0xce," "); break;}//按到S3代表当前时间结束设置 if(S1 == 0 && line == 2) { delay(300); clockhour++; if(clockhour == 60) clockhour = 0;}//按到S5代表闹钟小时设置 if(S2 == 0 && line == 2) { delay(300); clockmin++; if(clockmin == 60) clockmin = 0;}//按到S6代表闹钟分钟设置 if(S3 == 0 && line == 2) { delay(300); clocksecond++; if(clocksecOnd== 60) clocksecOnd= 0;}//按到S7代表闹钟秒设置 if(S4 == 0 && line == 2) { delay(300); break;}//按到S8代表退出闹钟设置 //P1进行左移操作为什么要与运算呢?若P1=10111011,temp=~p->左移后01110111这样行扫描会出现低电平 temp=~(P1|0x0f);//注意:与数码管部分的左右移代码不同,原因是由于我们按钮按下导致P1口前4个口有低电平(代表按下)->显示对面的字符 temp=temp<<1;//数码管项目有解释说明 P1=~temp; } } */ 
   
  

本文《单片机基础项目(上)》版权归小罗のdiary所有,引用单片机基础项目(上)需遵循CC 4.0 BY-SA版权协议。


推荐阅读
  • 主函数:CStringGetCPUIDString()Copyright(C)shangweixiao2011 ... [详细]
  • ejava,刘聪dejava
    本文目录一览:1、什么是Java?2、java ... [详细]
  • 本文介绍了基于c语言的mcs51单片机定时器计数器的应用教程,包括定时器的设置和计数方法,以及中断函数的使用。同时介绍了定时器应用的举例,包括定时器中断函数的编写和频率值的计算方法。主函数中设置了T0模式和T1计数的初值,并开启了T0和T1的中断,最后启动了CPU中断。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • 在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板
    本文介绍了在Xamarin XAML语言中如何在页面级别构建ControlTemplate控件模板的方法和步骤,包括将ResourceDictionary添加到页面中以及在ResourceDictionary中实现模板的构建。通过本文的阅读,读者可以了解到在Xamarin XAML语言中构建控件模板的具体操作步骤和语法形式。 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • 关于CMS收集器的知识介绍和优缺点分析
    本文介绍了CMS收集器的概念、运行过程和优缺点,并解释了垃圾回收器的作用和实践。CMS收集器是一种基于标记-清除算法的垃圾回收器,适用于互联网站和B/S系统等对响应速度和停顿时间有较高要求的应用。同时,还提供了其他垃圾回收器的参考资料。 ... [详细]
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
  • 本文介绍了操作系统的定义和功能,包括操作系统的本质、用户界面以及系统调用的分类。同时还介绍了进程和线程的区别,包括进程和线程的定义和作用。 ... [详细]
  • C语言的经典程序有哪些
    本篇内容介绍了“C语言的经典程序有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何 ... [详细]
  • 开发笔记:Python之路第一篇:初识Python
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Python之路第一篇:初识Python相关的知识,希望对你有一定的参考价值。Python简介& ... [详细]
author-avatar
想要把迩贴上私人标签92
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有