变参函数是C语言中经常用到的一类函数,例如常见的printf、scanf等都是变参函数
C库中有一个stdarg.h文件,其中包含有各个编译器的va_start、va_arg等函数,可以实现对变参的解析。
#define va_start(v,l) __builtin_va_start(v,l)
#define va_end(v) __builtin_va_end(v)
#define va_arg(v,l) __builtin_va_arg(v,l)
#if !defined(__STRICT_ANSI__) || __STDC_VERSION__ + 0 >= 199900L || __cplusplus + 0 >= 201103L
#define va_copy(d,s) __builtin_va_copy(d,s)
在MC3172的例程中有串口输出的函数
void GPCOM_UART_EXAMPLE(u32 gpcom_sel)
{
INTDEV_SET_CLK_RST(gpcom_sel,(INTDEV_RUN|INTDEV_IS_GROUP0|INTDEV_CLK_IS_CORECLK_DIV4));
GPCOM_SET_IN_PORT(gpcom_sel,(GPCOM_RXD_IS_P2));
GPCOM_SET_OUT_PORT(gpcom_sel,( \
GPCOM_P0_OUTPUT_DISABLE|GPCOM_P3_OUTPUT_ENABLE|GPCOM_P2_OUTPUT_DISABLE|GPCOM_P1_OUTPUT_DISABLE| \
GPCOM_P0_IS_HIGH |GPCOM_P3_IS_TXD |GPCOM_P2_IS_HIGH |GPCOM_P1_IS_HIGH \
));
GPCOM_SET_COM_MODE(gpcom_sel,GPCOM_UART_MODE);
GPCOM_SET_COM_SPEED(gpcom_sel,12000000,115200);
GPCOM_SET_OVERRIDE_GPIO(gpcom_sel, ( \
GPCOM_P2_OVERRIDE_GPIO|GPCOM_P2_INPUT_ENABLE | \
GPCOM_P3_OVERRIDE_GPIO \
));
#ifdef TEST_ONLY_UART_TX
while(1){
while(GPCOM_TX_FIFO_FULL(gpcom_sel));
for (u32 var = 0; var < 90; ++var) {
NOP();
}
GPCOM_PUSH_TX_DATA(gpcom_sel,0x31);
}
#else
u8 rx_data_rp=0;
u8 rx_data=0;
rx_data_rp=GPCOM_GET_RX_WP(gpcom_sel);
while(1) {
if(rx_data_rp!=(GPCOM_GET_RX_WP(gpcom_sel))){
rx_data=GPCOM_GET_RX_DATA(gpcom_sel,rx_data_rp);
GPCOM_PUSH_TX_DATA(gpcom_sel,rx_data);
rx_data_rp++;
rx_data_rp&=0x0f;
}
}
#endif
}
把配置GCOM0的代码复制到main文件的thread1中
void thread1_main(void)
{
//user code section
u32 gpcom_sel = GPCOM0_BASE_ADDR;
INTDEV_SET_CLK_RST(gpcom_sel,(INTDEV_RUN|INTDEV_IS_GROUP0|INTDEV_CLK_IS_CORECLK_DIV4));
GPCOM_SET_IN_PORT(gpcom_sel,(GPCOM_RXD_IS_P2));
GPCOM_SET_OUT_PORT(gpcom_sel,( \
GPCOM_P0_OUTPUT_DISABLE|GPCOM_P3_OUTPUT_ENABLE|GPCOM_P2_OUTPUT_DISABLE|GPCOM_P1_OUTPUT_DISABLE| \
GPCOM_P0_IS_HIGH |GPCOM_P3_IS_TXD |GPCOM_P2_IS_HIGH |GPCOM_P1_IS_HIGH \
));
GPCOM_SET_COM_MODE(gpcom_sel,GPCOM_UART_MODE);
GPCOM_SET_COM_SPEED(gpcom_sel,12000000,115200);
GPCOM_SET_OVERRIDE_GPIO(gpcom_sel, ( \
GPCOM_P2_OVERRIDE_GPIO|GPCOM_P2_INPUT_ENABLE | \
GPCOM_P3_OVERRIDE_GPIO \
));
while(1) {
}
thread_end();
}
发送一个字节的函数如下
void putch(u8 ch) {
while(GPCOM_TX_FIFO_FULL(GPCOM0_BASE_ADDR));
GPCOM_PUSH_TX_DATA(GPCOM0_BASE_ADDR, ch);
}
在此之上,编写printf函数对%d、%x、%s、%c、%o的解析和输出
void putch(u8 ch) {
while(GPCOM_TX_FIFO_FULL(GPCOM0_BASE_ADDR));
GPCOM_PUSH_TX_DATA(GPCOM0_BASE_ADDR, ch);
}
void putstr(u8 *str) {
while(*str != '\0') {
putch(*str);
str++;
}
}
char num_to_char(int num)
{
if(num>=0 && num<=9)
return (char)('0'+num-0);
else
return (char)('A'+num-10);
}
void putnum(i32 num, i32 carry) {
u8 i, num_arr[10];
if (num < 0) {
putch('-');
num = -num;
}
for (i = 0; i < 10; i++) {
if (!num) break;
num_arr[i] = num % carry;
num /= carry;
}
while(i--) {
putch(num_to_char(num_arr[i]));
}
}
void printf(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
for (; *fmt != '\0'; fmt++) {
if (*fmt != '%') {
putch(*fmt);
continue;
}
fmt++;
switch (*fmt) {
case 'd':
putnum(va_arg(ap, int), 10);
break;
case 'x':
putnum(va_arg(ap, int), 16);
break;
case 'o':
putnum(va_arg(ap, int), 8);
break;
case 'c':
putch(va_arg(ap, int));
break;
case 's':
putstr((u8 *) va_arg(ap, char*));
break;
default:
putch(*fmt);
break;
}
}
va_end(ap);
}
再写一个毫秒的延时宏
do { \
unsigned int i=0,j=0; \
for(i=0; i<n; i++) { \
for(j=0; j<4015; j++) { \
NOP(); \
} \
} \
} while(0)
在thread1函数中调用printf和DELAY_MS函数
while(1) {
tick++;
printf("tick:%d,hex:%x,oct:%o,char:%c,str:%s\r\n", tick, tick, tick, 'A', "hello");
DELAY_MS(500);
}
把USB转串口的RX连接到开发板的PA3管脚,使用串口助手查看输出
PS:在MC3172中调用stdio.h的printf函数、定义_write函数到串口输出,但是仍然会报错,如果有知道解决办法的大佬还请不吝赐教。