关于STM32空闲中断

有一次做一个东西,为了尽量不占用CPU的处理数据时间,所以就使用DMA接收串口的数据,但是呢问题来了.,,,,,怎么样才能确定接收到了一条完整的数据了,,我们都知道只要打开DMA

那家伙就不停的把接收的数据放到我们指定的地方.

只要接收到一条完整的数据我就该去处理了

关于空闲中断,,,就是说每接收到一条完整的数据就会置位空闲标志位,我们只需要判断空闲标志位是否置一,,就能知道是不是接收到了一条完整的数据

用空闲中断的好处就是,,对于以前我写程序通信都会在数据的后面加上尾,,然后另一个接收的单片机通过判断数据的尾来确定是不是一条完整的数据,,,有了空闲中断就不需要在给数据加上尾了,,,,,

直接程序吧

u8  Usart1_RX_Cop[1024]={0};   //串口2备用接收缓冲,最大 1024 个字节.
u8  Usart1_RX_BUF[1024]={0};   //串口1接收缓冲,最大 1024 个字节.
u16 Usart1_REC_Cnt = 0;        //串口1接收的数据个数
u16 Usart1_Current_Cnt = 0;    //串口1当前接收的数据个数
u16 Usart1_Current_cnt = 0;    //串口1当前接收的数据个数
u8  Usart1_AT_flage = 0;       //串口1接收完成标志位

u8  Usart2_RX_Cop[1024]={0};   //串口2备用接收缓冲,最大 1024 个字节.
u8  Usart2_RX_BUF[1024]={0};   //串口2接收缓冲,最大 1024 个字节.
u16 Usart2_REC_Cnt = 0;        //串口2接收的数据个数
u16 Usart2_Current_Cnt = 0;    //串口2当前接收的数据个数
u16 Usart2_Current_cnt = 0;    //串口2当前接收的数据个数
u8  Usart2_AT_flage = 0;       //串口2接收完成标志位

u8  Usart3_RX_BUF[1024]={0};   //串口3接收缓冲,最大 1024 个字节.
u16 Usart3_REC_Cnt = 0;        //串口3接收的数据个数
u8  Usart3_AT_flage = 0;       //串口3接收完成标志位

u8 Free_Read_Rst = 0;//读DR清除空闲中断
void USART123_Init(uint32_t bound_1,uint32_t bound_2,uint32_t bound_3)
{
    USART_InitTypeDef USART_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2|RCC_APB1Periph_USART3, ENABLE);//使能USART2,USART3时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_USART1|RCC_APB2Periph_AFIO , ENABLE);

    //USART1_TX  PA9
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;;
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
   //USART1_RX  PA10
   GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IN_FLOATING ;
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
   GPIO_Init(GPIOA, &GPIO_InitStructure);

    //USART2_TX   GPIOA.2
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //复用推挽输出
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  //USART2_RX      GPIOA.3初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);

    //USART3_TX   GPIOB.10
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;    //复用推挽输出
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  //USART3_RX      GPIOB.11初始化
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;//PB11
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
  GPIO_Init(GPIOB, &GPIO_InitStructure); 

  USART_InitStructure.USART_BaudRate = bound_1;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No ;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  USART_Init(USART1, &USART_InitStructure);

  USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //开启串口接受中断
  USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); //开启串口接受中断
  USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); //开启串口接受中断
  USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); //开启串口1总线空闲中断
  USART_ITConfig(USART2, USART_IT_IDLE, ENABLE); //开启串口2总线空闲中断

  USART_InitStructure.USART_BaudRate = bound_2;
  USART_Init(USART2, &USART_InitStructure);

  USART_InitStructure.USART_BaudRate = bound_3;
  USART_Init(USART3, &USART_InitStructure);

  USART_Cmd(USART1, ENABLE);
  USART_Cmd(USART2, ENABLE);
  USART_Cmd(USART3, ENABLE);
}
/********************串口 1 中断服务程序**********************/
void USART1_IRQHandler(void)
{
  if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //正常情况下进入这个接收
    {
        USART_ClearITPendingBit(USART1, USART_FLAG_ORE);
        USART_ClearITPendingBit(USART1,USART_IT_ORE);    //清除中断标志
        Usart1_RX_BUF[Usart1_REC_Cnt] =USART_ReceiveData(USART1);    //读取接收到的数据
        Usart1_REC_Cnt++;
  }
  else if(USART_GetITStatus(USART1,USART_IT_IDLE) == SET)//传输完一条完整的数据就会进入这个
    {
        Free_Read_Rst = USART1->DR; //清USART_IT_IDLE标志
        Usart1_AT_flage = 1;//接收到一条完整的数据
        Usart1_Current_Cnt = Usart1_REC_Cnt;//复制接收到的数据个数
        Usart1_REC_Cnt = 0;//清零接收的个数
   }
}

主函数循环里只需要......

其实昨天才发现这家伙真的太准确了,,准确到如果碰见通信中速率如果受到干扰变得不稳定,那么这家伙也会进空闲中断.......

所以嘛,,,,,自己写个别这么苛刻的,昨天写好了,不过呢今天主要是把自己遇到的问题说一下

其实思路都知道

串口接收的时候打开一个定时器,并且只要接收到数据就清零一个变量,这个变量是在定时器里面执行自加一操作,,

如果串口一段时间不接收数据了这个变量就能自加到我们设置的数,然后关掉定时器,置位接收完成标志位,...

直接上程序

/********************串口 1 中断服务程序**********************/
void USART1_IRQHandler(void)
{
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
        USART_ClearITPendingBit(USART1, USART_FLAG_ORE);
        USART_ClearITPendingBit(USART1,USART_IT_ORE);    //清除中断标志
        Usart1_RX_BUF[Usart1_REC_Cnt] =USART_ReceiveData(USART1);    //读取接收到的数据
        Usart1_REC_Cnt++;
        TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE );//打开定时器开始计时
        Time2_cnt = 0;//清零计数
  }}
void timer_config(void)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    /* Resets the TIM2 */
    TIM_DeInit(TIM2);
    //设置了时钟分割。
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    // 选择了计数器模式。
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    //初值
    TIM_TimeBaseStructure.TIM_Period = 10;//定时时间1ms进一次
    //设置了用来作为 TIMx 时钟频率除数的预分频值。72M / 7099+1 = 0.01M
    TIM_TimeBaseStructure.TIM_Prescaler = 7199;

    //TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    /* Enables the TIM2 counter */
    TIM_Cmd(TIM2, ENABLE);

    /* Enables the TIM2 Capture Compare channel 1 Interrupt source */
  TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE );
}
void TIM2_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
    {
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
        if(Time2_cnt<100)//防止累加循环过去
        {
          Time2_cnt ++ ;
        }
        if(Time2_cnt>3)//空闲时间大于约3毫秒
        {
            TIM_ITConfig(TIM2, TIM_IT_Update, DISABLE );//关闭定时器---注意千万不要放到主函数里面关,,,,大家可以试一试会出现什么问题.....
            Usart1_AT_flage = 1;//接收完成标志位置一
            Usart1_Current_Cnt = Usart1_REC_Cnt;//赋值接收的数据个数
            Usart1_REC_Cnt = 0;//清零接收的数据个数
       }}

源码,,这个是用的板子的空闲中断,,,,板子的其余文件删掉便可,,,,

链接:http://pan.baidu.com/s/1c228q6c 密码:pl3k

时间: 2024-10-12 21:11:22

关于STM32空闲中断的相关文章

STM32串口之空闲中断

NBiot模块一般都是串口接口,使用AT指令集,对接中国移动onenet平台.先用串口助手去测试,流程测试OK之后需要在MCU上重新写一遍. STM32串口 IDLE中断 IDLE其实是空闲的意思.IDLE中断叫空闲中断,不叫帧中断.那么什么叫空闲,怎么定义空闲呢?在实际发送数据的时候,比如一串字符串,我们会采用如下方式发送 void uart1_putc(char dat) { SBUF = dat; while (!TI); TI = 0; } void uart1_puts_n(char

关于STM32串口空闲中断的问题

1.空闲中断是接受数据后出现一个byte的高电平(空闲)状态,就会触发空闲中断.并不是空闲就会一直中断 2.关于第二点有要铺垫的三个情况,datasheet中 "当一空闲帧被检测到时,其处理步骤和接收到普通数据帧一样,但如果IDLEIE位被设置将产生一个中断" "空闲符号被视为完全由'1'组成的一个完整的数据帧,后面跟着包含了数据的下一帧的开始位'1'的位数也包括了停止位的位数” 空闲符号的配图后面跟这一个低电平.有人理解为只有收到下一个数据的起始位才会触发中断,这样理解是不

STM32的串口空闲中断及接受数据

源程序: IO口定义: void GPIO_ConfiguraTIon(void) { GPIO_InitTypeDef GPIO_InitStructure; /* 第1步:打开GPIO和USART部件的时钟 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); /* 第2步:将US

stm32 NVIC中断管理实现[直接操作寄存器]

本文转自:http://www.ichanging.org/stm32_NVIC.html cortex-m3支持256个中端,其中包含了16个内核中断,240个外部中断.stm32只有84个中断,包括16个内核中断和68个可屏蔽中断.stm32f103上只有60个中断,f107上才有68个中断. 中断是stm32很基础的一个功能,学会使用中断,才可以更好的使用其他的外设.理解stm32的中断,必须要先从stm32的中断优先级分组是怎么回事.要理解优先级分组,就要先理解什么是先占优先级,和次占优

STM32之中断与事件---中断与事件的区别

STM32之中断与事件---中断与事件的区别  http://blog.csdn.net/flydream0/article/details/8208463 这张图是一条外部中断线或外部事件线的示意图,图中信号线上划有一条斜线,旁边标志19字样的注释,表示这样的线路共有19套.图中的蓝色虚线箭头,标出了外部中断信号的传输路径,首先外部信号从编号1的芯片管脚进入,经过编号2的边沿检测电路,通过编号3的或门进入中断挂起请求寄存器,最后经过编号4的与门输出到NVIC中断检测电路,这个边沿检测电路受上升

利用串口空闲中断接收数据

1 void USART2_IRQHandler(void) 2 { 3 // 使能串口空闲中断 4 USART_ITConfig(USART2, USART_IT_IDLE , ENABLE); 5 6 if(USART_GetITStatus(USART2,USART_IT_RXNE)==SET) 7 { 8 9 rx_buf[cnt]=USART_ReceiveData(USART2); 10 rx_rxbuf[cnt] = rx_buf[cnt] ;//把接收到的数组存到备用的数组当中,

STM32串口中断的一些资料

在研究STM32串口接收发送中断的时候找到不少不错的资料,现在备份在这里.以供自己查阅,以及方便其他人. TC ====TXE 顺便预告下最近会写个有关串口处理数据的帖子,从查询和中断方面以及数据处理的方式,从队列以及FIFO方面写起. SECTION 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 /* 调试STM32串口过程中发现一个奇怪的问题,

STM32之中断

1.NVIC Nested vectored interrupt controller :可嵌套向量中断控制器 (NVIC) NVIC 特性 82个可屏蔽中断 ##不包括内核的16个中断 16个可编程优先级 ##适用于全部中断 低延迟异常和中断处理 电源管理控制 系统控制寄存器的实现 NVIC与处理器内核接口紧密耦合, 实现了高效快速的中断响应.所有的中断,包括内核异常都被 NVIC 所管理. 2.中断向量表 其实中断向量表在**STM32F4XX**启动文件里面就可以看出来,详情可看 :[ST

Stm32的中断在测试FREERTOS的时候的问题

在测试FreeRTOS在stm32上运行的时候,需要用到timer的中断,则打开了中断,但是如下的代码则让系统死机: /* 选择优先级分组0 */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); /* 开启 TIM2 中断, 0级先占优先级,0级后占优先级 */ NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPr