控制Windows Mobile的LED 之二:控制三个LED指示灯

网友投稿 787 2022-09-19

控制Windows Mobile的LED 之二:控制三个LED指示灯

控制Windows Mobile的LED 之二:控制三个LED指示灯

最近做的一个项目要求用三个GPIO同时独立的控制三个不同颜色的LED灯,且每个LED灯存在亮、灭、快闪、慢闪等四种状态。一开始想到在一个线程里面完成,但无法独立的控制三个LED灯的闪烁频率,无法避免相互影响。无奈之下,先用三个线程控制三个LED实现该功能,如果以后熟悉了线程定时器的做法,再优化。 (1)NLED设置结构体说明 struct NLED_SETTINGS_INFO{    UINT    LedNum;                 // @FIELD   LED number, 0 is first LED    INT     OffOnBlink;             // @FIELD   0 == off, 1 == on, 2 == blink    LONG    TotalCycleTime;         // @FIELD   total cycle time of a blink in microseconds    LONG    OnTime;                 // @FIELD   on time of a cycle in microseconds    LONG    OffTime;                // @FIELD   off time of a cycle in microseconds    INT     MetaCycleOn;            // @FIELD   number of on blink cycles    INT     MetaCycleOff;           // @FIELD   number of off blink cycles};       主要需要用到的几个参数是:LedNum标识不同的LED;OffOnBlink标识不同的工作状态;OnTime标识灯亮时间,OffTime标识灯灭时间,两者仅blink时有用。在很多LED的控制场合,只需要配置这个结构体之后,调用系统函数NLedSetDevice即可。例如: void LightOPLed(int onoff){    NLED_SETTINGS_INFO SettingsInfo;    BOOL nled_result;     SettingsInfo.LedNum = 0;    //0号LED    if(onoff)        SettingsInfo.OffOnBlink = 1;   //灯亮    else        SettingsInfo.OffOnBlink = 0;   //灯灭     SettingsInfo.OnTime = ~0x0;    SettingsInfo.OffTime = 0;    nled_result = NLedSetDevice( NLED_SETTINGS_INFO_ID, &SettingsInfo); } (2)GPIO的使用       用普通的GPIO来控制LED,置高亮,置低灭。因为在WINCE中需要对硬件进行虚拟映射之后才可以访问,一般是用MmMapIoSpace,本处是用的另外的一种方式,达到一样的效果。在NLedDriverInitialize中完成对所需硬件的映射,包括I2C,OSTimer,GPIO等。以下由于篇幅关系省略了错误判断和TRACE。 BYTE *pBaseVirtual;                                //虚拟映射地址变量 DWORD dwBasePhysical;                        //硬件基地址变量LONG dwMMLen;                                     //所需的内存长度dwMMLen = ((sizeof(XLLP_I2C_T) +4*1024-1)/(4*1024)) * 4*1024 +         ((sizeof(XLLP_OST_T) +4*1024-1)/(4*1024)) * 4*1024 +        ((sizeof(XLLP_GPIO_T) +4*1024-1)/(4*1024)) * 4*1024;/*以上是为了保证4K的页内存处理,所以会加4K取整*/    pBaseVirtual = (BYTE *)VirtualAlloc(NULL, dwMMLen, MEM_RESERVE, PAGE_NOACCESS);  //分配虚拟内存                 dwBasePhysical = MONAHANS_BASE_REG_PA_I2C;    //I2C硬件地址    bRet = VirtualCopy((LPVOID)pBaseVirtual, (LPVOID)((unsigned long)dwBasePhysical >> 8), sizeof(XLLP_I2C_T), (PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL));    s_Device.m_pI2CCtrlReg = (P_XLLP_I2C_T)pBaseVirtual;   //将分配的I2C映射地址赋给NLED全局变量    (BYTE *)pBaseVirtual += ((sizeof(XLLP_I2C_T) +4*1024-1)/(4*1024)) * 4*1024;  //跳过刚用过的I2C内存       dwBasePhysical = MONAHANS_BASE_REG_PA_OST;   //OSTimer硬件地址    bRet = VirtualCopy((LPVOID)pBaseVirtual, (LPVOID)((unsigned long)dwBasePhysical >> 8), sizeof(XLLP_OST_T), (PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL));    s_Device.m_pOSTimer = (P_XLLP_OST_T)pBaseVirtual;      //将分配的OSTimer映射地址赋给NLED全局变量    (BYTE *)pBaseVirtual += ((sizeof(XLLP_OST_T) +4*1024-1)/(4*1024)) * 4*1024;   //跳过刚用过的OSTimer内存       dwBasePhysical = MONAHANS_BASE_REG_PA_GPIO;   //GPIO硬件地址    bRet = VirtualCopy((LPVOID)pBaseVirtual, (LPVOID)((unsigned long)dwBasePhysical >> 8), sizeof(XLLP_GPIO_T), (PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL));   //将分配的GPIO映射地址赋给NLED全局变量    s_Device.m_pGPIOReg = (P_XLLP_GPIO_T)pBaseVirtual;  //将分配的GPIO映射地址赋给NLED全局变量  (3)对LED的亮和灭的控制       首先要在NLedDriverSetDevice添加对不同LED的控制,为此需添加三个LED的宏定义。由于三个LED类似,为此这里仅专门对红色LED的控制列举。对闪烁的控制需要建立一个线程和事件来控制,在下一节说明。如下: BOOL  WINAPI NLedDriverSetDevice(INT     nInfoId,  PVOID   pInput  ) {      .................    struct NLED_SETTINGS_INFO *p = ( struct NLED_SETTINGS_INFO* )pInput;    .................    switch(p->LedNum)  {          case RED_LED:         if(p->OffOnBlink == 1)     //如果是全亮         {                ResetEvent(nled_Redset_event);    //LED状态改变,取消闪烁事件               p->OffTime = 0;                               //灭时间为0               LedRGBSet(XLLP_GPIO2_2_RED_LED,p->OnTime,p->OffTime);   //设置GPIO          }          else if(p->OffOnBlink == 0)     //如果是全灭          {                ResetEvent(nled_Redset_event);     //LED状态改变,取消闪烁事件               p->OnTime = 0;                                 //亮时间为0               LedRGBSet(XLLP_GPIO2_2_RED_LED,p->OnTime,p->OffTime);   //设置GPIO           }           else                                                       //如果是闪烁           {                 RED.OffTime = p->OffTime;                              RED.OnTime = p->OnTime;               //获得亮灭的时间,并赋给全局变量,以便线程中调用                SetEvent( nled_Redset_event);       //置闪烁事件有效            }            break;       } } 其中,GPIO的控制函数如下: void LedRGBSet(UINT8 pinNum,DWORD onTime,  DWORD offTime) //zhangcheng 20101101{        XllpGpioSetDirection(s_Device.m_pGPIOReg, pinNum, XLLP_GPIO_DIRECTION_OUT);        if((onTime !=0)&&(offTime == 0))              XllpGpioSetOutputLevel(s_Device.m_pGPIOReg, pinNum, XLLP_HI);             else if((onTime == 0)&&(offTime != 0))              XllpGpioSetOutputLevel(s_Device.m_pGPIOReg, pinNum, XLLP_LO); } (4)LED闪烁线程的处理       定义三个LED的事件句柄和准备传入线程的全局变量 HANDLE nled_Redset_event,nled_Greenset_event,nled_Blueset_event;   struct NLED_SETTINGS_INFO RED,GREEN,BLUE;                                                在NLedDriverInitialize中要创建时间跟线程:  nled_Redset_event = CreateEvent(NULL, TRUE, FALSE,NULL);    //最后一个参数不需事件名字 nled_Greenset_event = CreateEvent(NULL, TRUE, FALSE,NULL);  //初始化是FALSE,必须是设置灯闪烁才为SETEVENT nled_Blueset_event = CreateEvent(NULL, TRUE, FALSE,NULL);   //手动清信号,这个很重要,否则线程循环会阻塞 CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)nled_Redset_thread, 0, 0, NULL); CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)nled_Greenset_thread, 0, 0, NULL); CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)nled_Blueset_thread, 0, 0, NULL);       以红色LED的线程说明: DWORD WINAPI nled_Redset_thread(){      DWORD dwWaitTime = INFINITE;        while(1)     {            int status;            status = WaitForSingleObject(nled_Redset_event, dwWaitTime);  //线程阻塞,必须事件有效才会往后执行            if (status == WAIT_FAILED){  //如果事件是线程等待函数执行完后清掉了,第二次就阻塞在这里了,所以要用不自动清的事件                  RETAILMSG(1,(TEXT("nled_Redset_thread: wait failed!/r/n")));            }            XllpGpioSetDirection(s_Device.m_pGPIOReg, XLLP_GPIO2_2_RED_LED, XLLP_GPIO_DIRECTION_OUT);             XllpGpioSetOutputLevel(s_Device.m_pGPIOReg, XLLP_GPIO2_2_RED_LED, XLLP_HI);             Sleep(RED.OnTime);                                   //亮OnTime时间            XllpGpioSetOutputLevel(s_Device.m_pGPIOReg, XLLP_GPIO2_2_RED_LED, XLLP_LO);             Sleep(RED.OffTime);                                   //灭OffTime时间,形成闪烁     }      return  TRUE;}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:利用Python爬虫采集mac电脑皮肤(mac 爬虫)
下一篇:inf文件规则
相关文章

 发表评论

暂时没有评论,来抢沙发吧~