第六章函数单片机C
- 格式:doc
- 大小:93.00 KB
- 文档页数:38
C51的常用库函数详解C51语言的编译器中包含有丰富的库函数,使用库函数可以大大简化用户程序设计的工作量,提高编程效率;每个库函数都在相应的头文件中给出了函数原型声明,在使用时,必须在源程序的开始处使用预处理命令include将有关的头文件包含进来;C51库函数中类型的选择考虑到了8051单片机的结构特性,用户在自己的应用程序中应尽可能地使用最小的数据类型,以最大限度地发挥8051单片机的性能,同时可减少应用程序的代码长度;下面将C51的库函数分类列出并详细介绍其用法;1字符函数字符函数的原型声明包含在头文件CTYPE.H中;常用的一些字符函数介绍如下;1.1检查英文字母函数检查英文字母函数用于检查形参字符是否为英文字母,其函数原型如下:bitisalphacharc;其中,c为待判断的字符,如果是英文字母则返回1,否则返回0;程序示例如下:1.2检查字母数字函数检查字母数字函数用于检查形参字符是否为英文字母或数字字符,其函数原型如下:bitisalnumcharc;1.3检查控制字符函数检查控制字符函数用于检查形参字符是否为控制字符,其函数原型:bitiscntrlcharc;其中,c为待判断的字符;控制字符其取值范围为0x00~0xlF之间或等于0x7F,如果是,则返回1,否则返回0;十进制数字检查函数用于检查形参字符是否为十进制数字,其函数原型如下:bitisdigitcharc;其中,c为待判断的字符,如果是十进制数字则返回1,否则返回0;1.5可打印字符检查函数可打印字符检查函数用于检查形参字符是否为可打印字符,其函数原型如下:bitisgraphcharc;其中,c为待判断的字符;可打印字符的取值范围为0x21~0x7C,不包含空格,如果是可打印字符则返回1,否则返回0;1.6包含空格的可打印字符检查函数包含空格的可打印字符检查函数用于检查形参字符是否为可打印字符以及空格,其函数原型如下:bitisprintcharc;其中,c为待判断字符;如果是则返回1,否则返回0;该函数与isgraph的区别在于包含了空格符,空格符为0x20;1.7格式字符检查函数格式字符检查函数用于检查形参字符是否为标点、空格或格式字符,其函数原型如下:bitispunctcharc;其中,c为待判断字符,如果是则返回1,否则返回0;1.8小写英文字母检查函数小写英文字母检查函数用于检查形参字符是否为小写英文字母,其函数原型如下:bitislowercharc;1.9大写英文字母检查函数大写英文字母检查函数用于检查形参字符是否为大写英文字母,其函数原型如下:bitisuppercharc;其中,c为待判断字符;如果是大写英文字母则返回1,否则返回0;1.10控制字符检查函数控制字符检查函数用于检查形参字符是否为控制字符,其函数原型如下:bitisspacecharc;其中,c为待判断字符;如果是控制字符则返回1,否则返回0;控制字符包括:空格、制表符、回车、换行、垂直制表符和送纸,其取值范围为0x09~0x0d,或为0x20;1.11十六进制数字检查函数十六进制数字检查函数用于检查形参字符是否为十六进制数字,其函数原型如下:bitisxdigitcharc;其中,c为待判断字符;如果是16进制数字字符则返回1,否则返回0;1.12十六进制数字转换函数十六进制数字检查函数用于转换形参字符为十六进制数字,其函数原型如下:chartointcharc;其中,c为待转换字符;该函数将形参字符0~9、a~f大小写无关转换为16进制数字;其中,对于字符0~9,返回值为0H~9H,对于ASCII字符a~f大小写无关,返回值为0AH~0FH;1.13大写字符转换函数chartolowercharc;其中,c为待转换的大写字符;如果字符参数不在A~Z之间,则该函数将不起作用,而直接返回原字符;1.14小写字符转换函数小写字符转换函数用于将小写字符转换为大写字符,其函数原型如下:chartouppercharc;其中,c为待转换的小写字符;如果字符参数不在a~z之间,则该函数将不起作用,而直接返回原字符;1.15ASCII字符转换函数ASCII字符转换函数用于将任何字符型参数缩小到有效的ASCII范围之内,其函数原型如下:chartoasciicharc;其中,c为待转换的字符;该函数执行的操作是将形参数值和0x7f做与运算,从而去掉第7位以上的所有位数;如果形参已是有效的ASCII字符,则不作处理,直接返回原字符;1.16大写字符宏转换函数大写字符宏转换函数用于大写字符转换为小写字符,其函数原型如下:char_tolowercharc;其中,c为待转换的大写字符;这其实是一个由宏定义完成的操作,其功能是将字符参数c与常数0x20逐位进行或运算,从而将大写字符转换为小写字符;1.17小写字符宏转换函数小写字符宏转换函数用于小写字符转换为大写字符,其函数原型如下:char_touppercharc;其中,c为待转换的小写字符;这其实是一个由宏定义完成的操作,其功能是将字符参数c与常数0xdf逐位进行与运算,从而将小写字符转换为大写字符;2字符串函数字符串函数的原型声明包含在头文件STRING.H中;在C51语言中,字符串应包括2个或多个字符,字符串的结尾以空字符来表示;字符串函数通过接受指针串来对字符串进行处理;常用的字符串函数介绍如下;2.1字符查找函数字符查找函数用于在字符串中顺序查找字符,其函数原型如下:voidmemchrvoidsl,charval,intlen;其中,s1为输入字符串,val为待查找的字符,len为查找的长度范围;该函数的功能是在字符串s1中顺序搜索前len个字符以找出字符val,如果找到则返回sl中指向val的指针,如果没有找到则返回NULL;2.2指定长度的字符串比较函数指定长度的字符串比较函数用于按照指定的长度比较两个字符串的大小,其函数原型如下:charmemcmpvoids1,voids2,intlen;其中,s1和s2为输入字符串,len为比较的长度;该函数的功能是逐个比较字符串sl和s2的前len个字符,如果相等则返回0,如果字符串s1大于s2,则返回一个正数,如果字符串s1小于s2,则返回一个负数;如果两个字符串的长度小于len,该函数仍将一直比较len个字符,这种情况下,有可能结果是错误的;因此应该保证len不能超过最短字符串的长度;2.3字符串复制函数字符串复制函数用于复制指定长度的字符串,其函数原型如下:其中,dest为目标字符串,src为源字符串,len为复制的长度;该函数的功能是从src所指向的字符串中复制len个字符到dest字符串中,其返回值指向dest中的最后一个字符的指针;2.4带终止字符的字符串复制函数带终止字符的字符串复制函数用于复制字符串,如果遇到终止字符则停止复制,其函数原型如下:voidmemccpyvoiddest,voidsrc,charval,intlen;其中,dest为目标字符串,src为源字符串,val为终止字符,len为复制的长度;该函数的功能是复制字符串src中的len个字符到dest中,复制len个字符后则返回NULL;如果遇到字符val则停止复制,此时返回一个指向dest中的下一个元素的指针;2.5字符串移动函数字符串移动函数同样用于复制字符串,其函数原型如下:voidmemmovevoiddest,voidsrc,intlen;其中,dest为目标字符串,src为源字符串,len为复制长度;该函数的功能是从src所指向的字符串中复制len个字符到dest字符串中,其返回值指向dest中的最后一个字符的指针;其功能与memcpy相同,但是复制区间src与dest可以发生交迭;2.6字符串填充函数字符串填充函数用于按规定的字符填充字符串,其函数原型如下:voidmemsetvoids,charval,intlen;其中,s为待填充的字符串,val为填充字符,len为填充的长度;该函数实现的操作是用字符val来填充字符串s,共填充len个单元2.7字符串追加函数voidstrcatchars1,chars2;其中,s1为目标字符串,s2为待复制的字符串;该函数实现的操作是将字符串s2复制到字符串s1的尾部;其中字符串s1要有足够的大小来保存两个字符串;该函数的返回值指向字符串s1中的第一个字符的指针;2.8指定长度的字符串追加函数指定长度的字符串追加函数用于复制指定长度的字符串到另一个字符串的尾部,其函数原型如下:voidstrncat,chars1,chars2,intn;其中,s1为目标字符串,s2为待复制的字符串,n为复制的长度;该函数实现的操作是从字符串s2中复制n个字符添加到字符串s1的尾部;其中,如果字符串s2的长度比n小,则将全部复制字符串s2包括串结束符;2.9字符串比较函数字符串比较函数用于比较两个字符串的大小,其函数原型如下:charstrcmpchars1,chars2;其中,s1和s2为待比较的字符串;该函数的功能是比较字符串s1和s2,如果两者相等则返回0;如果s1<s2,则返回一个负数;如果s1>s2,则返回一个正数;2.10包含结束符的字符串比较函数包含结束符的字符串比较函数用于比较两个字符串的大小,其函数原型如下:charstrncmpchars1,chars2,intn;其中,s1和s2为待比较的字符串,n为比较的长度;该函数的功能是比较字符串s1和s2的前n个字符,如果两者相等则返回0;如果s1<s2,则返回一个负数;如果s1>s2,则返回一个正数;这里需要和memcmp函数相区别,如果字符串的长度小于n,则strncmp函数比较到字符串结束符后便停止,这和memcmp函数是不一样的;字符串覆盖函数用于将一个字符串覆盖另一个字符串,其函数原型如下:charstrcpychars1,chars2;其中,s1为目标字符串,s2为源字符串;该函数的功能是将字符串s2包括结束符复制到字符串s1中的第1个字符指针处;这里需要注意和strcat函数相区别,strcat 函数将字符串s2复制到字符串s1的末尾;2.12指定长度的字符串覆盖函数指定长度的字符串覆盖函数用于将一个指定长度的字符串覆盖另一个字符串,其函数原型如下:charstrncpychars1,chars2,intn;其中,s1为目标字符串,s2为源字符串,n为长度;该函数实现的操作是从字符串s2包括结束符中复制n个字符到字符串s1中的第1个字符指针处;如果字符串s2的长度小于n,则s1串以0补齐到长度n;2.13获取字符串个数函数获取字符串个数函数用于返回字符串中字符总数,其函数原型如下:charstrlenchars1;其中,s1为输入字符串;该函数的功能是获取字符串s1中的字符个数,返回值的大小不包括结尾的字符串结束符;2.14搜索字符串函数搜索字符串函数用于搜索字符串出现的位置,其函数原型如下:charstrstrconstchars1,chars2;其中,s1为目标字符串,s2为搜索的字符串;该函数实现的操作是在字符串s1中搜索第一次出现字符串s2的位置,并返回该处的指针;如果字符串s1中不包括字符串s2,则该函数返回一个空指针;搜索字符函数用于搜索字符出现的位置,其函数原型如下:charstrchrchars1,charc;其中,s1为目标字符串,c为待搜索的字符;该函数的功能是搜索字符串s1中是否包含字符c,如果包含则返回第一次指向该字符的指针,否则返回NULL;被搜索的字符可以是串结束符,此时返回值是指向串结束符的指针;2.16返回位置值的字符搜索函数返回位置值的字符搜索函数用于搜索并返回字符出现的位置,其函数原型如下:intstrposchars1,charc;其中,s1为目标字符串,c为搜索的字符;该函数的功能是查找并返回字符c在字符串s1中第一次出现的位置值,没有找到该字符则返回-1,s1串首字符的位置值是0;strpos函数的功能与strchr类似,只不过返回值不同;2.17字符包含函数字符包含函数用于检查字符串中是否包含某字符,其函数原型如下:charstrrchrchars1,charc;其中,s1为目标字符串,c为查找的字符;该函数的功能是搜索字符串s1中是否包含字符c,如果包含则返回最后一次指向该字符的指针,否则返回NULL;被搜索的字符可以是串结束符,此时返回值是指向串结束符的指针;2.18返回位置值的字符包含函数返回位置值的字符包含函数同样用于检查字符串中是否包含某字符,其函数原型如下:intstrrposchars1,charc;其中,s1为目标字符串,c为查找的字符;该函数的功能是查找并返回字符c在字符串s1中最后一次出现的位置值,没有找到该字符则返回-1,s1串首字符的位置值是2.19在指定字符集中查找不包含字符函数在指定字符集中查找不包含字符函数用于查找不包含在指定字符集中的字符,其函数原型如下:intstrspnchars1,charset;其中,s1为目标字符串,set为字符集;该函数的功能是搜索字符串s1中第一个不包含在set串中的字符,返回值是字符串s1中包括在set中的字符的个数;如果s1中所有的字符都包含在set中,则返回s1的长度不包括结束符;如果set是空字符串则返回0;2.20在指定字符集中查找包含字符函数在指定字符集中查找包含字符函数用于查找包含在指定字符集中的字符,其函数原型如下:intstrcspnchars1,charset;其中,s1为目标字符串,set为字符集;该函数的功能是搜索的是第一个包含在set串中字符,返回值是字符串s1中包括在set中的字符的个数;如果s1中所有的字符都包含在set中,则返回s1的长度不包括结束符;如果set是空字符串则返回0;2.21查找第一个包含字符函数查找第一个包含字符函数用于查找第一个包含在指定字符集中的字符,其函数原型如下:charstrpbrkchars1,charset;其中,s1为目标字符串,set为字符集;该函数的功能是搜索字符串s1中第一个包含在set串中的字符,返回值指向搜索到的字符的指针,如果未找到,则返回NULL;2.22查找最后一个包含字符函数查找最后一个包含字符函数用于查找最后一个包含在指定字符集中的字符,其函charstrrpbrkchars1,charset;其中,s1为目标字符串,set为字符集;该函数的功能是搜索字符串s1中最后一个包含在set串中的字符,返回值指向搜索到的字符的指针,如果未找到,则返回NULL; 3I/O函数I/O函数主要用于数据的输入输出等操作,C51的I/O库函数的原型声明包含在头文件STDIO.H中;这些I/O函数使用8051单片机的串行接口进行通信,因此,在使用之前需要先进行串口的初始化;例如:SCON=0x50; //串口模式1,允许接收TMOD|=0x20; //初始化T1为定时功能,模式2PCON|=0x80; //设置SMOD=1TL1=0xF4; //波特率4800bit/s,初值TH1=0xF4;IE|=0x90; //中断TR1=1; //启动定时器3.1字符读入函数字符读入函数用于从串口读入一个字符,其函数原型如下:char_getkeyvoid;该函数执行的操作是等待从8051的串口读入一个字符,并返回读入的原字符;程序示例如下:3.2字符读入输出函数字符读入输出函数用于从串口读入一个字符并输出该字符,其函数原型如下:chargetcharvoid;该函数与_getkey函数有细微的不同,其执行的操作是使用_getkey从串口读入的一个字符,然后使用putchar函数将读入的字符输出;3.3字符串读入函数字符串读入函数用于从串口读入一个字符串,其函数原型如下:chargetschars,intn;其中,s保存读入的字符串,n为字符串的长度;该函数执行的操作是使用getchar 函数从串口读入一个长度为n的字符串,并存入字符数组s中;如果遇到换行符,则结束字符的输入;输入成功时将返回传入的参数指针,失败时返回空指针NULL;3.4字符回送函数字符回送函数用于将输入的字符回送到输入缓冲区,其函数原型如下:charungetcharcharc;其中,c为输入字符;该函数执行的操作是将输入的字符回送到输入缓冲区,如果函数调用成功则返回char型值c,失败时则返回EOF;3.5字符输出函数字符输出函数用于通过8051串行口输出字符,其函数原型如下:charputcharcharc;其中,c为通过8051串行口输出的字符;3.6格式化输出函数格式化输出函数用于按照一定的格式输出数据或字符串,其函数原型如下:intprintfconstcharfmstr,argument…;该函数的功能是以一定的格式通过8051单片机的串行口输出数值和字符串;其中第一个参数fmstr是格式控制字符串,参数argument可以是字符串指针、字符或数值,该函数的返回值为实际输出的字符个数;3.7格式化内存缓冲区输出函数格式化内存缓冲区输出函数用于按照一定的格式将数据或字符串输出到内存缓冲区中,其函数原型如下:intsprintfchars,constcharfmstr,argument…;该函数执行的操作是通过指针s,将字符串送入内存数据缓冲区,并以ASCII码的形式储存;3.8字符串输出函数字符串输出函数用于将字符串和换行符写入串行口,其函数原型如下:intputsconstchars;其中,s为输出的字符串或换行符;如果执行成功则返回0,错误时返回EOF;程序示例如下:3.9格式化输入函数格式化输入函数用于将字符串和数据按照一定的格式从串口读入,其函数原型如下:intscanfconstcharfmstr,argument…;该函数的功能是在格式字符的控制下从串行口读入数据;其中每个参数都必须是指针;scanf返回值是所发现并转换的输入项数,如遇到错误则返回EOF;该函数的格式控制字符串形式如下,方括号内是可选项;%width{Bhl}type3.10格式化内存缓冲区输入函数格式化内存缓冲区输入函数用于将格式化的字符串和数据送入数据缓冲区,其函数原型如下:intsscanfchars,constcharfmstr,argument…;该函数的功能是将输入的字符串通过指针s指向的数据缓冲区;输入数据根据格式控制字符串fmstr被存放到由argument指定的地址;其它方面,sscanf函数与scanf函数类似;3.11字符串内存输出函数字符串内存输出函数用于将格式化字符串输出到内存数据缓冲区,其函数原型如下:intvprintfconstcharfmstr,charargptr;其中,fmstr为格式化字符串,argptr指向变量表的指针而不是变量表,函数返回值为实际写入到输出字符串中的字符数;其它方面,vprintf函数与printf函数类似;3.12指向缓冲区的输出函数指向缓冲区的输出函数用于将格式化字符串和数字输出到由指针所指向的内存数据缓冲区,其函数原型如下:intvsprintfchars,constcharfmstr,charargptr;该函数执行的操作是将格式化字符串和数字输出到由指针所指向的内存数据缓冲区;其中,该函数接受的是一个指向变量表的指针而不是变量表,其返回值为实际写入到输出字符串中的字符数;其他方面vsprintf函数与sprintf函数类似;4数学函数数学函数主要用于进行数学运算,其原型声明包含在头文件MATH.H中;下面介绍一些常用的数学函数;4.1绝对值函数绝对值函数用于计算并返回输出数据的绝对值;按照其操作数的数据类型的不同,有如下几种形式:intabsintval;charcabscharval;floatfabsfloatval;longlabslongval这些函数分别用于计算整型、字符型、浮点型以及长整型数据的绝对值;4.2指数以及对数函数指数函数用于计算并返回输出数据的指数;对数函数用于计算并返回输出数据的对数;其函数原型示例如下:floatexpfloatx;floatlogfloatx;floatlog10floatx;floatsqrtfloatx;其中exp函数用于计算并返回浮点数x的指数,log函数用于计算并返回浮点数x 的自然对数自然对数以e为底,e=2.718282,log10函数用于计算并返回浮点数x的以10为底的对数值,sqrt函数用于计算并返回浮点数x的平方根;4.3三角函数三角函数用于计算数学中三角函数的值;在C51语言中包含如下几种三角函数:floatcosfloatx;floatsinfloatx;floattanfloatx;floatacosfloatx;floatasinfloatx;floatatanfloatx;floatatan2floaty,floatx;floatcoshfloatx;floatsinhfloatx;floattanhfloatx;4.4取整函数取整函数用于取输入数据的整数;在C51语言中,包含两类取整函数,示例如下:floatceilfloatx;floatfloorfloatx;其中ceil函数用于计算并返回一个不小于x的最小正整数作为浮点数,floor函数用于计算并返回一个不大于x的最小正整数作为浮点数;4.5浮点型分离函数浮点型分离函数用于将浮点型数据的整数和小数部分分开,其函数原型如下:floatmodffloatx,floatip;函数modf将浮点数x分成整数和小数两部分,整数部分放入ip,返回值为小数部分;两者都含有与x相同的符号;4.6幂函数幂函数用于进行幂指数运算;其函数原型如下:floatpowfloatx,floaty;该函数用于计算并返回xy的值;如果x不等于0而y=0,则返回1;当x=0且y<=0或x<0且y不是整数时,返回NaN;5标准函数标准函数主要用于完成数据类型转换以及存储器分配等操作;标准函数的原型声明包含在头文件STDLIB.H中;下面介绍常用的一些函数;5.1字符串转换函数字符串转换函数用于将字符串转换成数值类型并输出;根据输出数值类型的不同,可以有如下几种形式:floatatoicharsl;floatatolcharsl;floatatofcharsl;其中,atoi函数用于将字符串sl转换成整型数值并返回该值;输入字符串的格式为:whitespace{+/-}数字;其中,whitespace可由空格、/、制表符组成;这里的数字可以是一个或多个十进制数;5.2带返回指针的字符串转换函带返回指针的字符串转换函数将字符串转换成数值类型并输出,同时返回未转换部分的指针;根据输出数值类型的不同,可以有如下几种形式:floatstrtodconstchars,charptr;longstrtolconstchars,charptr,unsignedcharbase;unsignerlongstrtoulconstchars,charptr,unsignedcharbase;5.3随机函数随机函数用于产生伪随机数;在C51语言中,包含两种随机函数,其函数声明如下:intrand;voidsrandintn;其中,函数rand用于返回一个0到32767之间的伪随机数,而函数srand用来初始化随机数发生器的随机种子;如果不使用srand函数,则对rand函数的相继调用将产生相同的随机序列;5.4数组内存分配函数数组内存分配函数用于为n个元素的数组分配内存空间,其函数原型如下:voidcallocunsighedintn,unsighedintsize;其中n数组元素的个数,size为数组中每个元素的大小;该函数所分配的内存区域用0进行初始化;返回值为已分配的内存单元起始地址,如果不成功则返回0; 5.5释放内存函数释放内存函数用于释放前面已分配的内存空间,其函数原型如下:voidfreevoidxdatap;其中,指针p指向待释放的存储区域;p必须是以前用calloc、malloc或realloc 函数分配的存储区域,如果p为NULL,则该函数无效;经free函数所被释放的存储区域可以参与以后的分配;5.6初始化内存函数初始化内存函数用于对前面申请的内存进行初始化,其函数原型如下:voidinit_mempoolvoidxdatap,unsighedintsize;其中,指针p表示存储区首地址,size表示存储区大小;该函数可对被函数calloc、malloc、free或realloc管理的存储区域进行初始化;5.7内存分配函数内存分配函数用于在内存中分配指定大小的存储空间,其函数原型如下:voidmallocunsighedintsize;其中,size为分配的空间大小,返回值为指向所分配内存的指针;如果返回NULL,则表示没有足够的内存空间可用;5.8调整内存大小函数调整内存大小函数用于调整先前分配的存储器区域大小,其函数原型如下:voidreallocvoidxdatap,unsighedintsize;其中,参数p表示该存储区域的起始地址,参数size表示新分配的存储区域大小;该函数的返回值为新区域所指向的指针;如果返回NULL,则表示没有足够的内存空间可用;原存储器区域的内容被复制到新存储器区域中,如果新存储器区域较大,多出的区域不作初始化;6内部函数内部函数的原型声明包含在头文件INTRINS.H中;下面介绍常用的一些函数; 6.1循环左移函数循环左移函数主要用于将数据按照二进制循环左移n位;按照操作数据类型的不同,其函数原型如下几种形式:unsighedchar _crol_unsighedcharval,unsighedcharn;unsighedint _irol_unsighedintval,unsighedcharn;unsighedlong _lrol_unsighedlongval,unsighedcharn;其中,val为待移位的变量,n为循环移位的次数;函数_crol_、_irol_和_lrol_分别用于字符型、整型和长整形变量的循环左移,其返回值分别为移位后的字符型、整型和长整形;该函数与8051单片机的RLA指令相关;6.2循环右移函数循环右移函数主要用于将数据按照二进制循环右移n位;按照操作数据类型的不同,其函数原型如下几种形式:unsighedchar _cror_unsighedcharval,unsighedcharn;unsighedint _iror_unsighedintval,unsighedcharn;unsighedlong _lror_unsighedlongval,unsighedcharn;其中,val为待移位的变量,n为循环移位的次数;函数_cror_、_iror_和_lror_分别用于字符型、整型和长整形变量的循环右移,其返回值分别为移位后的字符型、整型和长整形;该函数与8051单片机的RRA指令相关;6.3延时函数延时函数用于使单片机程序产生延时,其函数原型如下:void_nop_void;该函数类似于8051单片机的NOP指令;程序示例如下:include<intrins.h> //头文件include<reg51.h>void mainvoid //主函数。
【单片机C语言基础入门】第六章:函数的入门与编写一般来说,一个单片机程序是有很多的部分构成每一个模块来实现某一个特定的功能,比如AD转换程序模块、timer定时器程序模块、PWM程序模块等。
单片机开发过程中我们将这些程序模块用函数的方法来实现。
这样一个单片机程序就可以由一个main函数和若干和函数模块来构成,同一个函数模块可以被一个或者多个函数调用任意多次。
基于这种思想很多的单片机厂家设计了单片机的固件库文件(其库文件是和硬件的资源相配套的,比如timer/counter模块、PWM模块、UART模块等)来驱动设备的内部和外设资源。
下图为STC15标准库文件的函数库的函数和文件。
每个文件都以函数的形式保存为文件,比如GPIO的文件打开如下:1.#include 'GPIO.h'2.// 函数: u8 GPIO_Inilize(u8GPIO,GPIO_InitTypeDef *GPIOx)3.// 描述: 初始化IO口.4.// 参数: GPIOx: 结构参数,请参考timer.h里的定义.5.// 返回: 成功返回0, 空操作返回1,错误返回2.6.// 版本: V1.0, 2012-10-227.//==================== =========================== =========================8.u8 GPIO_Inilize(u8GPIO, GPIO_InitTypeDef *GPIOx)9.{10.if(GPIO>GPIO_P5) return1; //空操作11.if(GPIOx->Mode>GPIO_OUT_PP) return 2; //错误12.if(GPIO ==GPIO_P0)13.{14.if(GPIOx->Mode==GPIO_PullUp) P0M1 &= ~GPIOx->Pin, P0M0&=~GPIOx->Pin; //上拉准双向口15.if(GPIOx->Mode==GPIO_HighZ) P0M1 |= GPIOx->Pin, P0M0 &= ~GPIOx->Pin; //浮空输入16.if(GPIOx->Mode==GPIO_OUT_OD) P0M1 |= GPIOx->Pin, P0M0 |= GPIOx->Pin; //开漏输出17.if(GPIOx->Mode==GPIO_OUT_PP) P0M1 &= ~GPIOx->Pin, P0M0|= GPIOx->Pin; //推挽输出18.}19.if(GPIO ==GPIO_P1)20.{21.if(GPIOx->Mode==GPIO_PullUp) P1M1 &= ~GPIOx->Pin, P1M0&=~GPIOx->Pin; //上拉准双向口22.if(GPIOx->Mode==GPIO_HighZ) P1M1 |= GPIOx->Pin, P1M0 &= ~GPIOx->Pin; //浮空输入23.if(GPIOx->Mode==GPIO_OUT_OD) P1M1 |= GPIOx->Pin, P1M0 |= GPIOx->Pin; //开漏输出24.if(GPIOx->Mode==GPIO_OUT_PP) P1M1 &= ~GPIOx->Pin, P1M0|= GPIOx->Pin; //推挽输出25.}26.if(GPIO ==GPIO_P2)27.{28.if(GPIOx->Mode==GPIO_PullUp) P2M1 &= ~GPIOx->Pin, P2M0&=~GPIOx->Pin; //上拉准双向口29.if(GPIOx->Mode==GPIO_HighZ) P2M1 |= GPIOx->Pin, P2M0 &= ~GPIOx->Pin; //浮空输入30.if(GPIOx->Mode==GPIO_OUT_OD) P2M1 |= GPIOx->Pin, P2M0 |= GPIOx->Pin; //开漏输出31.if(GPIOx->Mode==GPIO_OUT_PP) P2M1 &= ~GPIOx->Pin, P2M0|= GPIOx->Pin; //推挽输出32.}33.if(GPIO ==GPIO_P3)34.{35.if(GPIOx->Mode==GPIO_PullUp) P3M1 &= ~GPIOx->Pin, P3M0&=~GPIOx->Pin; //上拉准双向口36.if(GPIOx->Mode==GPIO_HighZ) P3M1 |= GPIOx->Pin, P3M0 &= ~GPIOx->Pin; //浮空输入37.if(GPIOx->Mode==GPIO_OUT_OD) P3M1 |= GPIOx->Pin, P3M0 |= GPIOx->Pin; //开漏输出38.if(GPIOx->Mode==GPIO_OUT_PP) P3M1 &= ~GPIOx->Pin, P3M0|= GPIOx->Pin; //推挽输出39.}40.if(GPIO ==GPIO_P4)41.{42.if(GPIOx->Mode==GPIO_PullUp) P4M1 &= ~GPIOx->Pin, P4M0&=~GPIOx->Pin; //上拉准双向口43.if(GPIOx->Mode==GPIO_HighZ) P4M1 |= GPIOx->Pin, P4M0 &= ~GPIOx->Pin; //浮空输入44.if(GPIOx->Mode==GPIO_OUT_OD) P4M1 |= GPIOx->Pin, P4M0 |= GPIOx->Pin; //开漏输出45.if(GPIOx->Mode==GPIO_OUT_PP) P4M1 &= ~GPIOx->Pin, P4M0|= GPIOx->Pin; //推挽输出46.}47.if(GPIO ==GPIO_P5)48.{49.if(GPIOx->Mode==GPIO_PullUp) P5M1 &= ~GPIOx->Pin, P5M0&=~GPIOx->Pin; //上拉准双向口50.if(GPIOx->Mode==GPIO_HighZ) P5M1 |= GPIOx->Pin, P5M0 &= ~GPIOx->Pin; //浮空输入51.if(GPIOx->Mode==GPIO_OUT_OD) P5M1 |= GPIOx->Pin, P5M0 |= GPIOx->Pin; //开漏输出52.if(GPIOx->Mode==GPIO_OUT_PP) P5M1 &=~GPIOx->Pin, P5M0|= GPIOx->Pin; //推挽输出53.}54.return 0; //成功55.}显然这是一个GPIO初始化的程序。
单片机_C语言函数_中断函数(中断服务程序)在开始写中断函数之前,我们来一起回顾一下,单片机的中断系统。
中断的意思(学习过微机原理与接口技术的同学,没学过单片机,也应该知道),我们在这里就不讲了,首先来回忆下中断系统涉及到哪些问题。
(1)中断源:中断请求信号的来源。
(8051有3个内部中断源T0,T1,串行口,2个外部中断源INT0,INT1(这两个低电平有效,上面的那个横杠不知道怎么加上去))(2)中断响应与返回:CPU采集到中断请求信号,怎样转向特定的中断服务子程序,并在执行完之后返回被中断程序继续执行。
期间涉及到C PU响应中断的条件,现场保护,现场恢复。
(3)优先级控制:中断优先级的控制就形成了中断嵌套(8051允许有两级的中断嵌套,优先权顺序为INT0,T0,INT1,T1,串行口),同一个优先级的中断,还存在优先权的高低。
优先级是可以编程的,而优先权是固定的。
80C51的原则是①同优先级,先响应高优先权②低优先级能被高优先级中断③正在进行的中断不能被同一级的中断请求或低优先级的中断请求中断。
80C51的中断系统涉及到的中断控制有中断请求,中断允许,中断优先级控制(1)3个内部中断源T0,T1,串行口,2个外部中断源INT0,INT1(2)中断控制寄存器:定时和外中断控制寄存器TCON(包括T0、T1,INT0、INT1),串行控制寄存器SCON,中断允许寄存器IE,中断优先级寄存器IP具体的是什么,包括哪些标志位,在这里不讲了,所有书上面都会讲。
在这里我们讲下注意的事项(1)CPU响应中断后,TF0(T0中断标志位)和TF1由硬件自动清0。
(2)CPU响应中断后,在边沿触发方式下,IE0(外部中断IN T0请求标志位)和IE1由硬件自动清零;在电平触发方式下,不能自动清楚IE0和I E1。
单片机编程中的常用函数在单片机编程中,常用函数是我们编写程序时经常使用到的函数。
这些函数不仅能够减少我们的工作量,还能提高程序的效率和可读性。
下面将介绍单片机编程中常用的几种函数。
一、延时函数延时函数是单片机编程中非常常用的函数之一,它可以在程序中引入适当的延时,以确保程序能够按照我们的期望进行运行。
延时函数通常使用定时器或者循环来实现。
下面是一个简单的延时函数示例:```cvoid delay(unsigned int ms){unsigned int i, j;for(i = 0; i < ms; i++)for(j = 0; j < 114; j++);}```在这个延时函数中,我们使用两个循环来进行延时操作。
内层循环是一个简单的计数器,当计数器达到一定值时,延时一毫秒。
外层循环控制延时的总时长。
通过调整内层循环的计数器初值,可以实现不同的延时时长。
二、IO口控制函数在单片机编程中,我们经常需要对IO口进行控制操作,例如点亮LED灯、控制继电器等。
为了简化这些操作,可以使用IO口控制函数。
下面是一个简单的IO口控制函数示例:```cvoid GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal){if(BitVal)GPIOx->ODR |= GPIO_Pin;elseGPIOx->ODR &= ~GPIO_Pin;}```这个函数接收三个参数,分别为GPIO端口、GPIO引脚和操作位的值。
通过判断操作位的值,可以实现对相应的GPIO引脚进行设置或清零操作,从而实现对IO口的控制。
三、定时器中断函数定时器中断函数是单片机编程中非常重要的函数之一,它可以在定时器溢出时触发相应的中断服务程序(ISR),从而实现定时任务。
下面是一个简单的定时器中断函数示例:```cvoid TIM3_IRQHandler(void){if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){// 定时器中断处理代码TIM_ClearITPendingBit(TIM3, TIM_IT_Update); // 清除中断标志位}}```在这个定时器中断函数中,我们首先判断定时器是否发生了溢出事件。
单片机C语言(C51)常用库函数单片机C语言(C51)常用库函数在单片机编程中,使用库函数可以大大提高开发效率和简化代码结构。
C51是一种常用的单片机编程语言,它提供了许多常用的库函数,本文将介绍一些常用的C51库函数及其用法。
1. 字符串处理函数字符串处理是单片机编程中常见的任务。
C51提供了一些常用的字符串处理函数,如strcpy、strcat、strcmp等。
这些函数可以简化对字符串的操作。
- strcpy:用于将一个字符串复制到另一个字符串中。
用法示例:```char str1[20];char str2[20] = "Hello, world!";strcpy(str1, str2);```- strcat:用于将一个字符串追加到另一个字符串的末尾。
用法示例:```char str1[20] = "Hello,";char str2[20] = " world!";strcat(str1, str2);```- strcmp:用于比较两个字符串是否相等。
用法示例:```char str1[20] = "Hello";char str2[20] = "World";if (strcmp(str1, str2) == 0) {// 字符串相等的处理逻辑} else {// 字符串不相等的处理逻辑}```2. 数学函数单片机编程中常常需要进行数学运算,C51提供了一些常用的数学函数,如abs、sqrt、sin等。
这些函数可以帮助实现各种数学计算。
- abs:用于计算一个整数的绝对值。
用法示例:```int num = -10;int abs_num = abs(num);```- sqrt:用于计算一个浮点数的平方根。
用法示例:```float x = 16.0;float sqrt_x = sqrt(x);```- sin:用于计算一个角度的正弦值。
单片机c语言di函数单片机C语言DI函数DI函数,即Digital Input函数,是单片机编程中常用的函数之一。
它用于检测和读取数字输入信号,并根据输入信号的状态执行相应的操作。
在单片机应用中,DI函数的使用广泛,可以实现各种功能,例如检测按键、读取传感器信号等。
在编写DI函数时,首先需要定义相应的引脚作为输入引脚。
单片机的引脚通常有多种功能,除了输入功能之外,还可以作为输出引脚、模拟输入引脚等。
在使用DI函数时,需要将引脚配置为输入模式,以便读取外部信号。
DI函数的实现方式有多种,其中一种常见的方式是使用端口输入寄存器。
通过读取端口输入寄存器的值,可以获取输入引脚的电平状态。
在C语言中,可以使用位操作来读取寄存器的值,进而获取输入引脚的状态。
在使用DI函数时,需要注意输入引脚的电平状态和信号的稳定性。
当输入引脚处于高电平状态时,表示输入信号为高电平;当输入引脚处于低电平状态时,表示输入信号为低电平。
为了确保读取到正确的输入信号,可以在程序中加入适当的延时,以保证信号的稳定性。
除了读取输入信号的状态之外,DI函数还可以进行一些附加操作,例如判断输入信号是否满足某种条件,或者根据输入信号的状态执行相应的逻辑。
这些操作可以根据具体的应用需求进行扩展,以实现更复杂的功能。
在实际应用中,DI函数常常与其他函数配合使用,以实现更高级的功能。
例如,可以将DI函数与中断函数结合使用,当检测到特定的输入信号时,触发中断函数执行相应的操作。
这种方式可以提高系统的响应速度和实时性。
DI函数是单片机编程中非常重要的一部分。
它可以实现对输入信号的检测和读取,并根据输入信号的状态执行相应的操作。
在实际应用中,我们需要根据具体的需求编写相应的DI函数,并结合其他函数进行功能扩展,以实现所需的系统功能。
第六章函数一、函数的分类与定义1、函数的分类从C 语言程序的结构上划分,C 语言函数分为主函数main( )和普通函数两种,而对于普通函数,又可以分为标准库函数和用户自定义函数。
1)标准库函数标准库函数是由C 编译系统提供的库函数,在C 编译系统中将一些独立的功能模块编写成公用函数,并将它们集中存放在系统的函数库中,供程序设计时使用,称之为标准库函数。
丰富的可直接调用的库函数是C51功能及其高效率的重要体现之一,多使用库函数使程序代码简单,结构清晰,易于调试和维护。
1 / 38C51几类重要库函数及简要说明对于标准C中原有的,在此不再说明,如MATH.H中的各数学运算函数。
①专用寄存器include文件包括了所有8051的SFR及其位定义,一般系统都必须包括本文件。
如REG51.H,AT89X51.H 等。
②绝对地址文件absacc.h, 见P337该文件中实际只定义了几个宏,以确定各存储空间的绝对地址,如定义了XBYTE宏,允许用户访问8051外部数据存储器中的某一字节。
③存储器分配函数,位于stdlib.h中,见2 / 38P340表B-11.④字符串操作函数位于“string.h”中,见P341其中包括拷贝比较移动等函数如: memccpy、memchr、memcmp、memcpy、memmove、memset这些函数对缓冲区进行处理很方便。
⑤流函数输入输出,位于“stdio.h”中,见P344。
流函数缺省为8051串口,如要修改,比如改为LCD显示,可修改lib目录中的 getkey.c及putchar.c源文件,然后在库中替换它们即可定3 / 38义用户的I/O口数据读写。
2)用户自定义函数用户自定义函数是用户根据自己的需要而编写的函数。
从函数定义的形式上可以将其划分无参数函数、有参数函数和空函数。
无参数函数被调用时,既无参数输入,也不返回结果给调用函数,它是为完成某种操作而编写的函数。
有参数函数在被调用时,必须提供实际的输入参数,必须说明与实际参数一一对应的形式参数,并在函数结束时返回结果供调用它的函数使用。
定义空函数的目的是为了以后程序功能的扩充。
4 / 382、函数的定义C51对函数的功能进行了扩展,函数定义的完整形式如下:返回数据类型函数名(形式参数列表) [reentrant] [interrupt n] [using m]{局部变量定义函数体;}(注意对于原型函数的说明,和定义函数相似,但无函数体,也不能说明工作寄存器组的切换using n和中断说明interrupt函数。
)其中:1)函数类型静态函数和外部函数。
(1)静态函数(内部函数,默认)5 / 38静态函数只能在定义它的文件中被调用,而不能在其他文件中的函数所调用。
(2)外部函数外部函数可以在定义它的文件和其它文件中被调用。
可以在函数定义和调用时使用extern说明是外部函数。
但必须注意:在一个文件中,若将主程序放到前面,对后面出现的函数,就必须在文件开始进行说明,说明方式同普通C语言。
否则出现警告如下:函数**.C(5): warning C206: 'func': missing function-prototype所以编程时,要习惯将main()放到最后。
(见“外部函数”)例:文件1:6 / 38#include<AT89X51.H>extern add(x1,x2);unsigned char data x1=12,x2=2,y;main(){y=add(x1,x2);}文件2:data char x3;add(x1,x2){x3=x1+x2;return x3;}2)函数返回值与数据类型如果返回数据,进行说明;如果不返回,一般用void说明,也可以不说明。
7 / 38函数返回值通过return x返回,返回值是通过函数名带回的,所以一个函数只能有一个返回值。
上例中的x3和y。
3)形参与实参形参:在定义函数时,函数名后面括号中的变量称为“形参”,定义时不赋值,由调用函数将值传过来。
实参:主调用函数后面括号中的表达式为“实参”,实参必须有确定的值。
该值在调用时按对应关系传递给形参。
C语言中参数传递是单向的。
4) 可重入函数什么是可重入函数?可重入函数就是允许被递归调用的函数。
函数的递归调用是指当一个函数正被调用尚8 / 38未返回时,又直接或间接调用函数本身。
有两种情况,一种是自身循环调用,另一种是其他函数调用,如程序中正在调用某个函数,而中断中也调用,就可能出现同时调用。
一般的函数不能做到这样,只有重入函数才允许递归调用。
因为8051 内部堆栈空间的限制,为了提高效率,C51 没有提供这种堆栈,而是提供一种压缩栈。
每个函数有一个给定存储空间,用于存放局部变量。
函数中的每个变量都存放在这个空间的固定位置。
当递归调用该过程时会导致变量被覆盖,所以通常情况下C51中的函数是不能重入的。
可重入函数为此必须使用reentrant函数属性来声明函数是可重入的。
9 / 38与不可重入函数的参数传递和局部变量的存储分配方法不同,C51编译器为再入函数生成一个模拟栈,通过这个模拟栈来完成参数传递和存放局部变量。
这样每次函数调用时的局部变量都会被单独保存,再入函数一般占用较大的内存空间,运行起来也比较慢,并且不允许传递bit 类型的变量,也不能定义局部位变量。
可重入函数经常在实时系统中应用,也可在中断函数和非中断函数同时调用同一个函数时使用。
5)规定函数使用的寄存器组切换using m可使用using函数说明属性来规定函数所使用的寄存器组。
10 / 38m是一个0-3的整形参数,分别对应0-3组工作寄存器。
这个参数表示使用的寄存器组的编号,这个参数不能使用带运算符的表达式。
using属性只能在函数定义中使用,不能在函数原型声明中使用。
使用using属性的函数将自动完成以下操作:进入函数前,将当前使用的寄存器组的标号保存在堆栈中。
更改PSW的寄存器组选择位,选择设定的寄存器组作为当前的寄存器组。
函数退出时,将寄存器组恢复成进入函数前的寄存器组。
6)中断函数说明interrupt n11 / 38C51最大支持32个中断,在单片机中n常用0-5。
对应中断源见P177。
注意:仅能在函数定义时使用interrupt 函数属性,不能在函数声明时使用interrupt 函数属性。
中断函数在运行过程中自动完成以下工作:1)当中断产生时,将特殊功能寄存器ACC、B、DPH、DPL、PSW的值将被保存在堆栈中。
2)如果中断函数未使用using属性进行修饰,中断函数中所使用的寄存器的值将保存在堆栈中。
3)中断函数运行完成退出时,堆栈中保存的数据将被恢复。
4)中断函数退出时,其对应的汇编代码使用RETI指令退出。
12 / 38中断函数应遵循以下规则:(1)中断函数不能进行参数传递。
(要传递参数怎么办)(2)中断函数没有返回值。
(要返回值怎么办)(3)不能在其它函数中直接调用中断函数(4)如果在中断中调用了其他函数,必须保证这些函数和中断函数使用了相同的寄存器组,并且这些函数应为可重入函数。
(5)C51编译器从绝地址8n+3产生一个中断向量,其中n为中断号。
该向量包含一个到13 / 38中断函数入口地址的绝对跳转。
(因为外部中断0从0003H开始,然后每个中断占8个字节)例1:定义了一个函数int func(x1,x2,x3);//函数声明main(){int a1=1,a2=2,a3=3,a4;a4=func(a1,a2,a3);}int func(x1,x2,x3){int data p2;p2=x1+x2+x3;return p2;14 / 38}在单片机c语言中,用下面的方法定义更方便:int func(x1,x2,x3){int data p2;p2=x1+x2+x3;return p2;}main(){int a1=1,a2=2,a3=3,a4;a4=func(a1,a2,a3);}二、函数与指针函数在编译时,编译器为每个函数分配一个入口地址,这个入口地址就称为函数的指15 / 38针。
函数的指针可以赋给函数指针变量,并能通过函数指针变量调用它所指向的函数。
指向函数指针变量的定义格式如下:存储器类型数据类型(*指针变量名)(参量列表)存储器类型是定义将指针变量存储的位置。
说明:1)函数指针变量定义时,两侧的()是必须的。
2)指向函数的指针变量可以指向任何一个格式相同的函数的入口地址。
3)C语言约定,函数名本身就是函数的入口地址。
4)当函数指针变量指向函数时,即可用它来调用所指的函数。
调用格式为(*指针变量名)(实参表)例1:函数指针的使用16 / 38int add(int a,int b){return a+b;}int sub(int a,int b){return a-b;}main(){int (*pFunc)(int,int);//定义函数指针变量,注意要定义数据类型int x,y;pFunc=add; //对函数指针变量赋值x=(*pFunc)(3,4);pFunc=sub;//由于两个函数格式相同,故定义了一个函数指针y=(*pFunc)(5,3);}函数的指针类型为普通指针。
(函数指针定义)三、函数的调用17 / 38函数的调用,必须保证被调用函数是已经存在的函数或者是库函数;如果是库函数,必须用#include 将所用函数信息包含到程序中。
如#include <math.h>。
对于无参数和无返回值的函数调用很简单,不再重复。
在函数调用中,最关键的是参数的传递与返回值,同普通c语言一样,调用时,可以由实元传递多个参数到函数中,但在返回时,只能返回一个值给函数名。
1、数组作为函数的参数(函数1)18 / 38下面调用函数时,实元传递给哑元的是数组名,将数组传递过去,实际是传递地址。
#include<at89x52.h>int func(x)int x[3];//注意说明方法,定义了一个数组,在花括号外{ int p2;p2=x[0]+x[1]+x[2];return p2;}main(){ int a[3]={3,6,9},a2;a2=func(a);//数组a作为函数的参数,传数组地址}将上式的数组,也可以改为指针。
(函数2) #include<at89x52.h>19 / 38int func(x)int *x;//定义指针,也就是数组的首地址,以下要按指针运算{char i;int p2=0;for(i=0;i<3;i++)p2+=*(x+i);// *为间接访问运算符return p2;}main(){int a[3]={3,6,9},a2;a2=func(a);}2、指针作为函数的参数(函数3)#include<at89x52.h>int func(x)int *x;//必须还要定义相同类型的指针20 / 38{int p2;p2=2*(*x);//传过来的内容乘2return p2;}main(){int a=5,a2;int *p=&a;//定义指针并赋值a2=func(p);}//用指针将a的地址传到函数3、用指针作为返回值(函数4)由于返回值只有一个,所以要返回多个值时,就要用数组或者指针。