在进行uCOSII的程序之前先来温习下,裸机平台下stm32的外部中止的操作。
大约能够分作4个进程:1-装备相应管脚为浮空输入;2-装备相应管脚为外部中止口并设定其中止特色及参数;3-装备NVIC相关寄存器,设定中止优先级;4-编写中止服务函数。废话不说直接上代码:
第一步:装备相应管脚为浮空输入,来自文件Key.c
{
GPIO_InitTypeDefGPIO_InitStructure_EXTI_KEY_PORTE;
GPIO_InitStructure_EXTI_KEY_PORTE.GPIO_Pin=GPIO_Pin_4;// 端口4
GPIO_InitStructure_EXTI_KEY_PORTE.GPIO_Mode=GPIO_Mode_IN_FLOATING;// 浮空输入
GPIO_InitStructure_EXTI_KEY_PORTE.GPIO_Speed=GPIO_Speed_50MHz;// 口线翻转速度为50MHz
GPIO_Init(GPIOE,&GPIO_InitStructure_EXTI_KEY_PORTE);// 端口初始化
GPIO_InitStructure_EXTI_KEY_PORTE.GPIO_Pin=GPIO_Pin_3;// 端口3
GPIO_InitStructure_EXTI_KEY_PORTE.GPIO_Mode=GPIO_Mode_IN_FLOATING;// 浮空输入
GPIO_InitStructure_EXTI_KEY_PORTE.GPIO_Speed=GPIO_Speed_50MHz;// 口线翻转速度为50MHz
GPIO_Init(GPIOE,&GPIO_InitStructure_EXTI_KEY_PORTE);// 端口初始化
}
第二步:装备相应管脚为外部中止口而且设定其中止特色及参数,来自文件EXTIG.c
{
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用作外部中止线路
/* 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;//装备 使能线路的触发边缘 — 下降沿触发中止
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_Mode_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 on EXTI line 13 */
EXTI_GenerateSWInterrupt(EXTI_Line4);//线路4发生一个软件中止
EXTI_GenerateSWInterrupt(EXTI_Line3);//线路3发生一个软件中止
}
第三步:装备NVIC相关寄存器,设定中止优先级,来自文件SysInit.c
{
NVIC_InitTypeDefNVIC_InitStructure_EXTI_LINE;
/* ================ NVIC-EXTI-PORTE ================= */
/* Configure 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的 组 优先级
NVIC_InitStructure_EXTI_LINE.NVIC_IRQChannelSubPriority=0;// 装备IRQ的 从 优先级
NVIC_InitStructure_EXTI_LINE.NVIC_IRQChannelCmd=ENABLE;// 装备IRQ 使能
NVIC_Init(&NVIC_InitStructure_EXTI_LINE);// 初始化 IRQ
NVIC_InitStructure_EXTI_LINE.NVIC_IRQChannel=EXTI3_IRQn;// 装备使能指定的IRQ(Interrupt ReQuest中止恳求)通道
NVIC_InitStructure_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
}
第四步:编写中止服务程序,来自文件stm32f10x_it.c
{
if(EXTI_GetITStatus(EXTI_Line3)==SET)// 读取中止状况
{
LED1_LOW;
EXTI_ClearITPendingBit(EXTI_Line3);// 铲除标志位
}
}
voidEXTI4_IRQHandler(void)
{
if(EXTI_GetITStatus(EXTI_Line4)==SET)// 读取中止状况
{
LED1_HIGH;
EXTI_ClearITPendingBit(EXTI_Line4);// 铲除标志位
}
}
下面就要说说在uCOSII里的时分了。
首要把上面所述进程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)
{
OSIntEnter();
OSSemPost(Sem_Task_LED2);// 发送信号量,这个函数并不会引起体系调度,所以中止服务函数一定要简练。
EXTI_ClearITPendingBit(EXTI_Line4);// 铲除标志位
OSIntExit();
}
如代码所示黄色高亮部分便是进入中止和出中止的ucos部分的代码,在出中止的时分会引起体系调度,然后最高优先级的使命会先履行,确保了体系的实时性。
进程1~3的代码和上面相似就不一一列举,体系运转进程如下:
首要体系树立一个开始使命START,这个使命的优先级最低为10,他主要是做体系心跳的显现,别的把其他需求的使命初始化。在例程里有别的两个使命,分别是KEY1使命(优先级为9)和LED2使命(优先级为5)。先初始化KEY1使命,初始化函数结束后就跳到KEY1使命代码处履行,当遇到OSTimeDlyHMSM()函数时,会引发体系调度,此刻就两个使命,所以肯定会回到开始使命START,然后初始化LED2使命,初始化函数结束后就跳到LED2使命代码处履行,在这个使命中有等候信号量的函数,所以体系会自己挂起使命,体系再进行调度的时分也会履行这个挂起使命里的代码。这时分假如按下按键,就会触发中止,在中止函数里会有信号量宣布来,在结束中止的时分会有体系调度,此刻体系会跳到恳求信号量的断点处去履行代码,这一点表现了ucos的抢占性的特色,便是中止的优先级都是赶过与非中止使命的,所以中止里宣布的信号量一定是要先相应的。然后体系就会遵从优先级凹凸进行体系调度。
在这个例程里还有一个新的知识点便是计数信号量的运用。
运用时分为4个进程:
- 界说信号量指针void*Sem_Task_LED2;
- 创立信号量 Sem_Task_LED2 = OSSemCreate(0); // 函数里参数是指信号量的初始值
- 设置等候信号量 OSSemPend(Sem_Task_LED2,0,&err);
- 设置发送信号量OSSemPost(Sem_Task_LED2);
这儿创立信号量和设置等候信号量都是在使命LED2里,设置发送信号量在中止服务函数里。见代码:
* Function Name : Task_LED2
* Description : LED2使命
* Input : None
* Output : None
* Return : None
*******************************************************************************/
voidTask_LED2(void*p_arg)
{
(void)p_arg;
Sem_Task_LED2=OSSemCreate(0);
while(1)
{
OSSemPend(Sem_Task_LED2,0,&err);// 等候信号量
LED2_HIGH;
OSTimeDlyHMSM(0,0,1,0);
LED2_LOW;
OSTimeDlyHMSM(0,0,1,0);// 延时,用来给其他使命留有运转的时刻
}
}
这儿要说一下留意点,首要界说的信号量指针是一个全局变量,需求在相应的头文件里进行extern声明,在这儿是把他放在task.c文件里的。别的创立信号量和设置等候信号量函数都放在详细的使命中,由于在逻辑上,创立信号量和等候信号量函数肯定要早与发送信号量函数履行,因此在设置等候信号量之前去创立信号量是彻底适宜的,而且把创立信号量函数放在详细使命的while(1)上面,在创立函数的时分信号量就现已被创立了,然后代码履行到等候信号量的时分使命就会被挂起,除非时刻到或许有信号量来的话才会被履行。最终设置发送信号量,在这儿发送信号量函数是放在中止服务程序里的,由于发送信号量函数的履行并不会引起体系调度,只要在中止服务函数履行结束,出中止函数的履行才会引发体系调度,所以中止服务函数里的内容一定要精简,不然就会影响体系的实时性。