最近在研究这块板子,发现官方例程里面的usart十分不好用,自己将程序修改为f1系列常用的形式供大家交流,有错误的地方还望提出!
1.rcc时钟配置请见http://bbs.eeworld.com.cn/thread-447853-1-1.html
2.usart设置,由于板载VCP,而且已经和usart2的RX、TX连接好,即PA2、PA3,那就不必使用usart1了(还有外接一个usb转串口模块)
主要设置异步方式、波特率、数据长度等常见参数,步骤如图所示,其他部分默认就好
2.gpio配置和usart2中断配置
>
3.printf函数重映射
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{
while((USART2->ISR&0X40)==0);//循环发送,直到发送完毕
USART2->TDR = (uint8_t) ch;
return ch;
}
#endif
由于使用printf函数请将stdio.h包含进来
4.使能接收中断
在初始化usart2函数中加入 __HAL_UART_ENABLE_IT(&huart2,UART_IT_RXNE);使能接收中断
5.中断服务函数书写(参考原子例程修改,详细内容请参考《STM32不完全手册-库函数版本_V3.0》)
void USART2_IRQHandler(void) //串口1中断服务程序
{
uint8_t Res;
HAL_UART_IRQHandler(&huart2);
if(__HAL_UART_GET_IT(&huart2, UART_IT_RXNE) != RESET)//
{
USART2->RQR |= 0x08;//?? RXNE
Res =USART2->RDR;//USARTx_RX_Data(&UartHandle);
if((USART_RX_STA&0x8000)==0)//
{
if(USART_RX_STA&0x4000)//
{
if(Res!=0x0a)USART_RX_STA=0;//
else USART_RX_STA|=0x8000; //
}
else //?????0X0D
{
if(Res==0x0d)USART_RX_STA|=0x4000;
else
{
USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
USART_RX_STA++;
if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//
}
}
}
}
HAL_NVIC_ClearPendingIRQ(USART2_IRQn);
}
由于我的中断函数直接写在了usart.c文件中,需要将stm32l0xx_it.c文件中的同名函数注释掉。
定义了一些变量详细内容请参考附件
6.主函数的任务
判断用户是否从串口输入内容,如果输入就将输入的内容再次从串口发送出去,否则一直发送默认内容
if(USART_RX_STA&0x8000)
{
len=USART_RX_STA&0x3f;//得到此次接收到的数据长度
printf("\r\n您发送的消息为:\r\n\r\n");
for(t=0;t<len;t++)
{
//printf("",USART_RX_BUF[t]);
USART2->TDR = (uint8_t)USART_RX_BUF[t];//向串口2发送数据
while((USART2->ISR&0X40)==0);//等待发送结束
}
printf("\r\n\r\n");//插入换行
USART_RX_STA=0;
}
else
{
times++;
if(times%1000==0)
{
printf("\r\nSTM32L053 Nucleo开发板串口实验\r\n");
}
if(times%200==0)printf("请输入数据,以回车键结束\n");
HAL_Delay(2);