《STM32 uCOS_II 实践 之 外部中断事件 及 系统运行过程 .dot.pdf》由会员分享,可在线阅读,更多相关《STM32 uCOS_II 实践 之 外部中断事件 及 系统运行过程 .dot.pdf(9页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、在进行 uCOSII 的程序之前先来复习下,裸机平台下stm32的外部中断的操作。大概可以分作4个步骤:1-配置相应管脚为浮空输入;2-配置相应管脚为外部中断口并设定其中断属性及参数;3-配置 NVIC 相关寄存器,设定中断优先级;4-编写中断服务函数。废话不说直接上代码:第一步:配置相应管脚为浮空输入,来自文件第一步:配置相应管脚为浮空输入,来自文件 Key.cKey.cvoidKey_Port_Configuration(void)GPIO_InitTypeDefGPIO_InitStructure_EXTI_KEY_PORTE;GPIO_InitStructure_EXTI_KEY_PO
2、RTE.GPIO_Pin=GPIO_Pin_4;/ 端口4GPIO_InitStructure_EXTI_KEY_PORTE.GPIO_Mode=GPIO_Mode_IN_FLOATING;/ 浮空输入GPIO_InitStructure_EXTI_KEY_PORTE.GPIO_Speed=GPIO_Speed_50MHz;/ 口线翻转速度为 50MHzGPIO_Init(GPIOE, &GPIO_InitStructure_EXTI_KEY_PORTE);/ 端口初始化GPIO_InitStructure_EXTI_KEY_PORTE.GPIO_Pin=GPIO_Pin_3;/ 端口3GPI
3、O_InitStructure_EXTI_KEY_PORTE.GPIO_Mode=GPIO_Mode_IN_FLOATING;/ 浮空输入GPIO_InitStructure_EXTI_KEY_PORTE.GPIO_Speed=GPIO_Speed_50MHz;/ 口线翻转速度为 50MHzGPIO_Init(GPIOE, &GPIO_InitStructure_EXTI_KEY_PORTE);/ 端口初始化第二步:配置相应管脚为外部中断口并且设定其中断属性及参数,来自文件第二步:配置相应管脚为外部中断口并且设定其中断属性及参数,来自文件EXTIGEXTIG.c.cvoidEXTI_PORTE
4、_Configuration(void)EXTI_InitTypeDefEXTI_InitStructure_EXTI_LINE4;EXTI_InitTypeDefEXTI_InitStructure_EXTI_LINE3;/* Connect EXTI Line4,3 to PE4,PE3 */GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource4);/ 配置 管脚PE4用作外部中断线路GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource3);/ 配置 管脚PE3用作外部中
5、断线路/* Configure EXTI Line4 to generate an interrupt on falling edge */EXTI_InitStructure_EXTI_LINE4.EXTI_Line=EXTI_Line4;/配置 使能或失能的外部线路EXTI_InitStructure_EXTI_LINE4.EXTI_Mode=EXTI_Mode_Interrupt;/配置 EXTI线路为中断请求(或者是事件请求)EXTI_InitStructure_EXTI_LINE4.EXTI_Trigger=EXTI_Trigger_Falling;/配置 使能线路的触发边沿 - 下
6、降沿触发中断EXTI_InitStructure_EXTI_LINE4.EXTI_LineCmd=ENABLE;/配置 状态为使能EXTI_Init(&EXTI_InitStructure_EXTI_LINE4);/ 初始化外部中断线路 4/* Configure EXTI Line3 to generate an interrupt on falling edge */EXTI_InitStructure_EXTI_LINE3.EXTI_Line=EXTI_Line3;/配置 使能或失能的外部线路EXTI_InitStructure_EXTI_LINE3.EXTI_Mode=EXTI_Mod
7、e_Interrupt;/配置 EXTI线路为中断请求(或者是事件请求)EXTI_InitStructure_EXTI_LINE3.EXTI_Trigger=EXTI_Trigger_Falling;/配置 使能线路的触发边沿 - 下降沿触发中断EXTI_InitStructure_EXTI_LINE3.EXTI_LineCmd=ENABLE;/配置 状态为使能EXTI_Init(&EXTI_InitStructure_EXTI_LINE3);/ 初始化外部中断线路 3/* Generate software interrupt: simulate a falling edge applied
8、 on EXTI line 13 */EXTI_GenerateSWInterrupt(EXTI_Line4);/线路4产生一个软件中断EXTI_GenerateSWInterrupt(EXTI_Line3);/线路3产生一个软件中断第三步:配置第三步:配置 NVICNVIC 相关寄存器,设定中断优先级,来自文件相关寄存器,设定中断优先级,来自文件 SysInit.cSysInit.cvoidNVIC_Configuration(void)NVIC_InitTypeDefNVIC_InitStructure_EXTI_LINE;/* = NVIC-EXTI-PORTE = */* Config
9、ure one bit for preemption priority */NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);/ 配置优先级分组长度/* Enable the EXTI15_10 Interrupt */NVIC_InitStructure_EXTI_LINE.NVIC_IRQChannel=EXTI4_IRQn;/ 配置使能指定的IRQ(Interrupt ReQuest 中断请求 )通道NVIC_InitStructure_EXTI_LINE.NVIC_IRQChannelPreemptionPriority=0;/ 配置IRQ的
10、 组 优先级NVIC_InitStructure_EXTI_LINE.NVIC_IRQChannelSubPriority=0;/ 配置IRQ的 从 优先级NVIC_InitStructure_EXTI_LINE.NVIC_IRQChannelCmd=ENABLE;/ 配置IRQ 使能NVIC_Init(&NVIC_InitStructure_EXTI_LINE);/ 初始化 IRQNVIC_InitStructure_EXTI_LINE.NVIC_IRQChannel=EXTI3_IRQn;/ 配置使能指定的IRQ(Interrupt ReQuest 中断请求 )通道NVIC_InitStr
11、ucture_EXTI_LINE.NVIC_IRQChannelPreemptionPriority=0;/ 配置IRQ的 组 优先级NVIC_InitStructure_EXTI_LINE.NVIC_IRQChannelSubPriority=0;/ 配置IRQ的 从 优先级NVIC_InitStructure_EXTI_LINE.NVIC_IRQChannelCmd=ENABLE;/ 配置IRQ 使能NVIC_Init(&NVIC_InitStructure_EXTI_LINE);/ 初始化 IRQ第四步:编写中断服务程序,来自文件第四步:编写中断服务程序,来自文件 stm32f10 x_
12、it.cstm32f10 x_it.cvoidEXTI3_IRQHandler(void)if if(EXTI_GetITStatus(EXTI_Line3) = SET)/ 读取中断状态LED1_LOW;EXTI_ClearITPendingBit(EXTI_Line3);/ 清除标志位voidEXTI4_IRQHandler(void)if if(EXTI_GetITStatus(EXTI_Line4) = SET)/ 读取中断状态LED1_HIGH;EXTI_ClearITPendingBit(EXTI_Line4);/ 清除标志位下面就要说说在 uCOSII 里的时候了。首先把上面所述
13、步骤1,步骤2和步骤4的代码放到 KEY.C 文件内,然后把步骤3的代码加入SysInit.C 文件内的 NVIC_Configuration()函数。步骤1,步骤2,和步骤3与没有操作系统的代码一致,都是最底层的东西。步骤 4需要符合 ucos 的代码规范,也要用到ucos 的系统函数,如下面代码:/* Function Name : Interrupt_Handle_KEY2* Description :按键2中断服务函数* Input : None* Output : None* Return : None*/voidInterrupt_Handle_KEY2(void)OSIntEnt
14、er();OSSemPost(Sem_T ask_LED2);/ 发送信号量 ,这个函数并不会引起系统调度,所以中断服务函数一定要简洁。EXTI_ClearITPendingBit(EXTI_Line4);/ 清除标志位OSIntExit();如代码所示黄色高亮部分就是进入中断和出中断的ucos 部分的代码,在出中断的时候会引起系统调度,然后最高优先级的任务会先执行,保证了系统的实时性。步骤13的代码和上面类似就不一一列举,系统运行过程如下:首先系统建立一个起始任务START,这个任务的优先级最低为10,他主要是做系统心跳的显示,另外把其他需要的任务初始化。在例程里有另外两个任务,分别是KEY
15、1任务(优先级为9)和LED2任务(优先级为5) 。先初始化KEY1任务,初始化函数结束后就跳到KEY1任务代码处执行,当遇到OSTimeDlyHMSM()函数时,会引发系统调度,此时就两个任务,所以肯定会回到起始任务START, 然后初始化 LED2任务,初始化函数结束后就跳到LED2任务代码处执行,在这个任务中有等待信号量的函数,所以系统会自己挂起任务,系统再进行调度的时候也会执行这个挂起任务里的代码。 这时候如果按下按键, 就会触发中断,在中断函数里会有信号量发出来, 在结束中断的时候会有系统调度, 此时系统会跳到请求信号量的断点处去执行代码,这一点体现了ucos 的抢占性的特点,就是中
16、断的优先级都是凌驾与非中断任务的, 所以中断里发出的信号量一定是要先相应的。 然后系统就会遵循优先级高低进行系统调度。在这个例程里还有一个新的知识点就是计数信号量的使用。使用时分为4个步骤:定义信号量指针void *Sem_Task_LED2;创建信号量Sem_Task_LED2 = OSSemCreate(0);/ 函数里参数是指信号量的初始值设置等待信号量OSSemPend(Sem_Task_LED2,0,&err);设置发送信号量OSSemPost(Sem_Task_LED2);这里创建信号量和设置等待信号量都是在任务LED2里,设置发送信号量在中断服务函数里。见代码:/* Functi
17、on Name : Task_LED2* Description : LED2 任务* Input : None* Output : None* Return : None*/voidTask_LED2(void* p_arg)(void) p_arg ;Sem_Task_LED2 = OSSemCreate(0);whilewhile(1)OSSemPend(Sem_Task_LED2, 0,&err);/ 等待信号量LED2_HIGH;OSTimeDlyHMSM(0,0,1,0);LED2_LOW;OSTimeDlyHMSM(0,0,1,0);/ 延时,用来给其他任务留有运行的时间这里要说
18、一下注意点, 首先定义的信号量指针是一个全局变量, 需要在相应的头文件里进行externextern 声明,在这里是把他放在 task.c 文件里的。另外创建信号量和设置等待信号量函数都放在具体的任务中, 因为在逻辑上, 创建信号量和等待信号量函数肯定要早与发送信号量函数执行, 因此在设置等待信号量之前去创建信号量是完全合适的, 并且把创建信号量函数放在具体任务的 while(1) 上面,在创建函数的时候信号量就已经被创建了,然后代码执行到等待信号量的时候任务就会被挂起, 除非时间到或者有信号量来的话才会被执行。 最后设置发送信号量, 在这里发送信号量函数是放在中断服务程序里的, 因为发送信号量函数的发送信号量函数的执行并不会引起系统调度执行并不会引起系统调度, 只有在中断服务函数执行完毕, 出中断函数的执行才会引发系统调度,所以中断服务函数里的内容一定要精简,否则就会影响系统的实时性。