STM32
直播中

王鹏

7年用户 1270经验值
私信 关注
[问答]

RXNE中断和IDLE中断的区别是什么?

RXNE中断和IDLE中断的区别是什么?

回帖(1)

陈平

2021-12-14 11:39:09
(RXNE中断和IDLE中断的区别?
当接收到1个字节,就会产生RXNE中断,当接收到一帧数据,就会产生IDLE中断。比如给单片机一次性发送了8个字节,就会产生8次RXNE中断,1次IDLE中断。于是我决定在产生RXNE中断时将接收到的一个字节的数据用数组保存起来。在产生IDLE中断的时候,改变ReceivedFlag(自己定义的一个检测帧数据接收完成状态的标志)的状态。
main.c
main.c:
#include "stm32f10x.h"
#include "stdio.h"
extern void delay_ms(u16 time);
void USART_Config(void);
void NVIC_Configuration(void);
int fputc(int ch, FILE *f);
void Usart_SendByte();
uint16_t  i;

uint8_t u2_Temp;
extern uint8_t u3Temp;
extern uint16_t uart_p;
int RxFlag;
extern uint8_t ReceivedFlag,tempU3,uart3_RXbuff[];


/*
* UART2: TX: PA2          RX:PA3       
* UART3:TX:PB10        RX:PB11        TXRXEN:PD3
* UART5:TX:PC12        RX:PD1         TXRXEN:PD0
*
*/
int main()
{
    SystemInit();//72m
   
                NVIC_Configuration();
    USART_Config();
//        printf("重定向成功n");
        for(i=0;i<=0xff;i++)
        {
                Usart_SendByte( USART2,i);
//                printf("%d",i);
        }       
    while(1)
                {
                        if(ReceivedFlag == 1)//帧数据显示。收到一帧数据时,显示接收中断数组保存的一帧数据
                        {                               
                                for(uart_p= 1; uart_p <= u3Temp; uart_p++)
                                {
                                        Usart_SendByte(USART2,uart3_RXbuff[uart_p]);
                                }
                                ReceivedFlag = 0;
                                uart_p = 1;
                        }                       
                       
                }
}




static void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* 嵌套向量中断控制器组选择 */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  
  /* 配置USART为中断源 */
  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
  /* 抢断优先级*/
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  /* 子优先级 */
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  /* 使能中断 */
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  /* 初始化配置NVIC */
  NVIC_Init(&NVIC_InitStructure);
}


void USART_Config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;

        // 打开串口GPIO的时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
       
        // 打开串口外设的时钟
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

        // 将USART Tx的GPIO配置为推挽复用模式
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);

  // 将USART Rx的GPIO配置为浮空输入模式
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
       
        // 配置串口的工作参数
        // 配置波特率
        USART_InitStructure.USART_BaudRate = 115200;
        // 配置 针数据字长
        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(USART2, &USART_InitStructure);
       
        // 串口中断优先级配置
        NVIC_Configuration();
        // 使能串口空闲中断(用于检测一帧数据接收完毕)
        USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);
       
        // 使能串口接收中断       
        USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);       
       
        // 使能串口
        USART_Cmd(USART2, ENABLE);               

  // 清除发送完成标志
        //USART_ClearFlag(USART1, USART_FLAG_TC);     
}

/*****************  发送一个字符 **********************/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
        /* 发送一个字节数据到USART */
        USART_SendData(pUSARTx,ch);
               
        /* 等待发送数据寄存器为空 */
        while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);       
}


//重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)//定义此函数需要添加stdio.h文件
{
                /* 发送一个字节数据到串口 */
                USART_SendData(USART2, (uint8_t) ch);
               
                /* 等待发送完毕 */
                while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);               
       
                return (ch);
}

///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
int fgetc(FILE *f)
{
                /* 等待串口输入数据 */
                while (USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == RESET);

                return (int)USART_ReceiveData(USART2);
}

stm32f10x_it.c:
#define UART_BUFF_SIZE      1024
uint16_t uart_p = 1;
uint8_t     uart3_RXbuff[UART_BUFF_SIZE];
uint8_t u3Temp;
uint8_t tempU3;
uint8_t ReceivedFlag = 1;
uint16_t clr;
void USART2_IRQHandler(void)
{
        if(USART_GetITStatus(USART2,USART_IT_RXNE)!=RESET)//收到一个字节数据
        {                               
                uart3_RXbuff[uart_p] = USART_ReceiveData(USART2);//保存串口接收到的数据
                USART_SendData(USART2,uart3_RXbuff[uart_p]); //将保存的串口接收到的数据在串口调试助手显示(单字节数据显示)
                uart_p++;       
        }       
        if (USART_GetITStatus(USART2, USART_IT_IDLE) != RESET) //收到一帧的数据
        {
                                ReceivedFlag = 1;
                                u3Temp = uart_p-1;               
                                clr = USART2->DR;//清除空闲中断标志
                                clr = USART2->SR;
        }

接下来附上RS485的收发例程:(其实没啥区别只是485多了一个收发控制引脚,发送数据的时候要记得将控制引脚拉高即置位该引脚,接收数据的时候将引脚拉低即复位该引脚,不多说  见程序吧)

main.c:
#include "stm32f10x.h"
#include "bsp_485.h"



uint8_t u2_Temp;
extern uint8_t u3Temp;
extern uint16_t uart3_p;
extern uint16_t ReceivedUsart3Flag,tempU3,uart3_RXbuff[];
char *pbuf;
uint16_t len,iU3;

void SendUsart3Buff();
void SendU3DatatoDebug();
static void Delay(__IO uint32_t nCount);         //简单的延时函数//设置static:解决重复定义

int main(void)
{       
  /*初始化USART 配置模式为 115200 8-N-1,中断接收*/
  USART_Config();
        /* 发送使能 */
        RS485_TX_EN() ;
        SendUsart3Buff();
//        Delay(0xFFF);               
        RS485_RX_EN();

        while(1)
        {
                if(ReceivedUsart3Flag == 1)//接收到一帧数据
                {               
                                SendU3DatatoDebug();
                }
        }
}

static void Delay(__IO uint32_t nCount)         //简单的延时函数
{
                        for(; nCount != 0; nCount--);
}

void SendUsart3Buff()
{
                        for(iU3=0;iU3<=0xff;iU3++)
                        {
                                Usart_SendByte(USART3,iU3);

                        }
}

/*Description:调试通信程序专用,用于将接收到的数据再发送到串口调试助手显示
*
*/
void SendU3DatatoDebug()
{
                        for(uart3_p= 1; uart3_p <= u3Temp; uart3_p++)
                        {
                                Usart_SendByte(USART3,uart3_RXbuff[uart3_p]);                               
                        }                               
                        uart3_p = 1;
                        RS485_RX_EN();
                        ReceivedUsart3Flag = 0;
}
       



485.c:
#include "bsp_485.h"
       
static void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* 嵌套向量中断控制器组选择 */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  
  /* 配置USART为中断源 */
  NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
  /* 抢断优先级*/
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  /* 子优先级 */
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  /* 使能中断 */
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  /* 初始化配置NVIC */
  NVIC_Init(&NVIC_InitStructure);
}

/**
  * U3:TX:PB10        RX:PB11        TXRXEN:PD3
  * U5:TX:PC12        RX:PD1         TXRXEN:PD0
  *
  */
void USART_Config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;

        // 打开串口GPIO的时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//TX、RX是时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE);//EN时钟
        // 打开串口外设的时钟
        DEBUG_USART_APBxClkCmd(RCC_APB1Periph_USART3, ENABLE);//USART时钟

        // 将USART Tx的GPIO配置为推挽复用模式
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOB, &GPIO_InitStructure);

  // 将USART Rx的GPIO配置为浮空输入模式
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOB, &GPIO_InitStructure);
       
        /* 设置485收发控制管脚为推挽输出Out_PP */
        GPIO_InitStructure.GPIO_Pin = RS485_RE_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOD , &GPIO_InitStructure);
       
        // 配置串口的工作参数
        // 配置波特率
        USART_InitStructure.USART_BaudRate = 115200;
        // 配置 针数据字长
        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(USART3, &USART_InitStructure);
       
        // 串口中断优先级配置
        NVIC_Configuration();
       
        // 使能串口接收中断
        USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
        // 使能串口空闲中断(用于检测一帧数据接收完毕)
        USART_ITConfig(USART3, USART_IT_IDLE, ENABLE);       
        // 使能串口
        USART_Cmd(USART3, ENABLE);               
  
        /*控制 485 芯片进入接收模式*/
        RS485_RX_EN();//
}

/*****************  发送一个字符 **********************/
void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch)
{
        /* 发送一个字节数据到USART */
        USART_SendData(pUSARTx,ch);
               
        /* 等待发送数据寄存器为空 */
        while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);       
}

/*****************  发送字符串 **********************/
void Usart_SendString( USART_TypeDef * pUSARTx, char *str)
{
        unsigned int k=0;
  do
  {
      Usart_SendByte( pUSARTx, *(str + k) );
      k++;
  } while(*(str + k)!='');
  
  /* 等待发送完成 */
  while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET)
  {}
}

/*****************  发送一个16位数 **********************/
void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch)
{
        uint8_t temp_h, temp_l;
       
        /* 取出高八位 */
        temp_h = (ch&0XFF00)>>8;
        /* 取出低八位 */
        temp_l = ch&0XFF;
       
        /* 发送高八位 */
        USART_SendData(pUSARTx,temp_h);       
        while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);
       
        /* 发送低八位 */
        USART_SendData(pUSARTx,temp_l);       
        while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET);       
}


/*
Desc:接收中断时,将接收到的所有数据用数组保存。
*/

//中断缓存串口数据
#define UART_BUFF_SIZE      1024
uint16_t uart3_p = 1;
uint16_t     uart3_RXbuff[UART_BUFF_SIZE];
uint8_t u3Temp;
uint8_t tempU3;
uint8_t ReceivedUsart3Flag = 0;
uint16_t clr;
uint16_t a=0x00;

void bsp_RS485_IRQHandler(void)
{
                        if (USART_GetITStatus( USART3, USART_IT_RXNE) != RESET) //收到一个字节的数据
                        {
                                uart3_RXbuff[uart3_p] = USART_ReceiveData(USART3);
                                uart3_p++;               
                        }       
                        if (USART_GetITStatus(USART3, USART_IT_IDLE) != RESET) //收到一帧的数据
                        {
                                        u3Temp = uart3_p-1;
                                        clr = USART3->SR;                               
                                        clr = USART3->DR;
                                        ReceivedUsart3Flag = 1;
                                        RS485_TX_EN() ;
//                                        for(uart3_p= 1; uart3_p <= u3Temp; uart3_p++)//调试通信程序专用,用于将接收到的数据再发送到串口调试助手显示
//                                        {
//                                                Usart_SendByte(USART3,uart3_RXbuff[uart3_p]);                               
//                                        }                               
//                                        uart3_p = 1;
//                                        RS485_RX_EN();
                        }                       
}


//只有用于串口调试助手显示的USART,printf才需要重定义fputc,fgetc函数
/重定向c库函数printf到串口,重定向后可使用printf函数
//int fputc(int ch, FILE *f)
//{
//                /* 发送一个字节数据到串口 */
//                USART_SendData(DEBUG_USARTx, (uint8_t) ch);
//               
//                /* 等待发送完毕 */
//                while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET);               
//       
//                return (ch);
//}

/重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数
//int fgetc(FILE *f)
//{
//                /* 等待串口输入数据 */
//                while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET);

//                return (int)USART_ReceiveData(DEBUG_USARTx);
//}

stm32f10x_it.c:
void USART3_IRQHandler(void)
{
    bsp_RS485_IRQHandler();

}
举报

更多回帖

发帖
×
20
完善资料,
赚取积分