电子说
首先要做根据UCOSII中定义的OS_TICKS_PER_SEC来计算出SysTick的装载值reload,开启SysTick中断,将reload值写进SysTick的LOAD寄存器中,最后开启SysTick,开启SysTick后还要编写其中断服务函数。
③微秒级别延时函数
void delay_us( u16 nus )
{
#if SYSTEM_SUPPORT_OS
u32 ticks, told, tnow, tcnt=0 ;
u32 reload = SysTick->LOAD ; //LOAD的值
ticks = nus*fac_us ; //需要的节拍数
OSSchedLock() ; //禁止调度,防止打断us延时
told = SysTick->VAL ; //刚进入时的计数器值
while( 1 )
{
tnow = SysTick->VAL ;
if( tnow!=told )
{
//这里注意一下SYSTICK是一个递减的计数器
if( tnowelse
tcnt += reload-tnow+told ;
told = tnow ;
//时间超过/等于要延迟的时间,则退出
if( tcnt>=ticks )
break ;
}
}
OSSchedUnlock() ; //UCOSII的方式,恢复调度
#else
u32 temp ;
SysTick->LOAD = nus*fac_us ; //时间加载
SysTick->VAL = 0x00 ; //清空计数器
SysTick->CTRL = 0x01 ; //开始倒数
do
{
temp = SysTick->CTRL ;
}while( ( temp&0x01 )&&!( temp&( 1<<16 ) ) ) ; //等待时间到达
SysTick->CTRL = 0x00 ; //关闭计数器
SysTick->VAL = 0x00 ; //清空计数器
#endif
}
④毫秒级别延时函数
void delay_ms( u16 nms )
{
#if SYSTEM_SUPPORT_OS
//如果OS已经在跑了,并且不是在中断里面(中断里面不能任务调度)
if( ( delay_osrunning==1 )&&( delay_osintnesting==0 ) )
{
//延时的时间大于OS的最少时间周期
if( nms>=fac_ms )
OSTimeDly( nms/fac_ms ) ; //UCOSII延时
nms %= fac_ms ; //延时太短,采用普通方式延时
}
delay_us( ( u32 )( nms*1000 ) ) ; //普通方式延时
#else
u32 temp ;
SysTick->LOAD = ( u32 )nms*fac_ms ; //时间加载(SysTick->LOAD为24bit)
SysTick->VAL = 0x00 ; //清空计数器
SysTick->CTRL = 0x01 ; //开始倒数
do
{
temp = SysTick->CTRL ;
}while( ( temp&0x01 )&&!( temp&( 1<<16 ) ) ) ; //等待时间到达
SysTick->CTRL = 0x00 ; //关闭计数器
SysTick->VAL = 0x00 ; //清空计数器
#endif
}
(5)usart1.c文件修改
①添加头文件定义
#if SYSTEM_SUPPORT_OS
#include "includes.h"
#endif
②修改串口中断服务函数
void USART1_IRQHandler()
{
#if SYSTEM_SUPPORT_OS
OSIntEnter() ;
#endif
//接收到数据
if( USART1->SR&( 1<<5 ) )
{
if( USART1->DR=='\\n' )
{
USART1_Data.Len = USART1_Rx_Count ;
USART1_Rx_Count = 0 ;
USART1_Data.State = 1 ;
}
USART1_Data.Buffer[ USART1_Rx_Count ] = USART1->DR ;
USART1_Rx_Count ++ ;
}
#if SYSTEM_SUPPORT_OS
OSIntExit() ;
#endif
}
例程:利用移植完成的ucos-ii系统新建两个任务,并且在两个任务中打印自定义的任务名称。
#include "sys.h"
#include "delay.h"
#include "usart1.h"
#include "includes.h"
/****************************************************
Name :Task01
Function :任务1
Paramater :None
Return :None
****************************************************/
#define TASK01_PRIO 7 //设置任务优先级
#define TASK01_SIZE 64 //设置任务堆栈大小
OS_STK TASK01_STK[ TASK01_SIZE ] ; //任务堆栈
void Task01( void *pdata )
{
while( 1 )
{
printf( "Task1 Run\\r\\n" ) ;
delay_ms( 1000 ) ;
}
}
/****************************************************
Name :Task02
Function :任务2
Paramater :None
Return :None
****************************************************/
#define TASK02_PRIO 6 //设置任务优先级
#define TASK02_SIZE 64 //设置任务堆栈大小
OS_STK TASK02_STK[ TASK02_SIZE ] ; //任务堆栈
void Task02( void *pdata )
{
while( 1 )
{
printf( "Task2 Run\\r\\n" ) ;
delay_ms( 2000 ) ;
}
}
/****************************************************
Name :Start
Function :开始任务
Paramater :None
Return :None
****************************************************/
#define START_PRIO 10 //开始任务的优先级设置为最低
#define START_SIZE 64 //设置任务堆栈大小
OS_STK START_STK[ START_SIZE ] ; //任务堆栈
void Start( void *pdata )
{
OS_CPU_SR cpu_sr=0 ;
pdata = pdata ;
OS_ENTER_CRITICAL() ; //进入临界区(无法被中断打断)
OSTaskCreate( Task01, ( void * )0, ( OS_STK* )&TASK01_STK[ TASK01_SIZE-1 ], TASK01_PRIO ) ;
OSTaskCreate( Task02, ( void * )0, ( OS_STK* )&TASK02_STK[ TASK02_SIZE-1 ], TASK02_PRIO ) ;
OSTaskSuspend( START_PRIO ) ; //挂起起始任务
OS_EXIT_CRITICAL() ; //退出临界区(可以被中断打断)
}
/****************************************************
Name :Main
Function :主函数
Paramater :None
Return :None
****************************************************/
int main()
{
STM32_Clock_Init( 9 ) ; //系统时钟设置
SysTick_Init( 72 ) ; //延时初始化
USART1_Init( 72, 115200 ) ; //串口初始化为115200
OSInit() ;
OSTaskCreate( Start, ( void * )0, ( OS_STK * )&START_STK[ START_SIZE-1 ], START_PRIO ) ; //创建起始任务
OSStart() ;
while( 1 ) ;
}
将程序下载进单片机,打开串口助手可以看到以下的效果。
通过时间可以看出,Task2的任务2s打印一次数据,Task1的任务1s打印一次数据,和我们程序所写一致,所以说明UCOS-II系统移植成功。
全部0条评论
快来发表一下你的评论吧 !