
《《《《《正文》》》》》
《前言》
基于UART的串口在实际项目中的应用相当广泛,包括wifi、can、lin等均可使用uart进行通信,方便且成本低;而uart串口功能不仅仅体现在产品使用功能上,在开发调试阶段更是一个必不可少的调试助手。今天就来构建一个基于uart的调试串口功能模块;
开发需求:使用stm32f103的usart模块开发一个具有发送任意字符串的调试串口功能的模块;
相关代码获取地址:
https://pan.baidu.com/s/1zyrOF18WxIq0H3_4qU7Evg
关注公众号,发送1234,获取提取码;
《硬件设计》
| TX | PA9 |
| RX | PA10 |

《加载USART库文件》



《软件设计》
第一步:中断等级配置函数
void NvicConfig(void){ NVIC_InitTypeDef NVIC_InitStruct; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); NVIC_InitStruct.NVIC_IRQChannel=USART1_IRQn; //USART中断通道 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2; //设置抢占优先级为0 NVIC_InitStruct.NVIC_IRQChannelSubPriority=1; //设置子优先级为1 NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE; //使能外USART中断通道 NVIC_Init(&NVIC_InitStruct); //中断优先级初始化函数}
第二步:串口初始化函数
//传入参数为波特率void USART_init(uint32_t baudrate){ GPIO_InitTypeDef GPIO_InitStruct; //定义GPIO结构体变量 USART_InitTypeDef USART_InitStruct; //定义串口结构体变量 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE); //使能GPIOA、USART1的时钟 GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9; //配置TX引脚 GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP; //配置PA9为复用推挽输出 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; //配置PA9速率 GPIO_Init(GPIOA,&GPIO_InitStruct); //GPIO初始化函数 GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10; //配置RX引脚 GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING; //配置PA10为浮空输入 GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz; //配置PA10速率 GPIO_Init(GPIOA,&GPIO_InitStruct); //GPIO初始化函数 USART_InitStruct.USART_Mode=USART_Mode_Tx|USART_Mode_Rx; //发送接收模式 USART_InitStruct.USART_Parity=USART_Parity_No; //无奇偶校验 USART_InitStruct.USART_BaudRate=baudrate; //波特率 USART_InitStruct.USART_StopBits=USART_StopBits_1; //停止位1位 USART_InitStruct.USART_WordLength=USART_WordLength_8b; //字长8位 USART_InitStruct.USART_HardwareFlowControl=USART_HardwareFlowControl_None; //无硬件数据流控制 USART_Init(USART1,&USART_InitStruct); //串口初始化函数 USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //串口接收中断 USART_ITConfig(USART1,USART_IT_IDLE,ENABLE); //串口空闲中断 USART_Cmd(USART1,ENABLE); //使能USART1}
第三步:中断处理函数
void USART1_IRQHandler(void){ uint8_t clear = clear; //定义这个变量是针对编译出现“没有用到这个变量”的警告提示 uint8_t res; if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断 { res = USART1->DR; //在此做数据接收处理 } else if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) //空闲中断 { clear = USART1->SR; //读SR寄存器 clear = USART1->DR; //读DR寄存器(先读SR,再度DR,就是为了清除IDIE中断) } USART_ClearITPendingBit(USART1,USART_IT_RXNE);}
第四步:写发送数据函数
void usart_send(uint8_t *data,uint8_t len){ uint8_t i; for(i=0;i<len;i++) { USART_SendData(USART1,*(data+i)); while(USART_GetFlagStatus(USART1,USART_FLAG_TC) == RESET); }}
第五步:来个简单的测试,主函数:
int main(void){ uint8_t usartSendbuf[5] = {1,2,3,4,5}; NvicConfig(); USART_init(115200); for(;;) { usart_send(usartSendbuf,5); }}
结果:

《printf函数重定向》
重定向函数:
int fputc(int ch,FILE *f) //printf重定向函数{ USART_SendData(USART1,(uint8_t)ch); //发送一字节数据 while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET); //等待发送完成 return ch;}
我们这里直接写是不行,因为这是C库自带的东西,但是可以重定向到这个函数(printf()在c标准库函数实质是一个宏,实际是调用fputc()函数),fputc()函数默认是把字符输出到调试器控制窗口,所以要想把数据通过USART输出到串口助手,需对基于fputc()的printf()系列函数的输出重定向到USART端口上去。
这里特别注意:打开“Options for target...”->“target”勾选“Use MiclroLIB” 不然用printf会有问题;

最后上测试函数:
int main(void){ NvicConfig(); USART_init(115200); for(;;) { printf("System Init Finish\n"); printf("我正在测试\n"); }}
结果:

《《《《《END》》》》》

转载:https://blog.csdn.net/qq_22520215/article/details/115802140
查看评论