stm编程中断操作练习

目录

一、中断

二、实例分析

1.中断模式编程控制LED亮灭

2.验证串口对中断是否有延迟

3.接收字符发送“hello windows!”

4.接收字符串发送“hello windows!”

三、总结

四、参考资料


一、中断

        中断处理流程:中断请求、中断响应、中断服务和中断返回。以下分别是单重中断与多重中断的处理流程。

        STM32的内部中断处理机制。

        标准库中断基本函数:

        1.NVIC中断优先级函数

 void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)//中断分组管理函数
 void NVIC_Init(NVIC_InitTypeDef*NVIC_InitStruct)         //中断初始化函数
 void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset);
 void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState);
 void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource);

        2.外部中断EXTI标准外设库接口函数

 EXTI_Init               //定义了EXTI_InitTypeDef结构体
 EXTI_GetITStatus        //用于检查指定的EXTI线路触发请求发生与否,返回值:SET或RESET
 EXTI_ClearITPendingBit  //用于清除EXTI线路挂起位
 GPIO_EXTILineConfig     //用于选择GPIO管脚用作外部中断线路

二、实例分析

1.中断模式编程控制LED亮灭

        要求:用stm32F103核心板的GPIOA端一管脚接一个LED,GPIOB端口一引脚接一个开关(用杜邦线模拟代替)。采用中断模式编程,当开关接高电平时,LED亮灯;接低电平时,LED灭灯。

        代码实现如下。

        exti_key.c文件。

#include "exti_key.h"
 #include "misc.h"
 ​
 void EXTI_Key_Init(void)
 {   
     GPIO_InitTypeDef GPIO_InitStructure;
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE|RCC_APB2Periph_AFIO,ENABLE);
                                                             //开启I/O端口的时钟和复用时钟
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
                                                             //初始化I/O口为浮空输入模式
     GPIO_Init(GPIOA,&GPIO_InitStructure);
 ​
     
     NVIC_InitTypeDef NVIC_InitStructure;
     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
                                                             //设置中断的优先级分组
     NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
                                                             //配置中断源,IRQ通道
     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
                                                             //配置抢占优先级
     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
                                                             //配置响应优先级
     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
                                                             //使能中断通道
     NVIC_Init(&NVIC_InitStructure); 
 ​
 ​
     EXTI_InitTypeDef EXTI_InitStructure;
                                                             //EXTI模式
     EXTI_ClearITPendingBit(EXTI_Line3);  
     GPIO_EXTILineConfig(GPIO_PortSourceGPIOE,GPIO_PinSource3);
                                                             //设置I/O引脚与中断线路的映射关系
     EXTI_InitStructure.EXTI_Line = EXTI_Line3;
                                                             //设置外部中断线3中断
     EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
                                                             //设置为中断模式
     EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
                                                             //触发类型
     EXTI_InitStructure.EXTI_LineCmd = ENABLE;
                                                             //使能该外部中断线
     EXTI_Init(&EXTI_InitStructure);
 }
 ​

main.c文件。

 #include "stm32f10x.h"
 ​
 #include "LED1.h"
 #include "exti_key.h"
 ​
 int main(void)
 {
     LED_Init();
     GPIO_ResetBits(GPIOB,GPIO_Pin_5);
     EXTI_Key_Init();
     while(1)
     {
     }
  }
 ​
 void EXTI3_IRQHandler(void)
 {
     if(EXTI_GetITStatus(EXTI_Line3) != RESET)
                                                         //判断某个线上的中断是否发生
     {
         GPIO_WriteBit(GPIOB,GPIO_Pin_5,(BitAction)((1-GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_5))));
         EXTI_ClearITPendingBit(EXTI_Line3);
                                                         //清除中断标志
     }
 }
 ​

        开发板展示。

2.验证串口对中断是否有延迟

        要求:在上述main函数while循环中加入一个串口每隔1s发送一次字符的代码片段,观察按键中断对串口发送是否会带来干扰或延迟。

        代码实现,在实例1的代码基础上,增加如下Serial.c文件,同时在main函数中使用Serial_SendByte函数打印字符。

 #include "stm32f10x.h"    // Device header
 #include <stdio.h>
 ​
 void Serial_Init(void)
 {
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
     
     GPIO_InitTypeDef GPIO_InitStructure;//定义结构体变量
     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);
     
     GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IPU;
     GPIO_InitStructure.GPIO_Pin =GPIO_Pin_10;
     GPIO_InitStructure.GPIO_Speed =GPIO_Speed_50MHz;//给三个结构体变量赋值
     GPIO_Init(GPIOA,&GPIO_InitStructure);
     
     USART_InitTypeDef USART_InitStructure;
     USART_InitStructure.USART_BaudRate=9600;//设置波特率为9600
     USART_InitStructure.USART_WordLength=USART_WordLength_8b;//数据位占8位
     USART_InitStructure.USART_StopBits=USART_StopBits_1;//1位停止位
     USART_InitStructure.USART_Parity=USART_Parity_No;//无校验
     USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
     USART_InitStructure.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
     USART_Init(USART1,&USART_InitStructure);
     
     USART_Cmd(USART1,ENABLE);
 }
 ​
 void Serial_SendByte(uint8_t Byte)//显示字符,参考ASCII字符集,例如发送A,Byte=0x41或者‘A’
 {
     USART_SendData(USART1,Byte);
     while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
 }
 ​
 int fputc(int ch,FILE *f)
 {
     Serial_SendByte(ch);
     return ch;
 }
 ​

        在串口助手中调试后发现串口不会对中断造成延时。

3.接收字符发送“hello windows!”

        要求:当stm32接收到1个字符“s”时,停止持续发送“hello windows!”; 当接收到1个字符“t”时,持续发送“hello windows!”。

        代码实现如下。

 #include "stm32f10x.h"                 
 #include "Delay.h"
 int send=0;//设置标志位
 void hellowindows()
 {
     if(send==1)
     {
     int i;
     char a [14]={'h','e','l','l','o','w','i','n','d','o','w','s','!',' '};
     for (i = 0; i < 14; i++)
     {
     USART_SendData(USART1,a[i]);
     while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
     }
     Delay_s(1);
   }
 }
 void USART1_IRQHandler(void)
 {
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
     {
         uint8_t receivedChar = USART_ReceiveData(USART1);
         
         if (receivedChar == 's')
         {
             send = 0;
         }
         else if (receivedChar == 't')
         {
             send = 1;
         }
     }   
 }
 int main(void)
 {
     USART_InitTypeDef USART_InitStructure;
 ​
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE);
 ​
     GPIO_InitTypeDef GPIO_InitStructure;
     GPIO_InitStructure.GPIO_Pin  =GPIO_Pin_9;
     GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; 
     GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP;
     GPIO_Init(GPIOA,&GPIO_InitStructure );
     
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
     GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
     GPIO_Init(GPIOA,&GPIO_InitStructure);
 ​
     USART_InitStructure.USART_BaudRate = 9600;
     USART_InitStructure.USART_WordLength= USART_WordLength_8b;
     USART_InitStructure.USART_StopBits= USART_StopBits_1;
     USART_InitStructure.USART_Parity = USART_Parity_No;
     USART_InitStructure.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
     USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
     USART_Init(USART1, &USART_InitStructure);
     USART_ClearFlag(USART1, USART_FLAG_TC);
 ​
     USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//当USART串口接收到数据的时候,就触发USART中断
     
     NVIC_InitTypeDef  NVIC_InitStructure;
     NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;      
     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3; //设置抢占(主)优先级    
     NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;      // 设置子优先级   
     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             
     NVIC_Init(&NVIC_InitStructure);    
 ​
     USART_Cmd(USART1, ENABLE);
     while(1)
     {
         hellowindows();
     }
 }
 ​

        在串口助手中进行调试可以观察到如下效果。

4.接收字符串发送“hello windows!”

        要求:当stm32接收到字符“stop stm32!”时,停止持续发送“hello windows!”; 当接收到字符“go stm32!”时,持续发送“hello windows!”。

 #include "stm32f10x.h"                 
 #include "Delay.h"
 int send=0;                 //全局变量,记录状态
 int count=0;                //全局变量,表示缓冲区的数组的下标
 char  receive_data[11];     //接收缓存区
 void  receive_data_init()   //接收缓存区初始化
 {
     count=0;
     for(int i=0;i<11;i++)
     {
         receive_data[i]=0;
     }
 }
 void hellowindows()
 {
     if(send==1)//当send为1,输出hellowindows!
     {
     int i;
     char a [14]={'h','e','l','l','o','w','i','n','d','o','w','s','!',' '};
     for (i = 0; i < 14; i++)
     {
     USART_SendData(USART1,a[i]);
     while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
     }
     Delay_s(1);//延时1s
   }
 }
 void USART1_IRQHandler(void)//中断函数,接收数据存入接收缓冲区
 {
    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)//判断中断是接收数据中断
     {
        receive_data[count]= USART_ReceiveData(USART1); //接收字符
                 count++;
     } 
 ​
     }
 int main(void)
 {
     USART_InitTypeDef USART_InitStructure;
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE);
     GPIO_InitTypeDef GPIO_InitStructure;
     GPIO_InitStructure.GPIO_Pin  =GPIO_Pin_9;
     GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; 
     GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP;
     GPIO_Init(GPIOA,&GPIO_InitStructure );
     
     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
     GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
     GPIO_Init(GPIOA,&GPIO_InitStructure);
 ​
     USART_InitStructure.USART_BaudRate = 9600;
     USART_InitStructure.USART_WordLength= USART_WordLength_8b;
     USART_InitStructure.USART_StopBits= USART_StopBits_1;
     USART_InitStructure.USART_Parity = USART_Parity_No;
     USART_InitStructure.USART_Mode=USART_Mode_Tx|USART_Mode_Rx;
     USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
     USART_Init(USART1, &USART_InitStructure);
     USART_ClearFlag(USART1, USART_FLAG_TC);
 ​
     USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//当USART串口接收到数据的时候,就触发USART中断
     
     NVIC_InitTypeDef  NVIC_InitStructure;
     NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;      
     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3; //设置抢占(主)优先级    
     NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;      // 设置子优先级   
     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             
     NVIC_Init(&NVIC_InitStructure);    
 ​
     USART_Cmd(USART1, ENABLE);
    
     receive_data_init();//初始化接收缓存区
     while(1)
     {
         hellowindows();
         if ( strcmp(receive_data,"stop stm32!")==0)
             {
                 send = 0;//结束发送
                 receive_data_init();
                     
             }
         else if (strcmp(receive_data,"go stm32!")==0)
         {
                 send = 1;//发送数据
                 receive_data_init();//重新初始化接收缓存区,以便下次接收数据
         }
     }
 }
 ​

        在串口助手中进行调试可以观察到如下效果。

三、总结

        通过标准库函数进行了stm编程中的中断操作,对于stm编程的认识在逐渐加深,南都也在加大,我还需要多加练习。

四、参考资料

STM32的USART窗口通讯程序——串口通讯

  • 23
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值