学习C51的第一个程序
- 格式:doc
- 大小:117.50 KB
- 文档页数:12
Keil C51软件入门1、新建一个文件夹,用来存放本次操作的文件。
2、启动Keil C51,进入Keil C51开发环境。
图1 启动Keil C51时的屏幕3、点击Project(工程)→New Project(新建工程),进入“Create New Project(创建新工程)”对话框。
图2 新建工程4、在“文件名”栏输入程序项目名称zdx,单击“保存”按钮,即保存一个zdx.uv2文件。
进入选择芯片对话框(Select Device for Target …Target 1‟)。
图3 保存工程5、进入选择芯片对话框(Select Device for Target …Target 1‟)。
在对话框中找到Atmel(Intel)公司,点击下来菜单找到AT89C51(8051AH)。
单击确定,弹出“启动代码选择”对话框,单击“是”,添加启动代码,单击“否”则以后需要再添加,一般选择“否”。
图4 选择单片机芯片6、点击Project(工程)→Options for Target…Target 1‟(项目选项)或在Target 1(目标1)上右击鼠标,出现“Options for Target…Target 1‟”对话框。
选择“Target(项目)”页面,将Xtal(时钟)栏的时钟改为12MHz。
再选择Output(输出)页面,勾选Create Hex File(输出十六进制文件)复选框。
(文件编译后可生成Hex 文件,在Proteus中可直接加载),其他默认,单击确认按钮。
7、点击File (文件)→New (新建),即新建“Text1(文本)”文件,在该文件编辑栏编写汇编程序。
完成后,点击File (文件)→Save As (保存为),在弹出的对话框的文件名栏输入“zdx.asm”(汇编程序)或”zdx.c”(C 程序)(必须输入后缀名)。
8、回到Keil C51开发环境,单击Target 1的下拉菜单,在Source Croup 1(源程序)上右击,选择“Add File to Group …Source Croup1‟(添加文件到源程序)命令,在弹出的“Add File to Group …Source Croup1‟”对话框的文件类型栏,选择Asm Source file (汇编源程序) 或C Source file (C 源程序),查找““zdx.asm”文件,单击Add 按钮,将源程序添加到Source Croup 1。
51单片机C语言学习杂记学习单片机实在不是件易事,一来要购买高价格的编程器,仿真器,二来要学习编程语言,还有众多种类的单片机选择真是件让人头痛的事。
在众多单片机中51 架构的芯片风行很久,学习资料也相对很多,是初学的较好的选择之一。
51 的编程语言常用的有二种,一种是汇编语言,一种是 C 语言。
汇编语言的机器代码生成效率很高但可读性却并不强,复杂一点的程序就更是难读懂,而 C 语言在大多数情况下其机器代码生成效率和汇编语言相当,但可读性和可移植性却远远超过汇编语言,而且 C 语言还可以嵌入汇编来解决高时效性的代码编写问题。
对于开发周期来说,中大型的软件编写用 C 语言的开发周期通常要小于汇编语言很多。
综合以上 C 语言的优点,我在学习时选择了 C 语言。
以后的教程也只是我在学习过程中的一些学习笔记和随笔,在这里加以整理和修改,希望和大家一起分享,一起交流,一起学习,一起进步。
*注:可以肯定的说这个教程只是为初学或入门者准备的,笔者本人也只是菜鸟一只,有望各位大侠高手指点错误提出建议。
明浩2003-3-30mailto:pnzwzw@ wzw@第一课建立您的第一个C项目使用C 语言肯定要使用到C 编译器,以便把写好的C 程序编译为机器码,这样单片机才能执行编写好的程序。
KEIL uVISION2 是众多单片机应用开发软件中优秀的软件之一,它支持众多不同公司的MCS51 架构的芯片,它集编辑,编译,仿真等于一体,同时还支持,PLM,汇编和C 语言的程序设计,它的界面和常用的微软VC++的界面相似,界面友好,易学易用,在调试程序,软件仿真方面也有很强大的功能。
因此很多开发51 应用的工程师或普通的单片机爱好者,都对它十分喜欢。
以上简单介绍了KEIL51 软件,要使用KEIL51 软件,必需先要安装它。
KEIL51 是一个商业的软件,对于我们这些普通爱好者可以到KEIL 中国代理周立功公司的网站上下载一份能编译2K 的DEMO 版软件,基本可以满足一般的个人学习和小型应用的开发。
51单片机C语言入门教程单片机是一种集成电路,可以完成各种功能。
C语言是一种高级编程语言,可以用来编写单片机的程序。
本文将介绍51单片机C语言的入门教程。
一、选择合适的开发环境选择合适的开发环境是学习51单片机C语言的第一步。
常用的开发环境有Keil C51、SDCC、IAR Embedded Workbench等。
这些开发环境都提供了开发工具和编译器,方便编写和调试代码。
二、了解51单片机的基本结构三、学习C语言的基本语法学习C语言的基本语法是学习51单片机C语言的基础。
C语言包括数据类型、变量、运算符、控制流语句等等。
学习C语言的基本语法可以参考相关的C语言教程。
四、掌握51单片机的特殊功能寄存器51单片机具有一些特殊功能寄存器,可以实现各种功能。
例如,P0是一个I/O口,可以用来控制外部设备的输入和输出;TMOD和TCON分别是定时器/计数器的模式和控制寄存器,可以实现定时和计数功能。
掌握这些特殊功能寄存器可以为后面的单片机编程做好准备。
五、编写第一个51单片机C语言程序编写第一个51单片机C语言程序可以帮助巩固前面学习的知识。
可以从简单的LED闪烁程序开始,逐步扩展到其他功能。
编写程序的过程中要注意语法的正确性和逻辑的合理性。
六、调试程序调试程序是保证程序正确运行的关键。
可以使用仿真器或者调试器对程序进行调试。
调试程序可以查看程序的运行状态、变量的值等等,帮助定位错误并进行修复。
七、深入学习更高级的C语言特性一旦掌握了基本的51单片机C语言编程,可以深入学习更高级的C语言特性。
例如,函数的使用、数组的应用、结构体和指针等等。
这些高级特性可以使程序更加模块化和灵活。
八、练习和实践练习和实践是巩固51单片机C语言编程知识的最好方法。
可以选择一些小项目或者例程进行练习,将理论知识应用于实际。
总结:通过以上的步骤,我们可以初步学习和掌握51单片机C语言的编程。
当然,这仅仅是入门级别的教程,还有很多更深入的知识需要进一步学习和探索。
第三章 C51语言作者:彭保基 西安交通大学 电信学院 电子2002级 版本:V1.1 写作时间:2004年12月---2005年3月本章主要介绍在Keil 的集成环境下用C 语言编程,并对C51语言与标准的C 语言的异同进行比较。
由于篇幅有限并考虑到读者大部分已经学过标准的C 语言,不再对C 语言进行深入的讲解;如果读者想深入了解和掌握C 语言,则可查阅和参考其他相关资料。
第一节 C51简介汇编语言是编写单片机程序的常用语言之一,很多老的单片机开发者使用汇编语言已经成为了一种习惯;汇编语言编写的程序所生成的代码效率很高,能直接操作硬件,指令的执行速度快。
但其指令系统的固有格式受硬件结构的限制很大,且难于编写与调试,可移植性也差。
随着单片机硬件性能的提高,其工作速度越来越快,因此在编写单片机应用系统程序时,更着重于程序本身的编写效率。
与汇编语言相比,C 语言在功能、结构、可读性和可维护性上有明显的优势,因而易学易用;在开发大型软件时更能体现其高级语言的优势。
因此,近些年来越来越多地人喜欢用C 语言来编写单片机的应用程序。
本章所说的C51语言就是标准C 语言的变种,是标准C 语言的扩展;关于两者的区别,将在下一节中详细的介绍。
第二节 C51与ANSI C 的比较Keil C51编译器是一个完全支持ANSI 标准C 语言的编译器,除了少数关键的地方之外,Keil C51和标准ANSI C 语言是基本类似的;但由于51单片机的特殊性,Keil C51在标准C 语言基础上进行了扩展,使其能够更有效地利用单片机各种有限的资源。
深入理解和掌握C51对标准C 语言的扩展,是学好C51语言的关键。
一、 Keil C51扩展关键字关键字 用 途 说 明bit 声明一个位标量或位类型的函数sbit 位标量声明声明一个可位寻址变量 Sfr 声明一个特殊功能寄存器 Sfr16 特殊功能寄存器声明声明一个16位的特殊功能寄存器 data 直接寻址的内部数据存储器 bdata可位寻址的内部数据存储器idata 间接寻址的内部数据存储器 pdata 分页寻址的外部数据存储器xdata 外部数据存储器 code 存储器类型说明 程序存储器interrupt 中断函数说明 定义一个中断函数 reentrant 再入函数说明 定义一个再入函数 using 寄存器组定义定义芯片的工作寄存器_at_ 绝对定位_task_ alien small compact large存储模式附表3- C51编译器的扩展关键字二、 数据类型Keil C51编译器支持下表列出的数据类型。
总的作用:STARTUP.A51//启动文件. 清理RAM.设置堆栈等.即执行完start.a51后跳转到.c文件的main 函数<reg51.h> //特殊寄存器的字节地址和位地址,sfr定义字节变量、sbit定义位变量,用通俗名作为变量名,并赋地址值,从而用名称来使用这些特殊寄存器。
<intrins.h> //定义了一些外部函数,在C51单片机编程中,头文件INTRINS.H的函数使用起来,就会让你像在用汇编时一样简便.特别需要注意的概念:地址与地址值:“地址是存放值的内存空间对应的门牌号码。
地址值是门牌号对应内存空间里存放内容。
通俗讲,一栋楼房, 101号房间什么都没只有1个人。
这个人是值。
101是地址。
房间是内存空间。
”启动程序详细解释;STARTUP.A51:用户上电初始化程序;------------------------------------------------------------------------------;; 用户定义需上电初始化的内存空间;; 使用以下EQU命令可定义在CPU复位时需用0进行初始化的内存空间;; ;IDATA 存储器的空间的绝对起始地址总是0.IDATALENEQU 80H ; 需用0进行初始化的IDATA存储器空间的字节数;XDATASTARTEQU 0H ; XDATA存储器空间的绝对起始地址XDATALENEQU 0H ; 需用0进行初始化的XDATA存储器的空间字节数.;PDATASTARTEQU 0H ; PDATA存储器的空间的绝对起始地址PDATALENEQU 0H ; 需用0进行初始化的PDATA存储器的空间字节数.;; 注意: IDATA 存储器的空间在物理上包括了8051单片机的DATA和BIT存储器空间.; 听说至少要保证与C51编译器运行库有关的存储器的空间进行0初始化不知是否;------------------------------------------------------------------------------;; 再入函数模拟初始化;; 以下用EQU指令定义了再入函数模拟堆栈指针的初始化;; 使用SMALL存储器模式时再入函数的堆栈空间.IBPSTACKEQU 0 ; 使用SMALL存储器模式再入函数时将其设置成1. IBPSTACKTOPEQU 0FFH+1 ; 将堆栈顶设置为最高地址+1.;; 使用LARGE存储器模式时再入函数的堆栈空间.XBPSTACKEQU 0 ; 使用LARGE存储器模式再入函数时将其设置成1. XBPSTACKTOPEQU 0FFFFH+1; 将堆栈顶设置为最高地址+1.;; 使用COMPACT存储器模式时再入函数的堆栈空间.PBPSTACKEQU 0 ; 使用COMPACT存储器模式再入函数时将其设置成1. PBPSTACKTOPEQU 0FFFFH+1; 将堆栈顶设置为最高地址+1.;;------------------------------------------------------------------------------;; 使用COMPACT存储器模式时64K字节XDATA存储器空间的分页定义;; 以下用EQU指令定义PDATA类型变量在XDATA存储器空间的页地址; 使用EQU指令定义PFAGE时必须与L51连接定位器PDATA指令的控制参数一致;PPAGEENABLEEQU 0 ; 使用PDATA类型变量时将其设置成1.PPAGEEQU 0 ; 定义页号.;;------------------------------------------------------------------------------NAME?C_STARTUP ; 模块名为?C_STAUTUP?C_C51STARTUPSEGMENT CODE ; 代码?STACKSEGMENT IDATA ; 堆栈RSEG?STACK ; 堆栈DS 1EXTRNCODE (?C_START) ; 程序开始地址PUBLIC?C_STARTUPCSEGAT 0x8000 ; 定义用户程序的起始地址,用MON51仿真器时可能有用?C_STARTUP:LJMP STARTUP1RSEG?C_C51STARTUPSTARTUP1:;; 初始化串口MOVSCON,#40HMOVTMOD,#20HMOVTH1,#0fdHSETBTR1CLRTI; 单片机上电IDATA内存清零如果不需要上电清零IDATA可以注销IF到IFEDN之间的话句; 或者修改IDTALEN的长度为了具有掉电保护功能不知IDTALEN多长为好IFIDATALEN <> 0MOVR0,#IDATALEN - 1CLR AIDATALOOP:MOV @R0,ADJNZR0,IDATALOOPENDIF;; 单片机上电XDATA内存清零如果不需要上电清零XDATA可以注销IF到IFEDN之间的话句; 或者修改XDATALEN的长度IFXDATALEN <> 0MOVDPTR,#XDATASTARTMOVR7,#LOW (XDATALEN)IF(LOW (XDATALEN)) <> 0MOVR6,#(HIGH (XDATALEN)) +1ELSEMOVR6,#HIGH (XDATALEN)ENDIFCLR AXDATALOOP:MOVX @DPTR,AINCDPTRDJNZR7,XDATALOOPDJNZR6,XDATALOOPENDIF;; 送PDATA存储器页面高位地址IFPPAGEENABLE <> 0MOVP2,#PPAGEENDIF;; 单片机上电PDATA内存清零如果不需要上电清零XDATA可以注销IF到IFEDN之间的话句; 或者修改PDATALEN的长度IFPDATALEN <> 0MOVR0,#PDATASTARTMOVR7,#LOW (PDATALEN)CLR APDATALOOP:MOVX @R0,AINCR0DJNZR7,PDATALOOPENDIF;; 设置使用SMALL存储器模式时再入函数的堆栈空间.IFIBPSTACK <> 0EXTRNDATA (?C_IBP)MOV?C_IBP,#LOW IBPSTACKTOPENDIF;; 设置使用LARGE存储器模式时再入函数的堆栈空间.IFXBPSTACK <> 0EXTRNDATA (?C_XBP)MOV?C_XBP,#HIGH XBPSTACKTOPMOV?C_XBP+1,#LOW XBPSTACKTOPENDIF;; 设置使用COMPACT存储器模式时再入函数的堆栈空间.IFPBPSTACK <> 0EXTRNDATA (?C_PBP)MOV?C_PBP,#LOW PBPSTACKTOPENDIF;; 设置堆栈的起始地址MOVSP,#?STACK-1 ; 例如MOV SP,#4FH;;This code is required if you use L51_BANK.A51 with Banking Mode 4; 如果你的程序使用了Mode 4 程序分组技术请启动下面的程序,不会吧你的程序超过64K 利害;EXTRN CODE (?B_SWITCH0);CALL ?B_SWITCH0 ; init bank mechanism to code bank 0; 程序从第一组bank 0 块开始执行; 跳转到用户程序MAIN函数LJMP?C_STARTEND总之,在KEIL中,汇编是从ORG 000H开始启动,那么它在C51中是如何启动MAIN()函数的呢?实际上是C51中有一个启启动程序STARTUP.A51,它总是和C程序一起编译和链接的.启动文件STARTUP.A51中包含目标板启动代码,可在每个project中加入这个文件,只要复位,则该文件立即执行,其功能包括:z 定义内部RAM大小、外部RAM大小、可重入堆栈位置z 清除内部、外部或者以此页为单元的外部存储器z 按存储模式初使化重入堆栈及堆栈指针z 初始化8051硬件堆栈指针z 向main( )函数交权头文件详解/*--------------------------------------------------------------------------REG51.HHeader file for generic 80C51 and 80C31 microcontroller.Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc.All rights reserved.--------------------------------------------------------------------------*/#ifndef __REG51_H__#define __REG51_H__/* BYTE Register */ sfr P0 = 0x80;sfr P1 = 0x90;sfr P2 = 0xA0;sfr P3 = 0xB0;sfr PSW = 0xD0; sfr ACC = 0xE0;sfr B = 0xF0;sfr SP = 0x81;sfr DPL = 0x82;sfr DPH = 0x83;sfr PCON = 0x87; sfr TCON = 0x88; sfr TMOD = 0x89; sfr TL0 = 0x8A;sfr TL1 = 0x8B;sfr TH0 = 0x8C;sfr TH1 = 0x8D;sfr IE = 0xA8;sfr IP = 0xB8;sfr SCON = 0x98; sfr SBUF = 0x99;/* BIT Register */ /* PSW */sbit CY = 0xD7; sbit AC = 0xD6; sbit F0 = 0xD5; sbit RS1 = 0xD4; sbit RS0 = 0xD3; sbit OV = 0xD2; sbit P = 0xD0;/* TCON */sbit TF1 = 0x8F; sbit TR1 = 0x8E; sbit TF0 = 0x8D; sbit TR0 = 0x8C; sbit IE1 = 0x8B; sbit IT1 = 0x8A; sbit IE0 = 0x89; sbit IT0 = 0x88;/* IE */sbit EA = 0xAF;sbit ES = 0xAC;sbit ET1 = 0xAB;sbit EX1 = 0xAA;sbit ET0 = 0xA9;sbit EX0 = 0xA8;/* IP */sbit PS = 0xBC;sbit PT1 = 0xBB;sbit PX1 = 0xBA;sbit PT0 = 0xB9;sbit PX0 = 0xB8;/* P3 */sbit RD = 0xB7;sbit WR = 0xB6;sbit T1 = 0xB5;sbit T0 = 0xB4;sbit INT1 = 0xB3;sbit INT0 = 0xB2;sbit TXD = 0xB1;sbit RXD = 0xB0;/* SCON */sbit SM0 = 0x9F;sbit SM1 = 0x9E;sbit SM2 = 0x9D;sbit REN = 0x9C;sbit TB8 = 0x9B;sbit RB8 = 0x9A;sbit TI = 0x99;sbit RI = 0x98;#endif/*-------------------------------------------------------------------------- INTRINS.HIntrinsic functions for C51.Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc. All rights reserved.--------------------------------------------------------------------------*/#ifndef __INTRINS_H__#define __INTRINS_H__extern void _nop_ (void);extern bit _testbit_ (bit);extern unsigned char _cror_ (unsigned char, unsigned char);extern unsigned int _iror_ (unsigned int, unsigned char);extern unsigned long _lror_ (unsigned long, unsigned char);extern unsigned char _crol_ (unsigned char, unsigned char);extern unsigned int _irol_ (unsigned int, unsigned char);extern unsigned long _lrol_ (unsigned long, unsigned char);extern unsigned char _chkfloat_(float);#endif关于sfr、sbit://如同int、char...sfr 似乎不是标准C 语言的关键字,而是Keil 为能直接访问80C51 中的SFR 而提供了一个新的关键词,其用法是:sfrt 变量名=地址值。
写第一C51程序时,请记住下面的编译器本身给处的内部程序库。
要将下面的函数名记住。
使用的操作语句是:Y =_crol_(Y,1); 语义是将变量Y的八位二进制数左移一位,相当与不带进位位的ROL汇编语言指令由此我们需要学习《c51编程及学习实例的详细内容》的详细内容使用超星阅读器阅读或买这本书进行学习。
先将整本阅读玩之后演示实验程序。
逐渐学习相关C51编程语法和原代码的具体内容。
Static 静态变量的关键字,记住它。
c_study1是LED跑马灯的程序.TXT 使用变量赋值的方法c_study2是LED跑马灯的程序.TXT 使用函数调用的方法将文件夹《C51入门教程》里的例程演示和阅读一下。
了解一下C51简单程序的设计方法和C51语句的具体写法。
#define uchar unsigned char //定义一下方便使用#define uint unsigned int#define ulong unsigned long //记住这三条常用变量类型定义语句.LESSON 1 while(1) //程序循环是单片主程序运行时的死循环语法。
无符号整型变量unsigned int最大值为65535for(n=0;n<30000;n++); //这是一个延时函数延时时间是30000x12/晶体频率12MHz 微秒for(n=0;n<30000;n++); //这里最大的延时变量最大值为65535sbit P10 = P1^0; //要控制的LED灯这是定义为变量对应某一个IO的表达语句sbit是对特殊寄存器的位变量进行定义的关键字。
P10=~P10;//将P1.0的前一个状态取反在从新赋值给P1.0 "~" 是取反运算符号P17=1;P10=0;for(n=0;n<20000;n++);//此段程序可以清楚的感受到C51 程序也是顺序向下执行的,执行的单元是语句P10=1;P11=0;for(n=0;n<20000;n++);if(!K1) //如果读到按键S11为0,点灯{P10=0;} //这是选择结构语句的最简单的写法.If(条件表达式) {具体的执行动作语句;}bit light; //位变量的定义语法。
bit是对0X20—0X2F寄存器的位变量进行定义的关键字light=~light; //每按键一次,标记变化一次, 位变量的使用这里使用的是取反运算符。
按键处理程序的问题稍后在解决。
???????????????????????、????????????????????????????????????????TMOD=0x01;//定时器0,16位工作方式TR0=1; //启动定时器ET0=1; //打开定时器0中断EA=1; //打开总中断//上面的语句是记住定时器TO程序初始化使用的赋值语句.//定时器0中断具体函数表达,请记住timer0() interrupt 1 // 定时器0中断是1号{TH0=0x00; //写入定时器0初始值0x0005TL0=0x06;//程序进入中断后需要对定时器的计时单元重新赋初始值P10=~P10; //这是在定时器中断中具体执行的语句反转LED灯的亮灭}static uchar t=0; //变量要定义在程序执行语句之前这里的t=0 在程运行时只执行一次t++;if(t==100) //T1的预置值0x10000,溢出100次就是1秒钟,晶振12{t=0;P10=~P10; //反转LED灯的亮灭}这段主是变量在程序中具体应用,这里是作为一个计时单元使用的计时值就是中断时间乘以计数值100.uchar code ledp[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//预定的写入P1的值上面语句是一维数组的初始化。
数据类型数组名[常量表达式] ;//注意后面要加分号.uchar ledi; //先定义一个无符号变量用来指示显示顺序P1=ledp[ledi]; //读出一个值送到P1口数组在具体程序的引用方法ledi++; //指向下一个if(ledi==8)ledi=0; //到了最后一个灯就换到第一个bit ldelay=0; //定义一个位变量用做定时溢出标记,预置是0if(ldelay){程序执行语句;}//发现有时间溢出标记,进入处理//在程序中作为一种判断条件决定程序的运行.ldelay=1;//在中断程序中每次定时器中断,就置一个标记,以便主程序处理uchar speed=10; //初始化中设置一个变量保存跑马灯的移动速度speed--;if(speed==0)speed=10;//按照工作目标在主程序中对变量数值进行调整//每循环显示一次,就调快一次溢出速度在中断函数或其它函数中对变量进行判断或调节实现程序控制.if(t==speed) //比较一个变化的数值,以实现变化的时间溢出下面是复杂判断条件的表达方式if((t==speed)||(t>30)) //比较一个变化的数值,以实现变化的时间溢出,同时限制了最慢速度为1秒uchar speedlever=0; //保存当前的速度档次为了可以改变LED转换速度新增一个可调变量下面的三条语句是对调速变量的具体处理语句speedlever++; //每按一次按键速度档位加一.if(speedlever==3) speedlever=0; //我们这里的程序有3档,按键按第三后回到初始档位.speed=speedlever*3; //档次和延时之间的预算法则,也可以用查表方法,做出不规则的法则.uchar code speedcode[10]={3,1,5,12,3,20,2,10,1,4};//10个预定义的速度C51中数值可以作为一种表格资源使用.uchar i;//LED档位速度选择变量//每跑一圈灯就根据预定设置的表格来决定下一圈的跑马速度speed=speedcode[i]; //根据数组位置将对应LED转换速度值赋给程序变量i++;if(i==10)i=0;//LED档位速度选择变量随程序运行自动调整这里是+1方式.上述两条语句可以作为查表方式使用. 可以看出C51 在写程序时的快捷和方便.使用外部中断时主程序的功能设置如下.IT0=1; //外中断跳变产生中断EX0=1;EA=1; //打开总中断外部中断函数的定义如下int0() interrupt 0 //外中断0{P10=~P10; //在中断里点亮和熄灭LED}if(tt==10) //每1/120秒整开始输出低电平{tt=0;if(scale!=0) //这里加这一句是为了消除灭灯状态产生的鬼影P1=0x00;}if(scale==tt) //按照当前占空比切换输出高电平P1=0xff;上面给出了函数嵌套的表达方式.蜂鸣器有有源和无源的几种。
也称为直流蜂鸣器和交流蜂鸣器。
有源蜂鸣器只要通上直流电,就会发出预定的声音,比如,连续嘀声,或者间断嘀嘀声,这种声音无法控制,频率也无法改变。
一般用在一些简单应用场合。
无源蜂鸣器相当于一个简单的喇叭,通上直流点不会发声,只有通上交流电时,才会根据交流点的频率发出相应的声音,这种蜂鸣器可以任意控制声音输出,但是需要用户以相应的信号驱动,工作复杂一些。
//定时函数void DelayMs(uint number){uchar temp;for(;number!=0;number--){for(temp=112;temp!=0;temp--) ;}} //此函数延时时间是:number * temp*单步运行时间//开始总线void Start(){SDA=1;SCL=1;SDA=0;SCL=0;} //记住这种函数结构//结束总线void Stop(){SCL=0;SDA=0;SCL=1;}//发ACK0void NoAck(){SDA=1;SCL=1;SCL=0;}//测试ACK 返回io口的电平状态.bit T estAck(){bit ErrorBit;SDA=1;SCL=1;ErrorBit=SDA;SCL=0;return(ErrorBit);}//写入8个bit到24c02// 此函数为串行移位输出八位字节.这种功能在程序设计中经常用到,请记住这段程序. Write8Bit(uchar input){uchar temp;for(temp=8;temp!=0;temp--){SDA=(bit)(input&0x80);SCL=1;SCL=0;input=input<<1;}}//写入一个字节到24c02中IIC写入一个字节标准函数.void Write24c02(uchar ch,uchar address){Start();Write8Bit(WriteDeviceAddress);T estAck();Write8Bit(address);T estAck();Write8Bit(ch);T estAck();Stop();DelayMs(10);}//从24c02中读出8个bit//// 此函数为串行移位输入八位字节.这种功能在程序设计中经常用到,请记住这段程序.uchar Read8Bit(){unsigned char temp,rbyte=0;for(temp=8;temp!=0;temp--){SCL=1;rbyte=rbyte<<1;rbyte=rbyte|((unsigned char)(SDA)); //读入数据的的语句,因为<<1是左移一位同时将最低位填充为零,或上要读入的口线状态,这样口线状态会被读入到八位字节当中.SCL=0;}return(rbyte);}//从24c02中读出1个字节IIC读出一个字节标准函数uchar Read24c02(uchar address){uchar ch;Start();Write8Bit(WriteDeviceAddress);T estAck();Write8Bit(address);T estAck();Start();Write8Bit(ReadDviceAddress);T estAck();ch=Read8Bit();NoAck();Stop();return(ch);}按键的一种处理方法.if(!K1) //按键处理{c1++; //值加1Write24c02(c1,0x01); //重新写入24c02while(!K1); //等待按键松开for(c2=0;c2<250;c2++); //松开按键去抖}蜂鸣器有有源和无源的几种。