基于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》
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 <stdio.h>
#include "NUC100Series.h"
#include "MCU_init.h"
#include "SYS_init.h"
#include <ucos_ii.h>
#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 <stdio.h>
#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版的都是一样的 关键是在串口中断中使用队列是否有特殊的要求呢?
消息 队列 有空 研究一下
(稍后补充)