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; //B口led设为输出 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那一项是等待时限timeout,0表示无限等待 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 }
|