我们从2011年坚守至今,只想做存粹的技术论坛。  由于网站在外面,点击附件后要很长世间才弹出下载,请耐心等待,勿重复点击不要用Edge和IE浏览器下载,否则提示不安全下载不了

 找回密码
 立即注册
搜索
查看: 4081|回复: 3

[资料贡献] 消息队列、信号量集和软件定时器

[复制链接]

该用户从未签到

811

主题

399

回帖

499

积分

二级逆天

积分
499

社区居民社区明星忠实会员宣传大使奖终身成就奖特殊贡献奖

QQ
发表于 2014-11-21 12:36:24 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区

您需要 登录 才可以下载或查看,没有账号?立即注册

×
#include "lcd.h"
#include "key.h"  
#include "usmart.h"  
#include "sram.h"   
#include "malloc.h"   
#include "tpad.h"   
#include "beep.h"   
#include "touch.h"   
#include "includes.h"  
/////////////////////////UCOSII任务设置///////////////////////////////////
//START 任务
//设置任务优先级
#define START_TASK_PRIO                  10 //开始任务的优先级设置为最低
//设置任务堆栈大小
#define START_STK_SIZE                  64
//任务堆栈   
OS_STK START_TASK_STK[START_STK_SIZE];
//任务函数
void start_task(void *pdata);   
               
//LED任务
//设置任务优先级
#define LED_TASK_PRIO                   7
//设置任务堆栈大小
#define LED_STK_SIZE                      64
//任务堆栈
OS_STK LED_TASK_STK[LED_STK_SIZE];
//任务函数
void led_task(void *pdata);

//触摸屏任务
//设置任务优先级
#define TOUCH_TASK_PRIO                    6
//设置任务堆栈大小
#define TOUCH_STK_SIZE                  128
//任务堆栈   
OS_STK TOUCH_TASK_STK[TOUCH_STK_SIZE];
//任务函数
void touch_task(void *pdata);

//队列消息显示任务
//设置任务优先级
#define QMSGSHOW_TASK_PRIO                5
//设置任务堆栈大小
#define QMSGSHOW_STK_SIZE                   128
//任务堆栈   
OS_STK QMSGSHOW_TASK_STK[QMSGSHOW_STK_SIZE];
//任务函数
void qmsgshow_task(void *pdata);


//主任务
//设置任务优先级
#define MAIN_TASK_PRIO                   4
//设置任务堆栈大小
#define MAIN_STK_SIZE                      128
//任务堆栈   
OS_STK MAIN_TASK_STK[MAIN_STK_SIZE];
//任务函数
void main_task(void *pdata);

//信号量集任务
//设置任务优先级
#define FLAGS_TASK_PRIO                   3
//设置任务堆栈大小
#define FLAGS_STK_SIZE                   128
//任务堆栈   
OS_STK FLAGS_TASK_STK[FLAGS_STK_SIZE];
//任务函数
void flags_task(void *pdata);


//按键扫描任务
//设置任务优先级
#define KEY_TASK_PRIO                   2
//设置任务堆栈大小
#define KEY_STK_SIZE                      128
//任务堆栈   
OS_STK KEY_TASK_STK[KEY_STK_SIZE];
//任务函数
void key_task(void *pdata);
//////////////////////////////////////////////////////////////////////////////
   
OS_EVENT * msg_key;            //按键邮箱事件块      
OS_EVENT * q_msg;            //消息队列
OS_TMR   * tmr1;            //软件定时器1
OS_TMR   * tmr2;            //软件定时器2
OS_TMR   * tmr3;            //软件定时器3
OS_FLAG_GRP * flags_key;    //按键信号量集
void * MsgGrp[256];            //消息队列存储地址,最大支持256个消息

//软件定时器1的回调函数   
//每100ms执行一次,用于显示CPU使用率和内存使用率           
void tmr1_callback(OS_TMR *ptmr,void *p_arg)
{
     static u16 cpuusage=0;
    static u8 tcnt=0;        
    POINT_COLOR=BLUE;
    if(tcnt==5)
    {
         LCD_ShowxNum(182,10,cpuusage/5,3,16,0);            //显示CPU使用率  
        cpuusage=0;
        tcnt=0;
    }
    cpuusage+=OSCPUUsage;
    tcnt++;                    
     LCD_ShowxNum(182,30,my_mem_perused(SRAMIN),3,16,0);    //显示内存使用率                                            
    LCD_ShowxNum(182,50,((OS_Q*)(q_msg->OSEventPtr))->OSQEntries,3,16,0X80);//显示队列当前的大小           
}

//软件定时器2的回调函数                        
void tmr2_callback(OS_TMR *ptmr,void *p_arg)
{   
    static u8 sta=0;
    switch(sta)
    {
        case 0:
            LCD_Fill(131,221,lcddev.width-1,lcddev.height-1,RED);
            break;
        case 1:
            LCD_Fill(131,221,lcddev.width-1,lcddev.height-1,GREEN);
            break;
        case 2:            
            LCD_Fill(131,221,lcddev.width-1,lcddev.height-1,BLUE);
            break;
        case 3:
            LCD_Fill(131,221,lcddev.width-1,lcddev.height-1,MAGENTA);
            break;
         case 4:
            LCD_Fill(131,221,lcddev.width-1,lcddev.height-1,GBLUE);
            break;
        case 5:
            LCD_Fill(131,221,lcddev.width-1,lcddev.height-1,YELLOW);
            break;
        case 6:
            LCD_Fill(131,221,lcddev.width-1,lcddev.height-1,BRRED);
            break;     
    }
    sta++;
    if(sta>6)sta=0;                                                   
}
//软件定时器3的回调函数                        
void tmr3_callback(OS_TMR *ptmr,void *p_arg)
{   
    u8* p;     
    u8 err;
    static u8 msg_cnt=0;    //msg编号      
    p=mymalloc(SRAMIN,13);    //申请13个字节的内存
    if(p)
    {
         sprintf((char*)p,"ALIENTEK %03d",msg_cnt);
        msg_cnt++;
        err=OSQPost(q_msg,p);    //发送队列
        if(err!=OS_ERR_NONE)     //发送失败
        {
            myfree(SRAMIN,p);    //释放内存
            OSTmrStop(tmr3,OS_TMR_OPT_NONE,0,&err);    //关闭软件定时器3
         }
    }
}
//加载主界面   
void ucos_load_main_ui(void)
{
    LCD_Clear(WHITE);    //清屏
     POINT_COLOR=RED;    //设置字体为红色
    LCD_ShowString(10,10,200,16,16,"Explorer STM32");   
    LCD_ShowString(10,30,200,16,16,"UCOSII TEST3");   
    LCD_ShowString(10,50,200,16,16,"ATOM@ALIENTEK");
       LCD_ShowString(10,75,240,16,16,"TPAD:TMR2 SW   KEY_UP:ADJUST");   
       LCD_ShowString(10,95,240,16,16,"KEY0S0 KEY1 SW KEY2:CLR");   
     LCD_DrawLine(0,70,lcddev.width,70);
    LCD_DrawLine(130,0,130,70);

     LCD_DrawLine(0,120,lcddev.width,120);
     LCD_DrawLine(0,220,lcddev.width,220);
    LCD_DrawLine(130,120,130,lcddev.height);
            
     LCD_ShowString(5,125,240,16,16,"QUEUE MSG");//队列消息
    LCD_ShowString(5,150,240,16,16,"Message:");     
    LCD_ShowString(5+130,125,240,16,16,"FLAGS");//信号量集
    LCD_ShowString(5,225,240,16,16,"TOUCH");    //触摸屏
    LCD_ShowString(5+130,225,240,16,16,"TMR2");    //队列消息
    POINT_COLOR=BLUE;//设置字体为蓝色
      LCD_ShowString(150,10,200,16,16,"CPU:   %");   
       LCD_ShowString(150,30,200,16,16,"MEM:   %");   
       LCD_ShowString(150,50,200,16,16," Q :000");   

    delay_ms(300);
}   
int main(void)
{         
    Stm32_Clock_Init(336,8,2,7);//设置时钟,168Mhz
    delay_init(168);            //延时初始化  
    uart_init(84,115200);        //初始化串口波特率为115200
    LED_Init();                    //初始化LED
    LCD_Init();                       //初始化LCD
    BEEP_Init();                //蜂鸣器初始化   
    KEY_Init();                    //按键初始化
    TPAD_Init(8);                //初始化TPAD
    my_mem_init(SRAMIN);        //初始化内部内存池
       tp_dev.init();                //初始化触摸屏
    ucos_load_main_ui();         //加载主界面
    OSInit();                       //初始化UCOSII
      OSTaskCreate(start_task,(void *)0,(OS_STK *)&START_TASK_STK[START_STK_SIZE-1],START_TASK_PRIO );//创建起始任务
    OSStart();      
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//画水平线
//x0,y0:坐标
//len:线长度
//color:颜色
void gui_draw_hline(u16 x0,u16 y0,u16 len,u16 color)
{
    if(len==0)return;
    LCD_Fill(x0,y0,x0+len-1,y0,color);   
}
//画实心圆
//x0,y0:坐标
//r:半径
//color:颜色
void gui_fill_circle(u16 x0,u16 y0,u16 r,u16 color)
{                                             
    u32 i;
    u32 imax = ((u32)r*707)/1000+1;
    u32 sqmax = (u32)r*(u32)r+(u32)r/2;
    u32 x=r;
    gui_draw_hline(x0-r,y0,2*r,color);
    for (i=1;i<=imax;i++)
    {
        if ((i*i+x*x)>sqmax)// draw lines from outside  
        {
             if (x>imax)
            {
                gui_draw_hline (x0-i+1,y0+x,2*(i-1),color);
                gui_draw_hline (x0-i+1,y0-x,2*(i-1),color);
            }
            x--;
        }
        // draw lines from inside (center)  
        gui_draw_hline(x0-x,y0+i,2*x,color);
        gui_draw_hline(x0-x,y0-i,2*x,color);
    }
}  
//两个数之差的绝对值
//x1,x2:需取差值的两个数
//返回值:|x1-x2|
u16 my_abs(u16 x1,u16 x2)
{            
    if(x1>x2)return x1-x2;
    else return x2-x1;
}  
//画一条粗线
//(x1,y1),(x2,y2):线条的起始坐标
//size:线条的粗细程度
//color:线条的颜色
void lcd_draw_bline(u16 x1, u16 y1, u16 x2, u16 y2,u8 size,u16 color)
{
    u16 t;
    int xerr=0,yerr=0,delta_x,delta_y,distance;
    int incx,incy,uRow,uCol;
    if(x1<size|| x2<size||y1<size|| y2<size)return;
    delta_x=x2-x1; //计算坐标增量
    delta_y=y2-y1;
    uRow=x1;
    uCol=y1;
    if(delta_x>0)incx=1; //设置单步方向
    else if(delta_x==0)incx=0;//垂直线
    else {incx=-1;delta_x=-delta_x;}
    if(delta_y>0)incy=1;
    else if(delta_y==0)incy=0;//水平线
    else{incy=-1;delta_y=-delta_y;}
    if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴
    else distance=delta_y;
    for(t=0;t<=distance+1;t++ )//画线输出
    {  
        gui_fill_circle(uRow,uCol,size,color);//画点
        xerr+=delta_x ;
        yerr+=delta_y ;
        if(xerr>distance)
        {
            xerr-=distance;
            uRow+=incx;
        }
        if(yerr>distance)
        {
            yerr-=distance;
            uCol+=incy;
        }
    }  
}
///////////////////////////////////////////////////////////////////////////////////////////////////

//开始任务
void start_task(void *pdata)
{
    OS_CPU_SR cpu_sr=0;
    u8 err;               
    pdata = pdata;     
    msg_key=OSMboxCreate((void*)0);        //创建消息邮箱
    q_msg=OSQCreate(&MsgGrp[0],256);    //创建消息队列
     flags_key=OSFlagCreate(0,&err);     //创建信号量集         
      
    OSStatInit();                    //初始化统计任务.这里会延时1秒钟左右   
     OS_ENTER_CRITICAL();            //进入临界区(无法被中断打断)   
     OSTaskCreate(led_task,(void *)0,(OS_STK*)&LED_TASK_STK[LED_STK_SIZE-1],LED_TASK_PRIO);                           
     OSTaskCreate(touch_task,(void *)0,(OS_STK*)&TOUCH_TASK_STK[TOUCH_STK_SIZE-1],TOUCH_TASK_PRIO);                        
     OSTaskCreate(qmsgshow_task,(void *)0,(OS_STK*)&QMSGSHOW_TASK_STK[QMSGSHOW_STK_SIZE-1],QMSGSHOW_TASK_PRIO);                        
     OSTaskCreate(main_task,(void *)0,(OS_STK*)&MAIN_TASK_STK[MAIN_STK_SIZE-1],MAIN_TASK_PRIO);                        
     OSTaskCreate(flags_task,(void *)0,(OS_STK*)&FLAGS_TASK_STK[FLAGS_STK_SIZE-1],FLAGS_TASK_PRIO);                        
     OSTaskCreate(key_task,(void *)0,(OS_STK*)&KEY_TASK_STK[KEY_STK_SIZE-1],KEY_TASK_PRIO);                        
     OSTaskSuspend(START_TASK_PRIO);    //挂起起始任务.
    OS_EXIT_CRITICAL();                //退出临界区(可以被中断打断)
}
//LED任务
void led_task(void *pdata)
{
    u8 t;
    while(1)
    {
        t++;
        delay_ms(10);
        if(t==8)LED0=1;    //LED0灭
        if(t==100)        //LED0亮
        {
            t=0;
            LED0=0;
        }
    }                                    
}
//触摸屏任务
void touch_task(void *pdata)
{         
    u32 cpu_sr;
     u16 lastpos[2];        //最后一次的数据
    while(1)
    {
        tp_dev.scan(0);         
        if(tp_dev.sta&TP_PRES_DOWN)        //触摸屏被按下
        {   
             if(tp_dev.x[0]<(130-1)&&tp_dev.y[0]<lcddev.height&&tp_dev.y[0]>(220+1))
            {            
                if(lastpos[0]==0XFFFF)
                {
                    lastpos[0]=tp_dev.x[0];
                    lastpos[1]=tp_dev.y[0];
                }
                OS_ENTER_CRITICAL();//进入临界段,防止其他任务,打断LCD操作,导致液晶乱序.
                lcd_draw_bline(lastpos[0],lastpos[1],tp_dev.x[0],tp_dev.y[0],2,RED);//画线
                OS_EXIT_CRITICAL();
                lastpos[0]=tp_dev.x[0];
                lastpos[1]=tp_dev.y[0];     
            }
        }else lastpos[0]=0XFFFF;//没有触摸
        delay_ms(5);     
    }
}     
//队列消息显示任务
void qmsgshow_task(void *pdata)
{
    u8 *p;
    u8 err;
    while(1)
    {
        p=OSQPend(q_msg,0,&err);//请求消息队列
        LCD_ShowString(5,170,240,16,16,p);//显示消息
         myfree(SRAMIN,p);      
        delay_ms(500);     
    }                                    
}
//主任务
void main_task(void *pdata)
{                             
    u32 key=0;   
    u8 err;   
     u8 tmr2sta=1;    //软件定时器2开关状态   
     u8 tmr3sta=0;    //软件定时器3开关状态
    u8 flagsclrt=0;    //信号量集显示清零倒计时   
     tmr1=OSTmrCreate(10,10,OS_TMR_OPT_PERIODIC,(OS_TMR_CALLBACK)tmr1_callback,0,"tmr1",&err);        //100ms执行一次
    tmr2=OSTmrCreate(10,20,OS_TMR_OPT_PERIODIC,(OS_TMR_CALLBACK)tmr2_callback,0,"tmr2",&err);        //200ms执行一次
    tmr3=OSTmrCreate(10,10,OS_TMR_OPT_PERIODIC,(OS_TMR_CALLBACK)tmr3_callback,0,"tmr3",&err);        //100ms执行一次
    OSTmrStart(tmr1,&err);//启动软件定时器1                 
    OSTmrStart(tmr2,&err);//启动软件定时器2                 
     while(1)
    {
        key=(u32)OSMboxPend(msg_key,10,&err);
        if(key)
        {
            flagsclrt=51;//500ms后清除
            OSFlagPost(flags_key,1<<(key-1),OS_FLAG_SET,&err);//设置对应的信号量为1
        }
        if(flagsclrt)//倒计时
        {
            flagsclrt--;
            if(flagsclrt==1)LCD_Fill(140,162,239,162+16,WHITE);//清除显示
        }
        switch(key)
        {
            case 1://控制DS1
                LED1=!LED1;
                break;
            case 2://控制软件定时器3     
                tmr3sta=!tmr3sta;
                if(tmr3sta)OSTmrStart(tmr3,&err);  
                else OSTmrStop(tmr3,OS_TMR_OPT_NONE,0,&err);        //关闭软件定时器3
                 break;
            case 3://清除
                 LCD_Fill(0,221,129,lcddev.height,WHITE);
                break;
            case 4://校准
                OSTaskSuspend(TOUCH_TASK_PRIO);                        //挂起触摸屏任务         
                OSTaskSuspend(QMSGSHOW_TASK_PRIO);                     //挂起队列信息显示任务         
                 OSTmrStop(tmr1,OS_TMR_OPT_NONE,0,&err);                //关闭软件定时器1
                if(tmr2sta)OSTmrStop(tmr2,OS_TMR_OPT_NONE,0,&err);    //关闭软件定时器2                 
                 if((tp_dev.touchtype&0X80)==0)TP_Adjust();   
                OSTmrStart(tmr1,&err);                //重新开启软件定时器1
                if(tmr2sta)OSTmrStart(tmr2,&err);    //重新开启软件定时器2     
                 OSTaskResume(TOUCH_TASK_PRIO);        //解挂
                 OSTaskResume(QMSGSHOW_TASK_PRIO);     //解挂
                ucos_load_main_ui();                //重新加载主界面         
                break;
            case 5://软件定时器2 开关
                tmr2sta=!tmr2sta;
                if(tmr2sta)OSTmrStart(tmr2,&err);                  //开启软件定时器2
                else
                {                        
                      OSTmrStop(tmr2,OS_TMR_OPT_NONE,0,&err);    //关闭软件定时器2
                     LCD_ShowString(148,262,240,16,16,"TMR2 STOP");//提示定时器2关闭了   
                }
                break;                 
               
        }  
        delay_ms(10);
    }
}           
//信号量集处理任务
void flags_task(void *pdata)
{   
    u16 flags;   
    u8 err;                                 
    while(1)
    {
        flags=OSFlagPend(flags_key,0X001F,OS_FLAG_WAIT_SET_ANY,0,&err);//等待信号量
         if(flags&0X0001)LCD_ShowString(140,162,240,16,16,"KEY0 DOWN  ");
        if(flags&0X0002)LCD_ShowString(140,162,240,16,16,"KEY1 DOWN  ");
        if(flags&0X0004)LCD_ShowString(140,162,240,16,16,"KEY2 DOWN  ");
        if(flags&0X0008)LCD_ShowString(140,162,240,16,16,"KEY_UP DOWN");
        if(flags&0X0010)LCD_ShowString(140,162,240,16,16,"TPAD DOWN  ");

        BEEP=1;
        delay_ms(50);
        BEEP=0;
        OSFlagPost(flags_key,0X001F,OS_FLAG_CLR,&err);//全部信号量清零
     }
}
               
//按键扫描任务
void key_task(void *pdata)
{   
    u8 key;                                    
    while(1)
    {
        key=KEY_Scan(0);   
        if(key==0)
        {
            if(TPAD_Scan(0))key=5;
        }
        if(key)OSMboxPost(msg_key,(void*)key);//发送消息
         delay_ms(10);
    }
}
回复

使用道具 举报

该用户从未签到

98

主题

674

回帖

103

积分

二级逆天

积分
103

社区居民忠实会员最爱沙发终身成就奖优秀斑竹奖

QQ
发表于 2014-11-21 15:53:12 | 显示全部楼层
回复

使用道具 举报

该用户从未签到

3

主题

103

回帖

116

积分

二级逆天

积分
116

社区居民

QQ
发表于 2015-3-2 09:27:14 | 显示全部楼层
回复

使用道具 举报

  • TA的每日心情
    开心
    8 小时前
  • 签到天数: 160 天

    [LV.7]常住居民III

    2

    主题

    8784

    回帖

    1万

    积分

    三级逆天

    积分
    10243

    社区居民终身成就奖特殊贡献奖原创先锋奖

    QQ
    发表于 2022-3-8 08:44:00 | 显示全部楼层
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    每日签到,有金币领取。


    Copyright ©2011-2024 NTpcb.com All Right Reserved.  Powered by Discuz! (NTpcb)

    本站信息均由会员发表,不代表NTpcb立场,如侵犯了您的权利请发帖投诉

    ( 闽ICP备2024076463号-1 ) 论坛技术支持QQ群171867948 ,论坛问题,充值问题请联系QQ1308068381

    平平安安
    TOP
    快速回复 返回顶部 返回列表