打印
[技术问答]

利用定时中断接收不定长度的串口数据

[复制链接]
1835|2
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
earlmax|  楼主 | 2024-7-25 14:42 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
timer.h进行定时器初始化函数的声明。

#define _TIMER_H
void TIM7_Int_Init(u16 arr,u16 psc);

timer.c进行定时器的定义及中断函数说明,其中中断函数内容的意思大致就是,当定时器溢出(计时到了),强制标记接收完成,然后清除中断标志位,禁用定时器,等待用户处理串口接收buffer。

#include "led.h"

//定时器7中断服务程序            
{
{          
TIM_ClearITPendingBit(TIM7, TIM_IT_Update  );  //清除TIM7更新中断标志   
}            
//通用定时器中断初始化
//arr:自动重装值。
void TIM7_Int_Init(u16 arr,u16 psc)
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);//TIM7时钟使能   

TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseInit(TIM7, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位

TIM_Cmd(TIM7,ENABLE);//使能定时器7

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0 ;//抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;        //IRQ通道使能
}

#ifndef __USART3_H
#include "sys.h"  
#define USART3_MAX_RECV_LEN        400        //最大接收缓存字节数
extern u8  USART3_RX_BUF[USART3_MAX_RECV_LEN]; //接收缓冲,最大USART3_MAX_RECV_LEN字节
extern u16 USART3_RX_STA;           //接收数据状态

void u3_printf(char* fmt, ...);
#endif

其中__align关键字用于内存对齐,具体可以参考原子的解释:
#include "delay.h"
#include "stdarg.h"
#include "string.h"
//串口发送缓存区
//串口接收缓存区
//通过判断接收连续2个字符之间的时间差不大于100ms来决定是不是一次连续的数据.
//任何数据,则表示此次接收完毕.
//[15]:0,没有接收到数据;1,接收到了一批数据.
u16 USART3_RX_STA=0;
{
    if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)//接收到数据
        res =USART_ReceiveData(USART3);
        {
            if(USART3_RX_STA<usart3_max_recv_len) 还可以接收数据
            {
                if(USART3_RX_STA==0)
                USART3_RX_BUF[USART3_RX_STA++]=res;        //记录接收到的值
            {
            }
    }
//初始化IO 串口3
void usart3_init(u32 bound)
    NVIC_InitTypeDef NVIC_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); //使能GPIOB时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_10; //GPIOB11和GPIOB10初始化
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //速度50MHz
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
    GPIO_PinAFConfig(GPIOB,GPIO_PinSource11,GPIO_AF_USART3); //GPIOB11复用为USART3
    USART_InitStructure.USART_BaudRate = bound;//波特率一般设置为9600;
    USART_InitStructure.USART_StopBits = USART_StopBits_2;//一个停止位
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
    USART_Init(USART3, &USART_InitStructure); //初始化串口3

    USART_Cmd(USART3, ENABLE);                    //使能串口


    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2 ;//抢占优先级2
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;        //IRQ通道使能
    TIM7_Int_Init(100-1,8400-1);        //10ms中断一次

    USART3_RX_STA=0;        //清零
//串口3,printf 函数
void u3_printf(char* fmt,...)
    u16 i,j;
    va_start(ap,fmt);
    va_end(ap);
        while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET);  //等待上次传输完成
    }

void u3_putchar(u8 data)
    while(USART_GetFlagStatus(USART3,USART_FLAG_TC)==RESET);  //等待上次传输完成
}

                TIM_SetCounter(TIM7,0);//计数器清空
                    TIM_Cmd(TIM7, ENABLE);  //使能定时器7
            }

这种方法就不需要以rn作为字符串的结束符了。

使用特权

评论回复
沙发
班杰明| | 2024-8-12 23:55 | 只看该作者
接收不定长数据比较方便

使用特权

评论回复
板凳
micoccd| | 2024-8-14 15:18 | 只看该作者
直接用空闲中断不行吗

使用特权

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

本版积分规则

43

主题

1471

帖子

1

粉丝