首页 单片机学习笔记

单片机学习笔记

举报
开通vip

单片机学习笔记第一课开发板单片机内部资源的三大指标:1.FLASH(程序存储空间<ROM>)相当于电脑的硬盘,掉电不消失读写次数很多,大约为10万次,不用担心用坏了2.RAM(内存)内存理论上无限次擦写,读取速度快3.SFR(特殊功能寄存器)specialfunctionregister单片机的选择:STC89C52:8KFLASH、512字节RAM、32个IO口、3个定时器、1个UART、8个中断源。P89V51RD+:64KFLASH、1024字节RAM、32个IO口、3个定时器、1个UART、8个中断源、1个S...

单片机学习笔记
第一课 旧约精览一百步肺炎基本知识第八章运动和力知识点六上学与问第一课时开学第一课收心教育 开发板单片机内部资源的三大指标:1.FLASH(程序存储空间<ROM>)相当于电脑的硬盘,掉电不消失读写次数很多,大约为10万次,不用担心用坏了2.RAM(内存)内存理论上无限次擦写,读取速度快3.SFR(特殊功能寄存器)specialfunctionregister单片机的选择:STC89C52:8KFLASH、512字节RAM、32个IO口、3个定时器、1个UART、8个中断源。P89V51RD+:64KFLASH、1024字节RAM、32个IO口、3个定时器、1个UART、8个中断源、1个SPI、PWM、并且支持与KEIL连机进行在线仿真。(单步调试)单片机最小系统三要素:电源电路、复位电路、晶振电路。特点:单片机可以运行程序,是单片机控制系统的核心。电源电路VCC为+GND为-电压为5V晶振电路是单片机的心脏,步调一次振动11.0592MHZ复位电路当掉电卡死时可以跳到第一行代码执行短路时保险丝自动断开不是玻璃管的保险丝,老师用的是自恢复保险丝,F1是保险丝,C16是电容,LED1是发光二极管,R34是电阻发光二极管(LED):通常红色贴片LED:电压1.6V~2.4V,电流2到20mA,在2到5mA亮度有所变化,5mA以上亮度基本无变化。电流2ma以下小灯不工作,电流20ma以上会烧坏LED两端电压为2V则求RES2的电阻范围(5-2)/r=2ma(5-2)/R=20ma150-1.5KLED和RES2两端电压一定,RES2的电阻越大,则支路中电流越小,故命名此电阻为限流电阻单片机(MCU),最小控制单元。首先,我们用单片机来控制一个灯的亮灭。P0.0是单片机的一个IO口,如果P0.0端输出5V,VCC也是5V,中间没有电流通过,故LED是灭的,如果P0.0端输出0V,则与GND端是一样的,这时LED亮下面通过软件来编程STC89C52:是国产芯片但我们使用的软件是国外开发的,我们在下面选择一款来代替这种P89V51RD+:以上两种单片机都是51的内核提示是否加入标准8051代码到我们的工程当中,这里点否,现在先不用理解,是个初始化的过程。要写程序必须先建立一个文件,写程序的地方新建以后马上保存,软件自动提示输入名称由于是*.*的文件,所以后缀要我们自己去打,有*.h*.c如果是汇编语言则是*.asm现在我们可以写代码了,但代码的这个文件还不属于这个工程,所以我们下一步右击把该文件加入工程当中。单片机C语言SFR声明:sfrP0=0x80; sfrTCON=0x88;一个字节是8位,一位控制一个I/O口,字节控制所有的I/O口 单片机内部有SFR(特殊功能寄存器)这样的资源,这种模块都是写在单片机内部的,每个模块都占用一个地址,相当于一个房间,在编写程序的时候,如果要用到某个模块,就要在之前声明一下之所以选择STC89C52:这种单片机,是因为它的中文手册很强大32个IO口,每个P口都有8位P0放在什么位置单片机中有这么多的特殊功能寄存器,如果我们每次写程序都要加入他们的话,那就太麻烦了,实际上我们软件开发的时候#include<reg51.h>或者#include<reg52.h>把这些库文件加入进来,我们就不需要对这些寄存器声明了还有一些51核没有的,我们就需要单独声明了如下面这个SFRCMOD=OXD9;完整的程序框架#include<reg51.h>SFRCMOD=OXD9;//51核之外的东西要单独声明main(){}一个P0口有8位进行位声明sbitIT0=TCON^0;sbitLED=P0^0;其实有些位在reg51.h里面有部分声明加WHILE的意思是不允许我们的程序运行到不可知的区域,如果我编写了100行代码,那么程序只能在这100行运行单片机编程是硬件编程,是根据电路图来编程的里面有8个小灯上面有一个三极管,这里起到一个总开关的作用,如果这里三极管不打开的话,下面的灯都不可能亮#include<reg52.h>SbitLED=P0^0;sbitENLED=P1^4;SbitADDR0=P1^0;SbitADDR1=P1^1;SbitADDR2=P1^2;SbitADDR3=P1^3;main(){ENLED=0;ADDR0=0;ADDR1=1;ADDR2=1;ADDR3=1;While(1){LED=0;//小灯的亮灭控制0为低电压,小灯亮;1为高电压,小灯灭}}写完代码后编绎一下再次编绎不同的单片机厂商提供的他们的下载软件都不一样步骤一步骤二步骤三步骤四参数不用改步骤五单片机机是先点下载,然后再上电,单片机在上电的一瞬间会检测是否有程序在下载,如果有程序下载,它就会下载程序,如要没有程序下载,它就会运行自己原来的程序,因此我们点“下载”之后,就要看一下板子改为1是高电压,则小灯灭第二课电磁干扰1、冬天的时候,空气比较干燥的城市,朋友们经常对电脑,铁柜等等放电,这就是“静电放电(ESD)”干扰。2、使用电钻的时候听收音机,看电视有杂音,这就是“快速瞬间脉冲群(EFT)”的效果。3、电脑性能不好,热插拔优盘等外围设备会出现蓝屏重启电脑等现象,这就是热插拔“浪涌(Surge)的效果。去耦电容的使用钽电容有深色线的一侧为正极另一端为负极接GND,体积很小,可以做贴片电容,很贵图上标107的意思是10*10的7次方皮法等于100微发1法拉(F)=1000毫法(mF)=1000000微法(μF)1微法(μF)=1000纳法(nF)=1000000皮法(pF)。电解电容它个头很大,容值也可以做得很大,占空间小,特性比不上坦电容,但便宜陶瓷电容个头小,容值小,但是质量最好的电容所起的作用一是稳定电压(水缸的作用)二是电压突变的时候(蓄水池的作用)低频滤波电容指标:耐压值(2倍以上的耐压值是非常安全的情况,也可以1.5倍,这样电容不致于做得很大)、容值(完全根据电路设计来决定的,耗电量大,容值就要大,要提供的电流给后继,像电路板的耗电是很低的,所以用100μF)低频滤波电容,平常应用最多的是钽电容,电解电容,陶瓷电容,起到去除电源低频纹波,稳定电源的作用。高频滤波电容,电源附近,通常用104电容来进行去除高频干扰。104是10乘以10的4次方pF0.1μF应用的很多,所有器件都需要这个器件电容对于高频信号相当于短路,(通高频,阻低频,根据大量前辈们的经验和实验来选取去除高频干扰,如“静电放电(ESD)”干扰和“快速瞬间脉冲群(EFT)”)三极管是我们的日常应用电路中经常会用到的一个器件。分为PNP和NPN型。三极管常用功能:1、开关控制2、信号放大用在模拟电路中,不属于数字电路的内容3、电平转换此处的三极管起到一个总开关的作用硅管和锗管,只介绍硅管半导体三极管又称“晶体三极管”或“晶体管”。在半导体锗或硅的单晶上制备两个能相互影响的PN结,组成一个PNP(或NPN)结构。中间的N区(或P区)叫基区,两边的区域叫发射区和集电区,这三部分各有一条电极引线,分别叫基极B、发射极E和集电极C,是能起放大、振荡或开关等作用的半导体电子器件。电压导通(导通电路靠电压)对于PNPe极比b极的电压高0.7v,则就有电流通过对于NPNb极比e极的电压高0.7v,则就有电流通过电流控制(如何让它工作在饱和状态靠电流)三极管起放大作用的时,有一种倍数关系,起一个开关作用,就是处于饱和状态,放大作用先不讲数字电路就只有两种状态,一种是截止,一种是饱和先讲开拿左边的PNP三极管来说我们只要保证b极电流100倍大于e极和c极之间的电流电流的流向e极和b极是e极向b极流e极和c极的电流上下都有可能,这个是不一定的LED本身是2V,三极管的电压很小,可以忽略不计(5-2)/330=0.01A1条支路的电流为0.01A8条支路为0.08A要进入饱和状态,b基极的电流要为0.08A的1/100即0.0008A即0.0008为最小电流(保证b极电流100倍大于e极和c极之间的电流)只有LEDS6为低电频才能电流通过,否则没有电流通过(5-0.7)/r=0.0008r=5375欧这里r算的是最大的电阻故R47只需要小于5375欧即可,上面选取了1000欧=1K欧的电阻三极管的电平转换常用的电压标准1.8V3V5V12V24V等等,通常不同的电压标准是不能连接,可能烧坏气件如何进行不同电压的通信?最简单的办法就是使用三极管了如果IO口是5V,如果是高电频,电路就导通了,中间横线支路就输出的是低电频,IO口就输出高电频如果IO口是低电频,电路不导通,中间横线支路就输出高电频也就是说用一个5V的系统控制了一个12V的系统,用三极管做了一个电平转换,这是一个典型特例三八译码器:在上面中一共有5个输入,分别为G1G2CBAG2上划线是包含两个的,与右边的4线与5线合成一线是一个意思我们把4线5线看成一个引脚,ENLED和ADDR3合起来称为使能引脚,也就是控制三八译码器到底是工作还是不工作如果这两个引脚,任何一个引脚达不到要求的话,不管你的输入A0A1A2怎么输入,Y0-Y1输出的都是高电平(数据手册上要求G1输入高电平,G2输入低电平)如上面图中,如果使能端不满足条件,无论CBA怎么输入,Y0-Y7都是高电平,我们加了5个输出口,实际上控制了三八译码器,用3个IO口扩展成8个,输入3个表现出8种状态结合程序来看,ENLED=0(4、5线合起来)表示该口为低电平,ADDR3=1表示该口为高电平使能端口的条件得到满足,故可以三种输入控制8种输出,三八译码器就可以工作了如果这样写程序,更容易看出实质所在第一行为使能条件第二行为3种不同条件的输入可以查表看到结果C对应A2B对应A1A对应A0作业第4课硬件底层驱动,不是纯软件流水灯既然可以点亮灯,可以熄灭灯,那么就可以使其闪烁常用延时办法非精确延时1、for(i=0;i<100;i++); 2、i=100;while(i--);把时间给浪费掉精确延时办法1、利用库 关于工期滞后的函关于工程严重滞后的函关于工程进度滞后的回复函关于征求同志党风廉政意见的函关于征求廉洁自律情况的复函 数_nop_();(需要include<intrins.h>) 2、利用定时器进行定时(后边的课程进行介绍)变量类型下面为小灯闪烁的程序#include<reg52.h>Typedefunsignedcharuint8;//注意这里并不是只能存字符Typedefunsignedintuint16;sbitLED=P0^0;sbitENLED=P1^4;sbitADDR0=P1^0;sbitADDR1=P1^1;sbitADDR2=P1^2;sbitADDR3=P1^3;main(){Uint8i; ENLED=0;ADDR3=1; ADDR0=0;ADDR1=1;ADDR2=1; while(1) { LED=0;For(i=0;i<100;i++);LED=1;For(i=0;i<100;i++); }}实际却没有达到效果,而是小灯一直亮着For(i=0;i<100;i++);因为我们并不知道这段时间是多长时间,少于10ms,人的肉眼根本无法察觉出来灭,是个长亮的过程Keil软件的仿真方框里为晶振大小,这里我们用的是11.0592Mhz,点确定,之后可以在软件仿真Debug选项里用默认用软件仿真,点确定这就进入了一个仿真环境,左侧会出现寄存器里的值,右边会出现单步运行,我们复位一下,黄色箭头就没有了,左侧的sec表示,程序运行到某一个需要的时间,我们在17行的前面双击一下,就会出现红点叫作断点,也就是程序运行到此处就会停止,左边为复位键,右边为全速运行键,是我们最常用的键,一全速运行就会运行到第一个断点也就是一个FOR语句才用了0.3个msUint8i;For(i=0;i<10000;i++);我们可以改一下i<10000可是我们别忘记了i的取值范围,应该uint16I;才对现在是54ms了54-0.4即为一个for循环的延时长时间的延时For(j=0;j<100;j++){For(j=0;j<10000;j++);}我们规定LED是P0.0口我们可以直接写成(11111110)与上面两句是一个效果,由于头文件中有对P0口的定义P0=0XFE;是让第一个小灯亮流水灯程序#include<reg52.h>Typedefunsignedcharuint8;//注意这里并不是只能存字符Typedefunsignedintuint16;sbitENLED=P1^4;sbitADDR0=P1^0;sbitADDR1=P1^1;sbitADDR2=P1^2;sbitADDR3=P1^3;main(){Uint16i; ENLED=0;ADDR3=1; ADDR0=0;ADDR1=1;ADDR2=1; while(1) {P0=0XFE;For(i=0;i<30000;i++);P0=0XFD;For(i=0;i<30000;i++);P0=0XFB;For(i=0;i<30000;i++);P0=0XF7;For(i=0;i<30000;i++);P0=0XEF;For(i=0;i<30000;i++);P0=0XDF;For(i=0;i<30000;i++);P0=0XBF;For(i=0;i<30000;i++);P0=0X7F;For(i=0;i<30000;i++); }}左移<<右移>>X<<2X>>2左移,最低位填0补充;右移,最高位填0补充0xf0=11110000左移一位变成11100000右移一位变成01111000按位取反符号~取反后1变成0,0变成10x0F取反后成为0xF0,即00001111->11110000流水灯程序就已经优化好了如下Uint8j;Uint16i; ENLED=0;ADDR3=1; ADDR0=0;ADDR1=1;ADDR2=1; while(1) {P0=~(1<<j++);当j=1时,1左移j位就是1位,移完之后,j=2,1是00000001左移一位为00000010但这不是我们要的效果,这样的话7个被点亮了,一个是灭的,再按位取反即可当j=0时00000001左移0位,取反为11111110j++之后当j=1时00000001左移1位,为00000010取反为11111101For(i=0;i<20000;i++)If(j==8)j=0;因为小灯只有8个 }可以扩展为从左到右亮,从右往左亮,全部亮,再一个一个依次灭等等多种花样的流水灯8个发光二极管组成了一个数码管,共阴数码管,共阳数码管共阴数码管就是所有发光二极管的阴极接在一起共阳数码管就是所有发光二极管的阳极接在一起这8个发光二极管的接法与下面8个小灯的接法完全一样的如果要使数码管上显示数字1,则只需要点亮b,c即可根据单片机连接电路,计算出数码管的真值表0123450xc00xf90xa40xb00x990x926789Ab0x820xf80x800x900x880x83CdEF0xa70xa10x860x8e作业·1、记住C语言2个变量类型及其范围,掌握C语言的位操作和字节操作。·2、用3个LED小灯做一个交通灯的程序。·3、根据原理图和流水灯程序,独立完成流水灯反方向流动以及小灯一个个点亮直到全亮的功能。·4、明白数码管的原理,写出数码管真值表。第5课我们用了一个11.0592Mhz的晶振,那么周期就是频率分之一了时钟周期和机器周期·时钟周期T是时序中最小的时间单位。具体计算就是1/时钟源。我们开发板上单片机使用的时钟周期=1/11059200s。·机器周期CPU完成一个操作的最短时间。普通51一个机器周期是12个时钟周期。定时器和计数器·2个定时器/计数器:定时器0和定时器1·定时器:每经过一个机器周期,寄存器加1。因此,可以将机器周期看作为计数周期。·计数器:后续课程介绍。·特殊功能寄存器TCONTF:定时器溢出标志。溢出时,该位自动置1。中断执行时硬件清零,或者软件清零。TR:定时器运行控制位,置1开始计时,清0停止计时。·特殊功能寄存器TMODT1和T0分别代表单片机两个计数器GATE:该位被置位时为门控位。仅当TR1被置位并且INT1脚为高,定时器开始计数。当该位被清零时,只要TR1被置位,定时器1马上开始计数。C/T:该位为0的时候,用作定时器,该位为1的时候,用做计数器。(功能转换的作用)GAT位(最高位)当TR1打开的时候,正常情况下,计数器开始计数,但是如果GAT位被置1,TR1被置位,并且INT1脚为高,定时器开始计数。测电平的宽度这个信号通过P3.3输入,然后我们在这个时间打开定时器,并且GAT位置1,在低电平的时候实际上是不计数的,计数必须满足两个条件,一是TR1被置为1,二是INT1脚为高电平。从低电平到高电平再到低电平,只有在高电平的时候才计数,我们可以把定时器的时间拿出来,这样我们就可以测电平的宽度。剩下的M1,M0位,控制着定时器4种不同的工作状态·00011011·模式0模式1模式2模式3·模式1:16位的计数器。(TH1,TL1)是定时位器的高8位和低8位(这节课只讲模式1)单片机内部是8位的,它就专门拿出2个字节来,就成了16位,一个字节是TH1,一个TL1,TL1从0开始,计到255,再加1溢出,那么TH1就加1,也就是256*256=65535才会溢出·模式2:自动装载8位计数器。主要应用在串口波特率发生器。·模式0&模式3:几乎不用。·TCON和TMOD复位后都会自动变成0x00.·12*(65536-x)/11059200=0.001TIPS:一个单片机被做好了,实际这些功能都固定了,这些模块是如何做的,不用我们管,我们只管会用就行了,刚才讲的理论,很可能理解不了,一讲应用就好了。使用定时器的方法·第一:设置特殊功能寄存器TMOD,使之工作在需求的状态。·第二:设置计数寄存器的初值,精确设定好定时时间。·第三:设置特殊功能寄存器TCON,通过打开TR来让定时器进行工作。(也可设置为中断模式)·TH1=0xfc;TL1=0X66;·12(65536–x)/11059200=0.02s我们看下TMOD,我们要设置它的时候,GATE位,我们是清零的,单片机可以复位,不管是上电复位,还是通过复位引脚复位,复位之后,所有有寄存器都会有一个复位值,对于这两个SFT来说,他们都会自动变成0。也就是说复位和重新上电之后,他们都会变成0。那么TMOD,首先GATE位我们清0,C/T位也是0。我们要用模式1,所以M1,M0位就是01了,如下所示剩下的M1,M0位,控制着定时器4种不同的工作状态·00011011·模式0模式1模式2模式3使用定时器的步骤1设置特殊功能寄存器TMOD上面的情况,是我们单用一个定时器T1的情况我们讲过一个机器周期的时间为12*(1/11059200)12倍的时钟周期0~65535一个循环是65536次,这个时间是多少呢?是12*65536*(1/11059200)=发生溢出一旦放生溢出,TF位置位,所以我们想控制多长时间,我们可以设置TH1和TL1,为什么这么讲?使用定时器的步骤2设置计数寄存器的初值如果TH1和TL1合成0x00我们可以知道计了这么长时间12*(65536-x)*(1/11059200)=1ms=0.001S假设我们定时为1ms,那么我们可以计算x的值,x=64614也就是我们的初始可以设置为64614,正好1ms之后就可以溢出了。64614转化为十六进制为FC66所以TH1=0XFC;TL1=0X66;上节课我们是让小灯以大约的时间闪烁,下面这节课我们让小灯进行精确的1S闪烁。#include<reg52.h>Typedefunsignedcharuint8;//注意这里并不是只能存字符可以存数字的,可以0-255Typedefunsignedintuint16;sbitENLED=P1^4;sbitADDR0=P1^0;sbitADDR1=P1^1;sbitADDR2=P1^2;sbitADDR3=P1^3;sbitLED=P0^0;main(){Uint8counter; ENLED=0;ADDR3=1;//三八译码器的使能 ADDR0=0;ADDR1=1;ADDR2=1; TMOD=0X01;//设置工作模式1的情况下8位是一起操作的,不是单位操作TH0=0XB8;TL0=0X00;//B800起始值的计算12*(65536-x)*(1/11059200)=1ms=0.001S假设我们定时为1ms,那么我们可以计算x的值,x=64614也就是我们的初始可以设置为64614,正好1ms之后就可以溢出了。64614转化为十六进制为FC66所以TH1=0XFC;TL1=0X66;TR0=1;//打开计时器是单位操作至于哪些可以单位操作,哪些不可以单位操作,我们可以查手册*表时寄存器可以进行位寻址只要可以进行位操作的,都可以进行字节操作TMOD只可以进行字节操作while(1) {//前面我们打开定时器后就开始计时了,定时器溢出的时候已经过了20ms,TF0自动变成1·If(1==TF0)//特殊功能寄存器TCON//TF:定时器溢出标志。溢出时,该位自动置1。中断执行时硬件清零,或者软件清零。{TF0=0;//我们前面讲过,如果不进行中断的话,必须软件清0TH0=0XB8;TL0=0X00;//经过计算从此处开始计时,刚好是20mscounter++;}IF(counter==50)//50次20ms的时间,正好1S{counter=0;LED=~LED;//取反,让高电平变成低电平,低变高一个小灯的情况,亮1S,灭1S} }}12*(1/11059200)*65536=0.0711S=71.1ms最大定时才71.1ms,那我们应该怎么做呢?我们只需要定时20ms,再让他产生50次20ms就是1S了第六课·数组是一组变量,这组变量需要满足三个条件:1、具有相同的数据类型2、具有相同的名字3、在存储器中是被连续存放的a[5]={1,2,3,4,5}a[]={1,2,3,4,5}a[0]=1;a[1]=2;a[2]=3;a[3]=4;a[4]=5;数码管接着LEDS0而LEDS0接着三八译码器的Y0,所以ADDR0到2都为0,Y0再输出0(低电平)下面这个程序的功能是在数码管上显示0到FUint8num[]={0xc0,0xf9,0xa4,0xb0,ox99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xa7,0xa1,0x86,0x8e};//把0-F的真值表放数组里Uint8counter,i; ENLED=0;ADDR3=1;//三八译码器的使能 ADDR0=0;ADDR1=0;ADDR2=0; TMOD=0X01;//设置工作模式1的情况下8位是一起操作的,不是单位操作TH0=0XB8;TL0=0X00;//B800起始值的计算TR0=1;//打开计时器是单位操作至于哪些可以单位操作,哪些不可以单位操作,我们可以查手册while(1) {if(1==TF0){TF0=0;//我们前面讲过,如果不进行中断的话,必须软件清0TH0=0XB8;TL0=0X00;//经过计算从此处开始计时,刚好是20mscounter++;}if(counter==50)//50次20ms的时间,正好1S,1S过后,才会显示下一个字符{P0=num[i++];counter=0;}If(i==16)执行上面的代程后i++共16个数,故判断i==16,如果显示到F再回到0重新显示{i=0;} }}·动态显示:轮流向各位数码管送入数据,并且将数据输入速度控制在人肉眼所分辨不出来的范围内,利用发光二极管的余晖让人的视觉能够识别的过程。下面这个程序的功能是把所有的数码管同时从0显示到FUint8num[]={0xc0,0xf9,0xa4,0xb0,ox99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xa7,0xa1,0x86,0x8e};//把0-F的真值表放数组里Uint8counter,i,j=0; ENLED=0;ADDR3=1;//三八译码器的使能 TMOD=0X01;//设置工作模式1的情况下8位是一起操作的,不是单位操作TH0=0XB8;TL0=0X00;//B800起始值的计算TR0=1;//打开计时器是单位操作至于哪些可以单位操作,哪些不可以单位操作,我们可以查手册while(1) {if(1==TF0){TF0=0;//我们前面讲过,如果不进行中断的话,必须软件清0TH0=0XB8;TL0=0X00;//经过计算从此处开始计时,刚好是20mscounter++;}if(counter==50)//50次20ms的时间,正好1S,每经过20ms,就点亮一个数码管,也就是在1S的时间里,把所有的数码管同步点亮,其实我们看到的只是余晖,而小灯早就已经灭了{P0=num[i++];counter=0;}If(i==16)//执行上面的代程后i++0到F共有16个数,故判断i==16{i=0;}If(j==0)//当j==0时,让第一个数码管发光{ ADDR0=0;ADDR1=0;ADDR2=0;j++;}If(j==1){ ADDR0=1;ADDR1=0;ADDR2=0;j++;}If(j==2){ ADDR0=0;ADDR1=1;ADDR2=0;j++;}If(j==3){ ADDR0=1;ADDR1=1;ADDR2=0;j++;}If(j==4){ ADDR0=0;ADDR1=0;ADDR2=1;j++;}If(j==5){ ADDR0=1;ADDR1=0;ADDR2=1;j=0;} }}实际上是分时处理每个数码管,只是我们人的肉眼无法辨别出来。switch语句·适合多选一的选择性语句,具体使用方法:·switch(表达式)·{case表达式一:语句1;·case表达式二:语句2;·……·default:语句n;·}对上面程序的改进如下Uint8num[]={0xc0,0xf9,0xa4,0xb0,ox99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xa7,0xa1,0x86,0x8e};//把0-F的真值表放数组里Uint8counter,i,j=0; ENLED=0;ADDR3=1;//三八译码器的使能 TMOD=0X01;//设置工作模式1的情况下8位是一起操作的,不是单位操作TH0=0XB8;TL0=0X00;//B800起始值的计算TR0=1;//打开计时器是单位操作至于哪些可以单位操作,哪些不可以单位操作,我们可以查手册while(1) {If(1==TF0){TF0=0;//我们前面讲过,如果不进行中断的话,必须软件清0TH0=0XB8;TL0=0X00;//经过计算从此处开始计时,刚好是20mscounter++;}if(counter==50)//50次20ms的时间,正好1S{P0=num[i++];counter=0;}If(i==16)执行上面的代程后i++共16个数,故判断i==16{i=0;}Switch(j){case0:ADDR0=0;ADDR1=0;ADDR2=0;j++;break;case1:ADDR0=1;ADDR1=0;ADDR2=0;j++;break;case2:ADDR0=0;ADDR1=1;ADDR2=0;j++;break;case3:ADDR0=1;ADDR1=1;ADDR2=0;j++;break;case4:ADDR0=0;ADDR1=0;ADDR2=1;j++;break;case5:ADDR0=1;ADDR1=0;ADDR2=1;j=0;break;default:break;}}}对于我们这个刷新速度来讲,我们是不可知的,刷新速度很快,不知道多长时间刷新一次,我们还可以进行刷新的定时,定时每1ms刷新一次,12*(65535-X)*1/HZ=0.001X=FC67Uint8num[]={0xc0,0xf9,0xa4,0xb0,ox99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xa7,0xa1,0x86,0x8e};//把0-F的真值表放数组里Uint8i,j=0;Uint16counter; ENLED=0;ADDR3=1;//三八译码器的使能 TMOD=0X01;//设置工作模式1的情况下8位是一起操作的,不是单位操作TH0=0XFC;TL0=0X67;//B800起始值的计算TR0=1;//打开计时器是单位操作至于哪些可以单位操作,哪些不可以单位操作,我们可以查手册while(1) {If(1==TF0){TF0=0;//我们前面讲过,如果不进行中断的话,必须软件清0TH0=0XFC;TL0=0X67;//经过计算从此处开始计时,刚好是20mscounter++;Switch(j)//进入一次定时器,进入一个1ms,就刷新一次,有6个数码管,轮流一圈就是6ms了,我们规定的{case0:ADDR0=0;ADDR1=0;ADDR2=0;j++;break;case1:ADDR0=1;ADDR1=0;ADDR2=0;j++;break;case2:ADDR0=0;ADDR1=1;ADDR2=0;j++;break;case3:ADDR0=1;ADDR1=1;ADDR2=0;j++;break;case4:ADDR0=0;ADDR1=0;ADDR2=1;j++;break;case5:ADDR0=1;ADDR1=0;ADDR2=1;j=0;break;default:break;}}if(counter==1000)//1000次1ms的时间,正好1S{P0=num[i++];//定时1S更新下一个字符,整个过程全部受控制,另外使用了动态显示counter=0;}If(i==16)执行上面的代程后i++共16个数,故判断i==16{i=0;}}}第七课冷启动就是先下载,后上电,默认选择第一项一旦选择第二项,等到你下次你再下载程序的时候,你当前的这一次,不管你什么下了,选择的是第二项,你都下载成功了,那么再次下载的时候,你必须等到P1.0P1.1两个引脚为低电平再可以,如果你选择第二项,下次下载时必须把这两个引脚置低电平,否则下载不成功上面两个是GND下面两个是P1.0和P1.1如果我们选择第二项,那么下次下载的时候,必须把P1.0和P1.1和GND连接起来,随便找一个导电的线,把4个引脚同时给连接到一起就可以了。连到一起都是低电平了。变量1、局部变量:在函数内部声明的变量是内部变量,它只在本函数内有效,在此函数外是不能作用的。函数体内占内存,出了函数释放内存。2、全局变量:在函数外边声明的变量就是外部变量,也叫做全局变量,一个源文件(.c)可以包含一个或者多个函数,全局变量的作用范围是从声明的位置一直到文件结束,一直占用内存。3、静态变量在函数体内声明,前边加static关键字声明,属于局部变量,和局部变量的区别是一直占用内存,和全局变量的区别是只能在函数体内使用。注意:只有第一次赋值有效。三要素:电源电路,晶振电路,复位电路电源电路是USB5V供电的最常用的CPU电压有3V和5V单片机的正常电压是3.8V-5V,高于5V会烧单片机,低于3.8V不会工作STC89C51RC我的用的单片机型号P89V51RD2上面有两个晶振引脚,对地接10PF到3040PF的两个电容,初学直接接20PF即可如下单片机不工作,就是检查最小电路,方法如下万用表测电压,看是不是在3.8V-5V之间晶振通常用示波器来测,我们也可以用万用表简单的测一下,用红表笔对晶振的引脚,黑表笔接GND,测电压,一般在1V-4V之间,如果在0V和5V和VCC一样,那就不正常晶振电路·1、晶振选择:·根据实际系统需求选择,6M,12M,11.0592M,20M等等·2、负载电容:·对地接2个10到30pF的电容即可,常用20pF。·3、万用表测晶振:·直接用红表笔对晶振引脚,黑表笔接GND,测量电压即可。复位电路·复位:·重新上电,把单片机内部电路设置成为一个确定的状态,所有的寄存器初始化,即设为最初的值。·标准51单片机的复位时间大约在2个机器周期左右,具体需要看芯片数据手册。这个时间比2个机器周期大可以,但小就不行了·一般通过复位芯片或者复位电路,具体的阻容参数的计算,通过google查找。才开始的可以用下面这个电路图高电平复位,低电平正常工作一个电容起充放电的作用,下面为一个下拉电阻当左边的按键不按下的时候,电容对直流是隔离的,GND和RST复位的接触点,而接触点与GND的电压是一定的,因为电流不通过,不存在任何电压差,电按键按下的时候,RST复位处于高电平,只要它的电压处在VCC的范围之内,按下按键的一瞬间,上电复位和按键复位,上电复位,当按键按下的时候,给C11充电,渐渐的C11两端的电压为5V时,RST引脚处的电压就为低电平。单片机IO口状态·1、普通IO口·2、强推挽·3、开漏(开集)·4、单片机IO口的驱动能力·5、74HC245(驱动的器件)的应用在驱动发光二极管和数码管的时候,我们用到了它是一个驱动的器件我们当时把GND去掉换成一个IO口我们可以把VCC去掉换成一个IO口吗?带着这个疑问,我们就可以知道单片机的IO口,如果是让它输出大电流的话,因为我们驱动LED前面讲过,它必须大于2MA,我把单片机的IO口,都用软件给画出来了红框框住的是单片的内部,其它为外部mos管我们还没讲,它和三极管的原理是一样的,我们先用它来代替讲解当单片机内部总线输出一个高电平的时候,三极管内管不会导通,单片机外部IO口输出一个高电平当单片机输出一个低电平的时候,三极管导通,VCC和GND就可以导通,单片机的IO口就输出一个低电平当输出高电平的时候,VCC下面有一个电阻,P1口是一个带内部上拉的8位双向口。P89V51RD2没有介绍,但STC89C51RC的介绍了,他的输出能力大约是250微安,也就是我们不带下接电阻的话,它的输出能力大约为250微安,5v/250uA=20K欧,如果这个时候我们要求它输出大电流的话,我们必须加一个下接电阻,用这个外部的电流输出,给它提供,对于外部电路想当于一个并联电路,(3、加大普通IO引脚驱动能力。)实际上250uA是很小的,根本可以忽略不计,所以我们就当成外部电路供电的。这是一个内部带上拉电阻的普通IO口。前面讲到LED小灯的时候,我们不仅仅用外部电路来输入,还加了一个三极管。使用方法可以参考。第二种叫强推挽输出这里我把它的IO口设置打开,对比讲一下它是可设置的,也就是说可编程的默认为00是标准的准双向口大家注意,灌电流单个引脚最高达20mA,但是它的整体电流最好不超过55mA,因此我反复强调,单片机是一个控制模块,不是一个驱动的东西,所以要避免给单片机输入或者输出一个大电流,那么这是它的普通IO口。什么叫推挽输出没有一个上拉电阻,一旦内部总线输出一个高电平,高电平在这里导通,上面的三极管就导通了,高电平经过一个反向器就会变成低电平,下面的三极管是截止不导通的。因此电流就从单片机的IO口直接输出了,没有限流电阻,电流是非常大的,因此外部一定要加限流电阻,不加限流电阻可能烧坏单片机的引脚。到内部是低电平的时候,上面三极管是截止的,下面三极管就会导通,如果外部是一个高电平,外部顺着就流进来了,这个电流也是非常大的,因此外部也要加限流电阻,这就是一个强推挽输出。开漏也叫开集,集电极嘛,假如内部总线是高电平,它内部总线经过一个反向器,经过之后变成低电平,它内部是没有下拉电阻,他是开路,完全是这样的·2、OC门必须加上拉电阻才能使用。开着的呢,左边即使是高电平,三极管导通,右边也不会输出一个高电平,内部是一个低电平的话,他还是一个低电平,因此呢,必须加一个上拉电阻,才有可能输出一个高电平。写1的话,三极管的左边是高电平,如果没有上拉电阻,内部是悬空的,不可能输出高电平,因此开漏的时候,外部要加上拉电阻的,它的作用也很多,比如我们说,在实际应用系统中,比如在电平转换当中,要用一个5V的系统控制一个12V的电路我们用5V来控制三极管的导通,一旦导通,外部电路就是12V,可以时行电平转换这里我们要尽量避免单片机外部直接接12V通过上面的了解,我们知道,单片机IO口的状态,大体知道是怎么回事,这里讲,只是让我们讲到的时候,我们有点印象单片机IO口仅做控制,不做驱动,普通的IO口最多会输出200多微安,如果是强推挽输出,可输出大电流20mA,但是对于整个单片机系统,我们推荐不超过50mA,如果要驱动的话,我们一般单独用驱动器件,不要直接用单片机的IO口去驱动,特殊的情况下是可以的。如果单片机的IO做驱动的话,它就会长时间的处在高功率的工作模式下,所以建议IO口不做驱动用。这就是一个驱动电路,单片机只是一个控制器件,真正的驱动全靠这个74HC245器件。这个器件可以通过最大电流为100mA,如果每条支路10mA,8条支路也才80mA。74HC245器件的左边是直接接单片机的IO口,右边是接小灯的,是一个驱动电路,内部构造可以看数据手册。上下拉电阻·上拉就是将不确定的信号通过一个电阻嵌位(保持)在高电平,另外起到限流的作用,下拉同理。高电平时嵌位,低电平限流·1、电平转换,提高输出电平数值。·2、OC门必须加上拉电阻才能使用。·2、OC门必须加上拉电阻才能使用。开着的呢,左边即使是高电平,三极管导通,右边也不会输出一个高电平,内部是一个低电平的话,他还是一个低电平,因此呢,必须加一个上拉电阻,才有可能输出一个高电平。··3、加大普通IO引脚驱动能力。·4、悬空引脚上下拉抗干扰。(悬空一定程度上有功耗和干扰。)默认左边为低电平,三极管是不导通的,外部没有电流通过电阻,电压不会下降,外部则长时间保持高电平,这个电阻就起到了高电平的作用,一旦三极管导通了,就会了电流向下流到GND,这时又起到限流作用。上拉电阻选取原则·1、从节约功耗及芯片灌电流能力考虑应当足够大;电阻大,电流小。·2、从确保足够的驱动电流考虑应当足够小;电阻小,电流大。·3、对于高速电路,过大的上拉电阻可能会导致边沿变平缓。(数字电路从0变成1实际上是一个缓慢的过程,并不是一下子就可以的)·综合考虑:上拉电阻常用值在1K到10K之间选取,下拉同理。在线仿真·ISP:In-SystemProgramming,是指在系统可编程,指电路板上的空白器件(单片机)可以编程写入最终用户代码,而不需要从电路板上取下器件,已经编程的器件也可以用ISP方式擦除或再编程。·Ice:InCircuitEmulator,是指在线仿真器,ICE是最为常用的调试设备,它的核心思想是完全模拟CPU工作,通过外围电路捕获CPU的各种状态信息,输送到PC端,通过PC来查看当前CPU的工作状态。流水灯程序从左往右流Uint8j;Uint16i; ENLED=0;ADDR3=1; ADDR0=0;ADDR1=1;ADDR2=1; while(1) {P0=~(0x80>>j++);10000000十六进制为0x80右移就可以了再取反就成01111111始终只有一个低电平当j=1时,1左移j位就是1位,移完之后,j=2,1是00000001左移一位为00000010但这不是我们要的效果,这样的话7个被点亮了,一个是灭的,再按位取反即可当j=0时00000001左移0位,取反为11111110j++之后当j=1时00000001左移1位,为00000010取反为11111101For(i=0;i<20000;i++)If(j==8)j=0;因为小灯只有8个 }从左往右流的另一种 方案 气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载 j=8; while(1) {P0=~(1<<j--);00000001 For(i=0;i<20000;i++)If(j==0)j=8; }程序有问题了,最后一个小灯不亮,因为j=0的时候,才亮到倒数第二个小灯经过下面的在线仿真,我们把程序改正如下(上面的j--的第一步是费的,不起作用的) while(1) {P0=~(1<<--j);00000001 For(i=0;i<20000;i++)If(j==0)j=8; }复位再次复位调COM4口真正的进入在线仿真左边复位,右边全速运行先点复位,再点全速运行,一旦点了全速运行,板子上就有情况了如果想回到之前的状态必须先按板子上的复位,停止之后,软件上就会停止,然后再按一下就会回到刚才的状态在这里可以看到变量的值在线仿真可以查看特殊功能寄存器进行程序调式&和|且或·对于不能进行直接位操作的SFR进行位操作的办法:·某一位置1的办法:a=a|10000000,将要置1的位为1,其他为0。·a|=0x01;低位置1a=xxxxxxx1·某一位清0的办法:a=a&xxxxxxx0,将要清0的位为0,其他为1。·a&=0xef;xxx0xxxx0xef的二进制为11101111第八课中断学会了,单片机的灵魂就会了板子上所有模块都可以同时工作单片机要同时控制很多模块,这时就要用中断中断的SFR中断使能控制寄存器IE·EA:总中断使能位,总阀门。·EC:PCA中断使能位·ET2:定时器2中断使能位定时器0,1与定时器2有些不同·ES:串口中断·ET1:定时器1溢出中断使能·EX1:外部中断1使能·ET0:定时器0溢出中断使能·EX0:外部中断0使能P3.2P3.3是外部中断中断使能位,相当于设定闹钟,时间一到,就会响有一中断使能位和溢出标识位两者的结合完成了中断的应用这节课用中断做一个秒表Typedefunsignedlonguint32;6个数码管已经超过了最大16位的数65536,换成32位的#include<reg52.h>typedefunsignedcharuint8;typedefunsignedintuint16;typedefunsignedlonguint32;codeuint8number[]={0xc0,0xf9,0xa4,0xb0, 0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x83, 0xa7,0xa1,0x86,0x8e};//加code不会变化的数组写入Flash里uint8a[6];//这种变化的只能放在内存里面由于RAM太小了,我们要尽量节省内存6个数码管来秒加,相当于秒表,有6位数,故为a[6]uint16counter=0;sbitENLED=P1^4;sbitADDR0=P1^0;sbitADDR1=P1^1;sbitADDR2=P1^2;sbitADDR3=P1^3;//上面5行是三八译码器的使能和选择voidtimer1_init()//定时器初始化{ TMOD|=0x10;//这样把定时器的M0位置1了·00011011·模式0模式1模式2模式3使用定时器的方法·第一:设置特殊功能寄存器TMOD,使之工作在需求的状态。·第二:设置计数寄存器的初值,精确设定好定时时间。·第三:设置特殊功能寄存器TCON,通过打开TR来让定时器进行工作。(也可设置为中断模式)·TH1=0xfc;TL1=0X66;·12(65536–x)/11059200=0.02s TMOD&=0xdf;//这样把定时器的M1清0了 ,也就确定了工作方式是模式1,是16位的定时器功能这个程序我们只用的T1,假设此程序即用到了T1又用到T0.voidtimer1_init(){ TMOD=0x11;//当我们还想用T0的时候,我们必须回头去参考T1的设置,如是写T1为TMOD=0x10;那么我们设置T0的时候只能写TMOD=0x11而不能写TMOD=0x01这样会改变T1的设置,所以这是用移位最大的好处,就是设置T1,再设置T0时不影响T1的设置与等,或等。因此以后寄存器的功能设置,如果我们只用到一位,我们就用与或进行位操作。如果要用到多位,就用字节操作。还有等以后程序大了,不同的人编写不一样的部分,用与等或等不会影响到他人。TMOD=0xdf;} TH1=0xFC; TL1=0x67; TR1=1;//上面三句定时器1的初始化}voidint_init(){ ET1=1; EA=1;//中断的SFR·中断使能控制寄存器IE·EA:总中断使能位,总阀门。·EC:PCA中断使能位·ET2:定时器2中断使能位定时器0,1与定时器2有些不同}voidrefresh_led()//毫秒刷新,数码管的动态显示{ staticuint8j=0; switch(j) { case0:ADDR0=0;ADDR1=0;ADDR2=0;j++;P0=number[a[0]];break; case1:ADDR0=1;ADDR1=0;ADDR2=0;j++;P0=number[a[1]];break; case2:ADDR0=0;ADDR1=1;ADDR2=0;j++;P0=number[a[2]];break; case3:ADDR0=1;ADDR1=1;ADDR2=0;j++;P0=number[a[3]];break; case4:ADDR0=0;ADDR1=0;ADDR2=1;j++;P0=number[a[4]];break; case5:ADDR0=1;ADDR1=0;ADDR2=1;j=0;P0=number[a[5]];break; default:break; } }main(){ ENLED=0;ADDR3=1;//三八译码器的使能 timer1_init();//定时器1的初始化 int_init();//中断的初始化 while(1);// }voidinterrupt_timer1() interrupt3//比较特殊的函数,可以放在main后面,也可以不声明发生中断了,硬件自动跳到这个函数来执行interrupt是关键字,正是由于它,所以它才特殊,3是从下面的框中选取的y=8*x+3x是中断标号,y是中断向量如上面是T1中断,那么1BH=27Y=27Y=8*X+3X=3即算出为3号中断{
本文档为【单片机学习笔记】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_211368
暂无简介~
格式:doc
大小:4MB
软件:Word
页数:51
分类:互联网
上传时间:2013-02-11
浏览量:116