当前位置:首页 > C51
  • 单片机的C51基础知识

    单片机的C51基础知识

    单片机是通过程序来实现各种功能。而单片机的常用的程序语言有C51、汇编编程等,我们今天就给大家讲讲其中一种语言:C51。 1.利用C语言开发单片机的优点  每一块单C语言作为一种非常方便的语言而得到广泛的支持,很多硬件开发都用C语言编程。单片机的C51与用汇编编程相比,有如下优点:  ①对单片机的指令系统不要求有任何的了解,就可以用C语言直接编程操作单片机。  ②寄存器分配、不同存储器的寻址及数据类型等细节完全由编译器自动管理。  ③程序有规范的结构,可分成不同的函数,可使程序结构化。  ④库中包含许多标准子程序,具有较强的数据处理能力,使用方便。 、⑤具有方便的模块化编程技术,使已编好的程序很容易移植。  C语言常用语法不多,尤其是单片机的C语言常用语法更少,有益于编写小而快的程序。  2.C51中的基本数据类型  当我们给单片机编程时,单片机也要运算,而在单片机的运算中,变量中数据的大小是有限制的,我们不能随意给一个变量赋任意的值,因为变量在单片机的内存中是要占据空间的,变量大小不同,所占据的空间就不同,为了合理利用单片机的内存空间,我们在编程序时就要设定合适的数据类型,不同的数据类型也就代表了十进制中不同的数据大小,所以我们在设定一个变量之前,必须要给编译器声明这个变量的类型,以便让编译器提前从单片机内存中分配给这个变量合适的空间。单片机的C语言中常用的数据类型如表1-1-3所示。  表1-1-3  C51中常用的数据类型 那么什么是所占的位数呢?在编写程序时,无论是以十进制、十六进制还是二进制表示的数,在单片机中,所有的数据都是以二进制的形式存储在存储器中的,既然是二进制,那么就只有两个数,0和1,这两个数每一个所占的空间就是一位(b),位也是单片机存储器中最小的单位。比位大的单位是字节(B),一个字节等于8位(即1B=8b)。 3.C51中的运算符  C51中的算术运算符如表1-1-4所示。  表1-1-4  C51中的算术运算符 C51中的关系(逻辑)运算符如表1-1-5所示。  表1-1-5  C51中的关系(逻辑)运算符 C51中的位运算符如表1-1-6所示。  表1-1-6  C51中的位运算符 4.C51中的基础语句  C51中用到的基础语句如表1-1-7所示。  表1-1-7  C51中的基础语句

    时间:2019-11-13 关键词: C51 单片机 汇编编程

  • 大牛分享单片机编程软件使用经验,Keil C51单片机编程软件使用教程

    大牛分享单片机编程软件使用经验,Keil C51单片机编程软件使用教程

    Keil C51是最知名的单片机编程软件之一,也是从事单片机开发人员必定会使用的单片机编程软件。对于Keil C51单片机编程软件,很多新手朋友并不熟知它的使用方法。为此,小编特地带来这篇有关Keil C51单片机编程软件的使用教程,希望为大家学习使用Keil C51单片机编程软件提供一定帮助。 KEIL C51标准C编译器为8051微控制器的软件开发提供了C语言环境,但是界面是英文的好多初学者看很多教程都是一头雾水,本站特地制作了一个相对简单的教程。他能能嵌入汇编语言保留了汇编代码高效,快速的特点。KEIL C51编译器的功能不断增强,使你可以更加贴近CPU本身,及其它的衍生产品,其效率已经达到了相当搞的程度。C51已被完全集成到uVision2的集成开发环境中,这个集成开发环境包含:编译器,汇编器,实时操作系统,项目管理器,调试器。uVision2 IDE可为它们提供单一而灵活的开发环境。 Keil C51 软件是众多单片机应用开发的优秀软件之一,它集编辑,编译,仿真于一体,支持汇编,PLM 语言和 C 语言的程序设计,界面友好,易学易用。 下面介绍Keil C51软件的使用方法: 进入 Keil C51 后,屏幕如下图所示。几秒钟后出现编辑界 启动Keil C51时的屏幕 进入Keil C51后的编辑界面 简单程序的调试 学习程序设计语言、学习某种程序软件,最好的方法是直接操作实践。下面通过简单的编程、调试,引导大家学习Keil C51软件的基本使用方法和基本的调试技巧。 1)建立一个新工程 单击Project菜单,在弹出的下拉菜单中选中New Project选项 2)然后选择你要保存的路径,输入工程文件的名字,比如保存到C51目录里,工程文件的名字为C51 如下图所示,然后点击保存。 3)这时会弹出一个对话框,要求你选择单片机的型号,你可以根据你使用的单片机来选择,keil c51几乎支持所有的51核的单片机,我这里还是以大家用的比较多的Atmel 的89C51来说明,如下图所示,选择89C51之后,右边栏是对这个单片机的基本的说明,然后点击确定。 4)完成上一步骤后,屏幕如下图所示 到现在为止,我们还没有编写一句程序,下面开始编写我们的第一个程序。  5)在下图中,单击“File”菜单,再在下拉菜单中单击“New”选项 新建文件后屏幕如下图所示 此时光标在编辑窗口里闪烁,这时可以键入用户的应用程序了,但笔者建议首先保存该空白的文件,单击菜单上的“File”,在下拉菜单中选中“Save As”选项单击,屏幕如下图所示,在“文件名”栏右侧的编辑框中,键入欲使用的文件名,同时,必须键入正确的扩展名。注意,如果用C语言编写程序,则扩展名为(.c);如果用汇编语言编写程序,则扩展名必须为(.asm)。然后,单击“保存”按钮。 6)回到编辑界面后,单击“Target 1”前面的“+”号,然后在“Source Group 1”上单击右键,弹出如下菜单 然后单击“Add File to Group ‘Source Group 1’” 屏幕如下图所示 选中Test.c,然后单击“Add ”屏幕好下图所示 注意到“Source Group 1”文件夹中多了一个子项“Text1.c”了吗?子项的多少与所增加的源程序的多少相同 7)现在,请输入如下的C语言源程序: #include 《reg52.h》//包含文件 #include 《stdio.h》 void main(void){ SCON=0x52; TMOD=0x20; TH1=0xf3; TR1=1;   //此行及以上3行为PRINTF函数所必须 printf(“Hello I am KEIL. \n”);   //打印程序执行的信息 printf(“I will be your friend.\n”); while(1); } 在输入上述程序时,读者已经看到了事先保存待编辑的文件的好处了吧,即Keil c51会自动识别关键字,并以不同的颜色提示用户加以注意,这样会使用户少犯错误,有利于提高编程效率。程序输入完毕后,如下图所示 8)在上图中,单击“Project”菜单,再在下拉菜单中单击“Built Target”选项(或者使用快捷键F7),编译成功后,再单击“Project”菜单,在下拉菜单中单击“Start/Stop Debug Session”(或者使用快捷键Ctrl+F5),屏幕如下所示 9)调试程序:在上图中,单击“Debug”菜单,在下拉菜单中单击“Go”选项,(或者使用快捷键F5),然后再单击“Debug”菜单,在下拉菜单中单击“Stop Running”选项(或者使用快捷键Esc);再单击“View”菜单,再在下拉菜单中单击“Serial Windows #1”选项,就可以看到程序运行后的结果,其结果如下图所示 至此,我们在Keil C51上做了一个完整工程的全过程。但这只是纯软件的开发过程,如何使用程序下载器看一看程序运行的结果呢? 10)单击“Project”菜单,再在下拉菜单中单击 最后单击“Output”中单击“Create HEX File” 选项,使程序编译后产生HEX代码,供下载器软件使用。把程序下载到AT89S51单片机中。

    时间:2019-08-05 关键词: C51 keil 使用教程 单片机编程软件

  • c51 串口 波特率的计算

    在串行通信中,收发双方对发送或接收的数据速率要有一定的约定,我们通过软件对MCS—51串行口编程可约定四种工作方式。其中,方式0和方式2的波特率是固定的,而方式1和方式3的波特率是可变的,由定时器T溢出率决定。 串行口的四种工作方式对应着三种波特率。由于输人的移位时钟的来源不同,所以,各种方式的波特率计算公式也不同。 一、方式0的波特率 方式0时,移位时钟脉冲由56(即第6个状态周期,第12个节拍)给出,即每个机器周期产生一个移位时钟,发送或接收一位数据。所以,波特率为振荡频率的十二分之一,并不受 PCON寄存器中SMOD的影响,即: 方式0的波特率=fosc/12   三、方式l和方式3的波特率 方式1和方式3的移位时钟脉冲由定时器T1的溢出率决定,故波特宰由定时器T1的 溢出率与SMOD值同时决定,即: 方式1和方式3的波特率=2SMOD/32·T1溢出率 其中,溢出率取决于计数速率和定时器的预置值。计数速率与TMOD寄存器中C/T的状态有关。当C/T=0时,计数速率=fosc/2;当C/T=1时,计数速率取决于外部输入时钟频率。 当定时器Tl作波特率发生器使用时,通常选用可自动装入初值模式(工作方式2),在 工作方式2中,TLl作为计数用,而自动装入的初值放在THl中,设计数初值为x,则每过“256一x”个机器周期,定时器T1就会产生一次溢出。为了避免因溢出而引起中断,此时应禁止T1中断。这时,溢出周期为:   系统晶振频率选为11.0592MHZ就是为了使初值为整数,从而产生精确的波特率。 如果串行通信选用很低的波特率,可将定时器Tl置于工作方式0或工作方式1,但在 这种情况下,T1溢出时,需用中断服务程序重装初值。中断响应时间和执行指令时间会使波特率产生一定的误差,可用改变初值的办法加以调整。 表6—2列出了各种常用的波特率及其初值。  

    时间:2019-08-04 关键词: C51 波特率 串口

  • AT89S51的由来及与C51的区别

    很多初学51单片机的网友会有这样的问题:AT89S51是什么?书上和网络教程上可都是8051,89C51等!没听 说过有89S51 ?! 这里,初学者要澄清单片机实际使用方面的一个产品概念,MCS-51单片机是美国INTEL公司于1980年推出的产品,典型产品有 8031(内部没有程序存储器,实际使用方面已经被市场淘汰)、8051(芯片采用HMOS,功耗是630mW,是89C51的5倍,实际使用方面已经被市场淘汰)和8751等通用产品,一直到现在, MCS-51内核系列兼容的单片机仍是应用的主流产品(比如目前流行的89S51、已经停产的89C51等),各高校及专业学校的培训教材仍与MCS-51单片机作为代表进行理论基础学习。 有些文献甚至也将8051泛指MCS-51系列单片机,8051是早期的最典型的代表作,由于MCS-51单片机影响极深远,许多公司都推出了兼容系列单片机,就是说MCS-51内核实际上已经成为一个8位单片机的标准。 其他的公司的51单片机产品都是和MCS-51内核兼容的产品而以。同样的一段程序,在各个单片机厂家的硬件上运行的结果都是一样的,如ATMEL的89C51(已经停产)、89S51, PHILIPS(菲利浦),和WINBOND(华邦)等,我们常说的已经停产的89C51指的是ATMEL公司的 AT89C51单片机,同时是在原基础上增强了许多特性,如时钟,更优秀的是由Flash(程序存储器的内容至少可以改写1000次)存储器取带了原来的ROM(一次性写入),AT89C51的性能相对于8051已经算是非常优越的了。 不过在市场化方面,89C51受到了PIC单片机阵营的挑战,89C51最致命的缺陷在于不支持ISP(在线更新程序)功能,必须加上ISP功能等新功能才能更好延续MCS-51的传奇。89S51就是在这样的背景下取代89C51的,现在,89S51目前已经成为了实际应用市场上新的宠儿,作为市场占有率第一的Atmel目前公司已经停产AT89C51,将用AT89S51代替。89S51在工艺上进行了改进,89S51采用0.35新工艺,成本降低,而且将功能提升,增加了竞争力。89SXX可以像下兼容89CXX等51系列芯片。同时,Atmel不再接受89CXX的定单,大家在市场上见到的89C51实际都是Atmel前期生产的巨量库存而 已。如果市场需要,Atmel当然也可以再恢复生产AT89C51。 89S51相对于89C51增加的新功能包括: -- 新增加很多功能,性能有了较大提升,价格只比89C51稍高一些 -- ISP在线编程功能,这个功能的优势在于改写单片机存储器内的程序不需要把芯片从工作环境中剥离。是一个强大易用的功能。 -- 最高工作频率为33MHz,大家都知道89C51的极限工作频率是24M,就是说S51具有更高工作频率,从而具有了更快的计算速度。 -- 具有双工UART串行通道。 -- 内部集成看门狗计时器,不再需要像89C51那样外接看门狗计时器单元电路。 -- 双数据指示器。 -- 电源关闭标识。 -- 全新的加密算法,这使得对于89S51的解密变为不可能,程序的保密性大大加强,这样就可以有效的保护知识产权不被侵犯。 -- 兼容性方面:向下完全兼容51全部字系列产品。比如8051、89C51等等早期MCS-51兼容产品。也就是说所有教科书、网络教程上的程序(不论教科书上采用的单片机是8051还是89C51还是MCS-51等等),在89S51上一样可以照常运行,这就是所谓的向下兼容。 比较结果:就如同INTEL的P3向P4升级一样,虽然都可以跑Windows,不过速度是不同的。 从AT89C51升级到AT89S51 ,也是同理。和S51比起来,C51就要逊色一些,实际应用市场方面技术的进步是永远向前的。

    时间:2019-08-04 关键词: C51 区别 at89s51

  • 基于C51实时控制设计与实现的嵌入式系统研究

    基于C51实时控制设计与实现的嵌入式系统研究

    随着嵌入式系统变得越来越复杂,设计者正面临着新的挑战:随着基于32位微控制器(MCU)的嵌入式系统的成本向16位系统逐步接近,在许多高级应用中,8位和16位微控制器正逐步让位给扩展性更佳,性能更好的32位系统芯片(SoC). 1 硬件设计与实现 1.1 总体方案设计 在该通信测试仪器中,实时控制模块主要实现对射频接收频综、射频发生频综、滤波器组件、射频输入模块、射频输出模块等实时控制作用。对射频检波信号进行A/D转换以获取数据。与上位计算机进行通信等功能。 根据待实现的系统功能要求,综合考虑系统资源,及芯片性价比等因素,确定采用以C51单片机为主控芯片的嵌入式系统方案,芯片为Silicon Labs的C8051F120,具有128 kB片内Flash存储器、8TImes;1 024+256 Byte的片内RAM,可寻址64 kB地址空间的外部数据存储器接口、SPI、UART、定时器、时钟振荡器、PLL等,片上外设资源丰富、控制方便。 系统资源分配:射频接收、发射频综模块,内含DDS,PLL等,外部控制接口是微控制接口,因此直接用单片机的地址、数据、控制三总线实施控制。滤波组 件、射频输入/输出模块等的工作状态与接口上信号电平高低有关,因此用GPIO的方式进行控制。A/D转换控制使用串行外围设备接口SPI.与上位机的通 信使用RS-232串口。总体设计框图如图1所示。     1.2 总线及I/O控制的设计 对于射频接收频综、射频发射频综模块,直接采用总线控制,为避免不同的模块控制时相互干扰,用3-8译码器对总线地址译码,产生不同模块的片选信号。同 时数据线通过总线收发器以提高带负载能力。对于滤波组件、射频输入/输出等用I/O控制的模块,并未直接使用51芯片的GPIO引脚,则是将数据总线经锁 存后模拟GPIO信号供相关模块使用,如图2所示,其中,IO_/WR1由B_/CS7与单片机写线逻辑或后产生。     1.3 SPI及RS232控制接口 C8051F120芯片上本身自带了A/D转换器,但只有12位,不适合该系统的需求,故在片外另加一片ADI公司的AD7707.其分辨率为16位, 是∑-△体系结构,转换的是输入电平的平均值。三通道,输入电平范围可达±10 mV~±10 V.根据实际要求,该系统使用AIN3高电平输入端口,Unbuffered模式,HICOM、REF-接模拟地,VBIAS与REF+均接+2.5 V参考电压,模拟电源5 V,数字电源3.3 V,能检测输入范围为0~10 V的单极性电平。其控制接口是同步串行口,用51芯片的SPI直接控制。图3是AD7707的电气连接图。     单片机与上位计算机的通信使用通用异步收发器UART,外接MAX3224,将UART信号转换为RS-232信号进行传输,MAX3224在 3~5.5 V低电压下工作,却可产生RS-232的±12 V电压,只需连接Tx、Rx和地线即可实现异步串行通信。系统中仍有一些时钟、复位电路和电源等,在此不再赘述。 2 软件设计与实现 2.1 主程序框架 主程序流程图如图4所示。     主程序是顺序结构,较为简单。主要分两部分:一是对系统各部分进行初始化设置,使其能够工作在正常状态。二是正常工作循环状态,当收到上位机的控制命令时,即进行相应的操作,无命令时则等待。对于嵌入式程序而言,无限循环是必要的。 2.2 串口通信程序 串口通信程序实现与上位机的通信功能。具体操作中使用一个循环队列存放接收到的上位机命令,分别用头指针和尾指针指向队头和队尾,将各命令字节取出,进行相应操作。命令执行完毕(队列取空),清标志位,等待新命令。如图5所示。     2.3 SPI通信程序 C51采用SPI主模式与AD7707进行通信。主模式写AD7707较为简单,单片机先写1 Byte的配置数据给AD7707,其会自动将该数据放入自身的通信寄存器,随后AD7707根据该配置值确定下一步要写的寄存器及数据大小,再将单片机 随后输入的数据放入指定位置。C8051F120发数据前,先根据SPICN寄存器的TXBMT位的值判断是否能够发送数据,再向自身的SPIDAT寄存 器写数据即可,硬件会自动将数据发出。 主模式读AD7707较为困难。当C51已设置AD7707的通信寄存器,表明下一步操作是读AD7707的某个寄存器值后,C51向SPIDAT写任 意值,之后SPI数据线(MOSI)上会串行移出数据,同时时钟线上产生串行时钟,从设备(AD7707)收到时钟,将预备的数据送到MISO线上交给 C51,同时不采纳主设备发送的任意值。C51将发送的串行数据放在移位寄存器中,当最后一位收到后即移入收缓冲器,再读SPIDAT便可读出数据。 2.4 其他软件模块 其他软件模块均是根据各部分硬件的具体要求,通过向所分配的对应地址空间按序发送所需数据来实现相关功能。 3 结束语 文中提出以C51单片机C8051F120为核心控制芯片的嵌入式系统,已成功应用于某通信测试仪器中,陔系统通过中断及查询等方式较好地实现了对整机的实时控制功能。

    时间:2019-07-24 关键词: 嵌入式 C51 嵌入式开发 实时控制设计

  • C51仿真器使用说明

    一、主要功能和特性 1.完全仿真p0,p2口,用户程序从0000地址仿真。 2.支持89C52等嵌入式CPU仿真,可以仿真标准的89C51,89C52,89C58等标准8051内核的单片机仿真,包括带ISP功能的新型单片机。 3.ISP 在线编程,在线下载,26K程序空间 4.仿真频率最高33MHz 5.支持同时最多10个断点(软件断点) 6.支持单步,断点,全速运行 7.支持汇编,C语言,混合调试,随时查看内部数据或内部资源,在线修改源程序。 8.支持KEIL C51的IDE开发仿真环境UV1 UV2 (V5.20 V6.02 V6.10 V6.12 V6.14) 二、功能限制: 仿真器占用单片机定时器2,以便于与Keil C(PC)通讯,故不支持串口及定时器2的仿真功能。其他所有片内资源均可由用户使用。如在开发中需要使用串口,可选用内部带双串口的单片机如DS80C320,Winbond77e58等。 三、仿真器使用方法: 1. 将仿真器插入需仿真的用户板的CPU插座中,仿真器由用户板供电; 2. 将仿真器的串行电缆和PC机接好,打开用户板电源; 3. 通过Keil C 的IDE开发仿真环境UV2 下载用户程序进行仿真、调试。 4. 仿真器硬件说明: a.使用用户板的晶振 仿真器晶振旁有两组跳线用来切换内部晶振和用户板晶振,仿真板上的晶振(22.1184MHz)。 b.为便于调试带看门狗的用户板,仿真器的复位端未与用户板复位端相连;故仿真器的复位按钮只复位仿真器,不复位用户板;若要复位用户板,请使用用户板复位按钮 四、Keil C51 IDE开发仿真环境的设置方法 1. 先打开一个工程文件。如果你没有工程文件就要先建立一个。这里拿 keil c51提供的 hello.prj为例子说明: 用鼠标点击菜单的project,选择open project。如图:   2. 选择keil\c51\examples\hello\hello,点击打开,如图:   3.选择菜单的Project->Option for Target 'Simulator',如图:   3.1选择C51栏的设置如图: 删掉define:里的MONITOR51这几个字母,如果define栏是空的,可以跳过这一步:   删掉MONTOR51之后的设置如下图,不要点击确定,因为还要进行其他设置:   附注:3.1的步骤是调试keil提供的这个Hello工程才需要做的,对你自己建立的工程不需要这个设 置,你自己的工程可以跳过这步,直接进行下一个设置.在这里用红色来写这个说明,是需要引起用 户注意。 4.选择debug栏的设置项目: Use: Keil Monitor-51 Driver :选择这一项 Load Application at Start:选择这项之后,keil才会自动装载你的程序代码。Go till main:调试C语言程序时可以选择这一项,PC会自动运行到main 程序处   点击上图的Settings,打开新的窗口: Port:设置你的串口号,为仿真器的串口电缆线所连接的串口。 Baudrate:设置为38400,仿真器固定使用38400bps跟keil C通讯。 Serial Interrupt: Cache Options: 这两项可以选也可以不选; 最后点击ok和确定关闭你的设置。   5. 编译你的程序,选择Project -> Rebuild all target files   6. 编译完毕之后,选择Debug->Start/Stop Debug Session,就进入仿真了   7. 装载代码之后,在左下角显示如图:   Connected to Monitor-51 V3.4 表示连接到仿真器,仿真器的版本号为3.4, Load "C:\\Keil\\C51\EXAMPLES\\HELLO\\HELLO" 表示代码装载成功。 8.其他的调试方法跟软件仿真一样,有单步,断点,全速运行等各种调试方法

    时间:2019-07-18 关键词: 仿真器 C51 使用说明

  • 基于C51的嵌入式实时控制模块的设计与实现

    随着现代通信技术的发展,通信测试仪器不断推陈出新。各种新型设备对系统的实时响应能力的要求越来越高,一种通信测试仪器的实时响应性能,就成为系统设计能否成功的关键因素之一。笔者曾在多个通信测试仪器项目中,成功地应用ARM处理器、C51单片机等为主控芯片的嵌入式系统,实现了对仪器相关模块的实时控制功能。因此提出一种在某通信测试仪器中使用C51单片机来实现实时控制的设计方案。 1 硬件设计与实现 1.1 总体方案设计 在该通信测试仪器中,实时控制模块主要实现对射频接收频综、射频发生频综、滤波器组件、射频输入模块、射频输出模块等实时控制作用。对射频检波信号进行A/D转换以获取数据。与上位计算机进行通信等功能。 根据待实现的系统功能要求,综合考虑系统资源,及芯片性价比等因素,确定采用以C51单片机为主控芯片的嵌入式系统方案,芯片为Silicon Labs的C8051F120,具有128 kB片内Flash存储器、8×1 024+256 Byte的片内RAM,可寻址64 kB地址空间的外部数据存储器接口、SPI、UART、定时器、时钟振荡器、PLL等,片上外设资源丰富、控制方便。 系统资源分配:射频接收、发射频综模块,内含DDS,PLL等,外部控制接口是微控制接口,因此直接用单片机的地址、数据、控制三总线实施控制。滤波组 件、射频输入/输出模块等的工作状态与接口上信号电平高低有关,因此用GPIO的方式进行控制。A/D转换控制使用串行外围设备接口SPI.与上位机的通 信使用RS-232串口。总体设计框图如图1所示。   1.2 总线及I/O控制的设计 对于射频接收频综、射频发射频综模块,直接采用总线控制,为避免不同的模块控制时相互干扰,用3-8译码器对总线地址译码,产生不同模块的片选信号。同 时数据线通过总线收发器以提高带负载能力。对于滤波组件、射频输入/输出等用I/O控制的模块,并未直接使用51芯片的GPIO引脚,则是将数据总线经锁 存后模拟GPIO信号供相关模块使用,如图2所示,其中,IO_/WR1由B_/CS7与单片机写线逻辑或后产生。   1.3 SPI及RS232控制接口 C8051F120芯片上本身自带了A/D转换器,但只有12位,不适合该系统的需求,故在片外另加一片ADI公司的AD7707.其分辨率为16位, 是∑-△体系结构,转换的是输入电平的平均值。三通道,输入电平范围可达±10 mV~±10 V.根据实际要求,该系统使用AIN3高电平输入端口,Unbuffered模式,HICOM、REF-接模拟地,VBIAS与REF+均接+2.5 V参考电压,模拟电源5 V,数字电源3.3 V,能检测输入范围为0~10 V的单极性电平。其控制接口是同步串行口,用51芯片的SPI直接控制。图3是AD7707的电气连接图。   单片机与上位计算机的通信使用通用异步收发器UART,外接MAX3224,将UART信号转换为RS-232信号进行传输,MAX3224在 3~5.5 V低电压下工作,却可产生RS-232的±12 V电压,只需连接Tx、Rx和地线即可实现异步串行通信。系统中仍有一些时钟、复位电路和电源等,在此不再赘述。 2 软件设计与实现 2.1 主程序框架 主程序流程图如图4所示。   主程序是顺序结构,较为简单。主要分两部分:一是对系统各部分进行初始化设置,使其能够工作在正常状态。二是正常工作循环状态,当收到上位机的控制命令时,即进行相应的操作,无命令时则等待。对于嵌入式程序而言,无限循环是必要的。 2.2 串口通信程序 串口通信程序实现与上位机的通信功能。具体操作中使用一个循环队列存放接收到的上位机命令,分别用头指针和尾指针指向队头和队尾,将各命令字节取出,进行相应操作。命令执行完毕(队列取空),清标志位,等待新命令。如图5所示。   2.3 SPI通信程序 C51采用SPI主模式与AD7707进行通信。主模式写AD7707较为简单,单片机先写1 Byte的配置数据给AD7707,其会自动将该数据放入自身的通信寄存器,随后AD7707根据该配置值确定下一步要写的寄存器及数据大小,再将单片机 随后输入的数据放入指定位置。C8051F120发数据前,先根据SPICN寄存器的TXBMT位的值判断是否能够发送数据,再向自身的SPIDAT寄存 器写数据即可,硬件会自动将数据发出。 主模式读AD7707较为困难。当C51已设置AD7707的通信寄存器,表明下一步操作是读AD7707的某个寄存器值后,C51向SPIDAT写任 意值,之后SPI数据线(MOSI)上会串行移出数据,同时时钟线上产生串行时钟,从设备(AD7707)收到时钟,将预备的数据送到MISO线上交给 C51,同时不采纳主设备发送的任意值。C51将发送的串行数据放在移位寄存器中,当最后一位收到后即移入收缓冲器,再读SPIDAT便可读出数据。 2.4 其他软件模块 其他软件模块均是根据各部分硬件的具体要求,通过向所分配的对应地址空间按序发送所需数据来实现相关功能。 3 结束语 文中提出以C51单片机C8051F120为核心控制芯片的嵌入式系统,已成功应用于某通信测试仪器中,陔系统通过中断及查询等方式较好地实现了对整机的实时控制功能。

    时间:2019-07-16 关键词: C51 实时控制模块

  • 如何用C51实现单片机和PLC之间通讯的实例

    1、 HMI(人机界面)以其体积小,高性能,强实时等特点,越来越多的应用于工业自动化系统和设备中。 它有字母、汉字、图形和图片等不同的显示,界面简单友好。配有长寿命的薄膜按钮键盘,操作简单。它一般采用具有集成度高、速度快、高可靠且价格低等优点的单片机[1]作为其核心控制器,以实现实时快速处理。PLC和单片机结合不仅可以提PLC的数据处理能力,还可以给用户带来友好简洁的界面。本文以Modbus通讯协议为例,详细讨论了一个人机系统中,如何用C51实现单片机和PLC之间通讯的实例。   2、Modbus通讯协议 Modbus协议是应用于电子控制器上的一种通用语言。通过此协议,控制器相互之间、控制器经由网络和其它设备之间可以通信。 Modbus协议提供了主—从原则,即仅一设备(主设备)能初始化传输(查询)。其它设备(从设备)根据主设备查询提供的数据作出相应反应。主设备查询的格式:设备地址(或广播,此时不需要回应)、功能代码、所有要发送的数据、和一错误检测域。从设备回应消息包括确认地址、功能码、任何要返回的数据、和一错误检测域。如果在消息接收过程中发生一错误,或从设备不能执行其命令,从设备将建立一错误消息并把它作为回应发送出去。 控制器能设置为两种传输模式:ASCII和RTU,在同样的波特率下,RTU可比ASCII方式传送更多的数据,所以采用KTU模式。 (1)典型的RTU消息帧 典型的RTU消息帧如表1所示。   RTU消息帧的地址域包含8bit。可能的从设备地址是0...127(十进制)。其中地址0是用作广播地址,以使所有的从设备都能认识。主设备通过将要联络的从设备的地址放入消息中的地址域来选通从设备。当从设备发送回应消息时,它把自己的地址放入回应的地址域中,以便主设备知道是哪一个设备作出回应。 RTU消息帧中的功能代码域包含了8bits,当消息从主设备发往从设备时,功能代码域将告之从设备需要执行哪些行为;当从设备回应时,它使用功能代码域来指示是正常回应(无误)还是有某种错误发生(称作异议回应,一般是将功能码的最高位由0改为1)。 从主设备发给从设备消息的数据域包含附加的信息:从设备必须用于进行执行由功能代码所定义的行为。这包括了像不连续的寄存器地址,要处理项的数目,域中实际数据字节数。如果没有错误发生,从从设备返回的数据域包含请求的数据。如果有错误发生,此域包含一异议代码,主设备应用程序可以用来判断采取下一步行动。 当选用RTU模式作字符帧时,错误检测域包含一16Bits值(用两个8位的字符来实现)。错误检测域的内容是通过对消息内容进行循环冗长检测(CRC)方法得出的。CRC域附加在消息的最后,添加时先是低字节然后是高字节。 (2)所有的Modbus功能码 Modbus的功能码定义如表2所示。   3、常用功能通讯程序的设计 本文介绍了几个Modbus常用功能程序的设计。笔者采用单片机作为主机,在单片机上编写程序实现单片机与PLC之间的通讯。由单片机向PLC发出命令信息,PLC自动作出回应。PLC通过单片机的串行通讯口通讯,程序用C51实现。程序的子函数及其功能: (1)串口初始化 voidProtocolInit(void) 函数功能:串口设置为异步通讯方式1(起始位1位,数据位8位,停止位1位);定时/计数器1设置为波特率发生器,通讯速率9600bps;开串行中断,并把串行中断设置为高优先级。 (2)CRC简单函数 unsignedcharCrc16(unsignedchar*puchMsg,unsignedcharusDataLen) 函数功能:先调入一值是全“1”的16位寄存器,然后调用一过程将消息中连续的8位字节各当前寄存器中的值进行处理。每个8位字符都单独和寄存器内容相或(OR),结果向最低有效位方向移动,最高有效位以0填充。LSB被提取出来检测,如果LSB为1,寄存器单独和预置的值或一下,如果LSB为0,则不进行。整个过程要重复8次。在最后一位(第8位)完成后,下一个8位字节又单独和寄存器的当前值相或。最终寄存器中的值,是消息中所有的字节都执行之后的CRC值。 (3)初始化变量 voidInitvar(void) 函数功能:初始化所有过程变量。 (4)串行中断服务程序 voidProtocolSerialProcess(void)interrupt4using2 函数功能:发送中断发送主机形成的命令数组,发送完后置标志位;接收中断接收PLC返回的响应数组,存入接收数组,并置标志位,且假设响应正确,留待主机处理。 (5)读N个位变量(线圈) voidProtocolRead_bit(unsignedcharDeviceAddr/*PLC局号*/,unsignedcharRegType/*寄存器类型*/,unsignedintBitAddr/*起始地址*/,unsignedcharSubAddr/*子地址*/,unsignedintBitNum/*位数*/) 函数功能:根据函数参数,形成读N个位变量的命令数组,启动发送。等待发送完并接收完(如超时未接收完则重新发送)。分析接收数组:正确,保存读取的数据;错误,重新发送。 (6)写一个位变量 voidProtocolSetBit(unsignedcharDeviceAddr/*PLC局号*/,unsignedcharRegType/*寄存器类型*/,unsignedintBitAddr/*地址*/,unsignedcharSubAddr/*子地址*/,unsignedi ntClrSet/*写值“1”或“0”*/) 函数功能:根据函数参数,形成置某位变量为“1”或“0”的命令数组,启动发送。等待发送完并接收完(如超时未接收完则重新发送)。分析接收数组:正确,返回;错误,重新发送。 (7)读N个字节变量 voidProtocolReadByte(unsignedcharDeviceAddr/*PLC局号*/,unsignedcharRegType/*寄存器类型*/,unsignedintRegAddr/*起始地址*/,unsignedcharSubAddr/*子地址*/,unsignedintRegNum/*个数*/) 函数功能:根据函数参数,形成读N个字节变量的命令数组,启动发送。等待发送完并接收完(如超时未接收完则重新发送)。分析接收数组:正确,保存读取的数据;错误,重新发送。 (8)写N个字节变量 voidProtocolSetByte(unsignedcharDeviceAddr/*PLC局号*/,unsignedcharRegType/*寄存器类型*/,unsignedintRegAddr/*起始地址*/,unsignedcharSubAddr/*子地址*/,unsignedintRegNum/*个数*/) 函数功能:根据函数参数,形成写N个字变量的命令数组(要写的数从某参数数组中读取),启动发送。等待发送完并接收完(如超时未接收完则重新发送)。分析接收数组:正确,返回;错误,重新发送。 4、结束语 以上的程序已经通过实验,并应用于实际的人机系统中。依照类似的方法,可以编写其他不同功能的程序,实现对PLC的不同控制和操作。利用单片机和PLC进行优势互补,可以组成网络化、智能化的工业控制系统。另外整个单片机系统程序用C51语言编程,程序简洁,便于阅读与调试。单片机和人机界面结合可以实时的显示PLC的工作状况,实时的控制、设置、调整PLC工作情况,提高工业控制的自动化程度和实时性。

    时间:2019-07-03 关键词: 通讯 plc C51 单片机

  • 单片机解码万能红外遥控器的C51程序

    使用方法:打开串口调试助手,设置为9600 bps 单片机这边用11.0592MHz的晶振,使用sm0038或者其他型号的红外接收头按下面的电路连接好,其中out直接与单片机的p3.2脚相连.按下遥控器,串口调试助手便会出现解码值.   /******************************************************************/ /* 本程序的蓝本从网上搜集,经修改并注释,万能遥控器解码成功 */ /* 晶振:11.0592MHz */ /************************* 说 明 *********************************/ /* 以一个9ms的低电平和4.5ms的高电平为引导码,后跟32位二进制代码 */ /* 前16位为8位用户码及其反码,后16位为8位的操作码及其反码 */ /* 以脉宽为0.565ms、间隔0.56ms、周期为1.125ms的组合表示"0"; */ /* 以脉宽为0.565ms、间隔1.685ms、周期为2.25ms的组合表示"1"。 */ /* 注意:接收码的脉宽与间隔是对发射码取反的,即间隔是0.565ms */ /* 解码后共有四个十六进制码,本程序取第三个作为识别码 */ /*******************************************************************/ #include #define uchar unsigned char uchar data IRcode[4]; //定义一个4字节的数组用来存储代码 uchar CodeTemp; //编码字节缓存变量 uchar i,j,k; //延时用的循环变量 sbit IRsignal=P3^2; //HS0038接收头OUT端直接连P3.2(INT0) sbit P0_0=P0^0; //P0连接到 LED 上 sbit P0_1=P0^1; sbit P0_2=P0^2; /**************************延时0.9ms子程序**********************/ void Delay0_9ms(void) { uchar j,k; for(j=18;j>0;j--) for(k=20;k>0;k--) ; } /***************************延时1ms子程序**********************/ void Delay1ms(void) { uchar i,j; for(i=2;i>0;i--) for(j=230;j>0;j--) ; } /***************************延时4.5ms子程序**********************/ void Delay4_5ms(void) { uchar i,j; for(i=10;i>0;i--) for(j=225;j>0;j--) ; } /**************************** 延时子程序 ************************/ void Delay(void) { uchar i,j,k; for(i=200;i>0;i--) for(j=200;j>0;j--) for(k=3;k>0;k--) ; } /******************** 中断0解码服务子程序 ********************/ void int0(void) interrupt 0 using 2 { EA = 0; //??? 可以这样,跳入中断,但仍可对P3.2(INT0)进行电平变化的读取 for(k=0;k<10;k++) { Delay0_9ms(); if (IRsignal==1) //如果0.9ms后IRsignal=1,说明不是引导码 { k=10; break; } else if(k==9) //如果 持续了10×0.9ms=9ms的低电平,说明是引导码 { while(IRsignal==0); Delay4_5ms(); //跳过持续4.5ms的高电平 for(i=0;i<4;i++) //分别读取4个字节 { for(j=1;j<=8;j++) //每个字节8个bit的判断 { while(IRsignal==0); //等待上升沿 此处用得很好:因为0.56ms的低电平(接收时)是代码0与1的相同部分 Delay0_9ms(); //从上升沿那一时刻开始延时0.9ms(因为0.9介于0.56(=1.125-0.56)与1.69(=2.25-0.56)之间),再判断IRsignal if(IRsignal==1) //如果IRsignal是"1",高位置"1",并向右移一位 { Delay1ms(); //为什么要延时1ms呢?因为要使IRsignal跳至低电平(即0.56ms的0与1相同部分上) CodeTemp=CodeTemp|0x80; //此处的算法很好 if(j<8) CodeTemp=CodeTemp>>1; } else if(j<8) CodeTemp=CodeTemp>>1;//如果IRsignal是"0",则直接向右移一位,自动补"0" } IRcode=CodeTemp; CodeTemp=0; } for(i=0;i<4;i++) //通过串口将代码发出 { SBUF=IRcode; while(!TI); //等待一个字节发送完毕 TI=0; } Delay(); } } EA = 1; } /***********************串口初始化程序*********************/ void initUART(void) { TMOD |= 0x20; // SCON = 0x50; // PCON |= 0x80; // TH1 = 250; // 9600 bps @ 11.0592MHz TL1 = 250; TR1 = 1; } /**************************主程序*************************/ void main() { P0=0XFF; initUart(); IT0 = 1; //INT0为负边沿触发, (1:负边沿触发,0:低电平触发) EX0 = 1; //外部中断INT0开, (1:开, 0:关 ) EA = 1; //开所有中断 CodeTemp = 0; //初始化红外编码字节缓存变量 Delay(); while(1) { switch(IRcode[2]) { case 0x42:P0=0XFF;P0_0=0;break; case 0x4e:P0=0XFF;P0_1=0;break; case 0x52:P0=0XFF;P0_2=0;break; } } }

    时间:2019-06-18 关键词: C51 单片机解码 万能红外遥控器

  • 汇编语言与C51语言实现跑马灯实验的比较

    当前开发单片机应用系统程序主要应用汇编语言和C51语言,采用汇编语言编写可直接操纵系统的硬件资源,能编写出高效运行的程序代码,程序运行速度快。而采用C51语言编写可改善程序的可读性和可移植性,利于产品的更新换代,大大加快了单片机应用程序的开发速度。下面通过一个简单的实验--跑马灯实验来分析一下这两种语言的差别。用AT89C5l实现的跑马灯实验的原理图如xia 图所示。   跑马灯实验的原理图用汇编语言编写程序来实现,程序如下: ORG 0 000H LJP START//转入主程序 ORG 0040H START:MOV SP,#60H//设置 堆栈指针 OV A,# 0 F EH / /送A 11111110 ROTATE = MOV P1,A//写 P1 SJMP ROTATE//循环 DELAY:MOV RO,们AH//延 时子程序( 1秒) DELAY 1 : 40V R1 , 110 OH DELAY2 , DOV R2 , # OB 3H DJNZ R2 , $ DJNZ R1 , DELAY2 DJNZ RO , Dl; LAYI RET//子程序返回 END 用C51语言编写程序实现跑马灯实验,程序如下: # include < r eg5 1 . h> void main (void)//主函 数 ( unsigned int n; uns igned char code I e d p 1 8 1 = ( Oxf e , Oxfd , Oxf b , Oxf 7 , Oxef,Oxdf,Oxbf,Ox7f};//定义 数组 unsigned char LEDi ; while(1)//无限循环 { P1= ledp [leDIL;//数值送 P1 口 for (n= 0 ; n< 4 0 0 0 0 ; n++ ) ; //延时 Ledi++;//力(x 1 i f ( ledi== 8 ) ledi= 0 ; } ) 通过这个实现同一功能的两个程序可以发现,采用汇编语言编写单片机应用系统程序必须对单片机的内部资源和存储器的结构了如指掌,而且必须记住单片机指令系统的固定格式,按实际地址处理端口数据。而采用C51语言编写单片机应用程序对单片机的指令系统不要求了解,不必考虑单片机的硬件特性与接口结构,采用自然语言,以近似人的思维过程方式使用,改善了程序的可读性,而且可以使程序结构化,易于移植,提高开发程序的效率。另外,由于51系列单片机资源非常有限,在使用C51时尽量使用无符号数和字节变量,尽量使用局部变量,编译器可自动将某些局部变量声明为寄存器变量。 用 C语言编写的程序在KeilμVision3仿真软件中经汇编后产生的汇编代码如下: C : OXO 8 0 0 ESO 8 P10V A, OXO 8 C;OXO802 90084F MOV DPTR, 教 OxO84F C: OX 0805 93 MO vC A, @A+ DPTR C : OXO 8 0 6 F59 0 DOv Pl (Ox90 ( , A C:OxO808 900000 MOV DPTR, { 10xO 0 0 0 C : OXO 8 OB AF 82 MOV R7 , DPL (Ox82) C : OXO 8 OD AE 83 MO v R6 , DPH ( Ox83 ) C : Ox O8OF E4 CLR A C:OxO810 FC MOV R4,A C = Ox O8l1 FD I4OV R5 , A C : Ox0812 7B40 MOV R3 11 OX 4 0 C : OX 0814 7A9C MOV' R2 , 井 Ox9C C : OX 0816 F9 MO v R1 , A C : OX 0817 F8 MOV RO , A C ; Ox0818 D3 SETB C C : Ox0819 12 082D LCALL (C : 082D) C : OXO 81C 4003 JC C : 0821 C = Ox O81E A3 INC DPTR C : Ox081 F 80EA SJMP C : 08 OB C:OxO821 0508 工NC OXO8 C : Ox O 82 3 E5 0 8 MOV A , Ox0 8 C= Ox0825 B408D8 CJNE A, 1} Ox O 8 , main ( C : 0 8 0 0 ) C : OX 0828 E4 CLR A C = Ox0 8 2 9 F5 0 8 MOV OXO 8 , A C : Ox082 B 80D3 SJMP main (C: 0800) C = Ox O 82D EB MOV A , R3 C : OX 082E 9F SUBB A, R7 C : Ox082 F FSF 0 MOV B (OXFO) , A C : Ox0 83 1 EA MOV A, R2 C : Ox0832 9E SUBB A, R6 c: OX 0833 42F0 ORL B ( OXF 0 ) , A C : Ox083 5 E9 MOV A, R1 C : Ox083 6 9D SUBB A, R5 C: Ox0837 42F0 ORL B ( OXFO ) , A C : Ox0 83 9 EC DOV A , R4 C = Ox0 8 3A 64 8 0 XRL A , {} PO ( Ox80 ) C : OX 083C C8 XCH A, R0 C : Ox O 8 3 D 6 4 8 0 XRL A , { f PO ( Ox80 ) C : OX 0 83F 9 8 SUBB A, R0 C : Ox0840 45F0 ORL A, B ( OXFO ) C : OX 0842 22 RET C : Ox0 8 4 3 7 87F MO v R0 井 OX7F C : OX 0845 E4 CLR A C : Ox0846 F6 MOV 6; RO , A C = Ox0847 D8FD DJNZ RO , C 0846 C ; OX 0849 758108 MOV SP ( Ox8 1 ) , l10x0 8 C:OxO84C 020800 LJ址P main (C: 0800) C : OX 0 8 4F FE 10V R6 , A C : OXO 8 5 0 FD OV R5 , A C : OX 0851 FB MOV R3 , A C : OX 0852 F7 MOV OR I , A C : Ox O 8 53 EF MO v A , R7 C ; Ox0 85 4 DFBF DJNZ R7 , C : 0815 C : Ox O 8 5 6 7 F0 0 MOV R7 , 甘σxOO 通过把C51程序经过 KeilμVi-sion3软件编译后生成的汇编程序与直接用汇编语言编写的程序比较,C51语言经编译后有54条指令,而直接用汇编语言编写只需要 17条指令。可以看出;直接用汇编语言编写的单片机的代码效率高。此外,我们还可以观察编译连接后产生的列表.MAP或. M51文件,在该文件中详细列出了分配给变量和代码的地址和生成代码的大小等信息,我们可以了解代码是否优化,变量分配是否合理,堆栈是否溢出等。 无论是汇编语言还是C51语言编写的程序都不是单片机直接运行的程序,只有机器码程序单片机才能直接运行,对于汇编语言程序需要通过汇编程序汇编成机器码程序,对于 C51程序需要通过编译器程序编译成机器码程序。 可以在一个应用程序中,按模块用不同的编程语言编写源程序,最后通过编译器 /连接器生成一个可执行的完整程序,这种编程方式称为混合编程,在编写单片机应用程序时可采用 C51和汇编语言混合编程,一般是用汇编语言编写与硬件有关的程序,用 C51 编写主程序以及数据处理程序。

    时间:2019-06-16 关键词: C51 汇编语言 跑马灯

  • 单片机C51位运算应用技巧

    位运算应用口诀: 清零取位要用与,某位置一可用或,若要取反和交换,轻轻松松用异或! 移位运算要点 1 它们都是双目运算符,两个运算分量都是整形,结果也是整形。 2 "<<" 左移:右边空出的位上补0,左边的位将从字头挤掉,其值相当于乘2。 3 ">>"右移:右边的位被挤掉。对于左边移出的空位,如果是正数则空位补0,若为负数,可能补0或补1,这取决于所用的计算机系统。 4 ">>>"运算符,右边的位被挤掉,对于左边移出的空位一概补上0。 位运算符的应用 (源操作数s 掩码mask) (1) 按位与-- & 1 清零特定位 (mask中特定位置0,其它位为1,s=s&mask) 2 取某数中指定位 (mask中特定位置1,其它位为0,s=s&mask) (2) 按位或-- | 常用来将源操作数某些位置1,其它位不变。 (mask中特定位置1,其它位为0 s=s|mask) (3) 位异或-- ^ 1 使特定位的值取反 (mask中特定位置1,其它位为0 s=s^mask) 2 不引入第三变量,交换两个变量的值 (设 a=a1,b=b1) 目标 操作 操作后状态 a=a1^b1 a=a^b a=a1^b1,b=b b=a1^b1^b1 b=a^b a=a1^b1,b=a a=b1^a1^a1 a=a^b a=b1,b=a 二进制补码运算公式: -x = ~x + 1 = ~(x-1) ~x = -x- -(~x) = x+ ~(-x) = x- x+y = x - ~y - 1 = (x|y)+(x&y) x-y = x + ~y + 1 = (x|~y)-(~x&y) x^y = (x|y)-(x&y) x|y = (x&~y)+y x&y = (~x|y)-~x x==y: ~(x-y|y-x) x!=y: x-y|y-x x< y: (x-y)^((x^y)&((x-y)^x)) x<=y: (x|~y)&((x^y)|~(y-x)) x< y: (~x&y)|((~x|y)&(x-y))//无符号x,y比较 x<=y: (~x|y)&((x^y)|~(y-x))//无符号x,y比较 应用举例 (1) 判断int型变量a是奇数还是偶数 a&1 = 0 偶数 a&1 = 1 奇数 (2) 取int型变量a的第k位 (k=0,1,2……sizeof(int)),即a>>k& (3) 将int型变量a的第k位清0,即a=a&~(1< (4) 将int型变量a的第k位置1, 即a=a|(1< (5) int型变量循环左移k次,即a=a< (6) int型变量a循环右移k次,即a=a>>k|a<<16-k (设sizeof(int)=16) (7)整数的平均值 对于两个整数x,y,如果用 (x+y)/2 求平均值,会产生溢出,因为 x+y 可能会大于INT_MAX,但是我们知道它们的平均值是肯定不会溢出的,我们用如下算法: int average(int x, int y) //返回X,Y 的平均值 { return (x&y)+((x^y)>>1); } (8)判断一个整数是不是2的幂,对于一个数 x >= 0,判断他是不是2的幂 boolean power2(int x) { return ((x&(x-1))==0)&&(x!=0); } (9)不用temp交换两个整数 void swap(int x , int y) { x ^= y; y ^= x; x ^= y; } (10)计算绝对值 int abs( int x ) { int y ; y = x >> 31 ; return (x^y)-y ; //or: (x+y)^y } (11)取模运算转化成位运算 (在不产生溢出的情况下):a % (2^n) 等价于 a & (2^n - 1) (12)乘法运算转化成位运算 (在不产生溢出的情况下):a * (2^n) 等价于 a<< n (13)除法运算转化成位运算 (在不产生溢出的情况下):a / (2^n) 等价于 a>> n 例: 12/8 == 12>>3 (14) a % 2 等价于 a & 1 (15) if (x == a) x= b; else x= a; 等价于 x= a ^ b ^ x; (16) x 的 相反数表示为 (~x+1) (17) 实现最低n位为1,其余位为0的位串信息:~(~0 << n) (18)截取变量x自p位开始的右边n位的信息:(x >> (1+p-n)) & ~(~0 << n) (19)截取old变量第row位,并将该位信息装配到变量new的第15-k位:new |= ((old >> row) & 1) << (15 – k) (20)设s不等于全0,代码寻找最右边为1的位的序号j: for(j = 0; ((1 << j) & s) == 0; j++) ;

    时间:2019-05-22 关键词: C51 单片机 位运算

  • 51单片机入门教程—— 开发环境配置

    本教程包含51单片机开发环境Keil_C51的安装、破解和汉化,以及51单片机仿真环境Proteus的安装、破解。 (说明:本教程仅供学习交流之用,禁止任何商业用途!请在24小时之内删除,如要使用Keil和Proteus请购买正版) 1、 Keil_C51 1.1 keil_c51简介 Keil C51是美国Keil Software公司出品的51系列兼容单片机C语言软件开发系统。与汇编相比,C语言在功能上、结构性、可读性、可维护性上有明显的优势,因而易学易用。Keil提供了包括C编译器、宏汇编、链接器、库管理和一个功能强大的仿真调试器等在内的完整开发方案,通过一个集成开发环境(μVision)将这些部分组合在一起。如果你使用C语言编程,那么Keil几乎就是你的不二之选,即使不使用C语言而仅用汇编语言编程,其方便易用的集成环境、强大的软件仿真调试工具也会令你事半功倍。 1.2 Keil_c51 安装 从官网上下载Keil的安装包(Keil官网),教程使用的版本是V9.0。 双击安装包,点击next,选中同意用户协议。点击next。 选择安装目录,这里选择装到D盘。点击next。 (记住安装目录,待会儿汉化要用到) 输入姓名和邮箱,可以随便写。点击next。 正在安装…… 点击Finish完成安装。 1.3 Keil_C51破解 在桌面上找到Keil的图标,右键单击选择以管理员身份运行。(重要!重要!重要!) 从菜单的File选项打开License Management。 可以看到如下的界面,复制Computer ID。 从网上下载Keil的注册机,双击打开。 把刚刚复制的Computer ID输入到CID栏中,点击Generate,得到注册码。 复制生成的注册码,返回到刚刚的license management界面,将注册码粘贴到LIC栏中,点击Add LIC。 看到如下的界面即为破解成功。 (说明:本教程仅供学习交流之用,禁止任何商业用途!请在24小时之内删除,如要使用Keil请购买正版) 1.4 Keil_C51汉化 从网上下载到Keil_C51的汉化包,找到如图的两个文件。 复制这两个文件到安装目录的UV4文件夹里,替换原文件。 (如安装目录为D:\Keil,就复制到D:\Keil\UV4里) 再次打开keil,可以看到汉化成功。 2、Proteus的安装 2.1 Proteus 简介 Proteus软件是英国Lab Center Electronics公司出版的EDA工具软件(该软件中国总代理为广州风标电子技术有限公司)。它不仅具有其它EDA工具软件的仿真功能,还能仿真单片机及外围器件。它是目前比较好的仿真单片机及外围器件的工具。虽然目前国内推广刚起步,但已受到单片机爱好者、从事单片机教学的教师、致力于单片机开发应用的科技工作者的青睐。 2.2 Proteus 安装 从官网上下载Proteus安装包(Proteus官网链接),双击打开安装包。 进入到安装界面,点击next;在随后的界面点击点击yes接受用户协议。 进入到license key安装模式选择界面,我们选择本地安装。点击next。 进入到证书管理界面,点击“Browse For Key File”,找到破解包里的LICENSE.lxk文件并打开,然后点击“Install” 点击close返回到安装界面就可以看到证书已经被安装了。点击next选择安装路径。(记住安装路径) 接下来一路next,没什么好说的。 点击finish完成安装 至此,proteus就安装完成了,不过安装程序没有帮我们创建桌面快捷方式,我们可以在开始菜单里找到proteus并创建桌面快捷方式。 2.3 Proteus的破解 安装完后我们打开程序会报错,需要破解后才能正常使用。从网上找到破解包,双击打开。 选择proteus的安装路径,点击升级。 再次打开proteus就发现可以正常使用了。 (说明:本教程仅供学习交流之用,禁止任何商业用途!请在24小时之内删除,如要使用Proteus请购买正版) 2.3 Proteus的汉化 在网上下载汉化包,在包里面找到这两个文件,复制到安装目录的BIN文件夹里,替换原有文件。 (例如安装目录是D:\Program Files (x86)\Labcenter Electronics\Proteus 7 Professional,则安装到D:\Program Files (x86)\Labcenter Electronics\Proteus 7 Professional\BIN) 打开Proteus,如果没有如下报错,就汉化成功了。 如果有报错就把 “汉化报错.exe” 文件复制到BIN目录里,双击运行,点击Apply patch。 打开Proteus,可以看到已经汉化。

    时间:2019-04-15 关键词: C51 51单片机 keil C语言

  • 用proteus+keil-C51入门单片机

    网上有用面包板入门单片机的,有自己焊板子入门单片机的,但很少有文章介绍用proteus入门单片机的。为什么呢,因为商人要赚钱,如果你不买他的硬件,买正版proteus赚的也不会到他的口袋里,所以商人绝对不会推广这种廉价而且高效的单片机入门方式。 之前我也尝试着焊一个单片机最小系统,结果电脑死活检测不到我焊的设备。又因为严重缺乏硬件调试的经验,单片机的自制之旅就暂时搁浅了。proteus在自制的期间就装好了,可是不会用,也就没有发现它的强大之处。 用了proteus,就可以省下买硬件的钱,对于入门级的爱好者来说,首先要搞清楚一些原理,对芯片和外设没有要求,所以使用proteus元件库中的器件就可以开始做仿真实验了,和在真板子上没什么区别,还省去了买编程器的钱。我用的是proteus 7。下面给张截图。 而keil uversion是一个很好的嵌入式开发工具软件,我用的是uversion4。可以和proteus连接调试,我暂时还不会。尝试了用keil写了汇编程序,C语言程序,C语言内嵌汇编程序,然后烧到proteus里看效果。这样单片机开发的流程就大概有数了。1)确定需求。单片机的主要就是功能点,以及实现的难点。需要什么资源,硬件资源,软件资源,人力资源。2)设计。  2.1)硬件设计。用什么硬件,实现什么样的功能;什么功能用硬件实现,什么功能用软件实现;PCB的设计。  2.2)软件设计。能否复用以前的模块,软件的架构,模块的功能正交性等等。3)编码。实现需求中的功能点。4)测试。  4.1)仿真测试。这步是很重要的,发现问题越早越有利。尤其是大型的工程,没有强大的仿真会损失很多金钱的!  4.2)真机测试。用来发现仿真没法发现的问题5)维护。出货后的产品服务。 软件开发的大体流程都是如此,对与用proteus和keil入门单片机而言,流程可以简化为:1)分析实验要求2)用proteus搭建仿真电路环境,也就是一个模拟的开发板。3)脑子里设计一下程序的结构,可以画画流程图,状态流图和数据流图。用keil编写程序。4)编译成功后,烧到proteus里看运行的效果是否符合实验的要求。不符合的话就再去修改程序,直到模拟到想要的结果。 目前为止的程序,我都是用内嵌汇编语言编写的,一则可以锻炼汇编语言的编程能力,二则可以熟悉单片机芯片的指令,三则可以熟悉如何用软件来控制硬件的运转(其实就是读写各种硬件的各种状态、数据寄存器)。 有一个高手写的单片机入门文章推荐给大家,地址是:http://www.doc88.com/p-94981043204.html,89c51单片机入门,作者是xcwzjxxj。我是照着他的文章,一步一步把里面的实验程序烧到proteus里运行的。下面的是今天花了一个下午调试出的交通灯程序:1 /*2 * traffic leds, red, yellow, green sequently lights and loop.3 * red lights for 2 mins, yellow lights for 1 mins, green lights for 3 mins.4 */5 #pragma asm6 ORG 0000H ;7 ajmp ASM_ENTRY ;8 ORG 000BH ;timer 0 interrupt vector address9 ajmp TIME0 ;jump to real timer program10 ORG 30H ;11 ASM_ENTRY:12 ; setb cy ;13 mov p1, #11111101B ;light yellow led for initial14 ; mov p1, #00H ;15 mov 30H, #200 ;first software timer, 50ms * 200 = 10s16 mov 31H, #1 ;second software timer, 10s for start red light. After 10s delay will red lights on.17 mov r7, #04H ;pretent previous green light on. set green light state bit r7.218 mov tmod, #01H ;timer/counter 0 works in mode 119 mov th0, #3CH ;20 mov tl0, #0B0H ;immediate number 0x3CB0H = 15536, taking 50000(50ms) to overflow21 setb ea ;enable interrupt22 setb et0 ;enable timer/counter 0 interrupt23 setb tr0 ;timer/counter 0 begin to run24 LOOP: ajmp LOOP ;do anything you want25 TIME0: push acc ;protect acc value26 push psw ;protect psw value27 dec 30H ;28 mov a, 30H ;29 jz TNEXT ;is 10s passed?30 ajmp TRET ;31 TNEXT:32 mov 30H, #200 ;restore counter for 10s33 dec 31H ;second timer begins to count34 mov a, 31H ;35 cjne a, #0, TRET ;is current traffic light exhausted its time?36 mov a, r7 ;a small state machine37 jbc acc.2, RED ;green->red38 jbc acc.0, YELLOW ;red->yellow39 jbc acc.1, GREEN ;yellow->green40 RED:41 mov p1, #11111110B ;light red on42 mov r7, #01H ;set red light state bit r7.043 mov 31H, #2 ;50ms * 200 * 12 = 120s = 2min44 ajmp TRET ;45 YELLOW:46 mov p1, #11111101B ;light yellow on47 mov r7, #02H ;set yellow light state bit r7.148 mov 31H, #1 ;50ms * 200 * 6 = 60s = 1min49 ajmp TRET ;50 GREEN: 51 mov p1, #11111011B ;light green on52 mov r7, #04H ;set green light state bit r7.253 mov 31H, #3 ;50ms * 200 * 18 = 180s = 3min54 TRET:55 mov th0, #3CH ;56 mov tl0, #0B0H ;reset timer constant57 pop psw ;58 pop acc ;59 reti ;60 #pragma endasm看到交通灯在proteus动起来的那一刻真的很让人兴奋!而且省去了硬件的各种问题。 proteus还有很多强大的功能,比如各种虚拟的仪表,不然买个便宜的示波器至少要几百块钱。如果能最大限度的发挥proteus的作用,可以为我们省去很多硬件的开销。 所以,本人建议想学单片机但不知如何入门的人用proteus和keil这两个强大的工具,采用模拟仿真的方式入门,可以迅速的进入状态。还有一点,应该结合芯片手册去学习单片机,对不了解的原理还可以从网上找高手的理解。

    时间:2019-01-16 关键词: C51 单片机 keil proteus

  • CS5532 C51驱动程序

    //The program for CS5532-ASZ//This is a 24bit ADC and PGIA//Made by OurWay and 2006/03/21//#include //#include //根据实际情况定义//sbit SDI5532 = P2^1;//sbit SDO5532 = P2^2;//sbit CLK5532 = P2^3;//sbit CS5532 = P2^0;//sbit ACC7 = ACC^7;//sbit ACC0 = ACC^0;//#define BYTE unsigned char//#define WORD unsigned int#define Adjust5532Run 0#define ReadSADC5532Run 1#define ReadMADC5532Run 1//The ADC results varibles definestruct{ unsigned char top; unsigned char high; unsigned char mid; unsigned char low; }RegDat;//The CS5532-ASZ comm define#define RegRead 0x08#define RegWrite 0x00//=== Offset Register ===#define OffsetRS 0x09//=== Gain Register ===#define GainRS 0x0a//=== Configuration Register ===#define ConfigWrite 0x03//write config#define ConfigRead 0x0b//read config#define PSS 0x80//Power Save Select#define PDW 0x40//Power Down Mode#define RS 0x20//Reset System#define RV 0x10 //Reset Valid#define IS 0x08//Input Short#define GB 0x04//Guard Signal Bit#define VRS 0x02//Voltage Reference Select(Ref>2.5V,VRS=0)#define A1 0x01#define A0 0x80#define OLS 0x40#define OGS 0x10#define FRS 0x08//=== Channel Setup Register ===#define SetupCH1 0x05#define SetupCH2 0x15//Channel Select Bits#define CH1 0x00//CS1=0,CS0=0#define CH2 0x40//CS1=0,CS0=1//Gain Bits#define Gain1 0x00#define Gain2 0x08#define Gain4 0x10#define Gain8 0x18#define Gain16 0x20#define Gain32 0x28#define Gain64 0x30//=== Converter mode ===#define SingleC 0x80#define ContinC 0xC0#define Setup1 0x00#define Setup2 0x08#define Setup3 0x10#define Setup4 0x18#define Setup5 0x20#define Setup6 0x28#define Setup7 0x30#define Setup8 0x38//The data(8bit) form MCU to CS5532void SendByte5532(unsigned char Dat) { unsigned char i; CLK5532 = 0; for(i=8;i>0;i--) { SDI5532=(bit)(Dat & 0x80); CLK5532=1; _nop_();_nop_(); _nop_();_nop_(); CLK5532=0; _nop_();_nop_(); _nop_();_nop_(); Dat = Dat

    时间:2019-01-16 关键词: C51 驱动程序 cs5532

  • 单片机C51的计数器

    该部分的硬件电路如图所示,U1的P0口和P2口的部份引脚构成了6位LED数码管驱动电路,数码管采用共阳型,使用PNP型三极管作为片选端的驱动,所 有三极管的发射极连在一起,接到正电源端,它们的基极则分别连到P2.0…P2.5,当P2.0…P2.5中某引脚输是低电平时,三极管导通,给相应的数 码管供电,该位数码管点亮哪些笔段,则取决于笔段引脚是高或低电平。图中看出,所有6位数码管的笔段连在一起,通过限流电阻后接到P0口,因此,哪些笔段 亮就取决于P0口的8根线的状态。 编写程序时,首先根据硬件连线写出LED数码管的字形码、位驱动码,然后编写程序如下:#include "reg51.h"#define uchar unsigned char#define uint unsigned intuchar code BitTab[]={0x7F,0xBF,0xDF,0xEF,0xF7,0xFB}; //位驱动码uchar code DispTab[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xFF}; //字形码uchar DispBuf[6]; //显示缓冲区void Timer1() interrupt 3{ uchar tmp;uchar Count; //计数器,显示程序通过它得知现正显示哪个数码管TH1=(65536-3000)/256;TL1=(65536-3000)%256; //重置初值tmp=BitTab[Count]; //取位值P2=P2|0xfc; //P2与11111100B相或P2=P2&tmp; //P2与取出的位值相与tmp=DispBuf[Count];//取出待显示的数tmp=DispTab[tmp]; //取字形码P0=tmp;Count++;if(Count==6)Count=0;}void main(){ uint tmp;P1=0xff;P0=0xff;TMOD=0x15; //定时器0工作于计数方式1,定时器1工作于定时方式1TH1=(65536-3000)/256;TL1=(65536-3000)%256; //定时时间为3000个周期TR0=1; //计数器0开始运行TR1=1;EA=1;ET1=1;for(;;){ tmp=TL0|(TH0

    时间:2019-01-16 关键词: C51 单片机 计数器

  • Keil C51使用教程---C51 vs 标准C(三)

    深入理解并应用C51对标准ANSIC的扩展是学习C51的关键之一。因为大多数扩展功能都是直接针对8051系列CPU硬件的。大致有以下8类: ●8051存储类型及存储区域 ●存储模式 ●存储器类型声明 ●变量类型声明 ●位变量与位寻址 ●特殊功能寄存器(SFR) ●C51指针 ●函数属性具体说明如下(8031为缺省CPU)。第一节 Keil C51扩展关键字C51 V4.0版本有以下扩展关键字(共19个):_at_ idata sfr16 alien interrupt smallbdata large _task_ Code bit pdatausing reentrant xdata compact sbit data sfr第二节 内存区域(Memory Areas):1. Pragram Area:由Code说明可有多达64kBytes的程序存储器2. Internal Data Memory: 内部数据存储器可用以下关键字说明: data:直接寻址区,为内部RAM的低128字节 00H~7FH idata:间接寻址区,包括整个内部RAM区 00H~FFH bdata:可位寻址区, 20H~2FH3. External Data Memory 外部RAM视使用情况可由以下关键字标识: xdata:可指定多达64KB的外部直接寻址区,地址范围0000H~0FFFFH pdata:能访问1页(25bBytes)的外部RAM,主要用于紧凑模式(Compact Model)。4. Speciac Function Register Memory8051提供128Bytes的SFR寻址区,这区域可位寻址、字节寻址或字寻址,用以控制定时器、计数器、串口、I/O及其它部件,可由以下几种关键字说明:sfr:字节寻址 比如 sfr P0=0x80;为PO口地址为80H,“=”后H~FFH之间的常数。sfr16:字寻址,如sfr16 T2=0xcc;指定Timer2口地址T2L=0xcc T2H=0xCDsbit:位寻址,如sbit EA=0xAF;指定第0xAF位为EA,即中断允许还可以有如下定义方法: sbit 0V=PSW^2;(定义0V为PSW的第2位) sbit 0V=0XDO^2;(同上)或bit 0V-=0xD2(同上)。第三节 存储模式存储模式决定了没有明确指定存储类型的变量,函数参数等的缺省存储区域,共三种:1. Small模式所有缺省变量参数均装入内部RAM,优点是访问速度快,缺点是空间有限,只适用于小程序。2. Compact模式所有缺省变量均位于外部RAM区的一页(256Bytes),具体哪一页可由P2口指定,在STARTUP.A51文件中说明,也可用pdata指定,优点是空间较Small为宽裕速度较Small慢,较large要快,是一种中间状态。3. large模式所有缺省变量可放在多达64KB的外部RAM区,优点是空间大,可存变量多,缺点是速度较慢。提示:存储模式在C51编译器选项中选择。第四节 存储类型声明变量或参数的存储类型可由存储模式指定缺省类型,也可由关键字直接声明指定。各类型分别用:code,data,idata,xdata,pdata说明,例:data uar1char code array[ ]=“hello!”;unsigned char xdata arr[10][4][4];第五节 变量或数据类型C51提供以下几种扩展数据类型: bit 位变量值为0或1 sbit 从字节中定义的位变量 0或1 sfr sfr字节地址 0~255 sfr16 sfr字地址 0~65535其余数据类型如:char,enum,short,int,long,float等与ANSI C相同。第六节 位变量与声明1. bit型变量bit型变量可用变量类型,函数声明、函数返回值等,存贮于内部RAM20H~2FH。注意:(1) 用#pragma disable说明函数和用“usign”指定的函数,不能返回bit值。(2) 一个bit变量不能声明为指针,如bit *ptr;是错误的(3) 不能有bit数组如:bit arr[5];错误。2. 可位寻址区说明20H-2FH可作如下定义:int bdata i;char bdata arr[3],然后:sbit bito=in0;sbit bit15=I^15;sbit arr07=arr[0]^7;sbit arr15=arr[i]^7;第七节 Keil C51指针C51支持一般指针(Generic Pointer)和存储器指针(Memory_Specific Pointer).1. 一般指针一般指针的声明和使用均与标准C相同,不过同时还可以说明指针的存储类型,例如: long * state;为一个指向long型整数的指针,而state本身则依存储模式存放。 char * xdata ptr;ptr为一个指向char数据的指针,而ptr本身放于外部RAM区,以上的long,char等指针指向的数据可存放于任何存储器中。一般指针本身用3个字节存放,分别为存储器类型,高位偏移,低位偏移量。2.存储器指针基于存储器的指针说明时即指定了存贮类型,例如: char data * str;str指向data区中char型数据 int xdata * pow; pow指向外部RAM的int型整数。这种指针存放时,只需一个字节或2个字节就够了,因为只需存放偏移量。3. 指针转换即指针在上两种类型之间转化: ●当基于存储器的指针作为一个实参传递给需要一般指针的函数时,指针自动转化。 ●如果不说明外部函数原形,基于存储器的指针自动转化为一般指针,导致错误,因而请用“#include”说明所有函数原形。 ●可以强行改变指针类型。第八节 Keil C51函数C51函数声明对ANSI C作了扩展,具体包括:1. 中断函数声明:中断声明方法如下:void serial_ISR () interrupt 4 [using 1]{/* ISR */}为提高代码的容错能力,在没用到的中断入口处生成iret语句,定义没用到的中断。/* define not used interrupt, so generate "IRET" in their entrance */void extern0_ISR() interrupt 0{} /* not used */void timer0_ISR () interrupt 1{} /* not used */void extern1_ISR() interrupt 2{} /* not used */void timer1_ISR () interrupt 3{} /* not used */void serial_ISR () interrupt 4{} /* not used */2. 通用存储工作区3. 选通用存储工作区由using x声明,见上例。4. 指定存储模式由small compact 及large说明,例如:void fun1(void) small { } 提示:small说明的函数内部变量全部使用内部RAM。关键的经常性的耗时的地方可以这样声明,以提高运行速度。5. #pragma disable在函数前声明,只对一个函数有效。该函数调用过程中将不可被中断。6. 递归或可重入函数指定在主程序和中断中都可调用的函数,容易产生问题。因为51和PC不同,PC使用堆栈传递参数,且静态变量以外的内部变量都在堆栈中;而51一般使用寄存器传递参数,内部变量一般在RAM中,函数重入时会破坏上次调用的数据。可以用以下两种方法解决函数重入:a、在相应的函数前使用前述“#pragma disable”声明,即只允许主程序或中断之一调用该函数;b、将该函数说明为可重入的。如下:void func(param...) reentrant;KeilC51编译后将生成一个可重入变量堆栈,然后就可以模拟通过堆栈传递变量的方法。由于一般可重入函数由主程序和中断调用,所以通常中断使用与主程序不同的R寄存器组。另外,对可重入函数,在相应的函数前面加上开关“#pragma noaregs”,以禁止编译器使用绝对寄存器寻址,可生成不依赖于寄存器组的代码。7. 指定PL/M-51函数由alien指定。

    时间:2019-01-15 关键词: C51 keil 标准c

  • uC/OS-II在C51上的移植步骤

    这段时间已成功把uC/OS-II 2.52移植到51单片机上,现总结移植步骤:1.在main函数只包括void main(void){OSInit();OSStart();}看是否能编译通过,可以通过后继续下一步。2.验证OSTaskStkInit()和OSStartHighRdy()函数这 里首先要修改OS_CFG.H文件,设置OS_TASK_STAT_EN 为0,以禁止统计任务。只让空闲任务工作,并单步执行,直到uC/OS-II切换到OS_TaskIdle()。单步时跳过OSInit()函数,单步进 入OSStart()函数。 一直单步运行到调用OSStartHighRdy()(这是OSStart()函数的最后一句),然后单步进入OSStartHighRdy()。这时, 编译器应该切换到汇编语言模式下,因为OSStartHighRdy()是用汇编语句实现的。OSStartRdy()会开始运行第1个任务;而此时并没 有任何应用任务.只有OS_TaskIdle()可以运行。如果调试器在OS_TaskIdle()循环中运行,且在无限循环中已经执行几次,那么就已经 验证了OSTaskStkInit()和OSStartHighRdy()函数是成功的。3.验证OSCtxSw()函数 (注这是中断是关着的,见OS_CORE.C的OS_Sched())如果上一步测试成功,这一步代码验 证就比较容易了.因为已经知道由OSTaskStkInit()初始化的堆栈结构是正确的。在这一步测试中,添加了一个应用程序.并不断切换到空闲任务。 在这之前,应该保证已经正确设置了软中断向量或指令陷阱TRAP向量,使之指向OSCtxSw()函数。这里uC/OS-II应该将TestTask() (假设刚建立的任务名为它)作为第1个任务开始执行,而不再是空闲任务。可以单步执行,一直到TestTask()函数的开始.注这时并没有允许中断,也 没有打开时钟节拍,所以OSTimeDly(1)不会返回到TestTask(). 并经调度后由OSCtxSw()返回到OS_TaskIdle()任务中。这样的说明OSCtxSw()函数移植成功。#i nclude "includes.h"OS_STK TestTaskStk[100];void TestTask(void *ptrdata){ptrdata=ptrdata;while(1){OSTimeDly(1);}}void main(void){OSInit();OSTaskCreate(TestTask,(void *)0,&TestTaskStk[99],0);//51仿真堆栈?C_XBP递增OSStart();}3.验证OSIntCtxSw()和OSTickISR()函数OSIntCtxSw()很像OSCtxSw(),且比OSCtxSw()简单。在此测试之前,应该保证时钟中断向量指向了时钟节拍中断服务子程序,然后,初始化时钟节拍并开中断。我这里测试使用100Hz的节拍,节拍的速度应该与在OS_CFG.H中设置的OS_TICKS_PER_SEC吻合。测试代码如下:#i nclude "includes.h"sbit LedBlink=P1^0;OS_STK TestTaskStk[100];void TestTask(void *ptrdata){ptrdata=ptrdata;OS_ENTER_CRITICAL();TMOD=0x01;TH0=0xdc;//10ms,100hzTL0=0x00;TR0=1;ET0=1;OS_EXIT_CRITICAL();while(1){OSTimeDly(1);if (LedBlink==FALSE){LedBlink=TRUE;}else{LedBlink=FALSE;}}}void main(void){OSInit();OSTaskCreate(TestTask,(void *)0,&TestTaskStk[99],0);//51仿真堆栈?C_XBP递增OSStart();}时钟节拍中断调用OSTickISR(),继而调用OSTimeTick。说明:OSTickISR中一定要有中断调度程序,否则的话,空闲任务无法再切换到其它应用任务,因为空闲任务没有任务延时函数.编译成功后,点Run,然后在TestTask任务OSTimeDly(1);处设置断点,并单步进入,看能否正确任务调度到 OSTaskIdle()即空闲任务,空闲任务一直到运行,直到接收到时钟节拍中断(即Timer0),时钟节拍中断调用OSTickISR(),继而调 用OSTimerTick().OSTimerTick()将TestTask()的.OSTCBDly计数器递减到0,使该任务进入就绪态;而当 OSTickISR()完成并调用OSIntExit()函数时,OSIntExit()将会注意到有更重要的任务,TestTask()已处于就绪态等 待运行。这时ISR就不会再返回到空闲任务,而是做任务切换,回到TestTask()任务。当然,以上是假设OSIntCtxSw()和 OSTickISR()这2个函数都能正常工作.如果OSIntCtxSw()正常工作,而且已经将时钟节拍频率设置为100Hz(10ms),这里可以 看到LED即P1.0在来回闪烁.4.然后再写其它中断服务函数的入口处程序,可以参考OSTickISR()。5.至此,uC/OS-II的移植工作就OK了,可以添加更多的应用程序了,真正的项目工作可以开始了。

    时间:2019-01-14 关键词: C51 uc os-ii 移植步骤

  • Keil C51使用教程---例子:Hello.c(六)

    Hello位于C51excmplesHello目录,其功能是向串口输出“Hello,world”整个程序如下:#pragma DB OE CD#indule#includevoid main(void) { SCOn=0x50; TMOD=0x20 TH1=0xf3; Tri=1; TI=1; printf(“Hello,world n”); while(1) { } }第一节 uVision for Windows的使用步骤(1) file_new新建一个hello.c文件,输入如上内容或直接用目录下源文件。(2) file_save或工具栏将文件存盘。(3) project_new project创建一个project名为hello,并在其中加入hello.c。 这时该project已是打开状态,或用open project打开已存在的project。(4) option_C51 compiler中选出至少包括两项DB OE。(5) option_dscope Debugger选中helloDS51.INI查看DS51.INI看其是否为: “load……BIN8051.DLL map 0, 0xffff”否则修改。(6) 在option_make选make文件顺序。(7) project选Build project,看是否有语法错误,若无则生成HEX文件,若有则修改源文件后重复以上部分步骤。(8) run_dScope debugger进入dScope51后装入hello则可用go直接运行看serial窗口有无输出,正常每系统运行一次,serial窗口均出现一个“Hello,world”表明运行无误。第二节 Ishell for Dos使用步骤(1) 进入Ishell 用Setup editer选择编辑器。然后单击Edit或用Edit命令编辑hello.c源文件,存盘,也可以在files窗口中直接选中hello.c。(2) 用cd改换project目录至hello目录。(3) 在setup_target一项目选8051。(4) 在setup_C51中输出DB OE。(5) 在setup_project输入project名hello。(6) 在setup_save保存Ishell.CFG文件。(7) 编辑一个Link文件hello.lin中有“hell.obj”一行。(8) 由光标落在files菜单中的Hello.c上,单击“translate”,如无语法错,再击“link”,则Hex文件生成。(9) 单击Simulate如在8051.CDF中选Simulate为dScope则进入dScope调试直接“Go”,看serial窗口输出为“Hello.world”。(10) 如程序有误修改源代码后不必再translate或link了,只要一步Amake即可。若project中包括不止一个文件,在DOS的Ishell中不能用Translate编译,而应建立bat文件,直接在命令窗编译,然后link连接。如还需用Translate则只能多个文件分别编译,然后连接。

    时间:2019-01-11 关键词: C51 keil

  • C51的中断函数的格式

    TFX4-20ma电流环专用ic90的中断函数的格式为:void FuncIr(void) 字库液晶4 x [using y]void 变频器开关电源维修3数名(void) interrupt n using m { 函数体语句 } interrupt using 是C51中断服务程序引入关?ps压力传感器8?只能用于C51中断服务程序逻辑定义中断函数时,using是一个选项,可以省略不用。如果不用则由编译器选择一个寄存器组作为绝对寄存器组。 n是中断号 0 是外部中断0 1 是定时中断T0 2 是外部中断1 3 是定时中断T1 4 是串行中断 5 是定时器T2 m是寄存器组 0——3 4组 不使用编译器将当前工作寄存器都入堆栈 注意#include 文件使用中断函数时要注意的问题:1.在设计中断时,要注意的是哪些功能应该放在中断程序中,哪些功能应该放在主程序中。一般来说中断服务程序应该做最少量的工作,这样做有很多好处。首先系统对中断的反应面更宽了,有些系统如果丢失中断或对中断反应太慢将产生十分严重的后果,这时有充足的时间等待中断是十分重要的。其次它可使中断服务程序的结构简单,不容易出错。中断程序中放入的东西越多,他们之间越容易起冲突。简化中断服务程序意味着软件中将有更多的代码段,但可把这些都放入主程序中。中断服务程序的设计对系统的成败有至关重要的作用,要仔细考虑各中断之间的关系和每个中断执行的时间,特别要注意那些对同一个数据进行操作的ISR.2.中断函数不能传递参数。3.中断函数没有返回值。4.中断函数调用其他函数,则要保证使用相同的寄存器组,否则出错。5.中断函数使用浮点运算要保存浮点寄存器的状态。

    时间:2019-01-11 关键词: C51 格式 中断函数

  • Keil C51使用教程---代码效率(七)

    C51程序编译生成汇编代码的效率,是由许多因素共同决定的,对于Keil C51,主要受以下两种因素影响:第一节 存储模式的影响存储模式决定了缺省变量的存储空间,而访问各空间变量的汇编代码的繁简程度决定了代码率的高低。例如:一个整形变量i,如放于内存18H、19H空间,则++i的操作编译成四条语句:INC 0x19MOV A,0x19JNZ 0x272DINC 0x180x272D:而如果放于外存空间0000H、0001H则++i的操作编译成九条语句:MOV DPTR,0001MOVX A,@ DPTRINC AMOVX @ DPTR,AJNz #5MOV OPTR,#0000MOVX A,@DPTRINC AMOVX @ DPTR,A就汇编之后的语句而言,对外部存储器的操作较内部存储器操作代码率要低得多,生成的语句为内存的两倍以上,而程序中有大量的这种操作,可见存储模式对代码率的响了。因此程序设计的原则是1、存储模式从small-Compact-large依次选择,实在是变量太多,才选large模式。2、即使选择了large模式,对一些常用的局部的或者可放于内存中的变量,最好放于内存中,以尽量提高程序的代码率。第二节 程序结构的影响程序的结构单元包括模块、函数等等。同样的功能,如果结构越复杂,其所涉及的操作、变量、功能模块函数等就越多,较之结构性好,代码简单的程序其代码率自然就低得多。此外程序的运行控制语句,也是影响代码率的关键因素,例如:switch -case语句,许多编译器都把它们译得非常复杂,Keil C51也不例外,相对较为简易的Switch-case语句,编译成跳转指令形式,代码率较高,但对较为复杂的Switch-Case,则要调用一个系统库函数?C?ICASE进行处理,非常复杂。再如if( ),while( ),等语句也是代码相对较低的语句,但编译以后比switch-case要高得多。因此建议设计者尽量少用switch-case之类语句来控制程序结构,以提高代码率。除以上两点外,其它因素也会对代码率产生影响,例如:是否用寄存器传递参数 即NOAREGS选项是否有是否包括调试信息:即DEBUG选项是否包括扩展的调试信息:即BJECTEXTEND

    时间:2019-01-09 关键词: C51 keil 代码效率

首页  上一页  1 2 3 4 5 6 7 8 9 10 下一页 尾页
发布文章

技术子站

更多

项目外包