串口经常需要接收指定范围的字符。比如程序运行到某处,提供给用户‘A’、‘B’、‘C’、‘D’四个选项,等待用户输入。如果输入是‘A’、‘B’、‘C’、‘D’的其中一个,则跳转;否则继续等待。
这个功能可以使用if判断语句来实现,它的优点是直观简单,缺点是代码有重复。如果程序中有十次这样的等待输入,就得编写十次if判断语句。
所以,这里使用变参函数将这个功能整合成一个模块。
// 定义在变参函数中,需要调用的显示函数,里面放置打印给用户的提示信息等等
// 函数类型需要符合变参函数中的uart_func
// USART_TypeDef用来选择串口号
// 第一个struct uartData用来存储串口接收中断的数据和标志位
// 第二个struct uartData是第一个的缓存,避免数据和标志位在处理的时候被串口接收中断更新
int uxah_dis(USART_TypeDef* USARTx, struct uartData *uartxData, struct uartData *uartxMain)
{
usart_printf(USARTx, "\r\nplease enter your choice: ");
return sFALSE;
}
// uart_func func是调用的显示函数,便于重复打印提示信息
// char *byte用来存储最终的有效字符
// int num是可用的字符数量,如果变参为‘A’、‘B’、‘C’、‘D,则num=4
int UART_wait_char(USART_TypeDef* USARTx, struct uartData *uartxData,
struct uartData *uartxMain, uart_func func, char *byte, int num, ...)
{
char *p = (char *)&num + sizeof(int);
uint32_t i = 0;
START:
func(USARTx, uartxData, uartxMain);
for (i = 0; i < num; i++) {
usart_send_byte(USARTx, *((char *)(p + i * sizeof(int))));
if (i != num - 1)
usart_printf(USARTx, "/");
}
usart_printf(USARTx, " ");
uartxData->recIrq = sFALSE;
while (1) {
if (uartxData->recIrq >= sTRUE) {
uartxMain->recTempH = uartxData->recTempH;
uartxData->recIrq = sFALSE;
usart_send_byte(USARTx, uartxMain->recTempH);
for (i = 0; i < num; i++) {
if (uartxMain->recTempH == *((char *)(p + i * sizeof(int)))) {
*byte = uartxMain->recTempH;
return sTRUE;
}
}
goto START;
}
}
return sFALSE;
}
当执行:
UART_wait_char(USART1, uart1Data, uart1Main, uxah_dis, &temp, 4, 'A', 'B', 'C', 'D');
时,会打印:
please enter your choice: A/B/C/D w
please enter your choice: A/B/C/D q
please enter your choice: A/B/C/D A
如果接收到'A', 'B', 'C', 'D'其中一个,则继续执行后面的程序,否则重复打印上面的内容。
当执行:
UART_wait_char(USART1, uart1Data, uart1Main, uxah_dis, &temp, 2, 'Y', 'N');
时,会打印
please enter your choice: Y/N Q
please enter your choice: Y/N N
如果接收到'Y', 'N'其中一个,则继续执行后面的程序,否则重复打印上面的内容。
变参函数,在形参的数量和内容不确定的情况下,能够简化分支判断语句,使代码干净整洁