none
Time(r) Based Interrupt Routine? RRS feed

  • Question

  • Hi,

    I have an application set up where I am polling a MCU through a COM port and would like to do so with 1 second periodicity.  Right now I am using Sleep() and it is horrendously inefficient and causes response delay in WndProc().  Does anyone know of a way to use a timer based interrupt to perhaps set a flag which then could then be evaluated for this purpose and allow other process tasks to still run in the background rather than halting thread execution?

    Monday, October 14, 2019 9:53 PM

Answers

  • You may be looking for SetTimer ( https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-settimer )

    Igor Tandetnik


    • Edited by Igor Tandetnik Monday, October 14, 2019 10:07 PM
    • Marked as answer by JigglyBit Tuesday, October 15, 2019 4:08 AM
    Monday, October 14, 2019 10:06 PM
  • Hello,

    Thank you for posting here.

    >>INTERRUPT_TMR1,            // timer identifier 

    I don't know how you define this character, so I'm replacing it with 1 here. You can check the gif. while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)), while should be changed to if. Although this may have no effect with the result. If it fails again, it may be related to the code which controls window redrawing and refreshing. I don't know how you implemented this function, so I'm sorry I can't test it.

        MSG msg;
        AllocConsole();//open console
        freopen("CONOUT$", "w", stdout);
        freopen("CONOUT$", "w", stderr);
        // Main message loop:
        SetTimer(hWnd, 1, 5000, (TIMERPROC)NULL);
        while (true)
        {
    		if(PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
    		{
    			if (msg.message == WM_QUIT)
    				break;
    			if (msg.message == WM_TIMER) 
    			{
    				if (msg.wParam == 1)
    				{
    					std::cout << "WM_TIMER" << std::endl;
    				}
    					
    			}
    			if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
    			{
    				TranslateMessage(&msg);
    				DispatchMessage(&msg);
    			}
    		}
    		
        }


    Best Regards,

    Suarez Zhou




    Tuesday, October 15, 2019 2:09 AM

All replies

  • You may be looking for SetTimer ( https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-settimer )

    Igor Tandetnik


    • Edited by Igor Tandetnik Monday, October 14, 2019 10:07 PM
    • Marked as answer by JigglyBit Tuesday, October 15, 2019 4:08 AM
    Monday, October 14, 2019 10:06 PM
  • This appears to be what I am looking for.  I however don't seem to be able to implement it.  Like the concept of passing WM_TIMER as a message but can't get SetTimer() to create a timer instance or nIDEvent.  Based on the description of the function, if not NULL, it should just create a timer object with specified name?  Can you perhaps give me an example of how to properly implement this since I can't figure it out from documentation?  When I try to call SetTimer() it doesn't like the timer name portion of the definition during compilation. 
    Monday, October 14, 2019 10:54 PM
  • I'm not sure what you mean by "name". SetTimer doesn't take any parameter that can be reasonably described this way.

    In the simplest case, you call it like

    SetTimer(hwnd, 1, 1000, nullptr);

    The window procedure associated with hwnd would then receive a WM_TIMER message every second, until KillTimer(hwnd, 1) is called or the window is destroyed.


    Igor Tandetnik

    Monday, October 14, 2019 11:27 PM
  • I did something similar and can now get it to compile.  I used #define TIMER 1001 in the global section.  It appears to resolve to a handle of 1001 (your 1 in the example) and compile.  I'm trying to evaluate a WM_TIMER in the winProc callback function now and resolve it to INTERRUPT_TMR1 and am not seeming to get any messages from it.  Program just waits forever.  I have SetTimer() defined in WinMain() like this before the while loop.  I also tried doing it like the below (granted PeekMessate() doesn't block) without luck.  I'm running out of things I could have broken.  Maybe the scope of hWnd is invalid?  No clue.

    SetTimer(hWnd,             // handle to main window 
    INTERRUPT_TMR1,            // timer identifier 
    5000,                 // 5 second interval 
    (TIMERPROC)NULL);     // no timer callback 

    while (TRUE)
    {
    while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
    {
    if (msg.message == WM_QUIT)
    break;
    if (msg.message == WM_TIMER) {
    if (msg.wParam == INTERRUPT_TMR1) {
    refreshWindowTimer = TRUE;
    }
    }
    if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
    {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
    }
    }

    if (msg.message == WM_QUIT)
    break;
    //rest of non-message stuff
    checkForRedraw();


    if (refreshWindowTimer) {       //used as a half assed event timer of sorts for now
    //LogData(sinecounter * 10);
    sinecounter++;
    retrieveDataFrame(PointArray);

    RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE | RDW_UPDATENOW);
    refreshWindowTimer = FALSE;
    }

    }
    return (int) msg.wParam;
    }


    Tuesday, October 15, 2019 12:58 AM
  • Hello,

    Thank you for posting here.

    >>INTERRUPT_TMR1,            // timer identifier 

    I don't know how you define this character, so I'm replacing it with 1 here. You can check the gif. while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)), while should be changed to if. Although this may have no effect with the result. If it fails again, it may be related to the code which controls window redrawing and refreshing. I don't know how you implemented this function, so I'm sorry I can't test it.

        MSG msg;
        AllocConsole();//open console
        freopen("CONOUT$", "w", stdout);
        freopen("CONOUT$", "w", stderr);
        // Main message loop:
        SetTimer(hWnd, 1, 5000, (TIMERPROC)NULL);
        while (true)
        {
    		if(PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
    		{
    			if (msg.message == WM_QUIT)
    				break;
    			if (msg.message == WM_TIMER) 
    			{
    				if (msg.wParam == 1)
    				{
    					std::cout << "WM_TIMER" << std::endl;
    				}
    					
    			}
    			if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
    			{
    				TranslateMessage(&msg);
    				DispatchMessage(&msg);
    			}
    		}
    		
        }


    Best Regards,

    Suarez Zhou




    Tuesday, October 15, 2019 2:09 AM
  • I appear to be having multiple issues here.  One seems to be PeekMessage().  Something about it only wants to process msg events when an event like a button click occurs.  It's like it disregards timer events until something else is processed.  Click a dummy button I embedded in my app and the WM_TIMER check executes.  But putting that on the back burner this is the new issue I now have.  I set this up like you had it and execute this.  I have the "abc" int counter commented out at the moment.  There is a singular timer in my program.  If I remove the comment and allow the variable to update I still process this "timer event" (see reaction in graphical display) and that should be impossible?  Notice I changed the identifier to '2' and it still triggers.  Moreover, it triggers much before the 5 seconds has elapsed.  Zero understanding of what is going on.

    SetTimer(hWnd,            // handle to main window 
    		2,					  // timer identifier 
    		5000,                 // 5 second interval 
    		(TIMERPROC)NULL);     // no timer callback 
    
    	
    	if (!InitInstance(hInstance, nCmdShow))
    	{
    		return FALSE;
    	}
    
    	HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WINDOWSPROJECT1));
    
    	MSG msg;
    	
    	// Main message loop:
    	while (TRUE)
    	{
    		while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
    		{
    			if (msg.message == WM_QUIT)
    				break;
    			if (msg.message == WM_TIMER) {
    				if (msg.wParam == 1) {
    					refreshWindowTimer = TRUE;
    					//abc++;
    				}
    			}
    			if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
    			{
    				TranslateMessage(&msg);
    				DispatchMessage(&msg);
    			}
    		}
    		
    		if (msg.message == WM_QUIT)
    			break;

    Tuesday, October 15, 2019 3:14 AM
  • Also note this only seems to happen when I evaluate msg.wParam == 1.  When I change the timer identifier and attempt to evaluate the new identifier nothing happens at all.  However when I set the check back to msg.wParam ==1 it does.  It's like there is something in the background already claiming this.  When I comment my SetTimer() declaration out so I have not even defined any timers in the program it still exhibits this behavior.
    Tuesday, October 15, 2019 3:25 AM
  • I finally figured it out!  My oversight...didn't have the timer defined in the correct hWnd scope.  Once I moved it to the InitInstance() of the window under the correct scope it works with "while PeekMessage()" in wWinMain() and identifies the new timer key & updates exactly as expected.  Thanks to all for the suggestions and code snapshots.  Helped me arrive at the bozo move on my behalf!
    Tuesday, October 15, 2019 4:00 AM