查看: 1932|回复: 0
打印 上一主题 下一主题

ucos-ii学习笔记——s12 lcd led 两任务信号量通信

[复制链接]
跳转到指定楼层
沙发
发表于 2015-4-13 21:15:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

Created on: 2012-10-17

      Author: zhang bin

学习笔记

for ucos-ii MC9S12XS128 lcd12864 ser_2_pin

redesigned by zhang bin

2012-10-17

versions:V-0.1

All Rights Reserved

//本程序实现lcd的显示和led的闪烁,这两个任务通过信号量进行通信,要实现的效果如下:

//lcd任务申请一个信号量后 显示完一个周期后停止显示并且释放信号量,led任务申请到信号量后开始闪烁,闪烁了10

//次后停止,释放信号量,lcd任务再申请信号量,继续开始显示,如此循环

//本程序实现lcd的显示和led的闪烁,这两个任务通过信号量进行通信,要实现的效果如下:

//lcd任务申请一个信号量后 显示完一个周期后停止显示并且释放信号量,led任务申请到信号量后开始闪烁,闪烁了10

//次后停止,释放信号量,lcd任务再申请信号量,继续开始显示,如此循环

#include "includes.h"

#include "pll.h"

#include "string.h"

#include "ser_12864.h"

#define  TASK_STK_SIZE    128  //定义任务堆栈长度

#define  TASK_START_PRIO    5    // 此版本的uC/OS-II最多支持256个用户定义任务。优先级号越低,任务的优先级别就越高

#define  TASK_1_PRIO       10

#define  TASK_2_PRIO       12

#define  TASK_3_PRIO       8

#define  TASK_4_PRIO       16

#define  TASK_5_PRIO       18

#define  TASK_6_PRIO       20

#define  TASK_7_PRIO       22

#define  TASK_8_PRIO       24

#define  TASK_9_PRIO       26

#define  TASK_A_PRIO       28

#define  TASK_B_PRIO       30

#define  TASK_C_PRIO       32

#define  TASK_D_PRIO       34

#define  TASK_E_PRIO       36

#define  TASK_F_PRIO       38

#define  MUTEX_PIP_1        8

#define  MUTEX_PIP_2        9

#define  EVENT_Q_1_SIZE    10

#define  EVENT_Q_2_SIZE    20

#define  MEM_BLKS_1        10

#define  MEM_BLK_SIZE_1     8

#define  MEM_BLKS_2         8

#define  MEM_BLK_SIZE_2    12

OS_STK       lcd_task_stk[TASK_STK_SIZE];  //定义任务堆栈

OS_STK       led_task_stk[TASK_STK_SIZE];

OS_STK        AppStartTaskStk[TASK_STK_SIZE]; //创建任务堆栈OS_STK 创建任务参数指针TASKDATA,调用函数创建任务

OS_STK        AppTask1Stk[TASK_STK_SIZE];

OS_STK        AppTask2Stk[TASK_STK_SIZE];

OS_STK        AppTask3Stk[TASK_STK_SIZE];

OS_STK        AppTask4Stk[TASK_STK_SIZE];               

OS_STK        AppTask5Stk[TASK_STK_SIZE];

OS_STK        AppTask6Stk[TASK_STK_SIZE];

OS_STK        AppTask7Stk[TASK_STK_SIZE];

OS_STK        AppTask8Stk[TASK_STK_SIZE];

OS_STK        AppTask9Stk[TASK_STK_SIZE];

OS_STK        AppTaskAStk[TASK_STK_SIZE];

OS_STK        AppTaskBStk[TASK_STK_SIZE];

OS_STK        AppTaskCStk[TASK_STK_SIZE];

OS_STK        AppTaskDStk[TASK_STK_SIZE];

OS_STK        AppTaskEStk[TASK_STK_SIZE];

OS_STK        AppTaskFStk[TASK_STK_SIZE];

INT16U        AppTask1Ctr;

INT16U        AppTask2Ctr;

INT16U        AppTask3Ctr;

INT16U        AppTask4Ctr;

INT16U        AppTask5Ctr;

INT16U        AppTask6Ctr;

INT16U        AppTask7Ctr;

INT16U        AppTask8Ctr;

INT16U        AppTask9Ctr;

INT16U        AppTaskACtr;

INT16U        AppTaskBCtr;

INT16U        AppTaskCCtr;

INT16U        AppTaskDCtr;

INT16U        AppTaskECtr;

INT16U        AppTaskFCtr;

INT8U sensor=0;      //定义8路传感器采集变量

INT8U test_value;    //定义第八路传感器故障时的变量

//下面定义一些事件等,方便使用,不习惯使用下面的定义,自己定义也可以

#if OS_SEM_EN > 0            //如果信号量使能位允许

OS_EVENT     *EventSem1;     //声明信号量  是事件控制块ECB类型的指针 存放创建信号量函数返回的创建的

OS_EVENT     *EventSem2;     //信号量的指针

#endif

#if OS_MBOX_EN > 0         

OS_EVENT     *EventMbox1;  //声明消息邮箱 是事件控制块ECB类型的指针

OS_EVENT     *EventMbox2;

#endif

#if OS_Q_EN > 0

OS_EVENT     *EventQ1;      //声明消息队列

OS_EVENT     *EventQ2;

void         *EventQTbl1[EVENT_Q_1_SIZE];

void         *EventQTbl2[EVENT_Q_2_SIZE];

//定义消息指针数组

//创建消息队列,首先需要定义一个指针数组(用于存放消息邮箱),然后把各个消息数据缓冲区的首地址存入这个数组中

//最后再调用函数OSQCreate()来创建消息队列

#endif

#if OS_MUTEX_EN > 0

OS_EVENT     *EventMutex1;    //声明互斥信号量

OS_EVENT     *EventMutex2;

#endif

#if OS_FLAG_EN > 0

OS_FLAG_GRP  *FlagGrp1;    //声明事件标志组 是标志组OS_FLAG_GRP类型的指针

OS_FLAG_GRP  *FlagGrp2;     //事件控制块用来描述信号量,消息邮箱,消息队列。标志组用来描述事件标志组

#endif

#if OS_MEM_EN > 0

OS_MEM       *MemPart1;     //声明内存块  是内存控制块OS_MEM类型的指针

OS_MEM       *MemPart2;

INT8U         MemPart1Tbl[MEM_BLKS_1][MEM_BLK_SIZE_1];     //内存分区

INT8U         MemPart2Tbl[MEM_BLKS_2][MEM_BLK_SIZE_2];

#endif

//任务的函数声明

static  void  AppStartTask(void *pdata);

static  void  AppTaskCreate(void);

static  void  AppEventCreate(void);

static  void  AppTask1(void *pdata);

static  void  AppTask2(void *pdata);

static  void  AppTask3(void *pdata);

static  void  AppTask4(void *pdata);

static  void  AppTask5(void *pdata);

static  void  AppTask6(void *pdata);

static  void  AppTask7(void *pdata);

static  void  AppTask8(void *pdata);

static  void  AppTask9(void *pdata);

static  void  AppTaskA(void *pdata);

static  void  AppTaskB(void *pdata);

static  void  AppTaskC(void *pdata);

static  void  AppTaskD(void *pdata);

static  void  AppTaskE(void *pdata);

static  void  AppTaskF(void *pdata);

static  void  AppTickInit(void);

static  void  lcd_task(void *pdata);

static  void  led_task(void *pdata);

OS_EVENT *event_sem;  //声明信号量  是事件控制块ECB类型的指针 存放创建信号量函数返回的创建的

INT8U err;   //定义一个错误信息

   //12864要显示的内容

static unsigned char s1[] ={"  汉字显示LCD   "};

static unsigned char s2[] ={"MC9S12  开发系统"};

static unsigned char s3[] ={"good good study "};

static unsigned char s4[] ={"2012-10-17-H23"};

   

//INT8U times_lcd=0;    //记录任务lcd的运行次数

//INT8U times_led=0;  //任务led的运行次数

void main (void)

{                                    //因为没有外设,所以不存在硬件初始化函数

    INT8U  err;

    INT16U  Startdata=0x1234;     //???

    //开始执行的位置 另一种定义方式:TASKDATA.myPPAGE=0x1234,为结构体变量的初始化

   

    DDRB = 0xff;  //Bled设为输出

    PORTB = 0xff;  //led 初始状态为灭

   

    DDRA |= 0x03;   //液晶的两条线

    init_lcd();

   

    pllbus_init16m();    //时钟初始化为16M

//   LcdInit();           //LCD初始化

   

    OSInit();  

   

    event_sem=OSSemCreate(1);

    //在主函数中创建信号量 返回值为创建的信号量指针,参数是信号量的计数器的值

//用该参数对信号量计数器OSEventCnt进行初始化

//1即代表只创建一个信号量,代表信号量用于对共享资源的访问(例如,把它当做二值信号量使用),详见P166

    //创建起始任务,作用:初始化时钟滴答,为操作系统提供时钟。初始化统计任务,创建应用任务,建立事件

    OSTaskCreateExt(AppStartTask,      //创建开始任务  处于休眠态的任务经过这个函数处理后转为就绪态

                    (void *)&Startdata,   //???            

                    (OS_STK *)&AppStartTaskStk[TASK_STK_SIZE-1],

                    TASK_START_PRIO,            //优先级为5

                    TASK_START_PRIO,

                    (OS_STK *)&AppStartTaskStk[0],

                    TASK_STK_SIZE,

                    (void *)0,

                    OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);

             //该函数参数的具体介绍见P121      

                  

    OSTaskNameSet(TASK_START_PRIO, "Start Task", &err);   //设置任务的名称 作用??

    OSTaskNameSet(OS_TASK_IDLE_PRIO, "uC/OS-II Idle", &err);   //空闲任务

   

    OSTaskNameSet(OS_TASK_STAT_PRIO, "uC/OS-II Stat", &err);   //统计任务

   // #define OS_TASK_STAT_EN  1u   //Enable (1) or Disable(0) the statistics task

   //因为在本系统中os_cfg_r.h文件中把 OS_TASK_STAT_EN设为了1(如上),所以系统的统计任务会建立

   //统计任务的建立是在OSInit()中被创建的,代码如下:

   

   

   

         

   

         

    OSStart();     

}

static void  AppStartTask (void *pdata)

{

    pdata = pdata;     //pdata没有用到,这样的目的是防止编译器提出warning

   

    AppTickInit();      //初始化时钟滴答,为操作系统提供时钟

   

    OSStatInit();    //初始化统计任务

   

    AppTaskCreate();   //创建应用任务

   

  //  AppEventCreate();    //建立事件

    while (TRUE)    //任务一般都是一个无限循环的结构

    {                          

        OSTimeDlyHMSM(0, 0, 1, 0);     //等待1s,交出cpu,由于while无限循环中只有这一条语句,所以

                                      //该起始任务第一次运行以后,就一直处于挂起等待状态

    }

}

static  void  AppTaskCreate (void)        //使1-f的任务处于就绪态,一旦OSstart(),优先级最高的任务获得CPU的使用权

{

   // INT8U  err;       //错误信息

    OSTaskCreate(lcd_task,(void *)0,&lcd_task_stk[TASK_STK_SIZE-1],6);  //创建任务lcd_task,优先级为6

    OSTaskCreate(led_task,(void *)0,&led_task_stk[TASK_STK_SIZE-1],7);

   

                  

   

                     

}

static  void  AppEventCreate (void)

{

    INT8U  err;

#if OS_SEM_EN > 0

    EventSem1   = OSSemCreate(1);

    OSEventNameSet(EventSem1, "Sem. #1", &err);

    EventSem2   = OSSemCreate(1);

    OSEventNameSet(EventSem2, "Sem. #2", &err);

#endif

#if OS_MBOX_EN > 0

    EventMbox1  = OSMboxCreate((void *)1);

    OSEventNameSet(EventMbox1, "Mailbox #1", &err);

    EventMbox2  = OSMboxCreate((void *)1);

    OSEventNameSet(EventMbox2, "Mailbox #2", &err);

#endif

#if OS_Q_EN > 0

    EventQ1     = OSQCreate(&EventQTbl1[0], EVENT_Q_1_SIZE);

    OSEventNameSet(EventQ1, "Queue #1", &err);

    EventQ2     = OSQCreate(&EventQTbl2[0], EVENT_Q_2_SIZE);

    OSEventNameSet(EventQ2, "Queue #2", &err);

#endif

#if OS_MUTEX_EN > 0

    EventMutex1 = OSMutexCreate(MUTEX_PIP_1, &err);

    OSEventNameSet(EventMutex1, "Mutex #1", &err);

    EventMutex2 = OSMutexCreate(MUTEX_PIP_2, &err);

    OSEventNameSet(EventMutex2, "Mutex #2", &err);

#endif

#if OS_FLAG_EN > 0

    FlagGrp1    = OSFlagCreate(0x00FF, &err);

    OSFlagNameSet(FlagGrp1, "Flag #1", &err);

    FlagGrp2    = OSFlagCreate(0xFF00, &err);

    OSFlagNameSet(FlagGrp2, "Flag #2", &err);

#endif

#if OS_MEM_EN > 0

    MemPart1    = OSMemCreate(&MemPart1Tbl[0], MEM_BLKS_1, MEM_BLK_SIZE_1, &err);

    OSMemNameSet(MemPart1, "Partition #1", &err);

    MemPart2    = OSMemCreate(&MemPart2Tbl[0], MEM_BLKS_2, MEM_BLK_SIZE_2, &err);

    OSMemNameSet(MemPart2, "Partition #2", &err);

#endif

}

   

static void lcd_task(void *pdata)    //任务lcd_task的函数代码

{

   pdata=pdata;    //pdata没有用到,这样的目的是防止编译器提出warning

   

   for(;;)

   {

     OSSemPend(event_sem,0,&err);

     //请求信号量 参数Fun_Semp是信号量指针  0那一项是等待时限timeout0表示无限等待 err表示错误信息

     

       delay_ms(5);

       wr_string(0,0,s1);      //第一行第一个位置显示s1

        delay_ms(1000);

        wr_string(0,1,s2);      //第一行第一个位置显示s2

         delay_ms(1000);

         wr_string(0,2,s3);      //第一行第一个位置显示s3

         delay_ms(1000);

        wr_string(0,3,s4);      //第一行第一个位置显示s4

        delay_ms(1000);

     

   

        wr_lcd(comm,0x01);//清除显示 全屏清除

        //init_lcd();

        

        OSSemPost(event_sem);  //释放信号量

        

      

      OSTimeDlyHMSM(0,0,1,0);   //等待1s,交出cpu,任务调度一次防止独占cpu,让其他任务有机会运行

   }

   

}

   

static void led_task(void *pdata)

{

   INT8U i=0;

   pdata=pdata;    //pdata没有用到,这样的目的是防止编译器提出warning

   for(;;)

   {

      OSSemPend(event_sem,0,&err);  //请求信号量

      

      for(i=0;i<10;i++)      //闪烁10

      {

        

      PORTB=0x00;  //led闪烁

      delay_ms(500);

      PORTB=0xff;

      delay_ms(500);

      }

      

        OSSemPost(event_sem);  //释放信号量

      OSTimeDlyHMSM(0,0,0,500);  //等待0.5s  交出cpu

   }

}

//问什么当两个任务等待时间相同时(都为1s),任务lcd每运行两次,任务led才运行一次,当等待时间不同时,

//才交替运行 (任务led的等待时间小于lcd时才正常交替运行)

//该问题要参考ucos-ii for s12 mytest工程的任务调度等待时间的问题,一块解决

   

   

   

static void AppTask1(void *pdata)

{

  pdata=pdata;

  for(;;)

   {

   Flash_Led(7,1);

   OSTimeDlyHMSM(0,0,1,0);

   

   }

   

}

static void AppTask2(void *pdata)

{

  

   pdata=pdata;

   LcdClear();

   for(;;)

   {

   

    LcdWriteStr(0,0,"i'll work hard");

    OSTimeDlyHMSM(0,0,1,0);

    LcdClear();

    LcdWriteStr(0,0,"if i can get the chance");

    LcdWriteStr(1,0,"i promise to you");

    OSTimeDlyHMSM(0,0,1,0);

    LcdClear();

  

   

   

   }

  

}

static void  AppTask3 (void *pdata)

{

   pdata=pdata;

   

   PWM_Init();                          //pwm初始化,将23通道级联

   LcdClear();

   DDRT=0x00;           //PORTT设置为输入

   

   for(;;)

   {

   

     LcdWriteStr(0,0,"welcome teacher!");

     PWM_Init();

     PWMDuo_Dutycycle(100);

     OSTimeDlyHMSM(0,0,1,0);

     Close_PWM();

     LcdClear();

     OSTimeDlyHMSM(0,0,0,500);

   }

   

   

}

static void  AppTask4 (void *pdata)

{

    INT8U  err;

   

   

}

static void  AppTask5 (void *pdata)

{

    INT8U  err;

    DDRB_DDRB3=1;

    pdata = pdata;

    while (TRUE) {

        AppTask5Ctr++;

#if OS_Q_EN > 0

OSQPost(EventQ1, (void *)"Msg #3 to Q1");

OSTimeDly(20);

OSQPost(EventQ2, (void *)"Msg #4 to Q2");

#endif

OSTimeDly(40);

PORTB_PB3=~PORTB_PB3;

    }

}

static void  AppTask6 (void *pdata)

{

    INT8U   err;

char   *pmsg;

char    s[30];

    pdata = pdata;

    while (TRUE) {

        AppTask6Ctr++;

#if OS_Q_EN > 0

        pmsg = (char *)OSQPend(EventQ1, 0, &err);

strcpy(s, pmsg);

#endif

OSTimeDly(1);

    }

}

static void  AppTask7 (void *pdata)

{

    INT8U   err;

char   *pmsg;

char    s[30];

    pdata = pdata;

    while (TRUE) {

        AppTask7Ctr++;

#if OS_Q_EN > 0

        pmsg = (char *)OSQPend(EventQ2, 0, &err);

strcpy(s, pmsg);

#endif

OSTimeDly(1);

    }

}

static void  AppTask8 (void *pdata)

{

    INT8U  err;

    pdata = pdata;

    while (TRUE) {

        AppTask8Ctr++;

#if OS_FLAG_EN > 0

OSFlagPost(FlagGrp1, 0x000F, OS_FLAG_SET, &err);

        OSTimeDly(100);

OSFlagPost(FlagGrp1, 0x00F0, OS_FLAG_SET, &err);

        OSTimeDly(100);

OSFlagPost(FlagGrp1, 0x0F00, OS_FLAG_SET, &err);

        OSTimeDly(100);

OSFlagPost(FlagGrp1, 0xF000, OS_FLAG_SET, &err);

        OSTimeDly(100);

#endif

        OSTimeDly(1);

    }

}

static void  AppTask9 (void *pdata)

{

    INT8U  err;

    pdata = pdata;

    while (TRUE) {

        AppTask9Ctr++;

#if OS_FLAG_EN > 0

        OSFlagPend(FlagGrp1, 0x00FF, OS_FLAG_WAIT_SET_ALL + OS_FLAG_CONSUME, 100, &err);

#endif

        OSTimeDly(100);

    }

}

static void  AppTaskA (void *pdata)

{

    INT8U  err;

    pdata = pdata;

    while (TRUE) {

        AppTaskACtr++;

#if OS_FLAG_EN > 0

        OSFlagPend(FlagGrp1, 0xFF00, OS_FLAG_WAIT_SET_ALL + OS_FLAG_CONSUME, 100, &err);

#endif

        OSTimeDly(100);

    }

}

static void  AppTaskB (void *pdata)

{

    INT8U  err;

    pdata = pdata;

    while (TRUE) {

        AppTaskBCtr++;

#if OS_FLAG_EN > 0

        OSFlagPend(FlagGrp1, 0x0FF0, OS_FLAG_WAIT_SET_ALL + OS_FLAG_CONSUME, 100, &err);

#endif

        OSTimeDly(100);

    }

}

static void  AppTaskC (void *pdata)

{

    INT8U  err;

    pdata = pdata;

    while (TRUE) {

        AppTaskCCtr++;

#if OS_MUTEX_EN > 0

        OSMutexPend(EventMutex1, 0, &err);

OSTimeDly(100);

OSMutexPost(EventMutex1);

#endif

OSTimeDly(1);

    }

}

static void  AppTaskD (void *pdata)

{

    INT8U  err;

    pdata = pdata;

    while (TRUE) {

        AppTaskDCtr++;

#if OS_MUTEX_EN > 0

        OSMutexPend(EventMutex1, 0, &err);

OSTimeDly(100);

OSMutexPost(EventMutex1);

#endif

OSTimeDly(1);

    }

}

static void  AppTaskE (void *pdata)

{

    INT8U  err;

    pdata = pdata;

    while (TRUE) {

        AppTaskECtr++;

#if OS_MBOX_EN > 0

        OSMboxPost(EventMbox1, (void *)"Msg #1");

OSTimeDly(100);

        OSMboxPost(EventMbox1, (void *)"Msg #2");

OSTimeDly(100);

        OSMboxPost(EventMbox1, (void *)"Msg #3");

OSTimeDly(100);

#endif

OSTimeDly(1);

    }

}

static void  AppTaskF (void *pdata)

{

    INT8U  err;

char  *pmsg;

char   s[30];

    pdata = pdata;

    while (TRUE) {

        AppTaskFCtr++;

#if OS_MBOX_EN > 0

        pmsg = (char *)OSMboxPend(EventMbox1, 0, &err);

strcpy(s, pmsg);

#endif

OSTimeDly(1);

    }

}

static void AppTickInit (void)

{

TSCR1   = 0x80;                        

#if OS_TICK_OC == 0

    TIOS  |= 0x01;                          

    TC0    = TCNT + OS_TICK_OC_CNTS;        

    TCTL2  |= 0x01;               

    TIE |= 0x01;                          

#endif

#if OS_TICK_OC == 1

    TIOS  |= 0x02;                          

    TC1    = TCNT + OS_TICK_OC_CNTS;        

    TCTL2  |= 0x04;               

    TIE |= 0x02;                          

#endif

#if OS_TICK_OC == 2

    TIOS  |= 0x04;                          

    TC2    = TCNT + OS_TICK_OC_CNTS;        

    TCTL2  |= 0x10;               

    TIE |= 0x04;                          

#endif

#if OS_TICK_OC == 3

    TIOS  |= 0x08;                          

    TC3    = TCNT + OS_TICK_OC_CNTS;        

    TCTL2  |= 0x40;               

    TIE |= 0x08;                          

#endif

#if OS_TICK_OC == 4

    TIOS  |= 0x10;                          

    TC4    = TCNT + OS_TICK_OC_CNTS;        

    TCTL1  |= 0x01;               

    TIE |= 0x10;                          

#endif

#if OS_TICK_OC == 5

    TIOS  |= 0x20;                          

    TC5    = TCNT + OS_TICK_OC_CNTS;        

    TCTL1  |= 0x04;               

    TIE |= 0x20;                          

#endif

#if OS_TICK_OC == 6

    TIOS  |= 0x40;                          

    TC6    = TCNT + OS_TICK_OC_CNTS;        

    TCTL1  |= 0x10;               

    TIE |= 0x40;                          

#endif

#if OS_TICK_OC == 7

    TIOS  |= 0x80;                          

    TC7    = TCNT + OS_TICK_OC_CNTS;

    TCTL1  |= 0x40;

    TIE |= 0x80;                          

                                 

#endif

}


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入中科因仑

本版积分规则

快速回复 返回顶部 返回列表