zoukankan      html  css  js  c++  java
  • 串口中断函数详解

    串口中断函数详解

    ARM cortex_m3 内核支持 256 个中断(16 个内核+240 外部)和可编程 256 级中断优先级的设置。

    STM32支持的中断共为84个(16个内核+68个外部),和16级可编程中断优先级的设置。

    AIRCR是NIVC配置中一个关键的寄存器,由于STM32有很多中断,要处理这些中断的时候总是需要先后顺序的,所以采用AIRCR寄存器给中断优先级进行分组。

    优先组别总用有5组, 0-4,分为抢占优先级和响应优先级(也称为子优先级),使用低字节的高四位来设置中断优先级分组。

    例如:当AIRCR寄存器的第八位到第十位都为1时,寄存器的第四位到第七位都是在设置响应优先级,最高可以有0个抢占优先级和16级响应优先级。具体分配如下表:

    AIRCR[10: 8] bit[7: 4] 结果
    0 111 0:4 0 位抢占优先级, 4 位响应优先级
    1 110 1:3 1 位抢占优先级, 3 位响应优先级
    2 101 2:2 2 位抢占优先级, 2 位响应优先级
    3 100 3:1 3 位抢占优先级, 1 位响应优先级
    4 011 4:0 4 位抢占优先级, 0 位响应优先级

    在使用NVIC初始化以前需要使用NVIC_PriorityGroupConfig( )函数设置中断优先级分组。分组后再在中断初始化函数中使用NVIC_IRQChannelPreemptionPriority设置具体的中断优先级。

    下面为串口初始化函数以及中断函数:

    void uart_init (){
      	//GPIO端口设置
      	GPIO_InitTypeDef GPIO_InitStructure;
    	USART_InitTypeDef USART_InitStructure;
    	NVIC_InitTypeDef NVIC_InitStructure;
    	 
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//使能	USART1,GPIOA时钟
      
    	//USART1_TX   GPIOA.9
      	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
     	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//复用推挽输出
      	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
       
      	//USART1_RX	  GPIOA.10初始化
      	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
      	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
      	GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10  
    
      	//Usart1 NVIC 配置
        //
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
      	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3
    	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		//子优先级3
    	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
    	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
      
       	//USART 初始化设置
    	USART_InitStructure.USART_BaudRate = 115200;//串口波特率
    	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
    	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); //初始化串口1
      	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启串口接受中断
      	USART_Cmd(USART1, ENABLE);                    //使能串口1 
    
    }
    
    void USART1_IRQHandler (void)                	//串口1中断服务程序
    {
    	u8 Res;
    	if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET){  //接收中断(接收到的数据必须是		0x0d 0x0a结尾)。USART_GetITStatus函数如果接收寄存器存在数据就返回SET   
    			Res =USART_ReceiveData(USART1);	 //读取接收到的数据,一次发送一个字节
    			if ((USART_RX_STA&0x8000)==0){   //接收未完成
    				if (USART_RX_STA&0x4000){     //接收到了0x0d 0x0D(asc码是13) 指的是“回车” 
                        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;//接收数据错误,重																		新开始接收	  
    					}		 
    				}
    			}   		 
         	} 
    } 
    

    这里详细介绍稍难理解一点的语句

    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
    
    • 第一个参数为使用串口1

    • 第二个参数为中断标志,串口有很多种中断,这里是使用USART_IT_RXNE中断

    • 第三个参数为使能

    下面为中断处理函数:

    if((USART_RX_STA&0x8000)==0) 
    

    USART_RX_STA是状态标记变量,bit0~13接收有效字节数目,bit14接收0x0d,bit15接收完成标志。当接收完成时,bit15置为1。

    该变量从0开始,串口中断接收到一个数据(一个字节)就自增1。当数据读取全部OK时候(回车和换行符号来的时候),那么 USART_RX_STA的最高位置1,表示串口数据接收全部完毕了,然后main函数里面可以处理数据了。

    当接收到从电脑发过来的数据,把接收到的数据保存在USART_RX_BUF 中,同时在接收状态寄存器(USART_RX_STA)中计数接收到的有效数据个数,当收到回车(0X0D,0X0A)的第一个字节0X0D 时,计数器将不再增加,等待0X0A 的到来,而如果0X0A 没有来到,则认为这次接收失败,重新开始下一次接收。如果顺利接收到0X0A,则标记USART_RX_STA的第16位,这样完成一次接收,并等待该位被其他程序清除,从而开始下一次的接收,而如果迟迟没有收到0X0D,那么在接收数据超过设定值个数后,会丢弃前面的数据,重新接收。

    0x4000,即二进制0100 0000 0000 0000,与变量USART_RX_STA,按位与(&),作用是判断USART_RX_STA数值第15位是否为0。

    0x8000,即二进制1000 0000 0000 0000,与变量USART_RX_STA,按位与(&),作用是判断USART_RX_STA数值第16位是否为0。

    USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
    

    为了去除最高两位的影响,将最高两位置0。

    if (USART_RX_STA>200) USART_RX_STA=0
    

    200为自己设定的值,如果接收到的函数大于这个值,就清除掉整个字符串重新输入。

  • 相关阅读:
    POJ 2342 树形DP入门题
    《4》CentOS7.0+OpenStack+kvm云平台部署—配置Nova
    GDI+ 填充背景时,非常多时候不起作用,GDI、GDI+配合运用
    Jave中System.getProperty()获取的值
    NYOJ128 前缀式计算(栈的运用)
    Web安全測试二步走
    一个SQL update语句
    C#时间格式之GMT时间的格式
    粘包的处理
    socket对于大数据的发送和接收
  • 原文地址:https://www.cnblogs.com/roscangjie/p/12485173.html
Copyright © 2011-2022 走看看