1. 程式人生 > >【UCOSIII】UCOSIII的同時等待多個核心物件

【UCOSIII】UCOSIII的同時等待多個核心物件

UCOSIII同時等待多個核心物件

前面講述了UCOSIII的訊號量(一個任務與另一個任務同步)、事件標誌組(一個任務與多個任務同步),它們都可以完成任務的同步。同時,訊號量(保證全域性變數)、訊息佇列,它們都可以完成訊息的傳遞。

但是,它們描述的情況都是任務如何等待單個物件,比如訊號量、互斥訊號量、訊息佇列和時間標誌組等。本文我們就講解一下UCOSIII如何同時等待多個核心物件,UCOSIII只支援同時等待多個訊號量和訊息佇列不支援同時等待多個事件標誌組和互斥訊號量。

UCOSIII中一個任務可以同時等待任意數量的訊號量或者訊息佇列,當只要等到其中的任意一個的時候就會導致該任務進入就緒態,如下圖所示:


需要注意:在事件標誌組中,使用者可以自主設定究竟是等待多個任務同時置1還是同時清零,或者是隻要有置1,只要有清零多種情況下的任務同步。但是在UCOSIII同時等待多個核心物件的情況下,只能等到任何一個訊號量或者訊息佇列就被同步,進入就緒態。只有這一種情況。

UCOSIII同時等待多個核心物件API函式

首先需要注意的是:同時等待多個核心物件並不需要和之前的訊號量、訊息佇列、事件標誌組一樣,先宣告一個物件,在通過xxxCreate()函式定義出來……它只有一個函式,直接用的函式!

OSPendMulti()函式

函式OSPendMulti()用來等待多個核心物件,呼叫OSPendMulti()時,如果這些物件中有多個可用,則所有可用的訊號量和訊息都將返回給呼叫者;如果沒有任何物件可用,則OSPendMulti()將掛起當前任務,直到以下任一情況發生:

  • 物件變為可用;
  • 到達設定的超時時間;
  • 一個或多個任務被刪除或被終止;
  • 一個或多個物件被刪除。

如果一個物件變為可用,並且有多個任務等待這個物件,則UCOSIII將恢復優先順序最高的那個任務函式OSPendMulti()原型如下:

OS_OBJ_QTY  OSPendMulti (OS_PEND_DATA  *p_pend_data_tbl,                //指向OS_PEND_DATA表的指標
                         OS_OBJ_QTY     tbl_size,                    //所等待的核心物件數量
                         OS_TICK        timeout,                        //設定一個等待超時值(時鐘節拍數)
                         OS_OPT         opt,                            //來選擇是否使用阻塞模式
                         OS_ERR        *p_err)
{
    CPU_BOOLEAN   valid;
    OS_OBJ_QTY    nbr_obj_rdy;
    CPU_SR_ALLOC();

    valid = OS_PendMultiValidate(p_pend_data_tbl,           /* -------- Validate objects to be OS_SEM or OS_Q ------- */
                                 tbl_size);
    if (valid == DEF_FALSE) {
       *p_err = OS_ERR_OBJ_TYPE;                            /* Invalid, not OS_SEM or OS_Q                            */
        return ((OS_OBJ_QTY)0);
    }

    CPU_CRITICAL_ENTER();
    nbr_obj_rdy = OS_PendMultiGetRdy(p_pend_data_tbl,       /* --------- SEE IF OBJECT(s) HAVE BEEN POSTED ---------- */
                                     tbl_size);
    if (nbr_obj_rdy > (OS_OBJ_QTY)0) {
        CPU_CRITICAL_EXIT();
       *p_err = OS_ERR_NONE;
        return ((OS_OBJ_QTY)nbr_obj_rdy);
    }

    if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) {    /* Caller wants to block if not available?                */
        CPU_CRITICAL_EXIT();
       *p_err = OS_ERR_PEND_WOULD_BLOCK;                    /* No                                                     */
        return ((OS_OBJ_QTY)0);
    } else {
        if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) {    /* Can't pend when the scheduler is locked                */
            CPU_CRITICAL_EXIT();
           *p_err = OS_ERR_SCHED_LOCKED;
            return ((OS_OBJ_QTY)0);
        }
    }
    OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT();                  /* Lock the scheduler/re-enable interrupts                */
                                                            /* ------ NO OBJECT READY, PEND ON MULTIPLE OBJECTS ----- */
    OS_PendMultiWait(p_pend_data_tbl,                       /* Suspend task until object posted or timeout occurs     */
                     tbl_size,
                     timeout);

    OS_CRITICAL_EXIT_NO_SCHED();

    OSSched();                                              /* Find next highest priority task ready                  */

    CPU_CRITICAL_ENTER();
    switch (OSTCBCurPtr->PendStatus) {
        case OS_STATUS_PEND_OK:                             /* We got one of the objects posted to                    */
            *p_err = OS_ERR_NONE;
             break;

        case OS_STATUS_PEND_ABORT:                          /* Indicate that the multi-pend was aborted               */
            *p_err = OS_ERR_PEND_ABORT;
             break;

        case OS_STATUS_PEND_TIMEOUT:                        /* Indicate that we didn't get semaphore within timeout   */
            *p_err = OS_ERR_TIMEOUT;
             break;

        case OS_STATUS_PEND_DEL:                            /* Indicate that an object pended on has been deleted     */
            *p_err = OS_ERR_OBJ_DEL;
            break;

        default:
            *p_err = OS_ERR_STATUS_INVALID;
             break;
    }

    OSTCBCurPtr->PendStatus = OS_STATUS_PEND_OK;
    CPU_CRITICAL_EXIT();

    return ((OS_OBJ_QTY)1);
}

p_pend_data_tbl:指向OS_PEND_DATA表的指標,呼叫者通過該表來查詢函式的呼叫結果。呼叫該函式的時候首先必須初始化OS_PEND_DATA表中的每個元素的PendObjPtr,使得各個指標指向被等待的物件。

tbl_siae:表p_pend_data_tbl的大小,也就是所等待的核心物件數量。

timeout:設定一個等待超時值(時鐘節拍數),用來設定任務等待物件傳送的時間,如果為0,表示這個任務將一直等待下去,直到物件被髮送。

opt:來選擇是否使用阻塞模式,有兩個選項可以選擇。OS_OPT_PEND_BLOCKING:如果沒有任何訊息存在的話就阻塞任務,一直等待,直到接收到訊息;OS_OPT_PEND_NON_BLOCKING:如果訊息佇列沒有任何訊息的話任務就直接返回。

本函式的返回值為等待的多個核心物件中哪些是可用的。

OS_PEND_DATA

雖然我們不需要定義一個同時等待多個核心物件,但是我們需要定義一個數組,用來將需要等待的核心物件放入其中:也就是OS_PEND_DATA型別的陣列:

struct  os_pend_data {
    OS_PEND_DATA        *PrevPtr;
    OS_PEND_DATA        *NextPtr;
    OS_TCB              *TCBPtr;
    OS_PEND_OBJ         *PendObjPtr;            //指向需要等待的核心物件
    OS_PEND_OBJ         *RdyObjPtr;
    void                *RdyMsgPtr;
    OS_MSG_SIZE          RdyMsgSize;
    CPU_TS               RdyTS;
};

在這個結構體中,PendObjPtr就是指向需要等待的核心物件。所以,我們需要定義一個OS_PEND_DATA型別的陣列,再向每個陣列元素的PendObjPtr成員物件賦需要等待的核心物件的地址。比如:

OS_SEM	Test_Sem1;			//訊號量1
OS_SEM	Test_Sem2;			//訊號量2
OS_Q	Test_Q;				//訊息佇列

OS_PEND_DATA pend_multi_tbl[CORE_OBJ_NUM];      //定義陣列		
pend_multi_tbl[0].PendObjPtr=(OS_PEND_OBJ*)&Test_Sem1;
pend_multi_tbl[1].PendObjPtr=(OS_PEND_OBJ*)&Test_Sem2;
pend_multi_tbl[2].PendObjPtr=(OS_PEND_OBJ*)&Test_Q;

UCOSIII實際例程

同時等待多個核心物件

例程要求:設計一個應用程式,該程式有3任務、2個訊號量和1個訊息佇列。任務A用於建立其他2個任務、2個訊號量和1個訊息佇列。B任務為任務1,用於檢測按鍵,當檢測到按鍵KEY1被按下就傳送訊號量1,當KEY2被按下就傳送訊號量2,當KEY_UP被按下就傳送訊息佇列,任務1還用來控制LED0的閃爍。任務C呼叫函式OSPendMulti()來同時等待2個訊號量和1個訊息佇列。

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "key.h"
#include "sram.h"
#include "malloc.h"
#include "includes.h"

//UCOSIII中以下優先順序使用者程式不能使用,ALIENTEK
//將這些優先順序分配給了UCOSIII的5個系統內部任務
//優先順序0:中斷服務服務管理任務 OS_IntQTask()
//優先順序1:時鐘節拍任務 OS_TickTask()
//優先順序2:定時任務 OS_TmrTask()
//優先順序OS_CFG_PRIO_MAX-2:統計任務 OS_StatTask()
//優先順序OS_CFG_PRIO_MAX-1:空閒任務 OS_IdleTask()

//任務優先順序
#define START_TASK_PRIO		3
//任務堆疊大小	
#define START_STK_SIZE 		128
//任務控制塊
OS_TCB StartTaskTCB;
//任務堆疊	
CPU_STK START_TASK_STK[START_STK_SIZE];
//任務函式
void start_task(void *p_arg);

//任務優先順序
#define TASK1_TASK_PRIO		4
//任務堆疊大小	
#define TASK1_STK_SIZE 		128
//任務控制塊
OS_TCB Task1_TaskTCB;
//任務堆疊	
CPU_STK TASK1_TASK_STK[TASK1_STK_SIZE];
void task1_task(void *p_arg);

//任務優先順序
#define TASK2_TASK_PRIO		5
//任務堆疊大小	
#define TASK2_STK_SIZE 		128
//任務控制塊
OS_TCB Task2_TaskTCB;
//任務堆疊	
CPU_STK TASK2_TASK_STK[TASK2_STK_SIZE];
void task2_task(void *p_arg);

//任務優先順序
#define MULTI_TASK_PRIO		6
//任務堆疊大小	
#define MULTI_STK_SIZE 		128
//任務控制塊
OS_TCB Multi_TaskTCB;
//任務堆疊	
CPU_STK MULTI_TASK_STK[MULTI_STK_SIZE];
void multi_task(void *p_arg);

//LCD刷屏時使用的顏色
int lcd_discolor[14]={	WHITE, BLACK, BLUE,  BRED,      
						GRED,  GBLUE, RED,   MAGENTA,       	 
						GREEN, CYAN,  YELLOW,BROWN, 			
						BRRED, GRAY };

OS_SEM	Test_Sem1;			//訊號量1		
OS_SEM	Test_Sem2;			//訊號量2
OS_Q	Test_Q;				//訊息佇列						
#define QUEUE_NUM		10	//訊息佇列長度
#define CORE_OBJ_NUM	3	//核心物件個數,一共3個:2個訊號量和一個訊息佇列											

int main(void)                        //主函式
{
	OS_ERR err;
	CPU_SR_ALLOC();
	
	delay_init();  	//時鐘初始化
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中斷分組配置
	uart_init(115200);  //串列埠初始化
	LED_Init();         //LED初始化	
	LCD_Init();			//LCD初始化	
	KEY_Init();			//按鍵初始化
	FSMC_SRAM_Init();	//初始化SRAM
	my_mem_init(SRAMIN);//初始化內部RAM
	
	POINT_COLOR = RED;
	LCD_ShowString(30,10,200,16,16,"ALIENTEK STM32F1");	
	LCD_ShowString(30,30,200,16,16,"UCOSIII Examp 13-1");
	LCD_ShowString(30,50,200,16,16,"Pend Multi");
	LCD_ShowString(30,70,200,16,16,"[email protected]");
	LCD_ShowString(30,90,200,16,16,"2015/5/20");
	
	POINT_COLOR = BLACK;
	LCD_DrawRectangle(5,110,234,314);	
	LCD_DrawLine(5,130,234,130);
	POINT_COLOR = RED;
	LCD_ShowString(50,111,200,16,16,"ObjRdy_NUM: 0");
	POINT_COLOR = BLUE;
	
	OSInit(&err);		    	//初始化UCOSIII
	OS_CRITICAL_ENTER();	//進入臨界區			 
	//建立開始任務
	OSTaskCreate((OS_TCB 	* )&StartTaskTCB,		//任務控制塊
				 (CPU_CHAR	* )"start task", 		//任務名字
                 (OS_TASK_PTR )start_task, 			//任務函式
                 (void		* )0,					//傳遞給任務函式的引數
                 (OS_PRIO	  )START_TASK_PRIO,     //任務優先順序
                 (CPU_STK   * )&START_TASK_STK[0],	//任務堆疊基地址
                 (CPU_STK_SIZE)START_STK_SIZE/10,	//任務堆疊深度限位
                 (CPU_STK_SIZE)START_STK_SIZE,		//任務堆疊大小
                 (OS_MSG_QTY  )0,					//任務內部訊息佇列能夠接收的最大訊息數目,為0時禁止接收訊息
                 (OS_TICK	  )0,					//當使能時間片輪轉時的時間片長度,為0時為預設長度,
                 (void   	* )0,					//使用者補充的儲存區
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任務選項
                 (OS_ERR 	* )&err);				//存放該函式錯誤時的返回值
	OS_CRITICAL_EXIT();	//退出臨界區	 
	OSStart(&err);      //開啟UCOSIII
}

void start_task(void *p_arg)                    //開始任務函式
{
	OS_ERR err;
	CPU_SR_ALLOC();
	p_arg = p_arg;
	
	CPU_Init();
#if OS_CFG_STAT_TASK_EN > 0u
   OSStatTaskCPUUsageInit(&err);  	//統計任務                
#endif
	
#ifdef CPU_CFG_INT_DIS_MEAS_EN		//如果使能了測量中斷關閉時間
    CPU_IntDisMeasMaxCurReset();	
#endif
	
#if	OS_CFG_SCHED_ROUND_ROBIN_EN  //當使用時間片輪轉的時候
	 //使能時間片輪轉排程功能,時間片長度為1個系統時鐘節拍,既1*5=5ms
	OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);  
#endif	
		
	OS_CRITICAL_ENTER();	//進入臨界區

	OSSemCreate ((OS_SEM*	)&Test_Sem1,            //建立訊號量Test_Sem1
                 (CPU_CHAR*	)"Test_Sem1",
                 (OS_SEM_CTR)0,		
                 (OS_ERR*	)&err);

	OSSemCreate ((OS_SEM*	)&Test_Sem2,            //建立訊號量Test_Sem2
                 (CPU_CHAR*	)"Test_Sem2",
                 (OS_SEM_CTR)0,		
                 (OS_ERR*	)&err);
	//建立訊息佇列
	OSQCreate ((OS_Q*		)&Test_Q,	//訊息佇列
                (CPU_CHAR*	)"KEY Msg",	//訊息佇列名稱
                (OS_MSG_QTY	)QUEUE_NUM,	//訊息佇列長度
                (OS_ERR*	)&err);		//錯誤碼

	OSTaskCreate((OS_TCB 	* )&Task1_TaskTCB,		        //建立TASK1任務
				 (CPU_CHAR	* )"Task1 task", 		
                 (OS_TASK_PTR )task1_task, 			
                 (void		* )0,					
                 (OS_PRIO	  )TASK1_TASK_PRIO,     
                 (CPU_STK   * )&TASK1_TASK_STK[0],	
                 (CPU_STK_SIZE)TASK1_STK_SIZE/10,	
                 (CPU_STK_SIZE)TASK1_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,  					
                 (void   	* )0,					
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                 (OS_ERR 	* )&err);				

	OSTaskCreate((OS_TCB 	* )&Multi_TaskTCB,		//建立MULTI測試任務
				 (CPU_CHAR	* )"Multi task", 		
                 (OS_TASK_PTR )multi_task, 			
                 (void		* )0,					
                 (OS_PRIO	  )MULTI_TASK_PRIO,     
                 (CPU_STK   * )&MULTI_TASK_STK[0],	
                 (CPU_STK_SIZE)MULTI_STK_SIZE/10,	
                 (CPU_STK_SIZE)MULTI_STK_SIZE,		
                 (OS_MSG_QTY  )0,					
                 (OS_TICK	  )0,  					
                 (void   	* )0,					
                 (OS_OPT      )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
                 (OS_ERR 	* )&err);	
	OS_CRITICAL_EXIT();	//退出臨界區
	OSTaskDel((OS_TCB*)0,&err);	//刪除start_task任務自身
}

void task1_task(void *p_arg)            //任務1的任務函式
{
	u8 key;
	OS_ERR err;
	u8 num;
	u8 *pbuf;
	static u8 msg_num;
	pbuf=mymalloc(SRAMIN,10);	//申請記憶體
	while(1)
	{
		key = KEY_Scan(0);  //掃描按鍵
		switch(key)
		{
			case KEY1_PRES:
				OSSemPost(&Test_Sem1,OS_OPT_POST_1,&err);//傳送訊號量1
				break;
			case KEY0_PRES:
				OSSemPost(&Test_Sem2,OS_OPT_POST_1,&err);//傳送訊號量2
			case WKUP_PRES:
				msg_num++;
				sprintf((char*)pbuf,"ALIENTEK %d",msg_num);
		
				//傳送訊息
				OSQPost((OS_Q*		)&Test_Q,		
						(void*		)pbuf,
						(OS_MSG_SIZE)10,
						(OS_OPT		)OS_OPT_POST_FIFO,
						(OS_ERR*	)&err);
				break;
		}
		num++;
		if(num==50)
		{
			num=0;
			LED0=~LED0;
		}
		OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err);   //延時10ms
	}
}

void multi_task(void *p_arg)                    //等待多個核心物件的任務函式
{	
	u8 num;
	OS_ERR err;
	OS_OBJ_QTY index;
	OS_PEND_DATA pend_multi_tbl[CORE_OBJ_NUM];	
	
	pend_multi_tbl[0].PendObjPtr=(OS_PEND_OBJ*)&Test_Sem1;
	pend_multi_tbl[1].PendObjPtr=(OS_PEND_OBJ*)&Test_Sem2;
	pend_multi_tbl[2].PendObjPtr=(OS_PEND_OBJ*)&Test_Q;
	
	while(1)
	{
		index=OSPendMulti((OS_PEND_DATA*	)pend_multi_tbl,	
						  (OS_OBJ_QTY		)CORE_OBJ_NUM,	//核心數量
						  (OS_TICK		   	)0,		
						  (OS_OPT         	)OS_OPT_PEND_BLOCKING,
						  (OS_ERR*			)&err);
		LCD_ShowNum(147,111,index,1,16);  					//顯示當前有幾個核心物件準備好了
		num++;
		LCD_Fill(6,131,233,313,lcd_discolor[num%14]);		//刷屏
		LED1 = ~LED1;
		OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);   //延時1s
	}
}

相關推薦

UCOSIIIUCOSIII同時等待核心物件

UCOSIII同時等待多個核心物件前面講述了UCOSIII的訊號量(一個任務與另一個任務同步)、事件標誌組(一個任務與多個任務同步),它們都可以完成任務的同步。同時,訊號量(保證全域性變數)、訊息佇列,它們都可以完成訊息的傳遞。但是,它們描述的情況都是任務如何等待單個物件,比

UCOSIII事件標誌組和同時等待核心物件

1.1事件標誌組:        有時候一個任務需要與多個事件同步,這個時候就需要使用事件標誌組。事件標誌組與任務之間有兩種同步機制:“或”同步和“與”同步。      “或”同步:等待多個事件時,任何一個事件發生 ,任務都被同步,這個就稱為“或”同步。     

Shellsed 同時匹配模式

之前在 【Linux】sed 命令最全解析 這篇文章中有提到,使用 sed 實現多個匹配的方法,但是寫的並不全,在此重新補充一下。 sed 命令功能非常強大,通常用於匹配和編輯文字。 預設情況下,一條 sed 命令只能匹配一個模式(模式即匹配規則的意思)。 怎麼用 sed 實

Big Data 每日一題20180922sparkstreaming同時消費topic的資料實現exactly-once的語義

最近很多人問我,sparkstreaming怎麼消費多個topic的資料,自己維護offest,其實這個跟消費一個topic是一樣的,但還是有很多問我,今天就簡單的寫一個demo,供大家參考,直接上程式碼吧,已經測試過了.我把offest存到redis裡了,當然也可以儲存在z

JS筆記頁面同時載入函式

《Javascript高階程式設計》 1.頁面需要繫結少量函式時可以用下面方法,使用匿名函式繫結所需要執行的函式: window.onload = function(){ firstFunction(); secondFunction(); } 2.推薦方

Javaecharts,highcharts中y軸對應的一個x軸的數量的Java對應排序程式碼(一個key下的value值對應key的位置)

1.首先,可以很輕鬆的從後臺資料庫獲取多個list。list如下: 2.根據其中一個的list的排序,獲取出x軸的陣列。(echarts,highcharts的X,Y軸一般為陣列)    Java程式碼: String x[] = new String[li

5、PythonMac安裝管理版本的python

一、問題由來     Mac OS 自帶的python是2.x,自己開發需要python 3.x,但擔心解除安裝系統自帶的python 2.x會造成系統的不穩定,因此,需要在系統中額外安裝python 3.x。pyenv就是這樣一個python版本管理器。 二、安裝過程 1、安裝

轉載Linux Yum安裝MYSQL例項

LINUX作業系統:centOS6.3 64bit(安裝了系統預設開發包) 資料庫一: MYSQL版本:mysql-5.0.56 PORT:3306 系統目錄:/usr/local/mysql3306 資料庫二: MYSQL版本:mysql-5.1.72 PORT:3307

FPGA FIR濾波器之 係數集問題以及 使用非整數實數的係數規範問題

多個係數集 對於多係數過濾器,單個.coe檔案用於指定係數集。 每個係數集應附加到前一組係數。 例如,如果設計了一個2係數集,10抽頭對稱濾波器, 係數集#0為:coefdata = -1,-2,-3,4,5,5,4,-3,-2 ,-1; 和係數集#1是: coef

jsoupjsoup選擇具有class的標籤

如果 html 標籤的class  只要一個,可以通過   Document  doc = Jsoup             &nbs

Jenkins——shell中執行指令碼

前言   前面已經寫了一篇部落格   上篇部落格中只提到了在shell中只執行一個指令碼,生成對應的jtl檔案   並對其進行資料分析。   有些時候我們可能需要測試很多的指令碼,但是因為每

JavaScriptfor迴圈得出span的值

http://topic.csdn.net/t/20060826/20/4977972.html <body> <form id="Form1" action=""> <span id ="sp1">

Windows10遠端桌面共享顯示屏

起因 平時時喜歡用自己的膝上型電腦遠端桌面到公司的工作電腦主機進行工作,公司分配的工作機配置方面都挺好的,主要還是喜歡用自己的筆記本敲程式碼。然而,有時候覺得自己筆記一個顯示屏不大夠用,想做螢幕擴充套件投影,可以外接顯示器。常理來說,Windows10直接連上外接顯示器再“Windows鍵+P鍵”就能進行擴

轉載Opencv同時呼叫兩攝像頭

參考原博地址 http://blog.csdn.net/zmdsjtu/article/details/69222388 原博中可以呼叫但是由於沒有包含釋放所以可能報錯 部落格 :編譯opencv程式錯誤除錯集合 http://blog.csdn.net/hx1298

libs解決android同時使用library時的問題

情景: 在專案引用多個可專案時,多個專案都有對support.v4.jar的引用,報了類似一下錯誤 log: Found 3 versions of android-support-v4.jar in the dependency list, [2014-05-04

JAVASEJava同時丟擲異常

Java有異常丟擲後,跳出程式,一般無法執行接下來的程式碼。 大家做登陸功能,經常會有使用者名稱和密碼的登陸校驗,使用者名稱或者密碼錯誤,如果一般是提示使用者名稱或者密碼錯誤,因為一般無法同時丟擲兩個異常資訊。我們如何來做到同時丟擲多個異常呢? 可以把多個異常資訊放到lis

三種方法讓你在I2C通信中同時從機通信

efi 抖動 萬能 stop ans ole println tran 正常 ref:http://tieba.baidu.com/p/3769008030對於不同地址的模塊就不用多說了,直接分別對其地址進行通信即可。那麽若拿到相同地址的模塊,或者直接是相同的多個模塊怎麽辦

Python + Appium 已解決driver(session)在class之間復用,執行完一個類的用例,再次執行下類的用例時不需要初始化

nic bject config com appium client lee session ted py文件的名稱為:appium_config.py 中的寫法如下 # coding=UTF-8 ‘‘‘ Created on 2017.1.13 @author: Lu

Semaphore控制同時訪問的線程個數countdownlatch等待線程執行完本身線程再執行

個數 post release 執行 控制 latch 釋放 OS 如果 Semaphore控制同時訪問的線程個數countdownlatch等待多個線程執行完本身線程再執行 Semaphore控制同時訪問的線程個數countdownlatch等待多個線程執行完本身線程再

Vue.js學習筆記8:建立Vue例項物件,認識Vue中的元件

建立多個Vue例項物件 這裡在同一個js檔案中建立了兩個Vue例項物件,它們各自能完成前面學的那些功能,同時使用物件名稱也可以互相訪問,協同實現一些功能。 index.html <!DOCTYPE html> <html lang="en" xmlns:v-