FreeRtos系统

前后台系统

       早期嵌入式开发没有嵌入式操作系统概念,直接操作裸机,直接在逻辑上写程序,比如51单片机没有操作系统的概念。通常把程序分为前台系统和后台系统。      

       签单的小系统通常是前后台系统。这样的程序包括一个死循环和若干个中断服务程序:应用程序是一个无限循环,循环中调用API库函数完成作需的操作,大循环叫做后台系统。中断服务程序用于处理系统的异步事件,也就是前台系统。前台是中断级,后台是任务级。

RTOS系统

RTOS全称为:Real time OS ,就是实时操作系统,强调的是:实时性。

实时操作系统又分为软实时和硬实时。硬实时要求在规定的时间内必须完成操作,硬实时不允许超时,软实时里面处理过程超时的后果就没有那么严格。          

在实时操作系统种,我们可以把要实现的功能划分为多个任务,每个任务负责实现其中的一部分,每个任务都是一个很简单的程序,通常是一个死循环。    RTOS操作系统: Freertos, UCOS,RTX,RT-THread,DJYOS等    

RTOS操作系统的核心内容在于: 实时内核。 

可剥夺型内核

RTOS的内核负责管理所有的任务,内核决定了运行哪个任务,何时停止当前任务切换到其他任务,这个是内核的多任务管理能力。多任务管理给人的感觉就是芯片有多个CPU,多任务管理实现了CPU资源的最大化利用,多任务管理有助于实现程序的模块化开发,能够实现复杂的实时用。   

可剥夺型内核顾名思义就是可以剥夺其他任务的CPU使用权,他总是运行就绪任务中优先级最高的任务。

FreeRtos系统简介

Freertos是一个可剪裁,可剥夺型的多任务内核,而且没有任务数限制。Freertos提供了实时操作系统所需的所有功能,包括资源管理、同步、任务通信等。    

Freertos是用C和汇编来写的,其中绝大部分都是用C语言编写的,只有极少数的与处理器密切相关的部分代码才是用汇编写的,Freertos结构简洁,可读性很强!最主要的是非常适合初次接触嵌入式实时操作系统开发者。

FreeRTOS任务特性

1.任务简单

2.任务没有数量使用限制

3.任务支持抢占(抢占式内核)

4.任务支持优先级

5.每个任务都拥有堆栈导致了RAM使用量增大

6.如果使用抢占的话必须仔细的考虑重入问题

FreeRTOS任务状态

FreeRTOS任务优先级

任务优先级决定了任务的执行优先级别,在FreeRTOS中优先级可选范围位:

  0 ~ configMAX_PRIORITIES-1

数字越大,优先级越高

FreeRTOS任务实现

任务实现即为任务的具体工作内容

void vATaskFuntion(void *pvParameters )

{  

 for(;;)    

    {                 --任务应用程序--    vTaskDelay();                      /*不能从任务函数中直接退出,     否则会调用configASSERT(),要退出一定要调用vTaskDelete(NULL)删除此任务。*/    

    }            

 vTaskDelete(NULL);

}

FreeRTOS任务控制块

描述任务属性的数据结构称为任务控制块,称为TCB_t.

typedef struct tskTaskControlBlock   {    

volatile StackType_t * pxTopOfStack;     #if ( portUSING_MPU_WRAPPERS == 1 )                                                                                       xMPU_SETTINGS xMPUSettings;    

                                                               #endif    

                                                                ListItem_t   xStateListItem;                      

                                                                ListItem_t xEventListItem;                              

                                                               UBaseType_t   uxPriority;                    

                                                                StackType_t * pxStack;

  } tskTCB  typedef tskTCB TCB_t;

FreeRTOS任务堆栈

    任务堆栈用来保存任务现场(CPU寄存器值),创建任务的时候需要指定任务堆栈, 任务堆栈的变量类型为  StackType_t ,此变量类型如下:  

#define portSTACK_TYPE uint32_t  

#define portBASK_TYPE long  

#define portSTACK_TYPE StackType_t

任务创建和删除API函数

建立一个任务,控制led灯的闪烁

led灯的初始化

void LED_Init(void)
{
 
 GPIO_InitTypeDef  GPIO_InitStructure;
 	
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOE, ENABLE);	 //ʹÄÜPB,PE¶Ë¿ÚʱÖÓ
	
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;				 //LED0-->PB.5 ¶Ë¿ÚÅäÖÃ
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //ÍÆÍìÊä³ö
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO¿ÚËÙ¶ÈΪ50MHz
 GPIO_Init(GPIOC, &GPIO_InitStructure);					 //¸ù¾ÝÉ趨²ÎÊý³õʼ»¯GPIOB.5
 GPIO_SetBits(GPIOC,GPIO_Pin_13);						 //PB.5 Êä³ö¸ß

 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;	    		 //LED1-->PE.5 ¶Ë¿ÚÅäÖÃ, ÍÆÍìÊä³ö
 GPIO_Init(GPIOA, &GPIO_InitStructure);	  				 //ÍÆÍìÊä³ö £¬IO¿ÚËÙ¶ÈΪ50MHz
 GPIO_SetBits(GPIOA,GPIO_Pin_5); 						 //PE.5 Êä³ö¸ß 
}

延迟初始化

void delay_init()
{
	u32 reload;
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//Ñ¡ÔñÍⲿʱÖÓ  HCLK
	fac_us=SystemCoreClock/1000000;				//²»ÂÛÊÇ·ñʹÓÃOS,fac_us¶¼ÐèҪʹÓÃ
	reload=SystemCoreClock/1000000;				//ÿÃëÖӵļÆÊý´ÎÊý µ¥Î»ÎªM  
	reload*=1000000/configTICK_RATE_HZ;			//¸ù¾ÝconfigTICK_RATE_HZÉ趨Òç³öʱ¼ä
												//reloadΪ24λ¼Ä´æÆ÷,×î´óÖµ:16777216,ÔÚ72MÏÂ,Ô¼ºÏ0.233s×óÓÒ	
	fac_ms=1000/configTICK_RATE_HZ;				//´ú±íOS¿ÉÒÔÑÓʱµÄ×îÉÙµ¥Î»	   

	SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;   	//¿ªÆôSYSTICKÖжÏ
	SysTick->LOAD=reload; 						//ÿ1/configTICK_RATE_HZÃëÖжÏÒ»´Î	
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;   	//¿ªÆôSYSTICK    
}	

串口初始化

void uart_init(u32 bound){
	//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_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 = bound;//´®¿Ú²¨ÌØÂÊ
	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 
}

动态

//ÈÎÎñÓÅÏȼ¶
#define START_TASK_PRIO		1
//ÈÎÎñ¶ÑÕ»´óС	
#define START_STK_SIZE 		128  
//ÈÎÎñ¾ä±ú
TaskHandle_t StartTask_Handler;
//ÈÎÎñº¯Êý
void start_task(void *pvParameters);

//ÈÎÎñÓÅÏȼ¶
#define LED0_TASK_PRIO		2
//ÈÎÎñ¶ÑÕ»´óС	
#define LED0_STK_SIZE 		50  
//ÈÎÎñ¾ä±ú
TaskHandle_t LED0Task_Handler;
//ÈÎÎñº¯Êý
void led0_task(void *pvParameters);

//ÈÎÎñÓÅÏȼ¶
#define LED1_TASK_PRIO		3
//ÈÎÎñ¶ÑÕ»´óС	
#define LED1_STK_SIZE 		50  
//ÈÎÎñ¾ä±ú
TaskHandle_t LED1Task_Handler;
//ÈÎÎñº¯Êý
void led1_task(void *pvParameters);

int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//ÉèÖÃϵͳÖжÏÓÅÏȼ¶·Ö×é4	 
	delay_init();	    				//ÑÓʱº¯Êý³õʼ»¯	  
	uart_init(115200);					//³õʼ»¯´®¿Ú
	LED_Init();		  					//³õʼ»¯LED
	 
	//´´½¨¿ªÊ¼ÈÎÎñ
    xTaskCreate((TaskFunction_t )start_task,            //ÈÎÎñº¯Êý
                (const char*    )"start_task",          //ÈÎÎñÃû³Æ
                (uint16_t       )START_STK_SIZE,        //ÈÎÎñ¶ÑÕ»´óС
                (void*          )NULL,                  //´«µÝ¸øÈÎÎñº¯ÊýµÄ²ÎÊý
                (UBaseType_t    )START_TASK_PRIO,       //ÈÎÎñÓÅÏȼ¶
                (TaskHandle_t*  )&StartTask_Handler);   //ÈÎÎñ¾ä±ú              
    vTaskStartScheduler();          //¿ªÆôÈÎÎñµ÷¶È
}

//¿ªÊ¼ÈÎÎñÈÎÎñº¯Êý
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //½øÈëÁÙ½çÇø
    //´´½¨LED0ÈÎÎñ
    xTaskCreate((TaskFunction_t )led0_task,     	
                (const char*    )"led0_task",   	
                (uint16_t       )LED0_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )LED0_TASK_PRIO,	
                (TaskHandle_t*  )&LED0Task_Handler);   
    //´´½¨LED1ÈÎÎñ
    xTaskCreate((TaskFunction_t )led1_task,     
                (const char*    )"led1_task",   
                (uint16_t       )LED1_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )LED1_TASK_PRIO,
                (TaskHandle_t*  )&LED1Task_Handler);         
    vTaskDelete(StartTask_Handler); //ɾ³ý¿ªÊ¼ÈÎÎñ
    taskEXIT_CRITICAL();            //Í˳öÁÙ½çÇø
}

//LED0ÈÎÎñº¯Êý 
void led0_task(void *pvParameters)
{
    while(1)
    {
        LED0=~LED0;
        vTaskDelay(500);
			  printf("tash0");
    }
}   

//LED1ÈÎÎñº¯Êý
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=0;
        vTaskDelay(200);
        LED1=1;
        vTaskDelay(800);
			  printf("task1");
    }
}

静态

//¿ªÊ¼ÈÎÎñ
#define STARE_SIZE 120
#define START_PRIO 1
void start_task(void *pvParameters);
TaskHandle_t StartTask_Handle;
StaticTask_t startTIDLTCB;
StackType_t startidletaskstack[STARE_SIZE];
//led0
#define LED0_STK_SIZE 120
#define LED0_TASK_PRIO 1
TaskHandle_t LED0Task_Handler;
void start_task(void *pvParameters);
void led0_task(void *pvParameters);
StaticTask_t led0TIDLTCB;
StackType_t led0idletaskstack[LED0_STK_SIZE];

//led1
#define LED1_STK_SIZE 120
#define LED1_TASK_PRIO 1
void start_task(void *pvParameters);
void led1_task(void *pvParameters);
TaskHandle_t LED1Task_Handler;
StaticTask_t led1TIDLTCB;
StackType_t led1idletaskstack[LED1_STK_SIZE];
//¿ÕÏÐÈÎÎñ
static StaticTask_t TIDLTCB;
static StackType_t idletaskstack[configMINIMAL_STACK_SIZE];

void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
                                    StackType_t ** ppxIdleTaskStackBuffer,
                                    uint32_t * pulIdleTaskStackSize )
{
	* ppxIdleTaskTCBBuffer=&TIDLTCB;
	* ppxIdleTaskStackBuffer=idletaskstack;
	* pulIdleTaskStackSize=configMINIMAL_STACK_SIZE;
}
static StaticTask_t TimerLTCB;
static StackType_t  timerletaskstack[configTIMER_TASK_STACK_DEPTH];
//¶¨Ê±Æ÷ÈÎÎñ
  extern void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
                                          StackType_t ** ppxTimerTaskStackBuffer,
                                              uint32_t * pulTimerTaskStackSize )
{
	* ppxTimerTaskTCBBuffer=&TimerLTCB;
	* ppxTimerTaskStackBuffer=timerletaskstack;
	* pulTimerTaskStackSize=configTIMER_TASK_STACK_DEPTH;
	
}




int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//ÉèÖÃϵͳÖжÏÓÅÏȼ¶·Ö×é4	 
	delay_init();	    				//ÑÓʱº¯Êý³õʼ»¯	  
	uart_init(115200);					//³õʼ»¯´®¿Ú
	LED_Init();		  					//³õʼ»¯LED
	GPIO_SetBits(GPIOA,GPIO_Pin_5); 	 
	//´´½¨¿ªÊ¼ÈÎÎñ
  StartTask_Handle = xTaskCreateStatic( (TaskFunction_t) start_task,
											 (char * )        "start_task",     
											 (uint32_t)        STARE_SIZE,
											(void *)            NULL,
											(UBaseType_t)      START_PRIO,
											(StackType_t *)    startidletaskstack,
											(StaticTask_t *)   &startTIDLTCB);
    vTaskStartScheduler();         
}

//¿ªÊ¼ÈÎÎñÈÎÎñº¯Êý
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //½øÈëÁÙ½çÇø
    //´´½¨LED0ÈÎÎñ
  LED0Task_Handler = xTaskCreateStatic( (TaskFunction_t) led0_task,
											 (char * )        "led0_task",     
											 (uint32_t)        LED0_STK_SIZE,
											(void *)            NULL,
											(UBaseType_t)      LED0_TASK_PRIO,
											(StackType_t *)    led0idletaskstack,
											(StaticTask_t *)   &led0TIDLTCB);
    //´´½¨LED1ÈÎÎñ
   LED1Task_Handler = xTaskCreateStatic( (TaskFunction_t) led1_task,
											 (char * )        "led1_task",     
											 (uint32_t)        LED1_STK_SIZE,
											(void *)            NULL,
											(UBaseType_t)      LED1_TASK_PRIO,
											(StackType_t *)    led1idletaskstack
											,
											(StaticTask_t *)   &led1TIDLTCB);        
    vTaskDelete(StartTask_Handle); //ɾ³ý¿ªÊ¼ÈÎÎñ
}

//LED0ÈÎÎñº¯Êý 
void led0_task(void *pvParameters)
{
    while(1)
    {
        LED0=~LED0;
        vTaskDelay(500);
			  printf("led0");
    }
}   

//LED1ÈÎÎñº¯Êý
void led1_task(void *pvParameters)
{
    while(1)
    {
        LED1=~LED1;
        vTaskDelay(500);
			  printf("led1");
    }
}

任务的恢复和挂起API

我在动态的基础上加了一个振动器

振动器的初始化

void key_init(void)
{
	GPIO_InitTypeDef  keyinit;
	
	RCC_APB2PeriphClockCmd(  RCC_APB2Periph_GPIOB ,  ENABLE);

	
	keyinit.GPIO_Mode = GPIO_Mode_IPD;
	keyinit.GPIO_Pin  = GPIO_Pin_10;
	keyinit.GPIO_Speed =   GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &keyinit);
	
	keyinit.GPIO_Mode = GPIO_Mode_IPD;
	keyinit.GPIO_Pin = GPIO_Pin_8;
	GPIO_Init(GPIOB, &keyinit);
	
}

振动器在主函数的使用

创建任务

    xTaskCreate((TaskFunction_t )KEY_task,     
                (const char*    )"KEY_task",   
                (uint16_t       )KEY_STK_SIZE, 
                (void*          )NULL,
                (UBaseType_t    )KEY_TASK_PRIO,
                (TaskHandle_t*  )&KEYTask_Handler); 

key任务函数 

void KEY_task(void *pvParameters)
{
	while(1)
	{
		if(GPIO_ReadInputDataBit( GPIOB,  GPIO_Pin_10)==0)
		{
			vTaskDelay(800);
			vTaskSuspend(LED0Task_Handler);
			printf("led0 is supsend");
		}
		else if(GPIO_ReadInputDataBit( GPIOB,  GPIO_Pin_8)==0)
		{
			vTaskDelay(800);
			vTaskResume(LED0Task_Handler);
			printf("led0 is supsend");
		}
	}
}

如果要是外部中断的话跟上面的是一样,不一样的地方就是将恢复状态放到中断函数的处理函数中

Cortex-M中断

中断简介

中断是微控制器一个很常见的特性,中断由硬件产生,当中断产生之后CPU就会中断当前的流程而去处理中断服务,Cortex-M 内核的MCU提供了一个用于中断管理的嵌套向量中断控制器NVIC。        Cotex-M3和M4的NVIC最多支持240个IRQ(中断请求),1个不可屏蔽中断(NMI),1个Systick(滴答定时器)定时器中断和多个系统异常。    与中断相关的寄存器都在NVIC和SCB中。

优先级分组

 为了使抢占机能变得更加可控,CM3还把256级优先级按位分成高低两段,分别是抢占优先级和亚优先级,MSB所在的位段(左边的)对应抢占优先级,而LSB所在的位段(右边的)对应亚优先级。

优先级设置

对于外设中断优先级的设置可以通过寄存器:        0XE000_E400 ~ 0XE000E4EF        

系统异常中断通过寄存器        0XE000_ED18 ~ 0XE000ED23

中断屏蔽寄存器

中断屏蔽寄存器有3个:

1.PRIMASK

2.PAULTMASK

3.BASEPRI

1.开中断函数 portENABLE_INTERRUPTS()

2.关中断函数 portDISABLE_INTERRUPTS()

FreeRtos中断实验

初始化两个定时器中断


Timer3

void TIM3_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //ʱÖÓʹÄÜ
	
	//¶¨Ê±Æ÷TIM3³õʼ»¯
	TIM_TimeBaseStructure.TIM_Period = arr; //ÉèÖÃÔÚÏÂÒ»¸ö¸üÐÂʼþ×°Èë»î¶¯µÄ×Ô¶¯ÖØ×°ÔؼĴæÆ÷ÖÜÆÚµÄÖµ	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //ÉèÖÃÓÃÀ´×÷ΪTIMxʱÖÓƵÂʳýÊýµÄÔ¤·ÖƵֵ
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //ÉèÖÃʱÖÓ·Ö¸î:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIMÏòÉϼÆÊýģʽ
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ»¯TIMxµÄʱ¼ä»ùÊýµ¥Î»
 
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //ʹÄÜÖ¸¶¨µÄTIM3ÖжÏ,ÔÊÐí¸üÐÂÖжÏ

	//ÖжÏÓÅÏȼ¶NVICÉèÖÃ
	NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3ÖжÏ
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 4;  //ÏÈÕ¼ÓÅÏȼ¶4¼¶
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //´ÓÓÅÏȼ¶0¼¶
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQͨµÀ±»Ê¹ÄÜ
	NVIC_Init(&NVIC_InitStructure);  //³õʼ»¯NVIC¼Ä´æÆ÷

	TIM_Cmd(TIM3, ENABLE);  //ʹÄÜTIMx					 
}

Timer5

void TIM5_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;

	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); //ʱÖÓʹÄÜ
	
	//¶¨Ê±Æ÷TIM5³õʼ»¯
	TIM_TimeBaseStructure.TIM_Period = arr; 					//ÉèÖÃÔÚÏÂÒ»¸ö¸üÐÂʼþ×°Èë»î¶¯µÄ×Ô¶¯ÖØ×°ÔؼĴæÆ÷ÖÜÆÚµÄÖµ	
	TIM_TimeBaseStructure.TIM_Prescaler =psc; 					//ÉèÖÃÓÃÀ´×÷ΪTIMxʱÖÓƵÂʳýÊýµÄÔ¤·ÖƵֵ
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; 	//ÉèÖÃʱÖÓ·Ö¸î:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIMÏòÉϼÆÊýģʽ
	TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure); 			//¸ù¾ÝÖ¸¶¨µÄ²ÎÊý³õʼ»¯TIMxµÄʱ¼ä»ùÊýµ¥Î»
 
	TIM_ITConfig(TIM5,TIM_IT_Update,ENABLE ); 					//ʹÄÜÖ¸¶¨µÄTIM5ÖжÏ,ÔÊÐí¸üÐÂÖжÏ

	//ÖжÏÓÅÏȼ¶NVICÉèÖÃ
	NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn;  			//TIM5ÖжÏ
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5;  	//ÏÈÕ¼ÓÅÏȼ¶5¼¶
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  		//´ÓÓÅÏȼ¶0¼¶
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 			//IRQͨµÀ±»Ê¹ÄÜ
	NVIC_Init(&NVIC_InitStructure);  							//³õʼ»¯NVIC¼Ä´æÆ÷

	TIM_Cmd(TIM5, ENABLE);  									//ʹÄÜTIM5					 
}

定时器3的服务中断函数

void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //Òç³öÖжÏ
	{
		printf("TIM3Êä³ö.......\r\n");
	}
	TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //Çå³ýÖжϱê־λ
}

定时器5的服务中断函数

void TIM5_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM5,TIM_IT_Update)==SET) //Òç³öÖжÏ
	{
		printf("TIM5Êä³ö.......\r\n");
	}
	TIM_ClearITPendingBit(TIM5,TIM_IT_Update);  //Çå³ýÖжϱê־λ
}

主函数中的测试任务函数

void interrupt_task(void *pvParameters)
{
	static u32 total_num=0;
    while(1)
    {
		total_num+=1;
		if(total_num==5) 
		{
			printf("¹Ø±ÕÖжÏ.............\r\n");
			portDISABLE_INTERRUPTS();				//¹Ø±ÕÖжÏ
			delay_xms(5000);						//ÑÓʱ5s
			printf("´ò¿ªÖжÏ.............\r\n");	//´ò¿ªÖжÏ
			portENABLE_INTERRUPTS();
		}
        LED0=~LED0;
        vTaskDelay(1000);
    }
} 

列表和列表项

Freertos列表与列表项是Freertos的一个数据结构,类似于链表。 Freertos中大量使用了列表和列表项,它是Freertos中的基石 方便我们学习Freertos源码和原理。

列表   

 列表是 Freertos中的一个数据结构,概念上和链表有点类似,列表被用于跟踪Freertos的任务。列表结构为List_t,在文件list.h中定义:

列表项相关API函数

注意在插入一般是按照插入数字的大小来排序的,列表其实就是一个双向链表,如果要是只有两个的话,就是两者互相指。

FreeRTOS信息查询和任务统计

可以根据操作手册简单测试一下

ESP8266 WIFI

        ESP-01s模块它是由一颗ESP8266作为主控再由一颗flash作为存储芯片组成的,带有板载芯片供电采用3.3V电压使用串口进行烧写程序和AT指令集调试的,注意芯片一旦烧写了程序便不可使用AT指令集需要重新刷回AT指令集固件才可以使用AT指令集 。

AT指令

CR (Carriage Return ) 表示回车       \r

LF (Line Feed)表示换行  \n

Dos和Windows采用回车+换行(CR+LF)

表示下一行 Unix/Linux采用换行符(LF)表示下一行 MAC OS 系统采用和回车符(CR)

表示下一行 Windows下编写的Shell脚本,直接放到Linux/unix下执行会报错, 就是因为行结束符不一样导致的。 \r 表示回车  \n 表示换行   \r\n表示回车换行

AT指令说明

常用AT指令 

ESP8266三种模式

1.Station(客户端模式)

2.AP(接入点模式)

3.Station+AP模式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值