- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include <inttypes.h>
- #include <avr/sfr_defs.h>
- #include <util/delay.h>
- #include <avr/pgmspace.h>
- #include <stdio.h>
- #include<stdarg.h>
- //使用的是mage128的板子,這個是抄別人的,覺得很好用,里面的可變參數的
- //理解起來還是有點兒困難的,不過myprintf()這個函數很好用,如果電腦沒有
- //串口,也可以用usb轉串口來實現,需要安裝usb轉串口驅動,硬件管理器里面可
- //以看到安裝后的usb-serial的com口,還有設置好波特率
- //初始化串口
- void init_uart(void)
- {
- //UART 初始化
- UCSR1B=_BV(RXEN1)|_BV(TXEN1);/*(1<<RXCIE0)|(1<<TXCIE0)|*/
- UBRR1L=103; //9600 baud 6MHz:38 4MHz:25 16MHZ:103
- }
- static int uart_putchar(char c)
- {
- if (c == '\n')
- uart_putchar('\r');
- loop_until_bit_is_set(UCSR1A, UDRE1);
- UDR1 = c;
- //mage128中有兩個串口可以使用,這里使用了usart1,來發送數據,如果只有一個串口只要把寄存器中的1去掉就可以了,
- //這個函數可以將數據發送給串口調試軟件,也可以通過xp自帶的超級終端來查看所以不一定非要下載串口調試軟件,
- //當然串口調試軟件用起來功能多
- return 0;
- }
- static int uart_getchar()
- {
- loop_until_bit_is_set(UCSR1A,RXC1);
- return UDR1;
- //mage128中有兩個串口可以使用,這里使用了usart1,來發送數據,如果只有一個串口只要把寄存器中的1去掉就可以了,
- //這個函數可以將數據發送給串口調試軟件,也可以通過xp自帶的超級終端
- }
- static void myprintf(const char* fmt,...)
- {
- const char* s;
- int16_t d;
- char buf[16];
- va_list ap;
- va_start(ap,fmt); // 將ap指向fmt(即可變參數的第一個?下一個?)
- while (*fmt)
- {
- if (*fmt != '%')//如果不是%,則正常發送,這里不用for來發送所有非%字符的,原因是因為if語句里面有continue語句,//可以跳出循環執行下一個while循環,將所有的非%字符發送完畢,很牛逼,值得學習
- {
- uart_putchar(*fmt++); // 正常發送
- continue; //發送完畢以后跳出繼續下一個循環,這樣就可以繼續發送下一個字符
- }
- //由于上面的if以及continue的組合導致非%字符時程序不可能運行到這里,所以一旦運行到這里就說明*fmt++得到的是一個
- //%字符
- switch (*++fmt) //此時fmt先加一再取該地址處的數據原因在于上面是再得到了一個%以后才運行到此的,
- //所以此時不需要理會%了,只要讀出%后的字符就可以
- {
- case 's':
- s = va_arg(ap,const char*); // 將ap指針指向的數據類型轉換成char*型,并返回之,此時返回一個字符串的首地址
- for (; *s; s++)
- uart_putchar(*s);
- break;
- case 'x':
- d = va_arg(ap,int); // 將ap指針指向的數據類型轉換成int型,并返回之
- itoa(d,buf,16); // 將整型d以16進制轉到buf中
- for (s = buf; *s; s++)
- uart_putchar(*s);
- break;
- case 'd':
- d = va_arg(ap,int);
- itoa(d,buf,10); // 將整型d以10進制轉到buf中
- for (s = buf; *s; s++)
- uart_putchar(*s);
- break;
- default:
- uart_putchar(*fmt); //%號后面出現的非格式制定字符則按常理發送打印
- break;
- }
- fmt++; //判斷%號后面的字符以后,跳出switch語句,繼續while循環,發送打印后面的字符
- }
- va_end(ap);
- }
- int main(void)
- {
- init_uart();// 初始化串口
- uint8_t i = 100;
- char * s = "Word!";
- myprintf("\n\rHello %s\n\r0x%x = %d\n",s,i,i);
- return 0;
- }
復制代碼
|