打印
[应用相关]

USART通过定时器中断方式接收不定长数据

[复制链接]
801|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
硬件准备

首先需要准备一个开发板,这里我准备的是NUCLEO-F030R8的开发板:

选择芯片型号

使用STM32CUBEMX选择芯片stm32f030r8,如下所示:


使用特权

评论回复
沙发
guanjiaer|  楼主 | 2021-8-3 12:44 | 只看该作者
配置时钟源

HSE与LSE分别为外部高速时钟和低速时钟,在本文中使用内置的时钟源,故都选择Disable选项,如下所示:

配置时钟树

STM32F0的最高主频到48M,所以配置48即可:


使用特权

评论回复
板凳
guanjiaer|  楼主 | 2021-8-3 12:44 | 只看该作者
串口配置

本次实验使用的串口1进行串口通信,波特率配置为115200。

中断


使用特权

评论回复
地板
guanjiaer|  楼主 | 2021-8-3 12:45 | 只看该作者
GPIO配置

板子上led为PA5端口,故设置PA5闪烁来验证是否正确。


定时器配置

本次实验使用的是TIM3来进行计数。

PWM频率计算如下所示

在上面配置TIM3参数,预分频系数设置为480-1, 自动重载值设置为10000-1,那么PWM频率为48,000,000/((480-1+1)*(10000-1+1))=10Hz,即 100ms一个周期。



使用特权

评论回复
5
guanjiaer|  楼主 | 2021-8-3 12:46 | 只看该作者
生成工程设置

注意在生成工程设置中不能出现中文,不然会报错。

代码生成设置

最后设置生成独立的初始化文件:

生成代码

配置keil


使用特权

评论回复
6
guanjiaer|  楼主 | 2021-8-3 12:49 | 只看该作者
代码
在main.c中,先加入头文件。

/* USER CODE BEGIN Includes */
#include "stdio.h"//printf头文件
#include "string.h"//memset头文件
/* USER CODE END Includes */



定义变量存储。

/* USER CODE BEGIN PV */
uint8_t RxBuff[1];      //进入中断接收数据的数组
uint8_t DataBuff[5000]; //保存接收到的数据的数组
int RxLine=0;           //接收到的数据长度
int Rx_flag=0;                                        //接受到数据标志
/* USER CODE END PV */



定义printf的重定向函数fputc。

/* USER CODE BEGIN 0 */
void printf_usart(void);//输出内容
int fputc(int ch, FILE* file)//定义printf的重定向函数fputc,满足串口调试打印
{
    return HAL_UART_Transmit(&huart1, (uint8_t*)&ch, 1, 100);
}
/* USER CODE END 0 */



打开串口和定时器。

  /* USER CODE BEGIN 2 */
        HAL_UART_Receive_IT(&huart1, (uint8_t *)RxBuff, 1); //打开串口中断接收
        HAL_TIM_Base_Start_IT(&htim3);//开启定时器
  /* USER CODE END 2 */



串口接受代码,当接受到最后数据为FF时候,直接打印,否则等待100ms打印。

/* USER CODE BEGIN 4 */
void printf_usart(void)
{
        printf("数据长度=%d\r\n",RxLine);
        for(int i=0;i<RxLine;i++)
                printf("数据:[%d] = 0x%x\r\n",i,DataBuff);                           
        memset(DataBuff,0,sizeof(DataBuff));  //清空缓存数组
        //memset()作用:可以方便的清空一个结构类型的变量或数组。
        //例句:memset(aTxbuffer,0,sizeof(aTxbuffer))  用memset清空aTxbuffer。
        RxLine=0;  //清空接收长度
}


void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == htim3.Instance)
    {
                        HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);
        /* Toggle LED */
                        if(Rx_flag==1)
                        {
                                printf_usart();
                                Rx_flag=0;
                        }
                }       
}



// 捕获中断回调函数,每次捕获到信号就会进入这个回调函数
void HAL_UART_RxCpltCallback(UART_HandleTypeDef*UartHandle)
{
    RxLine++;                      //每接收到一个数据,进入回调数据长度加1
    DataBuff[RxLine-1]=RxBuff[0];  //把每次接收到的数据保存到缓存数组
                Rx_flag=1;
    if(RxBuff[0]==0xff)            //接收结束标志位,这个数据可以自定义,根据实际需求,这里只做示例使用,不一定是0xff
    {
                        printf_usart();
    }   
    RxBuff[0]=0;
    HAL_UART_Receive_IT(&huart1, (uint8_t *)RxBuff, 1); //每接收一个数据,就打开一次串口中断接收,否则只会接收一个数据就停止接收
                __HAL_TIM_SET_COUNTER(&htim3, 1); // 计数清零,从头开始计
}
/* USER CODE END 4 */

演示效果

可以看到 发送11 12 13需要等待100ms左右才能发送,如果最后加上ff直接发送。



使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

77

主题

4116

帖子

2

粉丝