stm串口函数在某些条件下想要让其串口打印,但是在某些时候不想让其进行串口打印
本例程就是提供了一个这样的例程:
1.对串口进行初始化配置
void uart_initwBaudRate(void)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
UART_InitTypeDef UART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART2, ENABLE); //使能UART2,GPIOA时钟
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);
//UART2 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = UART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority=3 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
//UART 初始化设置
GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_1);
GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_1);
UART_InitStructure.UART_BaudRate = BaudRate;//串口波特率
UART_InitStructure.UART_WordLength = UART_WordLength_8b;//字长为8位数据格式
UART_InitStructure.UART_StopBits = UART_StopBits_1;//一个停止位
UART_InitStructure.UART_Parity = UART_Parity_No;//无奇偶校验位
UART_InitStructure.UART_HardwareFlowControl = UART_HardwareFlowControl_None;//无硬件数据流控制
UART_InitStructure.UART_Mode = UART_Mode_Rx | UART_Mode_Tx; //收发模式
UART_Init(UART2, &UART_InitStructure); //初始化串口1
//UART2->BRR = 9;
UART_ITConfig(UART2, UART_IT_RXIEN, ENABLE);//开启串口接受中断
UART_ITConfig(UART2, UART_IT_TXIEN, DISABLE);
UART_Cmd(UART2, ENABLE); //使能串口1
//UART2_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
//UART2_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
//printf("uart ok");
GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_3);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_3);
//RTS
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
GPIO_Init(GPIOB, &GPIO_InitStructure);
//CTS
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits(GPIOB, GPIO_Pin_7);
}
2.串口中断函数:
void UART2_IRQHandler(void) //串口1中断服务程序
{
if(UART_GetITStatus(UART2, UART_IT_RXIEN) != RESET) //接收中断
{
UART_ClearITPendingBit(UART2,UART_IT_RXIEN);
rxBuf[RxCont]=UART_ReceiveData(UART2);//串口2接受数据放在rxbuf
RxTimeout = SysTick_Count + 1000;
RxCont++;//接受数据的数量+1
if(RxCont >= MAX_SIZE)//判断是否到达最大数量
{
RxCont = 0;//如果满了清0
}
}
if(UART_GetITStatus(UART2, UART_IT_TXIEN) != RESET)
{
UART_ClearITPendingBit(UART2,UART_IT_TXIEN);
//
TxTimeout = SysTick_Count + (20000/BaudRate);
if (PosW < txLen)
{
UART_SendData(UART2,txBuf[PosW++]);
if (PosW == txLen)
{
txLen = 0;
PosW = 0;
}
}
else
{
UART_ITConfig(UART2, UART_IT_TXIEN, DISABLE);
}
}
}
3.串口发送函数:
void Usart2SendByte(char *data,u8 len)//发送一个字节 硬件连接选用的为USART2
{
u8 t=0;
for(t=0;t<len;t++)
{
RX_DATA_BUFF[t]=data[t];
while((UART2->CSR&0x1)==0);//循环发送,直到发送完毕 while((UART1->SR&0X40)==0);//等待发送结束
UART2->TDR=RX_DATA_BUFF[t];
}
UART_RX_STA=0;
}
由函数3来进项串口数据的打印也是可以的,但是不能让其在某些时候不打印,本例程想要的结果就是让其在某些条件之下进行选择性的打印
4.一下是本次主要讲解的函数:
void printf_uart(char *fmt,...)
{
long length = 0;
va_list ap;
char *pt;
int index = 0;
va_start(ap,fmt);
vsprintf((char *)gPrintString,(const char *)fmt,ap);
pt = &gPrintString[0];
while(*pt!='\0')
{
length++;
pt++;
}
while(1)
{
Usart2SendByte(((char *)&gPrintString[index]), 1);
index ++;
if(index == length)
break;
}
//FuartSend((u8*)&gPrintString[0],length);
va_end(ap);
}
/*在上面的函数中
va_list(va_list是在C语言中解决变参问题的一组宏)
va_list表示可变参数列表类型,实际上就是一个char指针fmt
然后是va_start:va_start用于获取函数参数列表中可变的头指针
(获取函数可变参数列表)
1.输出参数为ap,类型为va_list:
用于保存函数参数列表中可变参数的头指针(
即可变参数列表)
2.输入参数fmt,ap指向fmt后面的参数,
为第一个参数的前一个参数,是一个固定参数
vsprintf((char *)gPrintString, fmt, ap):
送格式化输出到串中 ,函数说明:
vsprintf()会根据参数fmt 字符串来转换并格式化数据,
然后将结果复制到参数char(*)gPrintString 的字符串数组,
直到出现字符串结束('\0')为止.
va_end():va_end用于结束对可变参数的处理。
对于这段代码的理解:
printf函数首先定义了一个char指针fmt,
然后后面紧跟的是printf的变参,那么变参转换就开始了,
下一个函数va_start定义了一个指向变参的首指针args,
紧接着利用vsprintf函数,按照fmt格式以及通过args指针,
将变参一个个按照规定好的格式转换数据,
结果复制到char(*)gPrintString这个数组中,
最后结束可变参数处理。
这里我对于fmt这个指针的理解是,定义了一个指针类型,
转换结果就是按照这个指针的类型转换的,
这里转换的结果就是将变参转换成char字符型
就是字符串转换到一个数组中
*/
上面的函数在进行串口打印时候每次打印一个字符的,转化一个就打印一个
5.下面的函数为串口选择性打印函数
#define DisplayATCMD(_x) if (!GetConnectedStatus()) do { printf_uart _x; } while(0)
上面的函数的选择性打印为当GetConnectedStatus()==0的时候,才会进行do while(0)循环,但是为0,所以就会执行一次do后面的语句,因此可以实现选择性的打印,打印函数为 DisplayATCMD("123456789")
本人也是小白,希望有错误的地方大家给指出来,及时修正共同进步