1. <em id="3qmea"><ol id="3qmea"></ol></em>
    2. <em id="3qmea"></em>
      中国领先的单片机及嵌入式资讯教程开发工具提供者!
      当前位置单片机教程网 >> 基础教程 >> 浏览文章

      第十二课 C51开关分支语句

      作者:佚名   来源:本站原创   点击数:  更新时间2007年07月14日   字体

      学习了条件语句用多个条件语句能实现多方向条件分支但是能发现使用过多的 条件语句实现多方向分支会使条件语句嵌套过多程序冗长这样读起来也很不好读这个时候 使用开关语句同样能达到处理多分支选择的目的又能使程序结构清晰它的语法为下

      switch  (表达式)

      {

      case  常量表达式 1:  语句 1;  break; case  常量表达式 2:  语句 2;  break; case  常量表达式 3:  语句 3;  break; case  常量表达式 n:  语句 n;  break; default:    语句

      }

      运行中 switch 后面的表达式的?#21040;?#20250;做为条件与 case 后面的各个常量表达式的值相 对比如果相等时则执行 case 后面的语句再执行 break间断语句语句跳出 switch 语句如果 case 后没有和条件相等的值?#26412;?#25191;行 default 后的语句当要求没有符合的条 件时不做任何处理则能不写 default 语句

      在上面的章节中我们一直在用 printf 这个标准的 C 输出函数做字符的输出使用它当 然会很方便但它的功能强大所占用的存储空间自然也很大要 1K 左右字节空间如果 再加上 scanf 输入函数就要达到 2K 左右的字节这样的话如果要求用 2K 存储空间的芯片时 就无法再使用这两个函数例如 AT89C2051在这些小项目中通常我们只是要求简单的字 符输入输出这里以笔者发表在本人网站的一个简单的串行口应用实例为例一来学习使用开 关语句的使用二来简单了解 51 芯片串行口基本编程这个实例是用 PC 串行口通过上位机程序 与由 AT89c51 组成的下位机相通信实现用 PC 软件控制 AT89c51 芯片的 IO 口这样也就可 以再通过相关电路实现对设备的控制为了方便实验在此所使用的硬件还是用回以上课程 中做好的硬件?#28304;?#34892;口和  PC  连接用  LED  查看实验的结果原代码请到在笔者的网站 下载上面有  单片机c语言  下位机源码PC 上位机源码电路图等资料

      代码中有多处使用开关语句的使用它对不一样的条件做不一样的处理如在 CSToOut 函数 中根据 CN[1]来选择输出到那个 IO 口CN[1]=0 则把 CN[2]的值送到 P0CN[1]=1 则送到 P1 这样的写法比起用 if (CN[1]==0)这样的判断语句来的清晰明了当然它们的效果没有太大 的差别在不考虑编译后的代码执行效率的情况下

      在这段代码主要的作用就是通过串行口和上位机软件进行通信跟据上位机的命令字串 对指定的 IO 端口进行读?#30784;InitCom 函数原型为 void InitCom(unsigned char BaudRate) 其作用为初始化串行口它的输入参数为一个字节程序就是用这个参数做为开关语句的选择 参数如调用 InitCom(6),函数就会把波特率设置为 9600当然这段代码只使用了一种波特 率能用更高效率的语句去编写这里就不多讨论了

      看到这里你也许会问函数中的 SCONTCONTMODSCOM 等是代表什么它们是特殊 功能寄存器

      SBUF    数据缓冲寄存器    这是一个能直接寻址的串行口专用寄存器有朋友这样问起 过为何在串行口收发中都只是使用到同一个寄存器 SBUF而不是收发各用一个寄存器 ?#23548;?#19978; SBUF 包含了两个独立的寄存器一个是发?#22270;?#23384;另一个是接?#21344;?#23384;器但它?#23884;?共同使用同一个寻址地址99HCPU 在读 SBUF 时会指到接?#21344;?#23384;器在写时会指到发?#22270;?/p>

      存器而且接?#21344;?#23384;器是双缓冲寄存器这样能避免接收中断没有及时的被响应数据没


       

      有被取走下一帧数据已到来而造成的数据重叠问题发送器则不需要用到双缓冲一般 情况下我们在写发送程序时也不必用到发送中?#20808;?#22806;理发送数据操作 SBUF 寄存器的方法 则很简单只要把这个 99H 地址用关键字 sfr 定义为一个变量就能对其进行读写操作了

      如 sfr  SBUF  =  0x99;当然你也能用其它的名称通常在标准的 reg51.h 或 at89x51.h 等 头文件中?#35759;?#20854;做了定义只要用#include 引用就能了

      SCON    串行口控制寄存器    通常在芯片或设备中为了监视或控制接口状态都会引用 到接口控制寄存器SCON 就是 51 芯片的串行口控制寄存器它的寻址地址是 98H是一个 能位寻址的寄存器作用就是监视和控制 51 芯片串行口的工作状态51 芯片的串行口能 工作在几个不一样的工作模式下其工作模式的设置就是使用 SCON 寄存器它的各个位的具 体定义如下

      MSB                                                                                                LSB SM0          SM1          SM2          REN          TB8          RB8           TI            RI

      表 81    串行口控制寄存器 SCON

      SM0SM1  为串行口工作模式设置位这样两位能对应进行四种模式的设置看表  8

      2 串行口工作模式设置

      SM0

      SM1

      模    式

      功    能

      波特率

      0

      0

      0

      同步移位寄存器

      fosc/12

      0

      1

      1

      8 位 UART

      可变

      1

      0

      2

      9 位 UART

      fosc/32 或 fosc/64

      1

      1

      3

      9 位 UART

      可变

      表 82    串行口工作模式设置

      在这里只说明最常用的模式 1其它的模式也就一一略过?#34892;?#36259;的朋友能找相关的 硬件资料查?#30784;?#34920;中的  fosc  代表振荡器的频率也就是晶体震荡器的频率UART  为(Universal Asynchronous  Receiver的英文缩?#30784;?/p>

      SM2 在模式 2模式 3 中为多处理机通信使能位在模式 0 中要求该位为 0

      REM 为允许接收位REM 置 1 时串行口允许接收置 0 时禁止接收REM 是由软件置位或 清零如果在一个电?#20998;?#25509;收和发送引脚 P3.0,P3.1 都和上位机相连在软件上有串行口中断 处理程序当要求在处理某个子程序时不允许串行口被上位机来的控制字符产生中断那么可 以在这个子程序的开始处加入 REM=0 来禁止接收在子程序结束处加入 REM=1 再次打开串行口 接收大家也能用上面的?#23548;?#28304;码加入 REM=0 来进行实验

      TB8 发送数据位 8在模式 2 和 3 是要发送的第 9 位该位能用软件根据需要置位或 清除通常这位在通信协议中做奇偶位在多处理机通信中这一位则用于表示是地?#20998;?#36824;是 数据帧

      RB8 接收数据位 8在模式 2 和 3 是已接收数据的第 9 位该位可能是奇偶位地址/ 数据标识位在模式 0 中RB8 为保留位没有被使用在模式 1 中当 SM2=0RB8 是已接 收数据的停止位

      TI 发送中断标识位在模式 0发送完第 8 位数据时由硬件置位其它模式中则是在 发送停止位之初由硬件置位TI 置位后申请中断CPU 响应中断后发送下一帧数据 在任何模式下TI 都必须由软件来清除也就是说在数据写入到 SBUF 后硬件发送数据

      中断响应如中断打开这个时候 TI=1表明发送已完成TI 不会由硬件清除所以这个时候必须


       

      用软件对其清零

      RI 接收中断标识位在模式 0接收第 8 位结束时由硬件置位其它模式中则是在接 收停止位的半中间由硬件置位RI=1申请中断要求 CPU 取走数据但在模式 1 中SM2=1 时当未收到?#34892;?#30340;停止位则不会对 RI 置位同样 RI 也必须要靠软件清除

      常用的串行口模式 1 是传输 10 个位的1 位起始位为 0,8 位数据位低位在先1 位停止 位为 1它的波特率是可变的其速率是取决于定时器 1 或定时器 2 的定时值溢出速率 AT89c51 和 AT89C2051 等 51 系?#34892;?#29255;只有两个定时器定时器 0 和定时器 1而定时器 2

      是 89C52 系?#34892;?#29255;才有的

      波特率    在使用串行口做通信时一个很重要的参数就是波特率只有上下位机的波特率 一样时才能进行正常通信波特率是指串行端口每秒内能传输的波特位数有一些开始学习 的朋友认为波特率是指每秒传输的字节数如标准  9600  会被误认为每秒种能传送  9600 个字节而?#23548;?#19978;它是指每秒能传送 9600 个二进位而一个字节要 8 个二进位如用串 口模式 1 来传输那么加上起始位和停止位每个数据字节就要占用 10 个二进位9600 波特 率用模式 1 传输时每秒传输的字节数是 960010960 字节51 芯片的串行口工作模式 0 的波特率是固定的为 fosc/12以一个 12M 的晶体震荡器来计算那?#27492;?#30340;波特率能达到 1M 模式 2 的波特率是固定在 fosc/64 或 fosc/32具体用那一种就取决于 PCON 寄存器中的 SMOD 位如 SMOD 为 0波特率为 focs/64,SMOD 为 1波特率为 focs/32模式 1 和模式 3 的波 特率是可变的取决于定时器 1 或 252 芯片的溢出速率那么我们怎么去计算这两个模 式的波特率设置时相关的寄存器的?#30340;أ?#33021;用以下的公式去计算

      波特率2SMOD32定时器 1 溢出速率

      上式中如设置了 PCON 寄存器中的 SMOD 位为 1 ?#26412;?#33021;把波特率提升 2 倍通常会使用 定时器 1 工作在定时器工作模式 2 下这个时候定时值中的 TL1 做为计数TH1 做为自动重装值     这个定时模式下定时器溢出后TH1 的值会自动装载到 TL1再次开始计数这样能不 用软件去干预使得定时更准确在这个定时模式 2 下定时器 1 溢出速率的计算公式如下

      溢出速率计数速率/(256TH1) 上式中的计数速率与所使用的晶体振荡器频率有关在 51 芯片中定时器启动后会

      在每一个机器周期使定时寄存器 TH 的值增加一一个机器周期等于十二个振荡周期所以

      能得知 51 芯片的计数速率为晶体振荡器频率的 1/12一个 12M 的晶体震荡器用在 51 芯片上 那么 51 的计数速率就为 1M通常用 11.0592M 晶体是为了得到标准的无误差的波特率那 么为?#25991;أ?#35745;算一下就知道了如我们要得到 9600 的波特率晶体震荡器为 11.0592M 和 12M定 时器 1 为模式 2SMOD 设为 1分别看看那所要求的 TH1 为何值代入公式

      11.0592M

      9600(232)((11.0592M/12)/(256-TH1))

      TH1250    //看看是不是和上面实例中的使用的数值一样

      12M

      9600(232)((12M/12)/(256-TH1)) TH1249.49

      上面的计算能看出使用 12M 晶体的时候计算出来的 TH1 不为整数而 TH1 的值只能取


       

      整数这样它就会有一定的误差存在不能产生精确的 9600 波特率当然一定的误差是能 在使用中被接受的就算使用 11.0592M 的晶体振荡器也会因晶体本身所存在的误差?#20849;?#29305;

      率产生误差但晶体本身的误差对波特率的影响是十分之小的能忽略不计

      发表评论告诉好友收藏此文关闭窗口

      文章评论

      相关文章

      ຣ11ѡ5app

        
        
        1. <em id="3qmea"><ol id="3qmea"></ol></em>
        2. <em id="3qmea"></em>

            
            
            1. <em id="3qmea"><ol id="3qmea"></ol></em>
            2. <em id="3qmea"></em>