实用干货下载: 运行中switch后面的表达式的值将会做为条件,与case后面的各个常量表达式的值相对比,如果相等时则执行case后面的语句,再执行break(间断语句)语句,跳出switch语句。如果case后没有和条件相等的值时就执行default后的语句。当要求没有符合的条件时不做任何处理,则能不写default语句。 在上面的章节中我们一直在用printf这个标准的C输出函数做字符的输出,使用它当然会很方便,但它的功能强大,所占用的存储空间自然也很大,要1K左右字节空间,如果再加上scanf输入函数就要达到2K左右的字节,这样的话如果要求用2K存储空间的芯片时就无法再使用这两个函数,例如AT89C。在这些小项目中,通常我们只是要求简单的字符输入输出,这里以笔者发表在本人网站的一个简单的串行口应用实例为例,一来学习使用开关语句的使用,二来简单了解51芯片串行口基本编程。这个实例是用PC串行口通过上位机程序与由AT89c51组成的下位机相通信,实现用PC软件控制AT89c51芯片的IO口,这样也就可以再通过相关电路实现对设备的控制。为了方便实验,在此所使用的硬件还是用回以上课程中做好的硬件,以串行口和PC连接,用LED查看实验的结果。原代码请到在笔者的网站下载,上面有单片机c语言下位机源码、PC上位机源码、电路图等资料。 代码中有多处使用开关语句的,使用它对不一样的条件做不一样的处理,如在CSToOut函数中根据CN[1]来选择输出到那个IO口,CN[1]=0则把CN[2]的值送到P0,CN[1]=1则送到P1,这样的写法比起用if(CN[1]==0)这样的判断语句来的清晰明了。当然它们的效果没有太大的差别(在不考虑编译后的代码执行效率的情况下)。 在这段代码主要的作用就是通过串行口和上位机软件进行通信,跟据上位机的命令字串,对指定的IO端口进行读写。InitCom函数,原型为voidInitCom(unsignedcharBaudRate),其作用为初始化串行口。它的输入参数为一个字节,程序就是用这个参数做为开关语句的选择参数。如调用InitCom(6),函数就会把波特率设置为。当然这段代码只使用了一种波特率,能用更高效率的语句去编写,这里就不多讨论了。 看到这里,你也许会问函数中的SCON,TCON,TMOD,SCOM等是代表什么?它们是特殊功能寄存器。 SBUF数据缓冲寄存器这是一个能直接寻址的串行口专用寄存器。有朋友这样问起过“为何在串行口收发中,都只是使用到同一个寄存器SBUF?而不是收发各用一个寄存器。”实际上SBUF包含了两个独立的寄存器,一个是发送寄存,另一个是接收寄存器,但它们都共同使用同一个寻址地址-99H。CPU在读SBUF时会指到接收寄存器,在写时会指到发送寄 存器,而且接收寄存器是双缓冲寄存器,这样能避免接收中断没有及时的被响应,数据没 有被取走,下一帧数据已到来,而造成的数据重叠问题。发送器则不需要用到双缓冲,一般情况下我们在写发送程序时也不必用到发送中断去外理发送数据。操作SBUF寄存器的方法则很简单,只要把这个99H地址用关键字sfr定义为一个变量就能对其进行读写操作了, 如sfrSBUF=0x99;当然你也能用其它的名称。通常在标准的reg51.h或at89x51.h等头文件中已对其做了定义,只要用#include引用就能了。 SCON串行口控制寄存器通常在芯片或设备中为了监视或控制接口状态,都会引用到接口控制寄存器。SCON就是51芯片的串行口控制寄存器。它的寻址地址是98H,是一个能位寻址的寄存器,作用就是监视和控制51芯片串行口的工作状态。51芯片的串行口能工作在几个不一样的工作模式下,其工作模式的设置就是使用SCON寄存器。它的各个位的具体定义如下: (MSB)(LSB)SM0SM1SM2RENTB8RB8TIRI 表8-1串行口控制寄存器SCON SM0、SM1为串行口工作模式设置位,这样两位能对应进行四种模式的设置。看表8 -2串行口工作模式设置。 SM0SM1模式功能波特率 同步移位寄存器fosc/12 位UART可变 位UARTfosc/32或fosc/64 位UART可变 表8-2串行口工作模式设置 在这里只说明最常用的模式1,其它的模式也就一一略过,有兴趣的朋友能找相关的硬件资料查看。表中的fosc代表振荡器的频率,也就是晶体震荡器的频率。UART为(UniversalAsynchronousReceiver)的英文缩写。 SM2在模式2、模式3中为多处理机通信使能位。在模式0中要求该位为0。 REM为允许接收位,REM置1时串行口允许接收,置0时禁止接收。REM是由软件置位或清零。如果在一个电路中接收和发送引脚P3.0,P3.1都和上位机相连,在软件上有串行口中断处理程序,当要求在处理某个子程序时不允许串行口被上位机来的控制字符产生中断,那么可以在这个子程序的开始处加入REM=0来禁止接收,在子程序结束处加入REM=1再次打开串行口接收。大家也能用上面的实际源码加入REM=0来进行实验。 TB8发送数据位8,在模式2和3是要发送的第9位。该位能用软件根据需要置位或清除,通常这位在通信协议中做奇偶位,在多处理机通信中这一位则用于表示是地址帧还是数据帧。 RB8接收数据位8,在模式2和3是已接收数据的第9位。该位可能是奇偶位,地址/数据标识位。在模式0中,RB8为保留位没有被使用。在模式1中,当SM2=0,RB8是已接收数据的停止位。 TI发送中断标识位。在模式0,发送完第8位数据时,由硬件置位。其它模式中则是在发送停止位之初,由硬件置位。TI置位后,申请中断,CPU响应中断后,发送下一帧数据。在任何模式下,TI都必须由软件来清除,也就是说在数据写入到SBUF后,硬件发送数据, 中断响应(如中断打开),这个时候TI=1,表明发送已完成,TI不会由硬件清除,所以这个时候必须 用软件对其清零。 RI接收中断标识位。在模式0,接收第8位结束时,由硬件置位。其它模式中则是在接收停止位的半中间,由硬件置位。RI=1,申请中断,要求CPU取走数据。但在模式1中,SM2=1时,当未收到有效的停止位,则不会对RI置位。同样RI也必须要靠软件清除。 常用的串行口模式1是传输10个位的,1位起始位为0,8位数据位,低位在先,1位停止位为1。它的波特率是可变的,其速率是取决于定时器1或定时器2的定时值(溢出速率)。AT89c51和AT89C等51系列芯片只有两个定时器,定时器0和定时器1,而定时器2 是89C52系列芯片才有的。 波特率在使用串行口做通信时,一个很重要的参数就是波特率,只有上下位机的波特率一样时才能进行正常通信。波特率是指串行端口每秒内能传输的波特位数。有一些开始学习的朋友认为波特率是指每秒传输的字节数,如标准会被误认为每秒种能传送个字节,而实际上它是指每秒能传送个二进位,而一个字节要8个二进位,如用串口模式1来传输那么加上起始位和停止位,每个数据字节就要占用10个二进位,波特率用模式1传输时,每秒传输的字节数是÷10=字节。51芯片的串行口工作模式0的波特率是固定的,为fosc/12,以一个12M的晶体震荡器来计算,那么它的波特率能达到1M。模式2的波特率是固定在fosc/64或fosc/32,具体用那一种就取决于PCON寄存器中的SMOD位,如SMOD为0,波特率为focs/64,SMOD为1,波特率为focs/32。模式1和模式3的波特率是可变的,取决于定时器1或2(52芯片)的溢出速率。那么我们怎么去计算这两个模式的波特率设置时相关的寄存器的值呢?能用以下的公式去计算。 波特率=(2SMOD÷32)×定时器1溢出速率 上式中如设置了PCON寄存器中的SMOD位为1时就能把波特率提升2倍。通常会使用定时器1工作在定时器工作模式2下,这个时候定时值中的TL1做为计数,TH1做为自动重装值,这个定时模式下,定时器溢出后,TH1的值会自动装载到TL1,再次开始计数,这样能不用软件去干预,使得定时更准确。在这个定时模式2下定时器1溢出速率的计算公式如下: 溢出速率=(计数速率)/(-TH1)上式中的“计数速率”与所使用的晶体振荡器频率有关,在51芯片中定时器启动后会 在每一个机器周期使定时寄存器TH的值增加一,一个机器周期等于十二个振荡周期,所以 能得知51芯片的计数速率为晶体振荡器频率的1/12,一个12M的晶体震荡器用在51芯片上,那么51的计数速率就为1M。通常用11.M晶体是为了得到标准的无误差的波特率,那么为何呢?计算一下就知道了。如我们要得到的波特率,晶体震荡器为11.M和12M,定时器1为模式2,SMOD设为1,分别看看那所要求的TH1为何值。代入公式: 11.M =(2÷32)×((11.M/12)/(-TH1)) TH1=//看看是不是和上面实例中的使用的数值一样? 12M =(2÷32)×((12M/12)/(-TH1))TH1≈.49 上面的计算能看出使用12M晶体的时候计算出来的TH1不为整数,而TH1的值只能取 整数,这样它就会有一定的误差存在不能产生精确的波特率。当然一定的误差是能在使用中被接受的,就算使用11.M的晶体振荡器也会因晶体本身所存在的误差使波特 率产生误差,但晶体本身的误差对波特率的影响是十分之小的,能忽略不计。 长按识别图中北京治疗白癜风的最好的医院呼和浩特治疗白癜风医院
|