将所有的函数都堆在main.c文件里不是好的选择,庞大的代码文件会是你维护的障碍,明智的做法是,一种功能封装到一个库文件里。
库文件就是你代码开始部分写的#include<xxxx.h>里面的xxxx.h,让我们打开stdio.h文件看一看里面具体有什么内容。

1/* Copyright (c) 2002, 2005, 2007 Joerg Wunsch 2 All rights reserved. 3 4 Portions of documentation Copyright (c) 1990, 1991, 1993 5 The Regents of the University of California. 6 7 All rights reserved. 8 9 Redistribution and use in source and binary forms, with or without 10 modification, are permitted provided that the following conditions are met: 11 12 * Redistributions of source code must retain the above copyright 13 notice, this list of conditions and the following disclaimer. 14 15 * Redistributions in binary form must reproduce the above copyright 16 notice, this list of conditions and the following disclaimer in 17 the documentation and/or other materials provided with the 18 distribution. 19 20 * Neither the name of the copyright holders nor the names of 21 contributors may be used to endorse or promote products derived 22 from this software without specific prior written permission. 23 24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 25 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 28 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 29 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 30 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 31 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 32 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 33 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 34 POSSIBILITY OF SUCH DAMAGE. 35 36 $Id: stdio.h,v 1.29.2.1 2008/02/23 08:59:27 dmix Exp $ 37*/ 38 39#ifndef _STDIO_H_ 40#define _STDIO_H_ 1 41 42#ifndef __ASSEMBLER__ 43 44#include <inttypes.h> 45#include <stdarg.h> 46 47#define __need_NULL 48#define __need_size_t 49#include <stddef.h> 50 51/** \file */ 52/** \defgroup avr_stdio <stdio.h>: Standard IO facilities 53 \code #include <stdio.h> \endcode 54 55 <h3>Introduction to the Standard IO facilities</h3> 56 57 This file declares the standard IO facilities that are implemented 58 in \c avr-libc. Due to the nature of the underlying hardware, 59 only a limited subset of standard IO is implemented. There is no 60 actual file implementation available, so only device IO can be 61 performed. Since there's no operating system, the application 62 needs to provide enough details about their devices in order to 63 make them usable by the standard IO facilities. 64 65 Due to space constraints, some functionality has not been 66 implemented at all (like some of the \c printf conversions that 67 have been left out). Nevertheless, potential users of this 68 implementation should be warned: the \c printf and \c scanf families of functions, although 69 usually associated with presumably simple things like the 70 famous "Hello, world!" program, are actually fairly complex 71 which causes their inclusion to eat up a fair amount of code space. 72 Also, they are not fast due to the nature of interpreting the 73 format string at run-time. Whenever possible, resorting to the 74 (sometimes non-standard) predetermined conversion facilities that are 75 offered by avr-libc will usually cost much less in terms of speed 76 and code size. 77 78 <h3>Tunable options for code size vs. feature set</h3> 79 80 In order to allow programmers a code size vs. functionality tradeoff, 81 the function vfprintf() which is the heart of the printf family can be 82 selected in different flavours using linker options. See the 83 documentation of vfprintf() for a detailed description. The same 84 applies to vfscanf() and the \c scanf family of functions. 85 86 <h3>Outline of the chosen API</h3> 87 88 The standard streams \c stdin, \c stdout, and \c stderr are 89 provided, but contrary to the C standard, since avr-libc has no 90 knowledge about applicable devices, these streams are not already 91 pre-initialized at application startup. Also, since there is no 92 notion of "file" whatsoever to avr-libc, there is no function 93 \c fopen() that could be used to associate a stream to some device. 94 (See \ref stdio_note1 "note 1".) Instead, the function \c fdevopen() 95 is provided to associate a stream to a device, where the device 96 needs to provide a function to send a character, to receive a 97 character, or both. There is no differentiation between "text" and 98 "binary" streams inside avr-libc. Character \c \\n is sent 99 literally down to the device's \c put() function. If the device 100 requires a carriage return (\c \\r) character to be sent before 101 the linefeed, its \c put() routine must implement this (see 102 \ref stdio_note2 "note 2"). 103 104 As an alternative method to fdevopen(), the macro 105 fdev_setup_stream() might be used to setup a user-supplied FILE 106 structure. 107 108 It should be noted that the automatic conversion of a newline 109 character into a carriage return - newline sequence breaks binary 110 transfers. If binary transfers are desired, no automatic 111 conversion should be performed, but instead any string that aims 112 to issue a CR-LF sequence must use <tt>"\r\n"</tt> explicitly. 113 114 For convenience, the first call to \c fdevopen() that opens a 115 stream for reading will cause the resulting stream to be aliased 116 to \c stdin. Likewise, the first call to \c fdevopen() that opens 117 a stream for writing will cause the resulting stream to be aliased 118 to both, \c stdout, and \c stderr. Thus, if the open was done 119 with both, read and write intent, all three standard streams will 120 be identical. Note that these aliases are indistinguishable from 121 each other, thus calling \c fclose() on such a stream will also 122 effectively close all of its aliases (\ref stdio_note3 "note 3"). 123 124 It is possible to tie additional user data to a stream, using 125 fdev_set_udata(). The backend put and get functions can then 126 extract this user data using fdev_get_udata(), and act 127 appropriately. For example, a single put function could be used 128 to talk to two different UARTs that way, or the put and get 129 functions could keep internal state between calls there. 130 131 <h3>Format strings in flash ROM</h3> 132 133 All the \c printf and \c scanf family functions come in two flavours: the 134 standard name, where the format string is expected to be in 135 SRAM, as well as a version with the suffix "_P" where the format 136 string is expected to reside in the flash ROM. The macro 137 \c PSTR (explained in \ref avr_pgmspace) becomes very handy 138 for declaring these format strings. 139 140 \anchor stdio_without_malloc 141 <h3>Running stdio without malloc()</h3> 142 143 By default, fdevopen() requires malloc(). As this is often 144 not desired in the limited environment of a microcontroller, an 145 alternative option is provided to run completely without malloc(). 146 147 The macro fdev_setup_stream() is provided to prepare a 148 user-supplied FILE buffer for operation with stdio. 149 150 <h4>Example</h4> 151 152 \code 153 #include <stdio.h> 154 155 static int uart_putchar(char c, FILE *stream); 156 157 static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, 158 _FDEV_SETUP_WRITE); 159 160 static int 161 uart_putchar(char c, FILE *stream) 162 { 163 164 if (c == '\n') 165 uart_putchar('\r', stream); 166 loop_until_bit_is_set(UCSRA, UDRE); 167 UDR = c; 168 return 0; 169 } 170 171 int 172 main(void) 173 { 174 init_uart(); 175 stdout = &mystdout; 176 printf("Hello, world!\n"); 177 178 return 0; 179 } 180 \endcode 181 182 This example uses the initializer form FDEV_SETUP_STREAM() rather 183 than the function-like fdev_setup_stream(), so all data 184 initialization happens during C start-up. 185 186 If streams initialized that way are no longer needed, they can be 187 destroyed by first calling the macro fdev_close(), and then 188 destroying the object itself. No call to fclose() should be 189 issued for these streams. While calling fclose() itself is 190 harmless, it will cause an undefined reference to free() and thus 191 cause the linker to link the malloc module into the application. 192 193 <h3>Notes</h3> 194 195 \anchor stdio_note1 \par Note 1: 196 It might have been possible to implement a device abstraction that 197 is compatible with \c fopen() but since this would have required 198 to parse a string, and to take all the information needed either 199 out of this string, or out of an additional table that would need to be 200 provided by the application, this approach was not taken. 201 202 \anchor stdio_note2 \par Note 2: 203 This basically follows the Unix approach: if a device such as a 204 terminal needs special handling, it is in the domain of the 205 terminal device driver to provide this functionality. Thus, a 206 simple function suitable as \c put() for \c fdevopen() that talks 207 to a UART interface might look like this: 208 209 \code 210 int 211 uart_putchar(char c, FILE *stream) 212 { 213 214 if (c == '\n') 215 uart_putchar('\r'); 216 loop_until_bit_is_set(UCSRA, UDRE); 217 UDR = c; 218 return 0; 219 } 220 \endcode 221 222 \anchor stdio_note3 \par Note 3: 223 This implementation has been chosen because the cost of maintaining 224 an alias is considerably smaller than the cost of maintaining full 225 copies of each stream. Yet, providing an implementation that offers 226 the complete set of standard streams was deemed to be useful. Not 227 only that writing \c printf() instead of <tt>fprintf(mystream, ...)</tt> 228 saves typing work, but since avr-gcc needs to resort to pass all 229 arguments of variadic functions on the stack (as opposed to passing 230 them in registers for functions that take a fixed number of 231 parameters), the ability to pass one parameter less by implying 232 \c stdin will also save some execution time. 233*/ 234 235#if !defined(__DOXYGEN__) 236 237/* 238 * This is an internal structure of the library that is subject to be 239 * changed without warnings at any time. Please do *never* reference 240 * elements of it beyond by using the official interfaces provided. 241 */ 242struct __file { 243 char *buf; /* buffer pointer */ 244 unsigned char unget; /* ungetc() buffer */ 245 uint8_t flags; /* flags, see below */ 246#define __SRD 0x0001 /* OK to read */ 247#define __SWR 0x0002 /* OK to write */ 248#define __SSTR 0x0004 /* this is an sprintf/snprintf string */ 249#define __SPGM 0x0008 /* fmt string is in progmem */ 250#define __SERR 0x0010 /* found error */ 251#define __SEOF 0x0020 /* found EOF */ 252#define __SUNGET 0x040 /* ungetc() happened */ 253#define __SMALLOC 0x80 /* handle is malloc()ed */ 254#if 0 255/* possible future extensions, will require uint16_t flags */ 256#define __SRW 0x0100 /* open for reading & writing */ 257#define __SLBF 0x0200 /* line buffered */ 258#define __SNBF 0x0400 /* unbuffered */ 259#define __SMBF 0x0800 /* buf is from malloc */ 260#endif 261 int size; /* size of buffer */ 262 int len; /* characters read or written so far */ 263 int (*put)(char, struct __file *); /* function to write one char to device */ 264 int (*get)(struct __file *); /* function to read one char from device */ 265 void *udata; /* User defined and accessible data. */ 266}; 267 268#endif /* not __DOXYGEN__ */ 269 270/*@{*/ 271/** 272 \c FILE is the opaque structure that is passed around between the 273 various standard IO functions. 274*/ 275#define FILE struct __file 276 277/** 278 Stream that will be used as an input stream by the simplified 279 functions that don't take a \c stream argument. 280 281 The first stream opened with read intent using \c fdevopen() 282 will be assigned to \c stdin. 283*/ 284#define stdin (__iob[0]) 285 286/** 287 Stream that will be used as an output stream by the simplified 288 functions that don't take a \c stream argument. 289 290 The first stream opened with write intent using \c fdevopen() 291 will be assigned to both, \c stdin, and \c stderr. 292*/ 293#define stdout (__iob[1]) 294 295/** 296 Stream destined for error output. Unless specifically assigned, 297 identical to \c stdout. 298 299 If \c stderr should point to another stream, the result of 300 another \c fdevopen() must be explicitly assigned to it without 301 closing the previous \c stderr (since this would also close 302 \c stdout). 303*/ 304#define stderr (__iob[2]) 305 306/** 307 \c EOF declares the value that is returned by various standard IO 308 functions in case of an error. Since the AVR platform (currently) 309 doesn't contain an abstraction for actual files, its origin as 310 "end of file" is somewhat meaningless here. 311*/ 312#define EOF (-1) 313 314/** This macro inserts a pointer to user defined data into a FILE 315 stream object. 316 317 The user data can be useful for tracking state in the put and get 318 functions supplied to the fdevopen() function. */ 319#define fdev_set_udata(stream, u) do { (stream)->udata = u; } while(0) 320 321/** This macro retrieves a pointer to user defined data from a FILE 322 stream object. */ 323#define fdev_get_udata(stream) ((stream)->udata) 324 325#if defined(__DOXYGEN__) 326/** 327 \brief Setup a user-supplied buffer as an stdio stream 328 329 This macro takes a user-supplied buffer \c stream, and sets it up 330 as a stream that is valid for stdio operations, similar to one that 331 has been obtained dynamically from fdevopen(). The buffer to setup 332 must be of type FILE. 333 334 The arguments \c put and \c get are identical to those that need to 335 be passed to fdevopen(). 336 337 The \c rwflag argument can take one of the values _FDEV_SETUP_READ, 338 _FDEV_SETUP_WRITE, or _FDEV_SETUP_RW, for read, write, or read/write 339 intent, respectively. 340 341 \note No assignments to the standard streams will be performed by 342 fdev_setup_stream(). If standard streams are to be used, these 343 need to be assigned by the user. See also under 344 \ref stdio_without_malloc "Running stdio without malloc()". 345 */ 346#define fdev_setup_stream(stream, put, get, rwflag) 347#else /* !DOXYGEN */ 348#define fdev_setup_stream(stream, p, g, f) \ 349 do { \ 350 (stream)->put = p; \ 351 (stream)->get = g; \ 352 (stream)->flags = f; \ 353 (stream)->udata = 0; \ 354 } while(0) 355#endif /* DOXYGEN */ 356 357#define _FDEV_SETUP_READ __SRD /**< fdev_setup_stream() with read intent */ 358#define _FDEV_SETUP_WRITE __SWR /**< fdev_setup_stream() with write intent */ 359#define _FDEV_SETUP_RW (__SRD|__SWR) /**< fdev_setup_stream() with read/write intent */ 360 361/** 362 * Return code for an error condition during device read. 363 * 364 * To be used in the get function of fdevopen(). 365 */ 366#define _FDEV_ERR (-1) 367 368/** 369 * Return code for an end-of-file condition during device read. 370 * 371 * To be used in the get function of fdevopen(). 372 */ 373#define _FDEV_EOF (-2) 374 375#if defined(__DOXYGEN__) 376/** 377 \brief Initializer for a user-supplied stdio stream 378 379 This macro acts similar to fdev_setup_stream(), but it is to be 380 used as the initializer of a variable of type FILE. 381 382 The remaining arguments are to be used as explained in 383 fdev_setup_stream(). 384 */ 385#define FDEV_SETUP_STREAM(put, get, rwflag) 386#else /* !DOXYGEN */ 387#define FDEV_SETUP_STREAM(p, g, f) \ 388 { \ 389 .put = p, \ 390 .get = g, \ 391 .flags = f, \ 392 .udata = 0, \ 393 } 394#endif /* DOXYGEN */ 395 396#ifdef __cplusplus 397extern "C" { 398#endif 399 400#if !defined(__DOXYGEN__) 401/* 402 * Doxygen documentation can be found in fdevopen.c. 403 */ 404 405extern struct __file *__iob[]; 406 407#if defined(__STDIO_FDEVOPEN_COMPAT_12) 408/* 409 * Declare prototype for the discontinued version of fdevopen() that 410 * has been in use up to avr-libc 1.2.x. The new implementation has 411 * some backwards compatibility with the old version. 412 */ 413extern FILE *fdevopen(int (*__put)(char), int (*__get)(void), 414 int __opts __attribute__((unused))); 415#else /* !defined(__STDIO_FDEVOPEN_COMPAT_12) */ 416/* New prototype for avr-libc 1.4 and above. */ 417extern FILE *fdevopen(int (*__put)(char, FILE*), int (*__get)(FILE*)); 418#endif /* defined(__STDIO_FDEVOPEN_COMPAT_12) */ 419 420#endif /* not __DOXYGEN__ */ 421 422/** 423 This function closes \c stream, and disallows and further 424 IO to and from it. 425 426 When using fdevopen() to setup the stream, a call to fclose() is 427 needed in order to free the internal resources allocated. 428 429 If the stream has been set up using fdev_setup_stream() or 430 FDEV_SETUP_STREAM(), use fdev_close() instead. 431 432 It currently always returns 0 (for success). 433*/ 434extern int fclose(FILE *__stream); 435 436/** 437 This macro frees up any library resources that might be associated 438 with \c stream. It should be called if \c stream is no longer 439 needed, right before the application is going to destroy the 440 \c stream object itself. 441 442 (Currently, this macro evaluates to nothing, but this might change 443 in future versions of the library.) 444*/ 445#if defined(__DOXYGEN__) 446# define fdev_close() 447#else 448# define fdev_close() ((void)0) 449#endif 450 451/** 452 \c vfprintf is the central facility of the \c printf family of 453 functions. It outputs values to \c stream under control of a 454 format string passed in \c fmt. The actual values to print are 455 passed as a variable argument list \c ap. 456 457 \c vfprintf returns the number of characters written to \c stream, 458 or \c EOF in case of an error. Currently, this will only happen 459 if \c stream has not been opened with write intent. 460 461 The format string is composed of zero or more directives: ordinary 462 characters (not \c %), which are copied unchanged to the output 463 stream; and conversion specifications, each of which results in 464 fetching zero or more subsequent arguments. Each conversion 465 specification is introduced by the \c % character. The arguments must 466 properly correspond (after type promotion) with the conversion 467 specifier. After the \c %, the following appear in sequence: 468 469 - Zero or more of the following flags: 470 <ul> 471 <li> \c # The value should be converted to an "alternate form". For 472 c, d, i, s, and u conversions, this option has no effect. 473 For o conversions, the precision of the number is 474 increased to force the first character of the output 475 string to a zero (except if a zero value is printed with 476 an explicit precision of zero). For x and X conversions, 477 a non-zero result has the string `0x' (or `0X' for X 478 conversions) prepended to it.</li> 479 <li> \c 0 (zero) Zero padding. For all conversions, the converted 480 value is padded on the left with zeros rather than blanks. 481 If a precision is given with a numeric conversion (d, i, 482 o, u, i, x, and X), the 0 flag is ignored.</li> 483 <li> \c - A negative field width flag; the converted value is to be 484 left adjusted on the field boundary. The converted value 485 is padded on the right with blanks, rather than on the 486 left with blanks or zeros. A - overrides a 0 if both are 487 given.</li> 488 <li> ' ' (space) A blank should be left before a positive number 489 produced by a signed conversion (d, or i).</li> 490 <li> \c + A sign must always be placed before a number produced by a 491 signed conversion. A + overrides a space if both are 492 used.</li> 493 </ul> 494 495 - An optional decimal digit string specifying a minimum field width. 496 If the converted value has fewer characters than the field width, it 497 will be padded with spaces on the left (or right, if the left-adjustment 498 flag has been given) to fill out the field width. 499 - An optional precision, in the form of a period . followed by an 500 optional digit string. If the digit string is omitted, the 501 precision is taken as zero. This gives the minimum number of 502 digits to appear for d, i, o, u, x, and X conversions, or the 503 maximum number of characters to be printed from a string for \c s 504 conversions. 505 - An optional \c l or \c h length modifier, that specifies that the 506 argument for the d, i, o, u, x, or X conversion is a \c "long int" 507 rather than \c int. The \c h is ignored, as \c "short int" is 508 equivalent to \c int. 509 - A character that specifies the type of conversion to be applied. 510 511 The conversion specifiers and their meanings are: 512 513 - \c diouxX The int (or appropriate variant) argument is converted 514 to signed decimal (d and i), unsigned octal (o), unsigned 515 decimal (u), or unsigned hexadecimal (x and X) notation. 516 The letters "abcdef" are used for x conversions; the 517 letters "ABCDEF" are used for X conversions. The 518 precision, if any, gives the minimum number of digits that 519 must appear; if the converted value requires fewer digits, 520 it is padded on the left with zeros. 521 - \c p The <tt>void *</tt> argument is taken as an unsigned integer, 522 and converted similarly as a <tt>%\#x</tt> command would do. 523 - \c c The \c int argument is converted to an \c "unsigned char", and the 524 resulting character is written. 525 - \c s The \c "char *" argument is expected to be a pointer to an array 526 of character type (pointer to a string). Characters from 527 the array are written up to (but not including) a 528 terminating NUL character; if a precision is specified, no 529 more than the number specified are written. If a precision 530 is given, no null character need be present; if the 531 precision is not specified, or is greater than the size of 532 the array, the array must contain a terminating NUL 533 character. 534 - \c % A \c % is written. No argument is converted. The complete 535 conversion specification is "%%". 536 - \c eE The double argument is rounded and converted in the format 537 \c "[-]d.ddde眃d" where there is one digit before the 538 decimal-point character and the number of digits after it 539 is equal to the precision; if the precision is missing, it 540 is taken as 6; if the precision is zero, no decimal-point 541 character appears. An \e E conversion uses the letter \c 'E' 542 (rather than \c 'e') to introduce the exponent. The exponent 543 always contains two digits; if the value is zero, 544 the exponent is 00. 545 - \c fF The double argument is rounded and converted to decimal notation 546 in the format \c "[-]ddd.ddd", where the number of digits after the 547 decimal-point character is equal to the precision specification. 548 If the precision is missing, it is taken as 6; if the precision 549 is explicitly zero, no decimal-point character appears. If a 550 decimal point appears, at least one digit appears before it. 551 - \c gG The double argument is converted in style \c f or \c e (or 552 \c F or \c E for \c G conversions). The precision 553 specifies the number of significant digits. If the 554 precision is missing, 6 digits are given; if the precision 555 is zero, it is treated as 1. Style \c e is used if the 556 exponent from its conversion is less than -4 or greater 557 than or equal to the precision. Trailing zeros are removed 558 from the fractional part of the result; a decimal point 559 appears only if it is followed by at least one digit. 560 - \c S Similar to the \c s format, except the pointer is expected to 561 point to a program-memory (ROM) string instead of a RAM string. 562 563 In no case does a non-existent or small field width cause truncation of a 564 numeric field; if the result of a conversion is wider than the field 565 width, the field is expanded to contain the conversion result. 566 567 Since the full implementation of all the mentioned features becomes 568 fairly large, three different flavours of vfprintf() can be 569 selected using linker options. The default vfprintf() implements 570 all the mentioned functionality except floating point conversions. 571 A minimized version of vfprintf() is available that only implements 572 the very basic integer and string conversion facilities, but only 573 the \c # additional option can be specified using conversion 574 flags (these flags are parsed correctly from the format 575 specification, but then simply ignored). This version can be 576 requested using the following \ref gcc_minusW "compiler options": 577 578 \code 579 -Wl,-u,vfprintf -lprintf_min 580 \endcode 581 582 If the full functionality including the floating point conversions 583 is required, the following options should be used: 584 585 \code 586 -Wl,-u,vfprintf -lprintf_flt -lm 587 \endcode 588 589 \par Limitations: 590 - The specified width and precision can be at most 255. 591 592 \par Notes: 593 - For floating-point conversions, if you link default or minimized 594 version of vfprintf(), the symbol \c ? will be output and double 595 argument will be skiped. So you output below will not be crashed. 596 For default version the width field and the "pad to left" ( symbol 597 minus ) option will work in this case. 598 - The \c hh length modifier is ignored (\c char argument is 599 promouted to \c int). More exactly, this realization does not check 600 the number of \c h symbols. 601 - But the \c ll length modifier will to abort the output, as this 602 realization does not operate \c long \c long arguments. 603 - The variable width or precision field (an asterisk \c * symbol) 604 is not realized and will to abort the output. 605 606 */ 607 608extern int vfprintf(FILE *__stream, const char *__fmt, va_list __ap); 609 610/** 611 Variant of \c vfprintf() that uses a \c fmt string that resides 612 in program memory. 613*/ 614extern int vfprintf_P(FILE *__stream, const char *__fmt, va_list __ap); 615 616/** 617 The function \c fputc sends the character \c c (though given as type 618 \c int) to \c stream. It returns the character, or \c EOF in case 619 an error occurred. 620*/ 621extern int fputc(int __c, FILE *__stream); 622 623#if !defined(__DOXYGEN__) 624 625/* putc() function implementation, required by standard */ 626extern int putc(int __c, FILE *__stream); 627 628/* putchar() function implementation, required by standard */ 629extern int putchar(int __c); 630 631#endif /* not __DOXYGEN__ */ 632 633/** 634 The macro \c putc used to be a "fast" macro implementation with a 635 functionality identical to fputc(). For space constraints, in 636 \c avr-libc, it is just an alias for \c fputc. 637*/ 638#define putc(__c, __stream) fputc(__c, __stream) 639 640/** 641 The macro \c putchar sends character \c c to \c stdout. 642*/ 643#define putchar(__c) fputc(__c, stdout) 644 645/** 646 The function \c printf performs formatted output to stream 647 \c stderr. See \c vfprintf() for details. 648*/ 649extern int printf(const char *__fmt, ...); 650 651/** 652 Variant of \c printf() that uses a \c fmt string that resides 653 in program memory. 654*/ 655extern int printf_P(const char *__fmt, ...); 656 657/** 658 The function \c vprintf performs formatted output to stream 659 \c stdout, taking a variable argument list as in vfprintf(). 660 661 See vfprintf() for details. 662*/ 663extern int vprintf(const char *__fmt, va_list __ap); 664 665/** 666 Variant of \c printf() that sends the formatted characters 667 to string \c s. 668*/ 669extern int sprintf(char *__s, const char *__fmt, ...); 670 671/** 672 Variant of \c sprintf() that uses a \c fmt string that resides 673 in program memory. 674*/ 675extern int sprintf_P(char *__s, const char *__fmt, ...); 676 677/** 678 Like \c sprintf(), but instead of assuming \c s to be of infinite 679 size, no more than \c n characters (including the trailing NUL 680 character) will be converted to \c s. 681 682 Returns the number of characters that would have been written to 683 \c s if there were enough space. 684*/ 685extern int snprintf(char *__s, size_t __n, const char *__fmt, ...); 686 687/** 688 Variant of \c snprintf() that uses a \c fmt string that resides 689 in program memory. 690*/ 691extern int snprintf_P(char *__s, size_t __n, const char *__fmt, ...); 692 693/** 694 Like \c sprintf() but takes a variable argument list for the 695 arguments. 696*/ 697extern int vsprintf(char *__s, const char *__fmt, va_list ap); 698 699/** 700 Variant of \c vsprintf() that uses a \c fmt string that resides 701 in program memory. 702*/ 703extern int vsprintf_P(char *__s, const char *__fmt, va_list ap); 704 705/** 706 Like \c vsprintf(), but instead of assuming \c s to be of infinite 707 size, no more than \c n characters (including the trailing NUL 708 character) will be converted to \c s. 709 710 Returns the number of characters that would have been written to 711 \c s if there were enough space. 712*/ 713extern int vsnprintf(char *__s, size_t __n, const char *__fmt, va_list ap); 714 715/** 716 Variant of \c vsnprintf() that uses a \c fmt string that resides 717 in program memory. 718*/ 719extern int vsnprintf_P(char *__s, size_t __n, const char *__fmt, va_list ap); 720/** 721 The function \c fprintf performs formatted output to \c stream. 722 See \c vfprintf() for details. 723*/ 724extern int fprintf(FILE *__stream, const char *__fmt, ...); 725 726/** 727 Variant of \c fprintf() that uses a \c fmt string that resides 728 in program memory. 729*/ 730extern int fprintf_P(FILE *__stream, const char *__fmt, ...); 731 732/** 733 Write the string pointed to by \c str to stream \c stream. 734 735 Returns 0 on success and EOF on error. 736*/ 737extern int fputs(const char *__str, FILE *__stream); 738 739/** 740 Variant of fputs() where \c str resides in program memory. 741*/ 742extern int fputs_P(const char *__str, FILE *__stream); 743 744/** 745 Write the string pointed to by \c str, and a trailing newline 746 character, to \c stdout. 747*/ 748extern int puts(const char *__str); 749 750/** 751 Variant of puts() where \c str resides in program memory. 752*/ 753extern int puts_P(const char *__str); 754 755/** 756 Write \c nmemb objects, \c size bytes each, to \c stream. 757 The first byte of the first object is referenced by \c ptr. 758 759 Returns the number of objects successfully written, i. e. 760 \c nmemb unless an output error occured. 761 */ 762extern size_t fwrite(const void *__ptr, size_t __size, size_t __nmemb, 763 FILE *__stream); 764 765/** 766 The function \c fgetc reads a character from \c stream. It returns 767 the character, or \c EOF in case end-of-file was encountered or an 768 error occurred. The routines feof() or ferror() must be used to 769 distinguish between both situations. 770*/ 771extern int fgetc(FILE *__stream); 772 773#if !defined(__DOXYGEN__) 774 775/* getc() function implementation, required by standard */ 776extern int getc(FILE *__stream); 777 778/* getchar() function implementation, required by standard */ 779extern int getchar(void); 780 781#endif /* not __DOXYGEN__ */ 782 783/** 784 The macro \c getc used to be a "fast" macro implementation with a 785 functionality identical to fgetc(). For space constraints, in 786 \c avr-libc, it is just an alias for \c fgetc. 787*/ 788#define getc(__stream) fgetc(__stream) 789 790/** 791 The macro \c getchar reads a character from \c stdin. Return 792 values and error handling is identical to fgetc(). 793*/ 794#define getchar() fgetc(stdin) 795 796/** 797 The ungetc() function pushes the character \c c (converted to an 798 unsigned char) back onto the input stream pointed to by \c stream. 799 The pushed-back character will be returned by a subsequent read on 800 the stream. 801 802 Currently, only a single character can be pushed back onto the 803 stream. 804 805 The ungetc() function returns the character pushed back after the 806 conversion, or \c EOF if the operation fails. If the value of the 807 argument \c c character equals \c EOF, the operation will fail and 808 the stream will remain unchanged. 809*/ 810extern int ungetc(int __c, FILE *__stream); 811 812/** 813 Read at most <tt>size - 1</tt> bytes from \c stream, until a 814 newline character was encountered, and store the characters in the 815 buffer pointed to by \c str. Unless an error was encountered while 816 reading, the string will then be terminated with a \c NUL 817 character. 818 819 If an error was encountered, the function returns NULL and sets the 820 error flag of \c stream, which can be tested using ferror(). 821 Otherwise, a pointer to the string will be returned. */ 822extern char *fgets(char *__str, int __size, FILE *__stream); 823 824/** 825 Similar to fgets() except that it will operate on stream \c stdin, 826 and the trailing newline (if any) will not be stored in the string. 827 It is the caller's responsibility to provide enough storage to hold 828 the characters read. */ 829extern char *gets(char *__str); 830 831/** 832 Read \c nmemb objects, \c size bytes each, from \c stream, 833 to the buffer pointed to by \c ptr. 834 835 Returns the number of objects successfully read, i. e. 836 \c nmemb unless an input error occured or end-of-file was 837 encountered. feof() and ferror() must be used to distinguish 838 between these two conditions. 839 */ 840extern size_t fread(void *__ptr, size_t __size, size_t __nmemb, 841 FILE *__stream); 842 843/** 844 Clear the error and end-of-file flags of \c stream. 845 */ 846extern void clearerr(FILE *__stream); 847 848#if !defined(__DOXYGEN__) 849/* fast inlined version of clearerr() */ 850#define clearerror(s) do { (s)->flags &= ~(__SERR | __SEOF); } while(0) 851#endif /* !defined(__DOXYGEN__) */ 852 853/** 854 Test the end-of-file flag of \c stream. This flag can only be cleared 855 by a call to clearerr(). 856 */ 857extern int feof(FILE *__stream); 858 859#if !defined(__DOXYGEN__) 860/* fast inlined version of feof() */ 861#define feof(s) ((s)->flags & __SEOF) 862#endif /* !defined(__DOXYGEN__) */ 863 864/** 865 Test the error flag of \c stream. This flag can only be cleared 866 by a call to clearerr(). 867 */ 868extern int ferror(FILE *__stream); 869 870#if !defined(__DOXYGEN__) 871/* fast inlined version of ferror() */ 872#define ferror(s) ((s)->flags & __SERR) 873#endif /* !defined(__DOXYGEN__) */ 874 875extern int vfscanf(FILE *__stream, const char *__fmt, va_list __ap); 876 877/** 878 Variant of vfscanf() using a \c fmt string in program memory. 879 */ 880extern int vfscanf_P(FILE *__stream, const char *__fmt, va_list __ap); 881 882/** 883 The function \c fscanf performs formatted input, reading the 884 input data from \c stream. 885 886 See vfscanf() for details. 887 */ 888extern int fscanf(FILE *__stream, const char *__fmt, ...); 889 890/** 891 Variant of fscanf() using a \c fmt string in program memory. 892 */ 893extern int fscanf_P(FILE *__stream, const char *__fmt, ...); 894 895/** 896 The function \c scanf performs formatted input from stream \c stdin. 897 898 See vfscanf() for details. 899 */ 900extern int scanf(const char *__fmt, ...); 901 902/** 903 Variant of scanf() where \c fmt resides in program memory. 904 */ 905extern int scanf_P(const char *__fmt, ...); 906 907/** 908 The function \c vscanf performs formatted input from stream 909 \c stdin, taking a variable argument list as in vfscanf(). 910 911 See vfscanf() for details. 912*/ 913extern int vscanf(const char *__fmt, va_list __ap); 914 915/** 916 The function \c sscanf performs formatted input, reading the 917 input data from the buffer pointed to by \c buf. 918 919 See vfscanf() for details. 920 */ 921extern int sscanf(const char *__buf, const char *__fmt, ...); 922 923/** 924 Variant of sscanf() using a \c fmt string in program memory. 925 */ 926extern int sscanf_P(const char *__buf, const char *__fmt, ...); 927 928#if defined(__DOXYGEN__) 929/** 930 Flush \c stream. 931 932 This is a null operation provided for source-code compatibility 933 only, as the standard IO implementation currently does not perform 934 any buffering. 935 */ 936extern int fflush(FILE *stream); 937#else 938static __inline__ int fflush(FILE *stream __attribute__((unused))) 939{ 940 return 0; 941} 942#endif 943 944#ifdef __cplusplus 945} 946#endif 947 948/*@}*/ 949 950/* 951 * The following constants are currently not used by avr-libc's 952 * stdio subsystem. They are defined here since the gcc build 953 * environment expects them to be here. 954 */ 955#define SEEK_SET 0 956#define SEEK_CUR 1 957#define SEEK_END 2 958 959#endif /* __ASSEMBLER */ 960 961#endif /* _STDLIB_H_ */
View Code
看见了吧,大部分是注释的废话,剩下的只有一堆宏命令和函数定义,一行具体实现也没有。
具体的实现被编译为二进制格式,并被封装为*.lib文件了,我们在调用时编译器会直接将我们调用的部分编译进我们的程序中,我们并不知道具体的代码是什么。
我们自己封装库文件时不用如此复杂,直接将函数源代码留着。编译器编译其他代码,需要调用时,直接再编译一遍。
实验四:将LED流水灯的功能封装进库文件中
在led.h文件中,我们只需效仿stdio.h,声明所有用到的函数。
1#include <stm32f10x.h> 2#ifndef _LED_H 3 #define _LED_H 4 void Delay(int time); 5 void LED_configer(void); 6 void LED_blingbling(void); 7#endif 8//led.h
注意,为了防止库函数被重复定义,我们要先判断,这个库函数对应的宏开关有没有打开,就是上文的_LED_H,如果打开了,我们就不应该再定义这个库中的函数。
而具体的函数实现,我们放在led.c中
1#include <led.h> 2#include <stm32f10x.h> 3void Delay(int time){ 4 for(int i=0;i<time;i++) 5 for(int j=0;j<1000;j++); 6} 7void LED_configer(){ 8 //led³õʼ»¯µÄº¯Êý 9 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); 10 GPIO_InitTypeDef GPIO_LED_INIT; 11 GPIO_LED_INIT.GPIO_Pin=GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4; 12 GPIO_LED_INIT.GPIO_Speed=GPIO_Speed_2MHz; 13 GPIO_LED_INIT.GPIO_Mode=GPIO_Mode_Out_PP; 14 GPIO_Init(GPIOA,&GPIO_LED_INIT); 15} 16void LED_blingbling(){ 17 while(1){ 18 GPIO_SetBits(GPIOA,GPIO_Pin_1); 19 Delay(500); 20 GPIO_ResetBits(GPIOA,GPIO_Pin_1); 21 GPIO_SetBits(GPIOA,GPIO_Pin_2); 22 Delay(500); 23 GPIO_ResetBits(GPIOA,GPIO_Pin_2); 24 GPIO_SetBits(GPIOA,GPIO_Pin_3); 25 Delay(500); 26 GPIO_ResetBits(GPIOA,GPIO_Pin_3); 27 GPIO_SetBits(GPIOA,GPIO_Pin_4); 28 Delay(500); 29 GPIO_ResetBits(GPIOA,GPIO_Pin_4); 30 } 31} 32//led.c
然后在main文件中,直接包含库,并调用库函数即可。如此,代码文件的可读性和可维护性便提高了很多。
1#include <stdio.h> 2#include <stm32f10x.h> 3#include <led.h> 4int main(){ 5 LED_configer(); 6 LED_blingbling(); 7 return 0; 8} 9//main.c