基于ucos操作系统的LED闪烁、串口通信简单例程

基于ucos操作系统的LED闪烁、串口通信简单例程

任务需求描述:

开发板上面3个LED灯,LED1,LED2,LED3.
默认闪烁间隔 500 ticks

可以通过串口 ,设置3个LED灯中,任意一个的闪烁频率。

设置方式为:

设置LED1的闪烁间隔时间是100ticks: 通过串口发送字符串: L1 100F

设置LED2的闪烁间隔时间是200ticks: 通过串口发送字符串: L2 200F

设置LED3的闪烁间隔时间是300ticks: 通过串口发送字符串: L3 300F

下面代码实现 有一个问题

下面的代码中,unsigned char RxBuffer[400],
会有可能被中断函数 和task0 同时访问,

以后改进代码的时候,需要,使用malloc的方式,或者使用内存池,
或者循环队列等等方式。

参考资料:

《奋斗版STM32开发板基于uCosII 2.86的LED灯闪烁实验手册.pdf》
基于ucos操作系统的LED闪烁、串口通信简单例程_第1张图片
LZ blog:http://www.cnblogs.com/zjutlitao/

工程代码:http://pan.baidu.com/s/1jG850X4

1. 任务划分

本例程操作系统采用ucos2.86a版本, 建立了5个任务
任务名 优先级
APP_TASK_START_PRIO 2 主任务
Task_Com1_PRIO 4 COM1通信任务
Task_Led1_PRIO 7 LED1 闪烁任务
Task_Led2_PRIO 8 LED2 闪烁任务
Task_Led3_PRIO 9 LED3 闪烁任务
当然还包含了系统任务:
OS_TaskIdle 空闲任务-----------------优先级最低
OS_TaskStat 统计运行时间的任务-------优先级次低

输入:L1 100F

在Nu_LB_NUC140 板子上面移植部分代码

E:\Nu_LB_Nuc140\ucos\Nu_LB_NUC140_UCOSII_UART

#include 
#include "NUC100Series.h"
#include "MCU_init.h"
#include "SYS_init.h"

#include 
#include "app_cfg.h" 
#include "cpu.h"

#define STACKSIZE 128


OS_STK Task0_Stack[STACKSIZE]; 
void Task0(void *Id);
#define Task0_Prio        5


OS_STK Task1_Stack[STACKSIZE]; 
void Task1(void *Id);
#define Task1_Prio        21

OS_STK Task2_Stack[STACKSIZE]; 
void Task2(void *Id); 
#define  Task2_Prio       22

OS_STK Task3_Stack[STACKSIZE]; 
void Task3(void *Id); 
#define  Task3_Prio       23



OS_EVENT* Com_MBOX;  

unsigned char RxBuffer[400];
volatile unsigned int RxCounter = 0; 

volatile unsigned  int  Led1Delay = 500;
volatile unsigned  int  Led2Delay = 500;
volatile unsigned  int  Led3Delay = 500;



void SysTick_Handler(void)
{
	OS_CPU_SR  cpu_sr;

	OS_ENTER_CRITICAL();;                                       
	OSIntNesting++;
	OS_EXIT_CRITICAL();

	OSTimeTick();

	OSIntExit();
}

int status = 0 ;

void HandleRcvMsg(char ch,int clr_flg)
{
	switch(status){

		case 0 :
			
			if(ch == 'L'){
				status = 1 ;
				RxBuffer[0]= ch;
				RxCounter = 1 ;
				UART_ENABLE_INT(UART0, UART_IER_TOUT_IEN_Msk);
			}
			break ;
	
		case 1 :

			RxBuffer[RxCounter++] = ch ;
			
			if(ch == 'F'){

				status = 0 ;
				UART_DISABLE_INT(UART0, UART_IER_TOUT_IEN_Msk);
				OSMboxPost(Com_MBOX,(void *)&RxBuffer);
			}			

			if(clr_flg == 1){

				status = 0 ;
				RxCounter = 0 ;
				UART_DISABLE_INT(UART0, UART_IER_TOUT_IEN_Msk);
			}
			
			break ;		
		
		default :

			break ;
	}	

	
}

void UART02_IRQHandler(void)
{
	OS_CPU_SR  cpu_sr;
	
	unsigned char ch;
	
	OS_ENTER_CRITICAL();;                                       
	OSIntNesting++;
	OS_EXIT_CRITICAL();

	while(UART_IS_RX_READY(UART0)){
	
		ch = UART_READ(UART0);
		printf("%c",ch);

		HandleRcvMsg(ch,0);
				
	}

	if(((UART0)->ISR & UART_ISR_TOUT_IF_Msk)>>UART_ISR_TOUT_IF_Pos){

		HandleRcvMsg('0',1);
	}
	
	
	OSIntExit();
}



/*
	GPB0 --- UART_RXD0
	GPB1 --- UART_TXD0
*/

int  App_Main (void)
{

	CPU_INT08U  err;

	Led1Delay = 500 ;
	Led2Delay = 500 ;
	Led3Delay = 500 ;
	/*初始化 SysTick时钟*/
	SysTick_Config(120000);
	
	OSInit();
	

	Com_MBOX=OSMboxCreate((void *) 0);		     //建立串口1中断的消息邮箱
	
	OSTaskCreate(Task0,  (void *)0,  (OS_STK *)&Task0_Stack[STACKSIZE-1],  Task0_Prio);	
	
	OSTaskCreate(Task1,  (void *)0,  (OS_STK *)&Task1_Stack[STACKSIZE-1],  Task1_Prio);	
	
	OSTaskCreate(Task2,  (void *)0,  (OS_STK *)&Task2_Stack[STACKSIZE-1],  Task2_Prio);
	
	OSTaskCreate(Task3,  (void *)0,  (OS_STK *)&Task3_Stack[STACKSIZE-1],  Task3_Prio);


	OSStart();                                                  /* Start multitasking (i.e. give control to uC/OS-II).  */
	
	return 0 ;
}


void Task0(void *Id)
{
	INT8U err;	
	unsigned char * msg;	
	int data ;
 
	for(;;){		

		msg=(unsigned char *)OSMboxPend(Com_MBOX,0,&err);

		if(msg[0]=='L'&&msg[1]==0x31){		
			printf("\nLED1\n");
			
			data = atoi(&msg[3]);
			printf("%d\n",data);
			if(data > 0){
				
				Led1Delay = data ;
			}
			
		}else if(msg[0]=='L'&&msg[1]==0x32){

			printf("\nLED2\n");	
			
			data = atoi(&msg[3]);
			printf("%d\n",data);
			if(data > 0){
				Led2Delay = data ;
			}

		}else if(msg[0]=='L'&&msg[1]==0x33){

			printf("\nLED3\n");	
			
			data = atoi(&msg[3]);
			printf("%d\n",data);
			if(data > 0){
				Led3Delay = data ;
			}

		}		
		
		#if 0 
		PC12 = 0;
		OSTimeDly(500);
		PC12 =  1;
		OSTimeDly(500);
		#endif
	}
}



void Task1(void *Id)
{
	INT8U err;	
	for(;;){		
		
		
		PC13 = 0;
		OSTimeDly(Led1Delay);
		PC13 =  1;
		OSTimeDly(Led1Delay);
		
	}
}

void Task2(void *Id)
{
	INT8U err;
	for (;;)
	{		

		PC14 = 0 ;
		OSTimeDly(Led2Delay);		
		PC14 = 1 ;	
		OSTimeDly(Led2Delay);		
		
	}
}

void Task3(void *Id)
{
	INT8U err;
	for (;;)
	{		

		PC15 = 0 ;
		OSTimeDly(Led3Delay);		
		PC15 = 1 ;	
		OSTimeDly(Led3Delay);
		
	}
}
	

初始化部分代码:

#include 
#include "NUC100Series.h"
#include "MCU_init.h"
#include "SYS_init.h"

int  App_Main (void);

int main(void)
{
  SYS_Init(); 	 

  UART_Open(UART0, 115200);

  UART_ENABLE_INT(UART0, UART_IER_RDA_IE_Msk);
 
  
  NVIC_EnableIRQ(UART02_IRQn);		
	
	printf("Hello World \r\n");	
	
	GPIO_SetMode(PC, BIT12, GPIO_MODE_OUTPUT);
	GPIO_SetMode(PC, BIT13, GPIO_MODE_OUTPUT);
	GPIO_SetMode(PC, BIT14, GPIO_MODE_OUTPUT);
	GPIO_SetMode(PC, BIT15, GPIO_MODE_OUTPUT);
	GPIO_SetMode(PA, BIT13, GPIO_MODE_OUTPUT);
	  

	App_Main();
	
    while(1) {
		;
	}
	
}

移植后的代码:

https://download.csdn.net/download/wowocpp/10969058

别人的解决方案:

http://www.openedv.com/posts/list/26938.htm

小苗开发板的环形队列
放弃OS的消息队列

你可以看下我们的例程么?
我们战舰板,ucosii的例程。

对于队列的使用和mini版的都是一样的 关键是在串口中断中使用队列是否有特殊的要求呢?

消息 队列 有空 研究一下
(稍后补充)

你可能感兴趣的:(rtos)